ia64/xen-unstable

changeset 138:4a4ae256b9b5

bitkeeper revision 1.22.1.10 (3e48f4c9XYI43AfrJ_7BMyjM2NofzA)

Changes to support zero-copy tx... incremental updates to synch with main repository.
author akw27@boulderdash.cl.cam.ac.uk
date Tue Feb 11 13:04:09 2003 +0000 (2003-02-11)
parents 3549eb0ec2db
children 2f78322be16a
files xen-2.4.16/common/kernel.c xen-2.4.16/common/network.c xen-2.4.16/include/xeno/vif.h xen-2.4.16/net/dev.c xenolinux-2.4.16-sparse/arch/xeno/drivers/network/network.c
line diff
     1.1 --- a/xen-2.4.16/common/kernel.c	Thu Feb 06 16:31:29 2003 +0000
     1.2 +++ b/xen-2.4.16/common/kernel.c	Tue Feb 11 13:04:09 2003 +0000
     1.3 @@ -14,6 +14,7 @@
     1.4  #include <xeno/dom0_ops.h>
     1.5  #include <asm/byteorder.h>
     1.6  #include <linux/if_ether.h>
     1.7 +#include <asm/domain_page.h>
     1.8  
     1.9  /* VGA text definitions. */
    1.10  #define COLUMNS	    80
    1.11 @@ -297,11 +298,11 @@ void panic(const char *fmt, ...)
    1.12      char buf[1024], *p;
    1.13      unsigned long flags;
    1.14      extern void machine_restart(char *);
    1.15 -
    1.16 +    
    1.17      va_start(args, fmt);
    1.18      (void)vsnprintf(buf, sizeof(buf), fmt, args);
    1.19      va_end(args);
    1.20 -  
    1.21 +    
    1.22      /* Spit out multiline message in one go. */
    1.23      spin_lock_irqsave(&console_lock, flags);
    1.24      __putstr("\n****************************************\n");
    1.25 @@ -353,6 +354,7 @@ unsigned short compute_cksum(unsigned sh
    1.26  /* XXX SMH: below is rather vile; pulled in to allow network console */
    1.27  
    1.28  extern int netif_rx(struct sk_buff *); 
    1.29 +extern struct net_device *the_dev;
    1.30  
    1.31  typedef struct my_udphdr {
    1.32      __u16 source;
    1.33 @@ -403,17 +405,24 @@ int console_export(char *str, int len)
    1.34      struct my_udphdr *udph = NULL; 
    1.35      struct my_ethhdr *ethh = NULL; 
    1.36      int hdr_size = sizeof(struct my_iphdr) + sizeof(struct my_udphdr); 
    1.37 -    
    1.38 -    // Prepare console packet
    1.39 -    console_packet = alloc_skb(sizeof(struct my_ethhdr) + hdr_size + len, 
    1.40 -			       GFP_KERNEL);
    1.41 +    u8 *skb_data;
    1.42 +
    1.43 +    // Prepare console packet - the grim + 20 in the alloc is for headroom.
    1.44 +    console_packet = dev_alloc_skb(sizeof(struct my_ethhdr) + hdr_size + len + 20);
    1.45 +    if (!console_packet) return 0;
    1.46 +//console_packet->security = 9; // hack to trace these packets.
    1.47 +    console_packet->dev = the_dev;
    1.48 +    skb_data = map_domain_mem((unsigned long)console_packet->head);
    1.49 +    skb_reserve(console_packet, 2); // ip header alignment.
    1.50 +//printk("Eth is: %d\n", console_packet->data - console_packet->head);
    1.51 +    ethh   = (struct my_ethhdr *) skb_data + (console_packet->data - console_packet->head);
    1.52      skb_reserve(console_packet, sizeof(struct my_ethhdr)); 
    1.53 -    ethh   = (struct my_ethhdr *)console_packet->head;
    1.54  
    1.55      skb_put(console_packet, hdr_size + len); 
    1.56 -    iph  = (struct my_iphdr *)console_packet->data; 
    1.57 -	udph = (struct my_udphdr *)(iph + 1); 
    1.58 -	memcpy((char *)(udph + 1), str, len); 
    1.59 +//printk("IP is: %d\n", console_packet->data - console_packet->head);
    1.60 +    iph  = (struct my_iphdr *)skb_data + (console_packet->data - console_packet->head); 
    1.61 +    udph = (struct my_udphdr *)(iph + 1); 
    1.62 +    memcpy((char *)(udph + 1), str, len); 
    1.63  
    1.64      // Build IP header
    1.65      iph->version = 4;
    1.66 @@ -442,6 +451,13 @@ int console_export(char *str, int len)
    1.67      memcpy(ethh->h_dest, "000000", 6);
    1.68      ethh->h_proto = htons(ETH_P_IP);
    1.69      console_packet->mac.ethernet= (struct ethhdr *)ethh;
    1.70 +
    1.71 +    // Make the packet appear to come off the external NIC so that the 
    1.72 +    // tables code doesn't get too confused.
    1.73 +    console_packet->src_vif = VIF_PHYSICAL_INTERFACE;
    1.74 +    console_packet->dst_vif = 0;
    1.75 +    
    1.76 +    unmap_domain_mem(skb_data);
    1.77      
    1.78      // Pass the packet to netif_rx
    1.79      (void)netif_rx(console_packet);
    1.80 @@ -477,23 +493,14 @@ long do_console_write(char *str, int cou
    1.81  	
    1.82          if ( !safe_str[i] ) break;
    1.83          putchar(prev = safe_str[i]);
    1.84 -	
    1.85 -        if ( prev == '\n' )
    1.86 -        {
    1.87 -	    exported_str[j]='\0';
    1.88 -	    console_export(exported_str, j-1);
    1.89 -	    j=0;
    1.90 -        }
    1.91 -	
    1.92      }
    1.93 -    if ( prev != '\n' ) 
    1.94 -    {
    1.95 -	putchar('\n');
    1.96 -        exported_str[j]='\0';
    1.97 -        console_export(exported_str, j-1);
    1.98 -    }
    1.99 +    
   1.100 +    if ( prev != '\n' ) putchar('\n');
   1.101      
   1.102      spin_unlock_irqrestore(&console_lock, flags);
   1.103      
   1.104 +    exported_str[j]='\0';
   1.105 +    console_export(exported_str, j-1);
   1.106 +    
   1.107      return(0);
   1.108  }
     2.1 --- a/xen-2.4.16/common/network.c	Thu Feb 06 16:31:29 2003 +0000
     2.2 +++ b/xen-2.4.16/common/network.c	Tue Feb 11 13:04:09 2003 +0000
     2.3 @@ -343,47 +343,56 @@ int net_find_rule(u8 nproto, u8 tproto, 
     2.4   * list.
     2.5   */
     2.6  
     2.7 -int net_get_target_vif(struct sk_buff *skb)
     2.8 +#define net_get_target_vif(skb) __net_get_target_vif(skb->data, skb->len, skb->src_vif)
     2.9 +
    2.10 +int __net_get_target_vif(u8 *data, unsigned int len, int src_vif)
    2.11  {
    2.12      int target = VIF_DROP;
    2.13 -    skb->h.raw = skb->nh.raw = skb->data;
    2.14 -    if ( skb->len < 2 ) goto drop;
    2.15 -    switch ( ntohs(skb->mac.ethernet->h_proto) )
    2.16 +    u8 *h_raw, *nh_raw;
    2.17 +    
    2.18 +    if ( len < 2 ) goto drop;
    2.19 +
    2.20 +    nh_raw = data + ETH_HLEN;
    2.21 +    switch ( ntohs(*(unsigned short *)(data + 12)) )
    2.22      {
    2.23      case ETH_P_ARP:
    2.24 -        if ( skb->len < 28 ) goto drop;
    2.25 -        target = net_find_rule((u8)ETH_P_ARP, 0, ntohl(*(u32 *)(skb->nh.raw + 14)),
    2.26 -                        ntohl(*(u32 *)(skb->nh.raw + 24)), 0, 0, 
    2.27 -                        skb->src_vif);
    2.28 +//printk("ARP!\n");
    2.29 +        if ( len < 28 ) goto drop;
    2.30 +        target = net_find_rule((u8)ETH_P_ARP, 0, ntohl(*(u32 *)(nh_raw + 14)),
    2.31 +                        ntohl(*(u32 *)(nh_raw + 24)), 0, 0, 
    2.32 +                        src_vif);
    2.33          break;
    2.34      case ETH_P_IP:
    2.35 -        if ( skb->len < 20 ) goto drop;
    2.36 -        skb->h.raw += ((*(unsigned char *)(skb->nh.raw)) & 0x0f) * 4;
    2.37 -        switch ( *(unsigned char *)(skb->nh.raw + 9) )
    2.38 +//printk("IP\n");
    2.39 +        if ( len < 20 ) goto drop;
    2.40 +        h_raw =  data + ((*(unsigned char *)(nh_raw)) & 0x0f) * 4;
    2.41 +        switch ( *(unsigned char *)(nh_raw + 9) )
    2.42          {
    2.43 -        case IPPROTO_TCP:
    2.44          case IPPROTO_UDP:
    2.45 -            target = net_find_rule((u8)ETH_P_IP,  *(u8 *)(skb->nh.raw + 9),
    2.46 -                    ntohl(*(u32 *)(skb->nh.raw + 12)),
    2.47 -                    ntohl(*(u32 *)(skb->nh.raw + 16)),
    2.48 -                    ntohs(*(u16 *)(skb->h.raw)),
    2.49 -                    ntohs(*(u16 *)(skb->h.raw + 2)), 
    2.50 -                    skb->src_vif);
    2.51 +//printk("UDP!\n");
    2.52 +        case IPPROTO_TCP:
    2.53 +            target = net_find_rule((u8)ETH_P_IP,  *(u8 *)(nh_raw + 9),
    2.54 +                    ntohl(*(u32 *)(nh_raw + 12)),
    2.55 +                    ntohl(*(u32 *)(nh_raw + 16)),
    2.56 +                    ntohs(*(u16 *)(h_raw)),
    2.57 +                    ntohs(*(u16 *)(h_raw + 2)), 
    2.58 +                    src_vif);
    2.59              break;
    2.60          default: // ip-based protocol where we don't have ports.
    2.61 -            target = net_find_rule((u8)ETH_P_IP,  *(u8 *)(skb->nh.raw + 9),
    2.62 -                    ntohl(*(u32 *)(skb->nh.raw + 12)),
    2.63 -                    ntohl(*(u32 *)(skb->nh.raw + 16)),
    2.64 +//printk("Other IP!\n");
    2.65 +            target = net_find_rule((u8)ETH_P_IP,  *(u8 *)(data + 9),
    2.66 +                    ntohl(*(u32 *)(nh_raw + 12)),
    2.67 +                    ntohl(*(u32 *)(nh_raw + 16)),
    2.68                      0,
    2.69                      0, 
    2.70 -                    skb->src_vif);
    2.71 +                    src_vif);
    2.72          }
    2.73          break;
    2.74      }
    2.75 -    skb->dst_vif=target;
    2.76      return target;
    2.77      
    2.78      drop:
    2.79 +//printk("Drop case!\n");
    2.80      return VIF_DROP;
    2.81  }
    2.82  
     3.1 --- a/xen-2.4.16/include/xeno/vif.h	Thu Feb 06 16:31:29 2003 +0000
     3.2 +++ b/xen-2.4.16/include/xeno/vif.h	Tue Feb 11 13:04:09 2003 +0000
     3.3 @@ -66,9 +66,10 @@ extern net_vif_t *sys_vif_list[];
     3.4  net_vif_t *create_net_vif(int domain);
     3.5  void destroy_net_vif(struct task_struct *p);
     3.6  void add_default_net_rule(int vif_id, u32 ipaddr);
     3.7 -int net_get_target_vif(struct sk_buff *skb);
     3.8 +int __net_get_target_vif(u8 *data, unsigned int len, int src_vif);
     3.9  void add_default_net_rule(int vif_id, u32 ipaddr);
    3.10  
    3.11 +#define net_get_target_vif(skb) __net_get_target_vif(skb->data, skb->len, skb->src_vif)
    3.12  /* status fields per-descriptor:
    3.13   */
    3.14  
     4.1 --- a/xen-2.4.16/net/dev.c	Thu Feb 06 16:31:29 2003 +0000
     4.2 +++ b/xen-2.4.16/net/dev.c	Tue Feb 11 13:04:09 2003 +0000
     4.3 @@ -501,7 +501,7 @@ int dev_queue_xmit(struct sk_buff *skb)
     4.4  {
     4.5  	struct net_device *dev = skb->dev;
     4.6  	struct Qdisc  *q;
     4.7 -
     4.8 +if (!(dev->features&NETIF_F_SG)) printk("NIC doesn't do SG!!!\n");
     4.9  	if (skb_shinfo(skb)->frag_list &&
    4.10  	    !(dev->features&NETIF_F_FRAGLIST) &&
    4.11  	    skb_linearize(skb, GFP_ATOMIC) != 0) {
    4.12 @@ -673,12 +673,11 @@ void deliver_packet(struct sk_buff *skb,
    4.13  {
    4.14          net_shadow_ring_t *shadow_ring;
    4.15          rx_shadow_entry_t *rx;
    4.16 -        unsigned long *g_pte, tmp;
    4.17 +        unsigned long *g_pte; //tmp
    4.18          struct pfn_info *g_pfn, *h_pfn;
    4.19          unsigned int i; //, nvif;
    4.20  
    4.21 -        if (skb->skb_type != SKB_ZERO_COPY) 
    4.22 -            return;
    4.23 +        
    4.24          
    4.25          /*
    4.26           * Write the virtual MAC address into the destination field
    4.27 @@ -724,10 +723,11 @@ void deliver_packet(struct sk_buff *skb,
    4.28              //flip and/or set relevant pf_info fields.
    4.29              //tmp = g_pfn->next; g_pfn->next = h_pfn->next; h_pfn->next = tmp;
    4.30              //tmp = g_pfn->prev; g_pfn->prev = h_pfn->prev; h_pfn->prev = tmp;
    4.31 -            tmp = g_pfn->flags; g_pfn->flags = h_pfn->flags; h_pfn->flags = tmp;
    4.32 +            //tmp = g_pfn->flags; g_pfn->flags = h_pfn->flags; h_pfn->flags = tmp;
    4.33              h_pfn->tot_count = h_pfn->type_count = 1;
    4.34              g_pfn->tot_count = g_pfn->type_count = 0;
    4.35 -            h_pfn->flags = g_pfn->flags & ~ PG_type_mask;
    4.36 +            h_pfn->flags = g_pfn->flags & (~PG_type_mask);
    4.37 +//if (h_pfn->flags & PG_domain_mask) printk("deliver packet to dom %lu\n", (h_pfn->flags & PG_domain_mask));
    4.38              if (*g_pte & _PAGE_RW) h_pfn->flags |= PGT_writeable_page;
    4.39              g_pfn->flags = 0;
    4.40              //point guest pte at the new page:
    4.41 @@ -783,25 +783,28 @@ int netif_rx(struct sk_buff *skb)
    4.42          net_vif_t *vif;
    4.43  
    4.44  	local_irq_save(flags);
    4.45 -        
    4.46 +
    4.47 +        if (skb->skb_type != SKB_ZERO_COPY) 
    4.48 +            BUG();
    4.49 +                
    4.50  	if (skb->stamp.tv_sec == 0)
    4.51 -		get_fast_time(&skb->stamp);
    4.52 -
    4.53 -        /* Attempt to handle zero-copy packets here: */
    4.54 -        if (skb->skb_type == SKB_ZERO_COPY)
    4.55 -        {
    4.56 -                skb->head = (u8 *)map_domain_mem(((skb->pf - frame_table) << PAGE_SHIFT));
    4.57 +	    get_fast_time(&skb->stamp);
    4.58  
    4.59 -                /* remapping this address really screws up all the skb pointers.  We need 
    4.60 -                 * to map them all here sufficiently to get the packet demultiplexed.
    4.61 -                 */
    4.62 +        if ( (skb->data - skb->head) != (18 + ETH_HLEN) )
    4.63 +            BUG();
    4.64 +        
    4.65 +        skb->head = (u8 *)map_domain_mem(((skb->pf - frame_table) << PAGE_SHIFT));
    4.66 +
    4.67 +        /* remapping this address really screws up all the skb pointers.  We need 
    4.68 +        * to map them all here sufficiently to get the packet demultiplexed.
    4.69 +        */
    4.70                  
    4.71 -                skb->data = skb->head;
    4.72 -                skb_reserve(skb,16); // need to ensure that all the drivers and not just tulip do this.
    4.73 -                skb->mac.raw = skb->data;
    4.74 -                skb->data += ETH_HLEN;
    4.75 -                skb->nh.raw = skb->data;
    4.76 -        }
    4.77 +        skb->data = skb->head;
    4.78 +        skb_reserve(skb,18); // 18 is the 16 from dev_alloc_skb plus 2 for #
    4.79 +                             // IP header alignment. 
    4.80 +        skb->mac.raw = skb->data;
    4.81 +        skb->data += ETH_HLEN;
    4.82 +        skb->nh.raw = skb->data;
    4.83          
    4.84  	/* The code is rearranged so that the path is the most
    4.85  	   short when CPU is congested, but is still operating.
    4.86 @@ -812,9 +815,11 @@ int netif_rx(struct sk_buff *skb)
    4.87  
    4.88          if ( skb->src_vif == VIF_UNKNOWN_INTERFACE )
    4.89              skb->src_vif = VIF_PHYSICAL_INTERFACE;
    4.90 -
    4.91 +                
    4.92          if ( skb->dst_vif == VIF_UNKNOWN_INTERFACE )
    4.93 -            net_get_target_vif(skb);
    4.94 +            skb->dst_vif = __net_get_target_vif(skb->mac.raw, skb->len, skb->src_vif);
    4.95 +if (skb->dst_vif == VIF_DROP)
    4.96 +printk("netif_rx target: %d (sec: %u)\n", skb->dst_vif, skb->security);
    4.97          
    4.98          if ( (vif = sys_vif_list[skb->dst_vif]) == NULL )
    4.99          {
   4.100 @@ -851,17 +856,14 @@ int netif_rx(struct sk_buff *skb)
   4.101  
   4.102  drop:
   4.103  	netdev_rx_stat[this_cpu].dropped++;
   4.104 -        if (skb->skb_type == SKB_ZERO_COPY)
   4.105 -                unmap_domain_mem(skb->head);
   4.106 +        unmap_domain_mem(skb->head);
   4.107  	kfree_skb(skb);
   4.108          local_irq_restore(flags);
   4.109  	return NET_RX_DROP;
   4.110  
   4.111  found:
   4.112 -        if (skb->skb_type == SKB_ZERO_COPY) {
   4.113 -                unmap_domain_mem(skb->head);
   4.114 -                skb->head = skb->data = skb->tail = (void *)0xdeadbeef;
   4.115 -        }
   4.116 +        unmap_domain_mem(skb->head);
   4.117 +        skb->head = skb->data = skb->tail = (void *)0xdeadbeef;
   4.118          kfree_skb(skb);
   4.119          hyp_event_notify(cpu_mask);
   4.120          local_irq_restore(flags);
   4.121 @@ -990,7 +992,7 @@ void update_shared_ring(void)
   4.122      net_ring_t *net_ring;
   4.123      net_shadow_ring_t *shadow_ring;
   4.124      unsigned int nvif;
   4.125 -
   4.126 +    
   4.127      clear_bit(_HYP_EVENT_NET_RX, &current->hyp_events);
   4.128      for (nvif = 0; nvif < current->num_net_vifs; nvif++)
   4.129      {
   4.130 @@ -1004,7 +1006,7 @@ void update_shared_ring(void)
   4.131  
   4.132              shadow_ring->rx_idx = RX_RING_INC(shadow_ring->rx_idx);
   4.133              net_ring->rx_cons   = RX_RING_INC(net_ring->rx_cons);
   4.134 -
   4.135 +            
   4.136              if (rx->flush_count == tlb_flush_count[smp_processor_id()])
   4.137                  __flush_tlb();
   4.138  
   4.139 @@ -2134,13 +2136,59 @@ int __init net_dev_init(void)
   4.140  	return 0;
   4.141  }
   4.142  
   4.143 +inline int init_tx_header(u8 *data, unsigned int len, struct net_device *dev)
   4.144 +{
   4.145 +        memcpy(data + ETH_ALEN, dev->dev_addr, ETH_ALEN);
   4.146 +        
   4.147 +        switch ( ntohs(*(unsigned short *)(data + 12)) )
   4.148 +        {
   4.149 +        case ETH_P_ARP:
   4.150 +            if ( len < 42 ) break;
   4.151 +            memcpy(data + 22, dev->dev_addr, 6);
   4.152 +            return ETH_P_ARP;
   4.153 +        case ETH_P_IP:
   4.154 +            return ETH_P_IP;
   4.155 +        }
   4.156 +        return 0;
   4.157 +}
   4.158  
   4.159 +/* 
   4.160 + * tx_skb_release
   4.161 + *
   4.162 + * skb destructor function that is attached to zero-copy tx skbs before 
   4.163 + * they are passed to the device driver for transmission.  The destructor 
   4.164 + * is responsible for unlinking the fragment pointer to the skb data that 
   4.165 + * is in guest memory, and decrementing the tot_count on the packet pages 
   4.166 + * pfn_info.
   4.167 + */
   4.168 +
   4.169 +void tx_skb_release(struct sk_buff *skb)
   4.170 +{
   4.171 +    int i;
   4.172 +    
   4.173 +    for (i= 0; i < skb_shinfo(skb)->nr_frags; i++)
   4.174 +        skb_shinfo(skb)->frags[i].page->tot_count--;
   4.175 +    
   4.176 +    skb_shinfo(skb)->nr_frags = 0; 
   4.177 +}
   4.178 +    
   4.179  /*
   4.180   * do_net_update:
   4.181   * 
   4.182   * Called from guest OS to notify updates to its transmit and/or receive
   4.183   * descriptor rings.
   4.184   */
   4.185 +#define PKT_PROT_LEN (ETH_HLEN + 8)
   4.186 +
   4.187 +void print_range2(u8 *start, unsigned int len)
   4.188 +{
   4.189 +    int i=0;
   4.190 +    while (i++ < len)
   4.191 +    {
   4.192 +        printk("%x:",start[i]);
   4.193 +    }
   4.194 +    printk("\n");
   4.195 +}
   4.196  
   4.197  long do_net_update(void)
   4.198  {
   4.199 @@ -2161,6 +2209,9 @@ long do_net_update(void)
   4.200      {
   4.201          current_vif = current->net_vif_list[j];
   4.202          net_ring = current_vif->net_ring;
   4.203 +        int target;
   4.204 +        u8 *g_data;
   4.205 +        unsigned short protocol;
   4.206  
   4.207          /* First, we send out pending TX descriptors if they exist on this ring.
   4.208           */
   4.209 @@ -2170,63 +2221,123 @@ long do_net_update(void)
   4.210              if ( copy_from_user(&tx, net_ring->tx_ring+i, sizeof(tx)) )
   4.211                  continue;
   4.212  
   4.213 +            if ( tx.size < PKT_PROT_LEN ) continue; // This should be reasonable.
   4.214 +            
   4.215 +            // Packets must not cross page boundaries.  For now, this is a 
   4.216 +            // kernel panic, later it may become a continue -- silent fail.
   4.217 +            
   4.218 +            if ( ((tx.addr & ~PAGE_MASK) + tx.size) >= PAGE_SIZE ) 
   4.219 +            {
   4.220 +                printk("tx.addr: %lx, size: %lu, end: %lu\n", tx.addr, tx.size,
   4.221 +                    (tx.addr &~PAGE_MASK) + tx.size);
   4.222 +                continue;
   4.223 +                //BUG();
   4.224 +            }
   4.225 +            
   4.226              if ( TX_RING_INC(i) == net_ring->tx_event )
   4.227                  set_bit(_EVENT_NET_TX_FOR_VIF(j), &shared->events);
   4.228  
   4.229 -            skb = alloc_skb(tx.size, GFP_KERNEL);
   4.230 -            if ( skb == NULL ) continue;
   4.231 -            skb_put(skb, tx.size);
   4.232 -            if ( copy_from_user(skb->data, (void *)tx.addr, tx.size) )
   4.233 +            /* Map the skb in from the guest, and get it's delivery target.
   4.234 +             * We need this to know whether the packet is to be sent locally
   4.235 +             * or remotely.
   4.236 +             */
   4.237 +            
   4.238 +            g_data = map_domain_mem(tx.addr);
   4.239 +
   4.240 +//print_range2(g_data, PKT_PROT_LEN);                
   4.241 +            protocol = __constant_htons(init_tx_header(g_data, tx.size, the_dev));
   4.242 +            if ( protocol == 0 )
   4.243              {
   4.244 -                kfree_skb(skb);
   4.245 -                continue;
   4.246 -            }
   4.247 -            skb->dev = the_dev;
   4.248 -
   4.249 -            if ( skb->len < 16 )
   4.250 -            {
   4.251 -                kfree_skb(skb);
   4.252 +                unmap_domain_mem(g_data);
   4.253                  continue;
   4.254              }
   4.255  
   4.256 -            memcpy(skb->data + ETH_ALEN, skb->dev->dev_addr, ETH_ALEN);
   4.257 -        
   4.258 -            switch ( ntohs(*(unsigned short *)(skb->data + 12)) )
   4.259 +            target = __net_get_target_vif(g_data, tx.size, current_vif->id);
   4.260 +//printk("Send to target: %d\n", target); 
   4.261 +            if (target > VIF_PHYSICAL_INTERFACE )
   4.262              {
   4.263 -            case ETH_P_ARP:
   4.264 -                skb->protocol = __constant_htons(ETH_P_ARP);
   4.265 -                if ( skb->len < 42 ) break;
   4.266 -                memcpy(skb->data + 22, skb->dev->dev_addr, 6);
   4.267 -                break;
   4.268 -            case ETH_P_IP:
   4.269 -                skb->protocol = __constant_htons(ETH_P_IP);
   4.270 -                break;
   4.271 -            default:
   4.272 -                kfree_skb(skb);
   4.273 -                skb = NULL;
   4.274 -                break;
   4.275 -            }
   4.276 +                // Local delivery: Allocate an skb off the domain free list
   4.277 +                // fil it, and pass it to netif_rx as if it came off the NIC.
   4.278 +
   4.279 +                skb = dev_alloc_skb(tx.size);
   4.280 +                if (skb == NULL) 
   4.281 +                {
   4.282 +                    unmap_domain_mem(g_data);
   4.283 +                    continue;
   4.284 +                }
   4.285 +                
   4.286 +                skb->src_vif = current_vif->id;
   4.287 +                skb->dst_vif = target;
   4.288 +                skb->protocol = protocol;
   4.289 +                if (copy_to_user(skb->data, g_data, tx.size))
   4.290 +                {
   4.291 +                    unmap_domain_mem(g_data);
   4.292 +                    continue;
   4.293 +                }
   4.294 +                
   4.295 +                (void)netif_rx(skb); // why is there a void here?  It's from the old code.
   4.296  
   4.297 -            if ( skb != NULL )
   4.298 +                unmap_domain_mem(g_data);
   4.299 +            }
   4.300 +            else if ( target == VIF_PHYSICAL_INTERFACE )
   4.301              {
   4.302 -                skb->protocol = eth_type_trans(skb, skb->dev);
   4.303 -                skb->src_vif = current_vif->id; 
   4.304 -                net_get_target_vif(skb);
   4.305 -                if ( skb->dst_vif > VIF_PHYSICAL_INTERFACE )
   4.306 +                // External delivery: Allocate a small skb to hold protected header info
   4.307 +                // and copy the eth header and IP address fields into that.
   4.308 +                // Set a frag link to the remaining data, and we will scatter-gather
   4.309 +                // in the device driver to send the two bits later.
   4.310 +                
   4.311 +                /*unmap_domain_mem(g_data);*/
   4.312 +                    
   4.313 +                skb = alloc_skb(PKT_PROT_LEN, GFP_KERNEL); // Eth header + two IP addrs.
   4.314 +                if (skb == NULL) 
   4.315                  {
   4.316 -printk("LOCAL DELIVERY!\n");
   4.317 -                    (void)netif_rx(skb);
   4.318 +printk("Alloc skb failed!\n");
   4.319 +                    continue;
   4.320 +                }
   4.321 +            
   4.322 +                skb_put(skb, PKT_PROT_LEN);
   4.323 +                /*if ( copy_from_user(skb->data, (void *)tx.addr, PKT_PROT_LEN) )
   4.324 +                {
   4.325 +printk("Copy from user failed!\n");
   4.326 +                    kfree_skb(skb);
   4.327 +                    continue;
   4.328                  }
   4.329 -                else if ( skb->dst_vif == VIF_PHYSICAL_INTERFACE )
   4.330 -                {
   4.331 -                    skb_push(skb, skb->dev->hard_header_len);
   4.332 -                    dev_queue_xmit(skb);
   4.333 -                } 
   4.334 -                else
   4.335 -                {
   4.336 -                    kfree_skb(skb);
   4.337 -                }
   4.338 +                */
   4.339 +                memcpy(skb->data, g_data, PKT_PROT_LEN);
   4.340 +                unmap_domain_mem(g_data);
   4.341 +//print_range2(g_data, PKT_PROT_LEN);                
   4.342 +                skb->dev = the_dev;
   4.343 +                skb->src_vif = current_vif->id;
   4.344 +                skb->dst_vif = target;
   4.345 +                skb->protocol = protocol; // These next two lines abbreviate the call 
   4.346 +                                          // to eth_type_trans as we already have our
   4.347 +                                          // protocol.
   4.348 +                //skb_pull(skb, skb->dev->hard_header_len);
   4.349 +                skb->mac.raw=skb->data; 
   4.350 +
   4.351 +                // set tot_count++ in the guest data pfn.
   4.352 +                page = (tx.addr >> PAGE_SHIFT) + frame_table;
   4.353 +                page->tot_count++;
   4.354  
   4.355 +                // place the remainder of the packet (which is in guest memory) into an
   4.356 +                // skb frag.
   4.357 +                skb_shinfo(skb)->frags[0].page = page;
   4.358 +                skb_shinfo(skb)->frags[0].size = tx.size - PKT_PROT_LEN;
   4.359 +                skb_shinfo(skb)->frags[0].page_offset 
   4.360 +                    = (tx.addr & ~PAGE_MASK) + PKT_PROT_LEN;
   4.361 +                skb_shinfo(skb)->nr_frags = 1;
   4.362 +                skb->data_len = tx.size - skb->len;
   4.363 +                skb->len = tx.size;
   4.364 +                
   4.365 +                // assign a destructor to the skb that will unlink and dec the tot_count
   4.366 +                skb->destructor = &tx_skb_release;
   4.367 +                //skb_push(skb, skb->dev->hard_header_len);
   4.368 +//printk("calling dev_queue_xmit!\n");
   4.369 +                dev_queue_xmit(skb);
   4.370 +            }
   4.371 +            else
   4.372 +            {
   4.373 +                unmap_domain_mem(g_data);
   4.374              }
   4.375          }
   4.376          net_ring->tx_cons = i;
     5.1 --- a/xenolinux-2.4.16-sparse/arch/xeno/drivers/network/network.c	Thu Feb 06 16:31:29 2003 +0000
     5.2 +++ b/xenolinux-2.4.16-sparse/arch/xeno/drivers/network/network.c	Tue Feb 11 13:04:09 2003 +0000
     5.3 @@ -241,7 +241,7 @@ static void network_alloc_rx_buffers(str
     5.4          skb = dev_alloc_skb(RX_BUF_SIZE);
     5.5          if ( skb == NULL ) break;
     5.6          skb->dev = dev;
     5.7 -        //skb_reserve(skb, 2); /* word align the IP header */
     5.8 +        skb_reserve(skb, 2); /* word align the IP header */
     5.9          np->rx_skb_ring[i] = skb;
    5.10          np->net_ring->rx_ring[i].addr = get_ppte(skb->head); 
    5.11          np->net_ring->rx_ring[i].size = RX_BUF_SIZE - 16; /* arbitrary */
    5.12 @@ -269,6 +269,14 @@ static void network_free_rx_buffers(stru
    5.13      }
    5.14  }
    5.15  
    5.16 +void print_range(u8 *start, unsigned int len)
    5.17 +{
    5.18 +    int i = 0;
    5.19 +
    5.20 +    while (i++ < len)
    5.21 +        printk("%x:", start[i]);
    5.22 +    printk("\n");
    5.23 +}
    5.24  
    5.25  static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
    5.26  {
    5.27 @@ -281,10 +289,13 @@ static int network_start_xmit(struct sk_
    5.28          netif_stop_queue(dev);
    5.29          return -ENOBUFS;
    5.30      }
    5.31 -
    5.32 +//print_range(skb->data, ETH_HLEN + 8);
    5.33 +//print_range(skb->data + ETH_HLEN + 8, 20);
    5.34 +//printk("skb->len is %u in guestOS (expected fraglen: %u).\n", skb->len, skb->len - (ETH_HLEN + 8));
    5.35      i = np->net_ring->tx_prod;
    5.36      np->tx_skb_ring[i] = skb;
    5.37 -    np->net_ring->tx_ring[i].addr = (unsigned long)skb->data;
    5.38 +    np->net_ring->tx_ring[i].addr 
    5.39 +        = (unsigned long)phys_to_machine(virt_to_phys(skb->data));
    5.40      np->net_ring->tx_ring[i].size = skb->len;
    5.41      np->net_ring->tx_prod = TX_RING_INC(i);
    5.42      atomic_inc(&np->tx_entries);