ia64/xen-unstable

changeset 176:36921c18576a

bitkeeper revision 1.42 (3e4e5147oIRUj1VB4sRCLLxTviTVaw)

network.c, dev.c, kernel.c:
Fixed console export via UDP. Was rather broken. Still dropping external packets though :-(
author kaf24@labyrinth.cl.cam.ac.uk
date Sat Feb 15 14:40:07 2003 +0000 (2003-02-15)
parents f38c3d392cac
children bc7bbe93a3f2
files xen-2.4.16/common/kernel.c xen-2.4.16/common/network.c 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	Sat Feb 15 10:53:19 2003 +0000
     1.2 +++ b/xen-2.4.16/common/kernel.c	Sat Feb 15 14:40:07 2003 +0000
     1.3 @@ -398,39 +398,37 @@ typedef struct my_ethhdr {
     1.4      unsigned short  h_proto;        
     1.5  } my_ethhdr_t; 
     1.6  
     1.7 -
     1.8 +/*
     1.9 + * Function written by ek247. Exports console output from all domains upwards 
    1.10 + * to domain0, by stuffing it into a fake network packet.
    1.11 + */
    1.12  int console_export(char *str, int len)
    1.13  {
    1.14 -    /* Function written by ek247
    1.15 -     * Exports console output from all domains upwards
    1.16 -     * to domain0, by stuffing it into a fake network
    1.17 -     * packet
    1.18 -     */
    1.19 -    struct sk_buff *console_packet;
    1.20 +    struct sk_buff *skb;
    1.21      struct my_iphdr *iph = NULL;  
    1.22      struct my_udphdr *udph = NULL; 
    1.23      struct my_ethhdr *ethh = NULL; 
    1.24      int hdr_size = sizeof(struct my_iphdr) + sizeof(struct my_udphdr); 
    1.25      u8 *skb_data;
    1.26  
    1.27 -    // Prepare console packet - the grim + 20 in the alloc is for headroom.
    1.28 -    console_packet = dev_alloc_skb(sizeof(struct my_ethhdr) + hdr_size + len + 20);
    1.29 -    if (!console_packet) return 0;
    1.30 -//console_packet->security = 9; // hack to trace these packets.
    1.31 -    console_packet->dev = the_dev;
    1.32 -    skb_data = map_domain_mem((unsigned long)console_packet->head);
    1.33 -    skb_reserve(console_packet, 2); // ip header alignment.
    1.34 -//printk("Eth is: %d\n", console_packet->data - console_packet->head);
    1.35 -    ethh   = (struct my_ethhdr *) skb_data + (console_packet->data - console_packet->head);
    1.36 -    skb_reserve(console_packet, sizeof(struct my_ethhdr)); 
    1.37 +    skb = dev_alloc_skb(sizeof(struct my_ethhdr) + 
    1.38 +                                   hdr_size + len + 20);
    1.39 +    if ( skb == NULL ) return 0;
    1.40 +
    1.41 +    skb->dev = the_dev;
    1.42 +    skb_data = (u8 *)map_domain_mem((skb->pf - frame_table) << PAGE_SHIFT);
    1.43 +    skb_reserve(skb, 2);
    1.44  
    1.45 -    skb_put(console_packet, hdr_size + len); 
    1.46 -//printk("IP is: %d\n", console_packet->data - console_packet->head);
    1.47 -    iph  = (struct my_iphdr *)skb_data + (console_packet->data - console_packet->head); 
    1.48 +    /* Get a pointer to each header. */
    1.49 +    ethh = (struct my_ethhdr *) 
    1.50 +        (skb_data + (skb->data - skb->head));
    1.51 +    iph  = (struct my_iphdr *)(ethh + 1);
    1.52      udph = (struct my_udphdr *)(iph + 1); 
    1.53 -    memcpy((char *)(udph + 1), str, len); 
    1.54  
    1.55 -    // Build IP header
    1.56 +    skb_reserve(skb, sizeof(struct my_ethhdr)); 
    1.57 +    skb_put(skb, hdr_size + len); 
    1.58 +
    1.59 +    /* Build IP header. */
    1.60      iph->version = 4;
    1.61      iph->ihl     = 5;
    1.62      iph->frag_off= 0;
    1.63 @@ -440,33 +438,31 @@ int console_export(char *str, int len)
    1.64      iph->daddr   = htonl(opt_ipbase);
    1.65      iph->saddr   = htonl(0xa9fe0001); 
    1.66      iph->tot_len = htons(hdr_size + len); 
    1.67 -
    1.68 -    // Calculating IP checksum
    1.69      iph->check	 = 0;
    1.70      iph->check   = compute_cksum((__u16 *)iph, sizeof(struct my_iphdr)/2); 
    1.71  
    1.72 +    /* Build UDP header. */
    1.73 +    udph->source = htons(current->domain);
    1.74 +    udph->dest   = htons(666);
    1.75 +    udph->len    = htons(sizeof(struct my_udphdr) + len);
    1.76 +    udph->check  = 0;
    1.77  
    1.78 -    // Build UDP header
    1.79 -    udph->source    = htons(current->domain);
    1.80 -    udph->dest      = htons(666);
    1.81 -    udph->len       = htons(sizeof(struct my_udphdr) + len);
    1.82 -    udph->check     = 0;
    1.83 -		
    1.84 -    // Fix Ethernet header
    1.85 -    memcpy(ethh->h_source, "000000", 6);
    1.86 -    memcpy(ethh->h_dest, "000000", 6);
    1.87 +    /* Build the UDP payload. */
    1.88 +    memcpy((char *)(udph + 1), str, len); 
    1.89 +
    1.90 +    /* Fix Ethernet header. */
    1.91 +    memset(ethh->h_source, 0, ETH_ALEN);
    1.92 +    memset(ethh->h_dest,   0, ETH_ALEN);
    1.93      ethh->h_proto = htons(ETH_P_IP);
    1.94 -    console_packet->mac.ethernet= (struct ethhdr *)ethh;
    1.95 +    skb->mac.ethernet= (struct ethhdr *)ethh;
    1.96  
    1.97 -    // Make the packet appear to come off the external NIC so that the 
    1.98 -    // tables code doesn't get too confused.
    1.99 -    console_packet->src_vif = VIF_PHYSICAL_INTERFACE;
   1.100 -    console_packet->dst_vif = 0;
   1.101 +    /* Keep the net rule tables happy. */
   1.102 +    skb->src_vif = VIF_PHYSICAL_INTERFACE;
   1.103 +    skb->dst_vif = 0;
   1.104      
   1.105      unmap_domain_mem(skb_data);
   1.106      
   1.107 -    // Pass the packet to netif_rx
   1.108 -    (void)netif_rx(console_packet);
   1.109 +    (void)netif_rx(skb);
   1.110  
   1.111      return 1;
   1.112  }
     2.1 --- a/xen-2.4.16/common/network.c	Sat Feb 15 10:53:19 2003 +0000
     2.2 +++ b/xen-2.4.16/common/network.c	Sat Feb 15 14:40:07 2003 +0000
     2.3 @@ -356,20 +356,18 @@ int __net_get_target_vif(u8 *data, unsig
     2.4      switch ( ntohs(*(unsigned short *)(data + 12)) )
     2.5      {
     2.6      case ETH_P_ARP:
     2.7 -//printk("ARP!\n");
     2.8          if ( len < 28 ) goto drop;
     2.9          target = net_find_rule((u8)ETH_P_ARP, 0, ntohl(*(u32 *)(nh_raw + 14)),
    2.10                          ntohl(*(u32 *)(nh_raw + 24)), 0, 0, 
    2.11                          src_vif);
    2.12          break;
    2.13 +
    2.14      case ETH_P_IP:
    2.15 -//printk("IP\n");
    2.16          if ( len < 20 ) goto drop;
    2.17          h_raw =  data + ((*(unsigned char *)(nh_raw)) & 0x0f) * 4;
    2.18          switch ( *(unsigned char *)(nh_raw + 9) )
    2.19          {
    2.20          case IPPROTO_UDP:
    2.21 -//printk("UDP!\n");
    2.22          case IPPROTO_TCP:
    2.23              target = net_find_rule((u8)ETH_P_IP,  *(u8 *)(nh_raw + 9),
    2.24                      ntohl(*(u32 *)(nh_raw + 12)),
    2.25 @@ -378,8 +376,8 @@ int __net_get_target_vif(u8 *data, unsig
    2.26                      ntohs(*(u16 *)(h_raw + 2)), 
    2.27                      src_vif);
    2.28              break;
    2.29 +
    2.30          default: // ip-based protocol where we don't have ports.
    2.31 -//printk("Other IP!\n");
    2.32              target = net_find_rule((u8)ETH_P_IP,  *(u8 *)(data + 9),
    2.33                      ntohl(*(u32 *)(nh_raw + 12)),
    2.34                      ntohl(*(u32 *)(nh_raw + 16)),
    2.35 @@ -388,6 +386,7 @@ int __net_get_target_vif(u8 *data, unsig
    2.36                      src_vif);
    2.37          }
    2.38          break;
    2.39 +
    2.40      }
    2.41      return target;
    2.42      
     3.1 --- a/xen-2.4.16/net/dev.c	Sat Feb 15 10:53:19 2003 +0000
     3.2 +++ b/xen-2.4.16/net/dev.c	Sat Feb 15 14:40:07 2003 +0000
     3.3 @@ -46,7 +46,6 @@
     3.4  #define DPRINTK(_f, _a...) ((void)0)
     3.5  #endif
     3.6  
     3.7 -// Ring defines:
     3.8  #define TX_RING_INC(_i)    (((_i)+1) & (TX_RING_SIZE-1))
     3.9  #define RX_RING_INC(_i)    (((_i)+1) & (RX_RING_SIZE-1))
    3.10  #define TX_RING_ADD(_i,_j) (((_i)+(_j)) & (TX_RING_SIZE-1))
    3.11 @@ -689,8 +688,6 @@ void deliver_packet(struct sk_buff *skb,
    3.12          struct pfn_info *g_pfn, *h_pfn;
    3.13          unsigned int i; 
    3.14  
    3.15 -        
    3.16 -        
    3.17          memset(skb->mac.ethernet->h_dest, 0, ETH_ALEN);
    3.18          if ( ntohs(skb->mac.ethernet->h_proto) == ETH_P_ARP )
    3.19          {
    3.20 @@ -698,44 +695,47 @@ void deliver_packet(struct sk_buff *skb,
    3.21          }
    3.22          shadow_ring = vif->shadow_ring;
    3.23  
    3.24 -        //Advance to next good buffer.
    3.25 -        for (i = shadow_ring->rx_cons; 
    3.26 -             (i != shadow_ring->rx_prod) 
    3.27 -             && ( shadow_ring->rx_ring[i].status != RING_STATUS_OK );
    3.28 -             i = RX_RING_INC(i));
    3.29 -            
    3.30 -        if (( i != shadow_ring->rx_prod ) &&
    3.31 -            ( shadow_ring->rx_ring[i].status == RING_STATUS_OK ))
    3.32 +        if ( (i = shadow_ring->rx_cons) == shadow_ring->rx_prod )
    3.33 +        {
    3.34 +            return;
    3.35 +        }
    3.36 +
    3.37 +        if ( shadow_ring->rx_ring[i].status != RING_STATUS_OK )
    3.38          {
    3.39 -            rx = shadow_ring->rx_ring+i;
    3.40 -            if ( (skb->len + ETH_HLEN) < rx->size )
    3.41 -                rx->size = skb->len + ETH_HLEN;
    3.42 +            DPRINTK("Bad buffer in deliver_packet()\n");
    3.43 +            shadow_ring->rx_cons = RX_RING_INC(i);
    3.44 +            return;
    3.45 +        }
    3.46 +
    3.47 +        rx = shadow_ring->rx_ring + i;
    3.48 +        if ( (skb->len + ETH_HLEN) < rx->size )
    3.49 +            rx->size = skb->len + ETH_HLEN;
    3.50              
    3.51 -            g_pte = map_domain_mem(rx->addr);
    3.52 -
    3.53 -            g_pfn =  frame_table + (*g_pte >> PAGE_SHIFT);
    3.54 -            h_pfn = skb->pf;
    3.55 +        g_pte = map_domain_mem(rx->addr);
    3.56  
    3.57 -            h_pfn->tot_count = h_pfn->type_count = 1;
    3.58 -            g_pfn->tot_count = g_pfn->type_count = 0;
    3.59 -            h_pfn->flags = g_pfn->flags & (~PG_type_mask);
    3.60 +        g_pfn = frame_table + (*g_pte >> PAGE_SHIFT);
    3.61 +        h_pfn = skb->pf;
    3.62 +        
    3.63 +        h_pfn->tot_count = h_pfn->type_count = 1;
    3.64 +        g_pfn->tot_count = g_pfn->type_count = 0;
    3.65 +        h_pfn->flags = g_pfn->flags & (~PG_type_mask);
    3.66 +        
    3.67 +        if (*g_pte & _PAGE_RW) h_pfn->flags |= PGT_writeable_page;
    3.68 +        g_pfn->flags = 0;
    3.69 +        
    3.70 +        /* Point the guest at the new machine frame. */
    3.71 +        machine_to_phys_mapping[h_pfn - frame_table] 
    3.72 +            = machine_to_phys_mapping[g_pfn - frame_table];        
    3.73 +        *g_pte = (*g_pte & ~PAGE_MASK) 
    3.74 +            | (((h_pfn - frame_table) << PAGE_SHIFT) & PAGE_MASK);
    3.75 +        *g_pte |= _PAGE_PRESENT;
    3.76 +        
    3.77 +        unmap_domain_mem(g_pte);
    3.78  
    3.79 -            if (*g_pte & _PAGE_RW) h_pfn->flags |= PGT_writeable_page;
    3.80 -            g_pfn->flags = 0;
    3.81 -            
    3.82 -            //point guest pte at the new page:
    3.83 -            machine_to_phys_mapping[h_pfn - frame_table] 
    3.84 -                    = machine_to_phys_mapping[g_pfn - frame_table];
    3.85 -
    3.86 -            *g_pte = (*g_pte & ~PAGE_MASK) 
    3.87 -                | (((h_pfn - frame_table) << PAGE_SHIFT) & PAGE_MASK);
    3.88 -            *g_pte |= _PAGE_PRESENT;
    3.89 -                
    3.90 -            unmap_domain_mem(g_pte);
    3.91 -            skb->pf = g_pfn; // return the guest pfn to be put on the free list
    3.92 -                
    3.93 -            shadow_ring->rx_cons = RX_RING_INC(i);
    3.94 -        }
    3.95 +        /* Our skbuff now points at the guest's old frame. */
    3.96 +        skb->pf = g_pfn;
    3.97 +        
    3.98 +        shadow_ring->rx_cons = RX_RING_INC(i);
    3.99  }
   3.100  
   3.101  /* Deliver skb to an old protocol, which is not threaded well
   3.102 @@ -785,17 +785,17 @@ int netif_rx(struct sk_buff *skb)
   3.103          
   3.104          skb->head = (u8 *)map_domain_mem(((skb->pf - frame_table) << PAGE_SHIFT));
   3.105  
   3.106 -        /* remapping this address really screws up all the skb pointers.  We need 
   3.107 -         * to map them all here sufficiently to get the packet demultiplexed.
   3.108 -         *
   3.109 -         * this remapping happens more than once in the code and is grim.  It will
   3.110 -         * be fixed in a later update -- drivers should be able to align the packet
   3.111 -         * arbitrarily.
   3.112 +        /*
   3.113 +         * remapping this address really screws up all the skb pointers.  We
   3.114 +         * need to map them all here sufficiently to get the packet
   3.115 +         * demultiplexed. this remapping happens more than once in the code and
   3.116 +         * is grim.  It will be fixed in a later update -- drivers should be
   3.117 +         * able to align the packet arbitrarily.
   3.118           */
   3.119                  
   3.120          skb->data = skb->head;
   3.121 -        skb_reserve(skb,18); // 18 is the 16 from dev_alloc_skb plus 2 for #
   3.122 -                             // IP header alignment. 
   3.123 +        skb_reserve(skb,18); /* 18 is the 16 from dev_alloc_skb plus 2 for
   3.124 +                                IP header alignment. */
   3.125          skb->mac.raw = skb->data;
   3.126          skb->data += ETH_HLEN;
   3.127          skb->nh.raw = skb->data;
   3.128 @@ -813,14 +813,14 @@ int netif_rx(struct sk_buff *skb)
   3.129          if ( (vif = sys_vif_list[skb->dst_vif]) == NULL )
   3.130              goto drop;
   3.131  
   3.132 -        /* This lock-and-walk of the task list isn't really necessary, and is an
   3.133 -         * artifact of the old code.  The vif contains a pointer to the skb list 
   3.134 -         * we are going to queue the packet in, so the lock and the inner loop
   3.135 -         * could be removed.
   3.136 -         *
   3.137 -         * The argument against this is a possible race in which a domain is killed
   3.138 -         * as packets are being delivered to it.  This would result in the dest vif
   3.139 -         * vanishing before we can deliver to it.
   3.140 +        /*
   3.141 +         * This lock-and-walk of the task list isn't really necessary, and is
   3.142 +         * an artifact of the old code.  The vif contains a pointer to the skb
   3.143 +         * list we are going to queue the packet in, so the lock and the inner
   3.144 +         * loop could be removed. The argument against this is a possible race
   3.145 +         * in which a domain is killed as packets are being delivered to it.
   3.146 +         * This would result in the dest vif vanishing before we can deliver to
   3.147 +         * it.
   3.148           */
   3.149          
   3.150          if ( skb->dst_vif >= VIF_PHYSICAL_INTERFACE )
   3.151 @@ -974,11 +974,11 @@ static inline void handle_diverter(struc
   3.152  
   3.153  /*
   3.154   * update_shared_ring(void)
   3.155 - *
   3.156 - * This replaces flush_rx_queue as the guest event handler to move packets queued in
   3.157 - * the guest ring up to the guest.  Really, the packet is already there, it was page
   3.158 - * flipped in deliver_packet, but this moves the ring descriptor across from the 
   3.159 - * shadow ring and increments the pointers.
   3.160 + * 
   3.161 + * This replaces flush_rx_queue as the guest event handler to move packets
   3.162 + * queued in the guest ring up to the guest.  Really, the packet is already
   3.163 + * there, it was page flipped in deliver_packet, but this moves the ring
   3.164 + * descriptor across from the shadow ring and increments the pointers.
   3.165   */
   3.166  
   3.167  void update_shared_ring(void)
   3.168 @@ -990,32 +990,37 @@ void update_shared_ring(void)
   3.169      unsigned int nvif;
   3.170      
   3.171      clear_bit(_HYP_EVENT_NET_RX, &current->hyp_events);
   3.172 -    for (nvif = 0; nvif < current->num_net_vifs; nvif++)
   3.173 +
   3.174 +    for ( nvif = 0; nvif < current->num_net_vifs; nvif++ )
   3.175      {
   3.176          net_ring = current->net_vif_list[nvif]->net_ring;
   3.177          shadow_ring = current->net_vif_list[nvif]->shadow_ring;
   3.178 -        while ((shadow_ring->rx_idx != shadow_ring->rx_cons) 
   3.179 -                && (net_ring->rx_cons != net_ring->rx_prod))
   3.180 +        
   3.181 +        if ( shadow_ring->rx_idx != net_ring->rx_cons )
   3.182          {
   3.183 -            rx = shadow_ring->rx_ring+shadow_ring->rx_idx;
   3.184 -            copy_to_user(net_ring->rx_ring + net_ring->rx_cons, rx, sizeof(rx_entry_t));
   3.185 +            DPRINTK("Shadow and shared rings out of sync (%d/%d)\n",
   3.186 +                    shadow_ring->rx_idx, net_ring->rx_cons);
   3.187 +        }
   3.188 +
   3.189 +        while ( (shadow_ring->rx_idx != shadow_ring->rx_cons) &&
   3.190 +                (net_ring->rx_cons != net_ring->rx_prod) )
   3.191 +        {
   3.192 +            rx = shadow_ring->rx_ring + shadow_ring->rx_idx;
   3.193 +            copy_to_user(net_ring->rx_ring + net_ring->rx_cons, rx, 
   3.194 +                         sizeof(rx_entry_t));
   3.195  
   3.196              shadow_ring->rx_idx = RX_RING_INC(shadow_ring->rx_idx);
   3.197              net_ring->rx_cons   = RX_RING_INC(net_ring->rx_cons);
   3.198              
   3.199 -            if (rx->flush_count == tlb_flush_count[smp_processor_id()])
   3.200 +            if ( rx->flush_count == tlb_flush_count[smp_processor_id()] )
   3.201                  __flush_tlb();
   3.202  
   3.203              if ( net_ring->rx_cons == net_ring->rx_event )
   3.204                  set_bit(_EVENT_NET_RX, &s->events);
   3.205 -            
   3.206          }
   3.207      }
   3.208  }
   3.209 -            
   3.210 -/*
   3.211 - *	Map an interface index to its name (SIOCGIFNAME)
   3.212 - */
   3.213 +
   3.214  
   3.215  /*
   3.216   *	We need this ioctl for efficient implementation of the
   3.217 @@ -2024,7 +2029,9 @@ void tx_skb_release(struct sk_buff *skb)
   3.218   * Called from guest OS to notify updates to its transmit and/or receive
   3.219   * descriptor rings.
   3.220   */
   3.221 -#define PKT_PROT_LEN (ETH_HLEN + 8)
   3.222 +
   3.223 +/* Ethernet + IP headers */
   3.224 +#define PKT_PROT_LEN (ETH_HLEN + 20)
   3.225  
   3.226  long do_net_update(void)
   3.227  {
   3.228 @@ -2049,35 +2056,49 @@ long do_net_update(void)
   3.229  
   3.230          current_vif = current->net_vif_list[j];
   3.231          net_ring = current_vif->net_ring;
   3.232 -
   3.233 -        /* First, we send out pending TX descriptors if they exist on this ring.
   3.234 +        
   3.235 +        /*
   3.236 +         * PHASE 1 -- TRANSMIT RING
   3.237           */
   3.238 -        
   3.239 -        for ( i = net_ring->tx_cons; i != net_ring->tx_prod; i = TX_RING_INC(i) )
   3.240 +
   3.241 +        for ( i = net_ring->tx_cons; 
   3.242 +              i != net_ring->tx_prod; 
   3.243 +              i = TX_RING_INC(i) )
   3.244          {
   3.245              if ( copy_from_user(&tx, net_ring->tx_ring+i, sizeof(tx)) )
   3.246 +            {
   3.247 +                DPRINTK("Bad copy_from_user for tx net descriptor\n");
   3.248                  continue;
   3.249 +            }
   3.250  
   3.251 -            if ( tx.size < PKT_PROT_LEN ) continue; 
   3.252 -            
   3.253 +            if ( tx.size < PKT_PROT_LEN )
   3.254 +            {
   3.255 +                DPRINTK("Runt packet %ld\n", tx.size);
   3.256 +                continue; 
   3.257 +            }
   3.258 +
   3.259              if ( ((tx.addr & ~PAGE_MASK) + tx.size) >= PAGE_SIZE ) 
   3.260              {
   3.261 -                DPRINTK("tx.addr: %lx, size: %lu, end: %lu\n", tx.addr, tx.size,
   3.262 -                    (tx.addr &~PAGE_MASK) + tx.size);
   3.263 +                DPRINTK("tx.addr: %lx, size: %lu, end: %lu\n", 
   3.264 +                        tx.addr, tx.size, (tx.addr &~PAGE_MASK) + tx.size);
   3.265                  continue;
   3.266              }
   3.267              
   3.268              if ( TX_RING_INC(i) == net_ring->tx_event )
   3.269 +            {
   3.270                  set_bit(_EVENT_NET_TX, &shared->events);
   3.271 +            }
   3.272  
   3.273 -            /* Map the skb in from the guest, and get it's delivery target.
   3.274 +            /* 
   3.275 +             * Map the skb in from the guest, and get it's delivery target.
   3.276               * We need this to know whether the packet is to be sent locally
   3.277               * or remotely.
   3.278               */
   3.279              
   3.280              g_data = map_domain_mem(tx.addr);
   3.281  
   3.282 -            protocol = __constant_htons(init_tx_header(g_data, tx.size, the_dev));
   3.283 +            protocol = __constant_htons(
   3.284 +                init_tx_header(g_data, tx.size, the_dev));
   3.285              if ( protocol == 0 )
   3.286              {
   3.287                  unmap_domain_mem(g_data);
   3.288 @@ -2088,9 +2109,7 @@ long do_net_update(void)
   3.289  
   3.290              if (target > VIF_PHYSICAL_INTERFACE )
   3.291              {
   3.292 -                // Local delivery: Allocate an skb off the domain free list
   3.293 -                // fil it, and pass it to netif_rx as if it came off the NIC.
   3.294 -
   3.295 +                /* Local delivery */
   3.296                  skb = dev_alloc_skb(tx.size);
   3.297  
   3.298                  if (skb == NULL) 
   3.299 @@ -2103,26 +2122,25 @@ long do_net_update(void)
   3.300                  skb->dst_vif = target;
   3.301                  skb->protocol = protocol;
   3.302                  
   3.303 -                skb->head = (u8 *)map_domain_mem(((skb->pf - frame_table) << PAGE_SHIFT));
   3.304 +                skb->head = (u8 *)map_domain_mem(
   3.305 +                    ((skb->pf - frame_table) << PAGE_SHIFT));
   3.306                  skb->data = skb->head + 16;
   3.307                  skb_reserve(skb,2);
   3.308                  memcpy(skb->data, g_data, tx.size);
   3.309                  skb->len = tx.size;
   3.310                  unmap_domain_mem(skb->head);
   3.311 -                skb->data += ETH_HLEN; // so the assertion in netif_RX doesn't freak out.
   3.312 -                
   3.313 +                skb->data += ETH_HLEN;
   3.314                  (void)netif_rx(skb);
   3.315 -
   3.316                  unmap_domain_mem(g_data);
   3.317              }
   3.318              else if ( target == VIF_PHYSICAL_INTERFACE )
   3.319              {
   3.320 -                // External delivery: Allocate a small skb to hold protected header info
   3.321 -                // and copy the eth header and IP address fields into that.
   3.322 -                // Set a frag link to the remaining data, and we will scatter-gather
   3.323 -                // in the device driver to send the two bits later.
   3.324 -                
   3.325 -                skb = alloc_skb(PKT_PROT_LEN, GFP_KERNEL); // Eth header + two IP addrs.
   3.326 +                /*
   3.327 +                 * External delivery: create a fragmented SKB, consisting of a
   3.328 +                 * small copied section for the header, then a reference to the
   3.329 +                 * in-place payload.
   3.330 +                 */                
   3.331 +                skb = alloc_skb(PKT_PROT_LEN, GFP_KERNEL);
   3.332                  if (skb == NULL) 
   3.333                      continue;
   3.334              
   3.335 @@ -2136,15 +2154,13 @@ long do_net_update(void)
   3.336                  skb->protocol = protocol; 
   3.337                  skb->mac.raw=skb->data; 
   3.338  
   3.339 -                // set tot_count++ in the guest data pfn.
   3.340 +                /* One more reference to guest page for duration of transfer */
   3.341                  page = (tx.addr >> PAGE_SHIFT) + frame_table;
   3.342                  page->tot_count++;
   3.343                  
   3.344 -                // assign a destructor to the skb that will unlink and dec the tot_count
   3.345 +                /* We have special destructor to deal with guest frag. */
   3.346                  skb->destructor = &tx_skb_release;
   3.347  
   3.348 -                // place the remainder of the packet (which is in guest memory) into an
   3.349 -                // skb frag.
   3.350                  skb_shinfo(skb)->frags[0].page = page;
   3.351                  skb_shinfo(skb)->frags[0].size = tx.size - PKT_PROT_LEN;
   3.352                  skb_shinfo(skb)->frags[0].page_offset 
   3.353 @@ -2162,60 +2178,67 @@ long do_net_update(void)
   3.354          }
   3.355          net_ring->tx_cons = i;
   3.356  
   3.357 -        /* Next, pull any new RX descriptors across to the shadow ring.
   3.358 +        /*
   3.359 +         * PHASE 2 -- RECEIVE RING
   3.360           */
   3.361 -    
   3.362 +
   3.363          shadow_ring = current_vif->shadow_ring;
   3.364  
   3.365 -        for (i = shadow_ring->rx_prod; i != net_ring->rx_prod; i = RX_RING_INC(i))
   3.366 +        for ( i = shadow_ring->rx_prod; 
   3.367 +              i != net_ring->rx_prod; 
   3.368 +              i = RX_RING_INC(i) )
   3.369          {
   3.370 -            /* This copy assumes that rx_shadow_entry_t is an extension of 
   3.371 +            /* 
   3.372 +             * This copy assumes that rx_shadow_entry_t is an extension of 
   3.373               * rx_net_entry_t extra fields must be tacked on to the end.
   3.374               */
   3.375              if ( copy_from_user( shadow_ring->rx_ring+i, net_ring->rx_ring+i, 
   3.376                                   sizeof (rx_entry_t) ) )
   3.377              {
   3.378 +                DPRINTK("Bad copy_from_user for rx ring\n");
   3.379                  shadow_ring->rx_ring[i].status = RING_STATUS_ERR_CFU;
   3.380                  continue;
   3.381 -            } else {
   3.382 -                    
   3.383 -                rx = shadow_ring->rx_ring + i;
   3.384 -                pfn = rx->addr >> PAGE_SHIFT;
   3.385 -                page = frame_table + pfn;
   3.386 -                
   3.387 -                shadow_ring->rx_ring[i].status = RING_STATUS_BAD_PAGE;
   3.388 -
   3.389 -                if  ( page->flags != (PGT_l1_page_table | current->domain) ) 
   3.390 -                {
   3.391 -                       continue;
   3.392 -                }
   3.393 -
   3.394 -
   3.395 -                g_pte = map_domain_mem(rx->addr);
   3.396 +            } 
   3.397  
   3.398 -                if (!(*g_pte & _PAGE_PRESENT))
   3.399 -                {
   3.400 -                        unmap_domain_mem(g_pte);
   3.401 -                        continue;
   3.402 -                }
   3.403 -                
   3.404 -                page = (*g_pte >> PAGE_SHIFT) + frame_table;
   3.405 -                
   3.406 -                if (page->tot_count != 1) 
   3.407 -                {
   3.408 -                        unmap_domain_mem(g_pte);
   3.409 -                        continue;
   3.410 -                }
   3.411 -                
   3.412 -                // The pte they passed was good, so we take it away from them.
   3.413 -                shadow_ring->rx_ring[i].status = RING_STATUS_OK;
   3.414 -                *g_pte &= ~_PAGE_PRESENT;
   3.415 -                page->flags = (page->flags & ~PG_type_mask) | PGT_net_rx_buf;
   3.416 -                rx->flush_count = tlb_flush_count[smp_processor_id()];
   3.417 -
   3.418 +            rx = shadow_ring->rx_ring + i;
   3.419 +            pfn = rx->addr >> PAGE_SHIFT;
   3.420 +            page = frame_table + pfn;
   3.421 +            
   3.422 +            shadow_ring->rx_ring[i].status = RING_STATUS_BAD_PAGE;
   3.423 +            
   3.424 +            if  ( page->flags != (PGT_l1_page_table | current->domain) ) 
   3.425 +            {
   3.426 +                DPRINTK("Bad page flags\n");
   3.427 +                continue;
   3.428 +            }
   3.429 +            
   3.430 +            g_pte = map_domain_mem(rx->addr);
   3.431 +            
   3.432 +            if (!(*g_pte & _PAGE_PRESENT))
   3.433 +            {
   3.434 +                DPRINTK("Inavlid PTE passed down (not present)\n");
   3.435                  unmap_domain_mem(g_pte);
   3.436 +                continue;
   3.437              }
   3.438 +            
   3.439 +            page = (*g_pte >> PAGE_SHIFT) + frame_table;
   3.440 +            
   3.441 +            if (page->tot_count != 1) 
   3.442 +            {
   3.443 +                DPRINTK("An rx page must be mapped exactly once\n");
   3.444 +                unmap_domain_mem(g_pte);
   3.445 +                continue;
   3.446 +            }
   3.447 +            
   3.448 +            /* The pte they passed was good, so take it away from them. */
   3.449 +            shadow_ring->rx_ring[i].status = RING_STATUS_OK;
   3.450 +            *g_pte &= ~_PAGE_PRESENT;
   3.451 +            page->flags = (page->flags & ~PG_type_mask) | PGT_net_rx_buf;
   3.452 +            rx->flush_count = tlb_flush_count[smp_processor_id()];
   3.453 +            
   3.454 +            unmap_domain_mem(g_pte);
   3.455          }
   3.456 +        smp_wmb(); /* Let other CPUs see new descriptors first. */
   3.457          shadow_ring->rx_prod = net_ring->rx_prod;
   3.458      }
   3.459      return 0;
     4.1 --- a/xenolinux-2.4.16-sparse/arch/xeno/drivers/network/network.c	Sat Feb 15 10:53:19 2003 +0000
     4.2 +++ b/xenolinux-2.4.16-sparse/arch/xeno/drivers/network/network.c	Sat Feb 15 14:40:07 2003 +0000
     4.3 @@ -46,8 +46,6 @@ static void cleanup_module(void);
     4.4  
     4.5  static struct list_head dev_list;
     4.6  
     4.7 -static unsigned int net_countx;
     4.8 -
     4.9  /*
    4.10   * RX RING:   RX_IDX <= rx_cons <= rx_prod
    4.11   * TX RING:   TX_IDX <= tx_cons <= tx_prod
    4.12 @@ -171,15 +169,14 @@ static void network_tx_buf_gc(struct net
    4.13  
    4.14  inline unsigned long get_ppte(unsigned long addr)
    4.15  {
    4.16 -    unsigned long ppte = 0xdeadbeef;
    4.17 +    unsigned long ppte;
    4.18      pgd_t *pgd; pmd_t *pmd; pte_t *ptep;
    4.19      pgd = pgd_offset_k(addr);
    4.20  
    4.21 -    if (pgd_none(*pgd) || pgd_bad(*pgd)) BUG();
    4.22 +    if ( pgd_none(*pgd) || pgd_bad(*pgd) ) BUG();
    4.23          
    4.24      pmd = pmd_offset(pgd, addr);
    4.25 -    if (pmd_none(*pmd)) BUG(); 
    4.26 -    if (pmd_bad(*pmd)) BUG();
    4.27 +    if ( pmd_none(*pmd) || pmd_bad(*pmd) ) BUG(); 
    4.28          
    4.29      ptep = pte_offset(pmd, addr);
    4.30      ppte = (unsigned long)phys_to_machine(virt_to_phys(ptep));
    4.31 @@ -202,7 +199,7 @@ static void network_alloc_rx_buffers(str
    4.32          skb->dev = dev;
    4.33          skb_reserve(skb, 2); /* word align the IP header */
    4.34          np->rx_skb_ring[i] = skb;
    4.35 -        np->net_ring->rx_ring[i].addr = get_ppte(skb->head); 
    4.36 +        np->net_ring->rx_ring[i].addr = get_ppte((unsigned long)skb->head); 
    4.37          np->net_ring->rx_ring[i].size = RX_BUF_SIZE - 16; /* arbitrary */
    4.38      }
    4.39  
    4.40 @@ -310,11 +307,10 @@ static void network_rx_int(int irq, void
    4.41          skb->protocol = eth_type_trans(skb, dev);
    4.42  
    4.43          /*
    4.44 -         * Set up shinfo -- from alloc_skb This was particularily nasty:  the 
    4.45 -         * shared info is hidden at the back of the data area (presumably so 
    4.46 -         * it can be shared), but on page flip it gets very spunked.
    4.47 +         * Set up shinfo -- from alloc_skb This was particularily nasty:  the
    4.48 +         * shared info is hidden at the back of the data area (presumably so it
    4.49 +         * can be shared), but on page flip it gets very spunked.
    4.50           */
    4.51 -
    4.52          atomic_set(&(skb_shinfo(skb)->dataref), 1);
    4.53          skb_shinfo(skb)->nr_frags = 0;
    4.54          skb_shinfo(skb)->frag_list = NULL;