mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
bitkeeper revision 1.22.1.10 (3e48f4c9XYI43AfrJ_7BMyjM2NofzA)
Changes to support zero-copy tx... incremental updates to synch with main repository.
This commit is contained in:
1 parent
cb4878ee12
commit
0c9fe16459
5 files changed
+263
-124
No files matched your search
+31
-24
@@ -14,6 +14,7 @@
|
||||
#include <xeno/dom0_ops.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <asm/domain_page.h>
|
||||
|
||||
/* VGA text definitions. */
|
||||
#define COLUMNS 80
|
||||
@@ -297,11 +298,11 @@ void panic(const char *fmt, ...)
|
||||
char buf[1024], *p;
|
||||
unsigned long flags;
|
||||
extern void machine_restart(char *);
|
||||
|
||||
|
||||
va_start(args, fmt);
|
||||
(void)vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
|
||||
/* Spit out multiline message in one go. */
|
||||
spin_lock_irqsave(&console_lock, flags);
|
||||
__putstr("\n****************************************\n");
|
||||
@@ -353,6 +354,7 @@ unsigned short compute_cksum(unsigned short *buf, int count)
|
||||
/* XXX SMH: below is rather vile; pulled in to allow network console */
|
||||
|
||||
extern int netif_rx(struct sk_buff *);
|
||||
extern struct net_device *the_dev;
|
||||
|
||||
typedef struct my_udphdr {
|
||||
__u16 source;
|
||||
@@ -403,17 +405,24 @@ int console_export(char *str, int len)
|
||||
struct my_udphdr *udph = NULL;
|
||||
struct my_ethhdr *ethh = NULL;
|
||||
int hdr_size = sizeof(struct my_iphdr) + sizeof(struct my_udphdr);
|
||||
|
||||
// Prepare console packet
|
||||
console_packet = alloc_skb(sizeof(struct my_ethhdr) + hdr_size + len,
|
||||
GFP_KERNEL);
|
||||
u8 *skb_data;
|
||||
|
||||
// Prepare console packet - the grim + 20 in the alloc is for headroom.
|
||||
console_packet = dev_alloc_skb(sizeof(struct my_ethhdr) + hdr_size + len + 20);
|
||||
if (!console_packet) return 0;
|
||||
//console_packet->security = 9; // hack to trace these packets.
|
||||
console_packet->dev = the_dev;
|
||||
skb_data = map_domain_mem((unsigned long)console_packet->head);
|
||||
skb_reserve(console_packet, 2); // ip header alignment.
|
||||
//printk("Eth is: %d\n", console_packet->data - console_packet->head);
|
||||
ethh = (struct my_ethhdr *) skb_data + (console_packet->data - console_packet->head);
|
||||
skb_reserve(console_packet, sizeof(struct my_ethhdr));
|
||||
ethh = (struct my_ethhdr *)console_packet->head;
|
||||
|
||||
skb_put(console_packet, hdr_size + len);
|
||||
iph = (struct my_iphdr *)console_packet->data;
|
||||
udph = (struct my_udphdr *)(iph + 1);
|
||||
memcpy((char *)(udph + 1), str, len);
|
||||
//printk("IP is: %d\n", console_packet->data - console_packet->head);
|
||||
iph = (struct my_iphdr *)skb_data + (console_packet->data - console_packet->head);
|
||||
udph = (struct my_udphdr *)(iph + 1);
|
||||
memcpy((char *)(udph + 1), str, len);
|
||||
|
||||
// Build IP header
|
||||
iph->version = 4;
|
||||
@@ -442,6 +451,13 @@ int console_export(char *str, int len)
|
||||
memcpy(ethh->h_dest, "000000", 6);
|
||||
ethh->h_proto = htons(ETH_P_IP);
|
||||
console_packet->mac.ethernet= (struct ethhdr *)ethh;
|
||||
|
||||
// Make the packet appear to come off the external NIC so that the
|
||||
// tables code doesn't get too confused.
|
||||
console_packet->src_vif = VIF_PHYSICAL_INTERFACE;
|
||||
console_packet->dst_vif = 0;
|
||||
|
||||
unmap_domain_mem(skb_data);
|
||||
|
||||
// Pass the packet to netif_rx
|
||||
(void)netif_rx(console_packet);
|
||||
@@ -477,23 +493,14 @@ long do_console_write(char *str, int count)
|
||||
|
||||
if ( !safe_str[i] ) break;
|
||||
putchar(prev = safe_str[i]);
|
||||
|
||||
if ( prev == '\n' )
|
||||
{
|
||||
exported_str[j]='\0';
|
||||
console_export(exported_str, j-1);
|
||||
j=0;
|
||||
}
|
||||
|
||||
}
|
||||
if ( prev != '\n' )
|
||||
{
|
||||
putchar('\n');
|
||||
exported_str[j]='\0';
|
||||
console_export(exported_str, j-1);
|
||||
}
|
||||
|
||||
if ( prev != '\n' ) putchar('\n');
|
||||
|
||||
spin_unlock_irqrestore(&console_lock, flags);
|
||||
|
||||
exported_str[j]='\0';
|
||||
console_export(exported_str, j-1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
+32
-23
@@ -343,47 +343,56 @@ int net_find_rule(u8 nproto, u8 tproto, u32 src_addr, u32 dst_addr, u16 src_port
|
||||
* list.
|
||||
*/
|
||||
|
||||
int net_get_target_vif(struct sk_buff *skb)
|
||||
#define net_get_target_vif(skb) __net_get_target_vif(skb->data, skb->len, skb->src_vif)
|
||||
|
||||
int __net_get_target_vif(u8 *data, unsigned int len, int src_vif)
|
||||
{
|
||||
int target = VIF_DROP;
|
||||
skb->h.raw = skb->nh.raw = skb->data;
|
||||
if ( skb->len < 2 ) goto drop;
|
||||
switch ( ntohs(skb->mac.ethernet->h_proto) )
|
||||
u8 *h_raw, *nh_raw;
|
||||
|
||||
if ( len < 2 ) goto drop;
|
||||
|
||||
nh_raw = data + ETH_HLEN;
|
||||
switch ( ntohs(*(unsigned short *)(data + 12)) )
|
||||
{
|
||||
case ETH_P_ARP:
|
||||
if ( skb->len < 28 ) goto drop;
|
||||
target = net_find_rule((u8)ETH_P_ARP, 0, ntohl(*(u32 *)(skb->nh.raw + 14)),
|
||||
ntohl(*(u32 *)(skb->nh.raw + 24)), 0, 0,
|
||||
skb->src_vif);
|
||||
//printk("ARP!\n");
|
||||
if ( len < 28 ) goto drop;
|
||||
target = net_find_rule((u8)ETH_P_ARP, 0, ntohl(*(u32 *)(nh_raw + 14)),
|
||||
ntohl(*(u32 *)(nh_raw + 24)), 0, 0,
|
||||
src_vif);
|
||||
break;
|
||||
case ETH_P_IP:
|
||||
if ( skb->len < 20 ) goto drop;
|
||||
skb->h.raw += ((*(unsigned char *)(skb->nh.raw)) & 0x0f) * 4;
|
||||
switch ( *(unsigned char *)(skb->nh.raw + 9) )
|
||||
//printk("IP\n");
|
||||
if ( len < 20 ) goto drop;
|
||||
h_raw = data + ((*(unsigned char *)(nh_raw)) & 0x0f) * 4;
|
||||
switch ( *(unsigned char *)(nh_raw + 9) )
|
||||
{
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
target = net_find_rule((u8)ETH_P_IP, *(u8 *)(skb->nh.raw + 9),
|
||||
ntohl(*(u32 *)(skb->nh.raw + 12)),
|
||||
ntohl(*(u32 *)(skb->nh.raw + 16)),
|
||||
ntohs(*(u16 *)(skb->h.raw)),
|
||||
ntohs(*(u16 *)(skb->h.raw + 2)),
|
||||
skb->src_vif);
|
||||
//printk("UDP!\n");
|
||||
case IPPROTO_TCP:
|
||||
target = net_find_rule((u8)ETH_P_IP, *(u8 *)(nh_raw + 9),
|
||||
ntohl(*(u32 *)(nh_raw + 12)),
|
||||
ntohl(*(u32 *)(nh_raw + 16)),
|
||||
ntohs(*(u16 *)(h_raw)),
|
||||
ntohs(*(u16 *)(h_raw + 2)),
|
||||
src_vif);
|
||||
break;
|
||||
default: // ip-based protocol where we don't have ports.
|
||||
target = net_find_rule((u8)ETH_P_IP, *(u8 *)(skb->nh.raw + 9),
|
||||
ntohl(*(u32 *)(skb->nh.raw + 12)),
|
||||
ntohl(*(u32 *)(skb->nh.raw + 16)),
|
||||
//printk("Other IP!\n");
|
||||
target = net_find_rule((u8)ETH_P_IP, *(u8 *)(data + 9),
|
||||
ntohl(*(u32 *)(nh_raw + 12)),
|
||||
ntohl(*(u32 *)(nh_raw + 16)),
|
||||
0,
|
||||
0,
|
||||
skb->src_vif);
|
||||
src_vif);
|
||||
}
|
||||
break;
|
||||
}
|
||||
skb->dst_vif=target;
|
||||
return target;
|
||||
|
||||
drop:
|
||||
//printk("Drop case!\n");
|
||||
return VIF_DROP;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,9 +66,10 @@ extern net_vif_t *sys_vif_list[];
|
||||
net_vif_t *create_net_vif(int domain);
|
||||
void destroy_net_vif(struct task_struct *p);
|
||||
void add_default_net_rule(int vif_id, u32 ipaddr);
|
||||
int net_get_target_vif(struct sk_buff *skb);
|
||||
int __net_get_target_vif(u8 *data, unsigned int len, int src_vif);
|
||||
void add_default_net_rule(int vif_id, u32 ipaddr);
|
||||
|
||||
#define net_get_target_vif(skb) __net_get_target_vif(skb->data, skb->len, skb->src_vif)
|
||||
/* status fields per-descriptor:
|
||||
*/
|
||||
|
||||
|
||||
+184
-73
@@ -501,7 +501,7 @@ int dev_queue_xmit(struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev = skb->dev;
|
||||
struct Qdisc *q;
|
||||
|
||||
if (!(dev->features&NETIF_F_SG)) printk("NIC doesn't do SG!!!\n");
|
||||
if (skb_shinfo(skb)->frag_list &&
|
||||
!(dev->features&NETIF_F_FRAGLIST) &&
|
||||
skb_linearize(skb, GFP_ATOMIC) != 0) {
|
||||
@@ -673,12 +673,11 @@ void deliver_packet(struct sk_buff *skb, net_vif_t *vif)
|
||||
{
|
||||
net_shadow_ring_t *shadow_ring;
|
||||
rx_shadow_entry_t *rx;
|
||||
unsigned long *g_pte, tmp;
|
||||
unsigned long *g_pte; //tmp
|
||||
struct pfn_info *g_pfn, *h_pfn;
|
||||
unsigned int i; //, nvif;
|
||||
|
||||
if (skb->skb_type != SKB_ZERO_COPY)
|
||||
return;
|
||||
|
||||
|
||||
/*
|
||||
* Write the virtual MAC address into the destination field
|
||||
@@ -724,10 +723,11 @@ void deliver_packet(struct sk_buff *skb, net_vif_t *vif)
|
||||
//flip and/or set relevant pf_info fields.
|
||||
//tmp = g_pfn->next; g_pfn->next = h_pfn->next; h_pfn->next = tmp;
|
||||
//tmp = g_pfn->prev; g_pfn->prev = h_pfn->prev; h_pfn->prev = tmp;
|
||||
tmp = g_pfn->flags; g_pfn->flags = h_pfn->flags; h_pfn->flags = tmp;
|
||||
//tmp = g_pfn->flags; g_pfn->flags = h_pfn->flags; h_pfn->flags = tmp;
|
||||
h_pfn->tot_count = h_pfn->type_count = 1;
|
||||
g_pfn->tot_count = g_pfn->type_count = 0;
|
||||
h_pfn->flags = g_pfn->flags & ~ PG_type_mask;
|
||||
h_pfn->flags = g_pfn->flags & (~PG_type_mask);
|
||||
//if (h_pfn->flags & PG_domain_mask) printk("deliver packet to dom %lu\n", (h_pfn->flags & PG_domain_mask));
|
||||
if (*g_pte & _PAGE_RW) h_pfn->flags |= PGT_writeable_page;
|
||||
g_pfn->flags = 0;
|
||||
//point guest pte at the new page:
|
||||
@@ -783,25 +783,28 @@ int netif_rx(struct sk_buff *skb)
|
||||
net_vif_t *vif;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
if (skb->stamp.tv_sec == 0)
|
||||
get_fast_time(&skb->stamp);
|
||||
|
||||
/* Attempt to handle zero-copy packets here: */
|
||||
if (skb->skb_type == SKB_ZERO_COPY)
|
||||
{
|
||||
skb->head = (u8 *)map_domain_mem(((skb->pf - frame_table) << PAGE_SHIFT));
|
||||
|
||||
/* remapping this address really screws up all the skb pointers. We need
|
||||
* to map them all here sufficiently to get the packet demultiplexed.
|
||||
*/
|
||||
if (skb->skb_type != SKB_ZERO_COPY)
|
||||
BUG();
|
||||
|
||||
skb->data = skb->head;
|
||||
skb_reserve(skb,16); // need to ensure that all the drivers and not just tulip do this.
|
||||
skb->mac.raw = skb->data;
|
||||
skb->data += ETH_HLEN;
|
||||
skb->nh.raw = skb->data;
|
||||
}
|
||||
if (skb->stamp.tv_sec == 0)
|
||||
get_fast_time(&skb->stamp);
|
||||
|
||||
if ( (skb->data - skb->head) != (18 + ETH_HLEN) )
|
||||
BUG();
|
||||
|
||||
skb->head = (u8 *)map_domain_mem(((skb->pf - frame_table) << PAGE_SHIFT));
|
||||
|
||||
/* remapping this address really screws up all the skb pointers. We need
|
||||
* to map them all here sufficiently to get the packet demultiplexed.
|
||||
*/
|
||||
|
||||
skb->data = skb->head;
|
||||
skb_reserve(skb,18); // 18 is the 16 from dev_alloc_skb plus 2 for #
|
||||
// IP header alignment.
|
||||
skb->mac.raw = skb->data;
|
||||
skb->data += ETH_HLEN;
|
||||
skb->nh.raw = skb->data;
|
||||
|
||||
/* The code is rearranged so that the path is the most
|
||||
short when CPU is congested, but is still operating.
|
||||
@@ -812,9 +815,11 @@ int netif_rx(struct sk_buff *skb)
|
||||
|
||||
if ( skb->src_vif == VIF_UNKNOWN_INTERFACE )
|
||||
skb->src_vif = VIF_PHYSICAL_INTERFACE;
|
||||
|
||||
|
||||
if ( skb->dst_vif == VIF_UNKNOWN_INTERFACE )
|
||||
net_get_target_vif(skb);
|
||||
skb->dst_vif = __net_get_target_vif(skb->mac.raw, skb->len, skb->src_vif);
|
||||
if (skb->dst_vif == VIF_DROP)
|
||||
printk("netif_rx target: %d (sec: %u)\n", skb->dst_vif, skb->security);
|
||||
|
||||
if ( (vif = sys_vif_list[skb->dst_vif]) == NULL )
|
||||
{
|
||||
@@ -851,17 +856,14 @@ int netif_rx(struct sk_buff *skb)
|
||||
|
||||
drop:
|
||||
netdev_rx_stat[this_cpu].dropped++;
|
||||
if (skb->skb_type == SKB_ZERO_COPY)
|
||||
unmap_domain_mem(skb->head);
|
||||
unmap_domain_mem(skb->head);
|
||||
kfree_skb(skb);
|
||||
local_irq_restore(flags);
|
||||
return NET_RX_DROP;
|
||||
|
||||
found:
|
||||
if (skb->skb_type == SKB_ZERO_COPY) {
|
||||
unmap_domain_mem(skb->head);
|
||||
skb->head = skb->data = skb->tail = (void *)0xdeadbeef;
|
||||
}
|
||||
unmap_domain_mem(skb->head);
|
||||
skb->head = skb->data = skb->tail = (void *)0xdeadbeef;
|
||||
kfree_skb(skb);
|
||||
hyp_event_notify(cpu_mask);
|
||||
local_irq_restore(flags);
|
||||
@@ -990,7 +992,7 @@ void update_shared_ring(void)
|
||||
net_ring_t *net_ring;
|
||||
net_shadow_ring_t *shadow_ring;
|
||||
unsigned int nvif;
|
||||
|
||||
|
||||
clear_bit(_HYP_EVENT_NET_RX, ¤t->hyp_events);
|
||||
for (nvif = 0; nvif < current->num_net_vifs; nvif++)
|
||||
{
|
||||
@@ -1004,7 +1006,7 @@ void update_shared_ring(void)
|
||||
|
||||
shadow_ring->rx_idx = RX_RING_INC(shadow_ring->rx_idx);
|
||||
net_ring->rx_cons = RX_RING_INC(net_ring->rx_cons);
|
||||
|
||||
|
||||
if (rx->flush_count == tlb_flush_count[smp_processor_id()])
|
||||
__flush_tlb();
|
||||
|
||||
@@ -2134,13 +2136,59 @@ int __init net_dev_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline int init_tx_header(u8 *data, unsigned int len, struct net_device *dev)
|
||||
{
|
||||
memcpy(data + ETH_ALEN, dev->dev_addr, ETH_ALEN);
|
||||
|
||||
switch ( ntohs(*(unsigned short *)(data + 12)) )
|
||||
{
|
||||
case ETH_P_ARP:
|
||||
if ( len < 42 ) break;
|
||||
memcpy(data + 22, dev->dev_addr, 6);
|
||||
return ETH_P_ARP;
|
||||
case ETH_P_IP:
|
||||
return ETH_P_IP;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* tx_skb_release
|
||||
*
|
||||
* skb destructor function that is attached to zero-copy tx skbs before
|
||||
* they are passed to the device driver for transmission. The destructor
|
||||
* is responsible for unlinking the fragment pointer to the skb data that
|
||||
* is in guest memory, and decrementing the tot_count on the packet pages
|
||||
* pfn_info.
|
||||
*/
|
||||
|
||||
void tx_skb_release(struct sk_buff *skb)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i= 0; i < skb_shinfo(skb)->nr_frags; i++)
|
||||
skb_shinfo(skb)->frags[i].page->tot_count--;
|
||||
|
||||
skb_shinfo(skb)->nr_frags = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* do_net_update:
|
||||
*
|
||||
* Called from guest OS to notify updates to its transmit and/or receive
|
||||
* descriptor rings.
|
||||
*/
|
||||
#define PKT_PROT_LEN (ETH_HLEN + 8)
|
||||
|
||||
void print_range2(u8 *start, unsigned int len)
|
||||
{
|
||||
int i=0;
|
||||
while (i++ < len)
|
||||
{
|
||||
printk("%x:",start[i]);
|
||||
}
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
long do_net_update(void)
|
||||
{
|
||||
@@ -2161,6 +2209,9 @@ long do_net_update(void)
|
||||
{
|
||||
current_vif = current->net_vif_list[j];
|
||||
net_ring = current_vif->net_ring;
|
||||
int target;
|
||||
u8 *g_data;
|
||||
unsigned short protocol;
|
||||
|
||||
/* First, we send out pending TX descriptors if they exist on this ring.
|
||||
*/
|
||||
@@ -2170,63 +2221,123 @@ long do_net_update(void)
|
||||
if ( copy_from_user(&tx, net_ring->tx_ring+i, sizeof(tx)) )
|
||||
continue;
|
||||
|
||||
if ( tx.size < PKT_PROT_LEN ) continue; // This should be reasonable.
|
||||
|
||||
// Packets must not cross page boundaries. For now, this is a
|
||||
// kernel panic, later it may become a continue -- silent fail.
|
||||
|
||||
if ( ((tx.addr & ~PAGE_MASK) + tx.size) >= PAGE_SIZE )
|
||||
{
|
||||
printk("tx.addr: %lx, size: %lu, end: %lu\n", tx.addr, tx.size,
|
||||
(tx.addr &~PAGE_MASK) + tx.size);
|
||||
continue;
|
||||
//BUG();
|
||||
}
|
||||
|
||||
if ( TX_RING_INC(i) == net_ring->tx_event )
|
||||
set_bit(_EVENT_NET_TX_FOR_VIF(j), &shared->events);
|
||||
|
||||
skb = alloc_skb(tx.size, GFP_KERNEL);
|
||||
if ( skb == NULL ) continue;
|
||||
skb_put(skb, tx.size);
|
||||
if ( copy_from_user(skb->data, (void *)tx.addr, tx.size) )
|
||||
{
|
||||
kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
skb->dev = the_dev;
|
||||
/* Map the skb in from the guest, and get it's delivery target.
|
||||
* We need this to know whether the packet is to be sent locally
|
||||
* or remotely.
|
||||
*/
|
||||
|
||||
g_data = map_domain_mem(tx.addr);
|
||||
|
||||
if ( skb->len < 16 )
|
||||
//print_range2(g_data, PKT_PROT_LEN);
|
||||
protocol = __constant_htons(init_tx_header(g_data, tx.size, the_dev));
|
||||
if ( protocol == 0 )
|
||||
{
|
||||
kfree_skb(skb);
|
||||
unmap_domain_mem(g_data);
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(skb->data + ETH_ALEN, skb->dev->dev_addr, ETH_ALEN);
|
||||
|
||||
switch ( ntohs(*(unsigned short *)(skb->data + 12)) )
|
||||
target = __net_get_target_vif(g_data, tx.size, current_vif->id);
|
||||
//printk("Send to target: %d\n", target);
|
||||
if (target > VIF_PHYSICAL_INTERFACE )
|
||||
{
|
||||
case ETH_P_ARP:
|
||||
skb->protocol = __constant_htons(ETH_P_ARP);
|
||||
if ( skb->len < 42 ) break;
|
||||
memcpy(skb->data + 22, skb->dev->dev_addr, 6);
|
||||
break;
|
||||
case ETH_P_IP:
|
||||
skb->protocol = __constant_htons(ETH_P_IP);
|
||||
break;
|
||||
default:
|
||||
kfree_skb(skb);
|
||||
skb = NULL;
|
||||
break;
|
||||
}
|
||||
// Local delivery: Allocate an skb off the domain free list
|
||||
// fil it, and pass it to netif_rx as if it came off the NIC.
|
||||
|
||||
if ( skb != NULL )
|
||||
{
|
||||
skb->protocol = eth_type_trans(skb, skb->dev);
|
||||
skb->src_vif = current_vif->id;
|
||||
net_get_target_vif(skb);
|
||||
if ( skb->dst_vif > VIF_PHYSICAL_INTERFACE )
|
||||
skb = dev_alloc_skb(tx.size);
|
||||
if (skb == NULL)
|
||||
{
|
||||
printk("LOCAL DELIVERY!\n");
|
||||
(void)netif_rx(skb);
|
||||
unmap_domain_mem(g_data);
|
||||
continue;
|
||||
}
|
||||
else if ( skb->dst_vif == VIF_PHYSICAL_INTERFACE )
|
||||
|
||||
skb->src_vif = current_vif->id;
|
||||
skb->dst_vif = target;
|
||||
skb->protocol = protocol;
|
||||
if (copy_to_user(skb->data, g_data, tx.size))
|
||||
{
|
||||
skb_push(skb, skb->dev->hard_header_len);
|
||||
dev_queue_xmit(skb);
|
||||
}
|
||||
else
|
||||
unmap_domain_mem(g_data);
|
||||
continue;
|
||||
}
|
||||
|
||||
(void)netif_rx(skb); // why is there a void here? It's from the old code.
|
||||
|
||||
unmap_domain_mem(g_data);
|
||||
}
|
||||
else if ( target == VIF_PHYSICAL_INTERFACE )
|
||||
{
|
||||
// External delivery: Allocate a small skb to hold protected header info
|
||||
// and copy the eth header and IP address fields into that.
|
||||
// Set a frag link to the remaining data, and we will scatter-gather
|
||||
// in the device driver to send the two bits later.
|
||||
|
||||
/*unmap_domain_mem(g_data);*/
|
||||
|
||||
skb = alloc_skb(PKT_PROT_LEN, GFP_KERNEL); // Eth header + two IP addrs.
|
||||
if (skb == NULL)
|
||||
{
|
||||
printk("Alloc skb failed!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
skb_put(skb, PKT_PROT_LEN);
|
||||
/*if ( copy_from_user(skb->data, (void *)tx.addr, PKT_PROT_LEN) )
|
||||
{
|
||||
printk("Copy from user failed!\n");
|
||||
kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
memcpy(skb->data, g_data, PKT_PROT_LEN);
|
||||
unmap_domain_mem(g_data);
|
||||
//print_range2(g_data, PKT_PROT_LEN);
|
||||
skb->dev = the_dev;
|
||||
skb->src_vif = current_vif->id;
|
||||
skb->dst_vif = target;
|
||||
skb->protocol = protocol; // These next two lines abbreviate the call
|
||||
// to eth_type_trans as we already have our
|
||||
// protocol.
|
||||
//skb_pull(skb, skb->dev->hard_header_len);
|
||||
skb->mac.raw=skb->data;
|
||||
|
||||
// set tot_count++ in the guest data pfn.
|
||||
page = (tx.addr >> PAGE_SHIFT) + frame_table;
|
||||
page->tot_count++;
|
||||
|
||||
// place the remainder of the packet (which is in guest memory) into an
|
||||
// skb frag.
|
||||
skb_shinfo(skb)->frags[0].page = page;
|
||||
skb_shinfo(skb)->frags[0].size = tx.size - PKT_PROT_LEN;
|
||||
skb_shinfo(skb)->frags[0].page_offset
|
||||
= (tx.addr & ~PAGE_MASK) + PKT_PROT_LEN;
|
||||
skb_shinfo(skb)->nr_frags = 1;
|
||||
skb->data_len = tx.size - skb->len;
|
||||
skb->len = tx.size;
|
||||
|
||||
// assign a destructor to the skb that will unlink and dec the tot_count
|
||||
skb->destructor = &tx_skb_release;
|
||||
//skb_push(skb, skb->dev->hard_header_len);
|
||||
//printk("calling dev_queue_xmit!\n");
|
||||
dev_queue_xmit(skb);
|
||||
}
|
||||
else
|
||||
{
|
||||
unmap_domain_mem(g_data);
|
||||
}
|
||||
}
|
||||
net_ring->tx_cons = i;
|
||||
|
||||
@@ -241,7 +241,7 @@ static void network_alloc_rx_buffers(struct net_device *dev)
|
||||
skb = dev_alloc_skb(RX_BUF_SIZE);
|
||||
if ( skb == NULL ) break;
|
||||
skb->dev = dev;
|
||||
//skb_reserve(skb, 2); /* word align the IP header */
|
||||
skb_reserve(skb, 2); /* word align the IP header */
|
||||
np->rx_skb_ring[i] = skb;
|
||||
np->net_ring->rx_ring[i].addr = get_ppte(skb->head);
|
||||
np->net_ring->rx_ring[i].size = RX_BUF_SIZE - 16; /* arbitrary */
|
||||
@@ -269,6 +269,14 @@ static void network_free_rx_buffers(struct net_device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
void print_range(u8 *start, unsigned int len)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (i++ < len)
|
||||
printk("%x:", start[i]);
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
@@ -281,10 +289,13 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
netif_stop_queue(dev);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
//print_range(skb->data, ETH_HLEN + 8);
|
||||
//print_range(skb->data + ETH_HLEN + 8, 20);
|
||||
//printk("skb->len is %u in guestOS (expected fraglen: %u).\n", skb->len, skb->len - (ETH_HLEN + 8));
|
||||
i = np->net_ring->tx_prod;
|
||||
np->tx_skb_ring[i] = skb;
|
||||
np->net_ring->tx_ring[i].addr = (unsigned long)skb->data;
|
||||
np->net_ring->tx_ring[i].addr
|
||||
= (unsigned long)phys_to_machine(virt_to_phys(skb->data));
|
||||
np->net_ring->tx_ring[i].size = skb->len;
|
||||
np->net_ring->tx_prod = TX_RING_INC(i);
|
||||
atomic_inc(&np->tx_entries);
|
||||
|
||||