diff options
-rw-r--r-- | .rootkeys | 1 | ||||
-rw-r--r-- | BitKeeper/etc/logging_ok | 1 | ||||
-rw-r--r-- | xen-2.4.16/Makefile | 1 | ||||
-rw-r--r-- | xen-2.4.16/common/domain.c | 5 | ||||
-rw-r--r-- | xen-2.4.16/common/kernel.c | 1 | ||||
-rw-r--r-- | xen-2.4.16/common/network.c | 268 | ||||
-rw-r--r-- | xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h | 46 | ||||
-rw-r--r-- | xen-2.4.16/include/hypervisor-ifs/network.h | 15 | ||||
-rw-r--r-- | xen-2.4.16/include/xeno/in.h | 190 | ||||
-rw-r--r-- | xen-2.4.16/include/xeno/skbuff.h | 12 | ||||
-rw-r--r-- | xen-2.4.16/include/xeno/vif.h | 13 | ||||
-rw-r--r-- | xen-2.4.16/net/dev.c | 128 | ||||
-rw-r--r-- | xen-2.4.16/net/skbuff.c | 2 | ||||
-rw-r--r-- | xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/vfr.c | 77 | ||||
-rw-r--r-- | xenolinux-2.4.16-sparse/arch/xeno/drivers/network/network.c | 42 | ||||
-rw-r--r-- | xenolinux-2.4.16-sparse/include/asm-xeno/irq.h | 2 |
16 files changed, 663 insertions, 141 deletions
@@ -196,6 +196,7 @@ 3ddb79c1yHLp08JhgPxIMcZ8DwN9hg xen-2.4.16/include/xeno/if.h 3ddb79c1RCWOkWPQRzbYVTX_e-E7CA xen-2.4.16/include/xeno/if_ether.h 3ddb79c2IYah7z7hkzPyOiG8szKkyw xen-2.4.16/include/xeno/if_packet.h +3df0af1c-QrOEqpPHq4uL3NZzCeJCg xen-2.4.16/include/xeno/in.h 3ddb79c0GurNF9tDWqQbAwJFH8ugfA xen-2.4.16/include/xeno/init.h 3ddb79c1Vi5VleJAOKHAlY0G2zAsgw xen-2.4.16/include/xeno/interrupt.h 3ddb79c2J6EnruiygRhBCgftzMzTeQ xen-2.4.16/include/xeno/ioctl.h diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index c3ebee9a35..bf45a4d7d0 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -1,4 +1,5 @@ akw27@boulderdash.cl.cam.ac.uk +akw27@labyrinth.cl.cam.ac.uk kaf24@labyrinth.cl.cam.ac.uk kaf24@plym.cl.cam.ac.uk kaf24@striker.cl.cam.ac.uk diff --git a/xen-2.4.16/Makefile b/xen-2.4.16/Makefile index 7ede454ee8..846c0e6f12 100644 --- a/xen-2.4.16/Makefile +++ b/xen-2.4.16/Makefile @@ -4,6 +4,7 @@ export BASEDIR := $(shell pwd) include Rules.mk default: $(TARGET) + gzip -f -9 < $(TARGET) > $(TARGET).gz install: $(TARGET) gzip -f -9 < $(TARGET) > $(TARGET).gz diff --git a/xen-2.4.16/common/domain.c b/xen-2.4.16/common/domain.c index 30b9209ccc..962ac5f38b 100644 --- a/xen-2.4.16/common/domain.c +++ b/xen-2.4.16/common/domain.c @@ -410,6 +410,8 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params) l1_pgentry_t *l1tab = NULL; struct pfn_info *page = NULL; net_ring_t *net_ring; + blk_ring_t *blk_ring; + net_vif_t *net_vif; if ( strncmp(__va(mod[0].mod_start), "XenoGues", 8) ) { @@ -574,7 +576,8 @@ int setup_guestos(struct task_struct *p, dom0_newdomain_t *params) /* Add virtual network interfaces and point to them in startinfo. */ while (params->num_vifs-- > 0) { - net_ring = create_net_vif(dom); + net_vif = create_net_vif(dom); + net_ring = net_vif->net_ring; if (!net_ring) panic("no network ring!\n"); } diff --git a/xen-2.4.16/common/kernel.c b/xen-2.4.16/common/kernel.c index fc49e8641d..4c4d354f47 100644 --- a/xen-2.4.16/common/kernel.c +++ b/xen-2.4.16/common/kernel.c @@ -176,6 +176,7 @@ void cmain (unsigned long magic, multiboot_info_t *mbi) /* Create initial domain 0. */ dom0_params.num_vifs = 1; dom0_params.memory_kb = opt_dom0_mem; + add_default_net_rule(0, opt_ipbase); // add vfr info for dom0 new_dom = do_newdomain(); if ( new_dom == NULL ) panic("Error creating domain 0\n"); diff --git a/xen-2.4.16/common/network.c b/xen-2.4.16/common/network.c index e64c740f45..64c32a704f 100644 --- a/xen-2.4.16/common/network.c +++ b/xen-2.4.16/common/network.c @@ -1,8 +1,11 @@ -/* net_ring.c +/* network.c * - * ring data structures for buffering messages between hypervisor and - * guestos's. As it stands this is only used for network buffer exchange. + * Network virtualization for Xen. Lower-level network interactions are in + * net/dev.c and in the drivers. This file contains routines to interact + * with the virtual interfaces (vifs) and the virtual firewall/router through + * the use of rules. * + * Copyright (c) 2002, A K Warfield and K A Fraser */ #include <hypervisor-ifs/network.h> @@ -11,20 +14,38 @@ #include <xeno/init.h> #include <xeno/slab.h> #include <xeno/spinlock.h> +#include <xeno/if_ether.h> +#include <linux/skbuff.h> +#include <xeno/netdevice.h> +#include <xeno/in.h> /* vif globals * sys_vif_list is a lookup table for vifs, used in packet forwarding. - * it should be replaced later by something a little more flexible. + * it will be replaced later by something a little more flexible. */ -int sys_vif_count; -net_vif_t *sys_vif_list[MAX_SYSTEM_VIFS]; -net_rule_ent_t *net_rule_list; -kmem_cache_t *net_vif_cache; +int sys_vif_count; /* global vif count */ +net_vif_t *sys_vif_list[MAX_SYSTEM_VIFS]; /* global vif array */ +net_rule_ent_t *net_rule_list; /* global list of rules */ +kmem_cache_t *net_vif_cache; kmem_cache_t *net_rule_cache; -static rwlock_t net_rule_lock = RW_LOCK_UNLOCKED; +static rwlock_t net_rule_lock = RW_LOCK_UNLOCKED; /* rule mutex */ +static rwlock_t sys_vif_lock = RW_LOCK_UNLOCKED; /* vif mutex */ -net_ring_t *create_net_vif(int domain) +void print_net_rule_list(); + + +/* ----[ VIF Functions ]----------------------------------------------------*/ + +/* create_net_vif - Create a new vif and append it to the specified domain. + * + * the domain is examined to determine how many vifs currently are allocated + * and the newly allocated vif is appended. The vif is also added to the + * global list. + * + */ + +net_vif_t *create_net_vif(int domain) { net_vif_t *new_vif; net_ring_t *new_ring; @@ -39,23 +60,31 @@ net_ring_t *create_net_vif(int domain) { return NULL; } - dom_task->net_vif_list[dom_task->num_net_vifs] = new_vif; new_ring = dom_task->net_ring_base + dom_task->num_net_vifs; memset(new_ring, 0, sizeof(net_ring_t)); - dom_task->net_vif_list[dom_task->num_net_vifs]->net_ring = new_ring; - skb_queue_head_init( - &dom_task->net_vif_list[dom_task->num_net_vifs]->skb_list); - dom_task->net_vif_list[dom_task->num_net_vifs]->id = sys_vif_count++; - dom_task->num_net_vifs++; + new_vif->net_ring = new_ring; + skb_queue_head_init(&new_vif->skb_list); + new_vif->domain = domain; + + write_lock(&sys_vif_lock); + new_vif->id = sys_vif_count; + sys_vif_list[sys_vif_count++] = new_vif; + write_unlock(&sys_vif_lock); - return new_ring; + dom_task->net_vif_list[dom_task->num_net_vifs] = new_vif; + dom_task->num_net_vifs++; + + return new_vif; } -/* delete the last vif in the given domain. There doesn't seem to be any reason - * (yet) to be able to axe an arbitrary vif, by vif id. +/* delete_net_vif - Delete the last vif in the given domain. + * + * There doesn't seem to be any reason (yet) to be able to axe an arbitrary + * vif, by vif id. */ + void destroy_net_vif(struct task_struct *p) { struct sk_buff *skb; @@ -68,9 +97,36 @@ void destroy_net_vif(struct task_struct *p) { kfree_skb(skb); } + + write_lock(&sys_vif_lock); + sys_vif_list[p->net_vif_list[i]->id] = NULL; // system vif list not gc'ed + write_unlock(&sys_vif_lock); + kmem_cache_free(net_vif_cache, p->net_vif_list[i]); } +/* print_vif_list - Print the contents of the global vif table. + */ + +void print_vif_list() +{ + int i; + net_vif_t *v; + + printk("Currently, there are %d VIFs.\n", sys_vif_count); + for (i=0; i<sys_vif_count; i++) + { + v = sys_vif_list[i]; + printk("] VIF Entry %d(%d):\n", i, v->id); + printk(" > net_ring*: %p\n", v->net_ring); + printk(" > domain : %u\n", v->domain); + } +} + +/* ----[ Net Rule Functions ]-----------------------------------------------*/ + +/* add_net_rule - Add a new network filter rule. + */ int add_net_rule(net_rule_t *rule) { @@ -91,20 +147,22 @@ int add_net_rule(net_rule_t *rule) return 0; } +/* delete_net_rule - Delete an existing network rule. + */ + int delete_net_rule(net_rule_t *rule) { net_rule_ent_t *ent = net_rule_list, *prev = NULL; - - while ( (ent) && (!(memcmp(rule, &ent->r, sizeof(net_rule_t)))) ) + while ( (ent) && ((memcmp(rule, &ent->r, sizeof(net_rule_t))) != 0) ) { prev = ent; ent = ent->next; } - if (ent) + if (ent != NULL) { write_lock(&net_rule_lock); - if (prev) + if (prev != NULL) { prev->next = ent->next; } @@ -115,10 +173,44 @@ int delete_net_rule(net_rule_t *rule) kmem_cache_free(net_rule_cache, ent); write_unlock(&net_rule_lock); } - return 0; } - + +/* add_default_net_rule - Set up default network path (ie for dom0). + * + * this is a utility function to route all traffic with the specified + * ip address to the specified vif. It's used to set up domain zero. + */ + +void add_default_net_rule(int vif_id, u32 ipaddr) +{ + net_rule_t new_rule; + + //outbound rule. + memset(&new_rule, 0, sizeof(net_rule_t)); + new_rule.src_addr = ipaddr; + new_rule.src_addr_mask = 0xffffffff; + new_rule.src_interface = vif_id; + new_rule.dst_interface = VIF_PHYSICAL_INTERFACE; + new_rule.action = NETWORK_ACTION_ACCEPT; + new_rule.proto = NETWORK_PROTO_ANY; + add_net_rule(&new_rule); + + //inbound rule; + memset(&new_rule, 0, sizeof(net_rule_t)); + new_rule.dst_addr = ipaddr; + new_rule.dst_addr_mask = 0xffffffff; + new_rule.src_interface = VIF_PHYSICAL_INTERFACE; + new_rule.dst_interface = vif_id; + new_rule.action = NETWORK_ACTION_ACCEPT; + new_rule.proto = NETWORK_PROTO_ANY; + add_net_rule(&new_rule); + +} + +/* print_net_rule - Print a single net rule. + */ + void print_net_rule(net_rule_t *r) { printk("===] NET RULE:\n"); @@ -131,16 +223,23 @@ void print_net_rule(net_rule_t *r) printk("=] dst_port : %u\n", r->dst_port); printk("=] dst_port_mask : %u\n", r->dst_port_mask); printk("=] dst_proto : %u\n", r->proto); - printk("=] src_interface : %u\n", r->src_interface); - printk("=] dst_interface : %u\n", r->dst_interface); + printk("=] src_interface : %d\n", r->src_interface); + printk("=] dst_interface : %d\n", r->dst_interface); printk("=] action : %u\n", r->action); } +/* print_net_rule_list - Print the global rule table. + */ + void print_net_rule_list() { - net_rule_ent_t *ent = net_rule_list; + net_rule_ent_t *ent; int count = 0; + read_lock(&net_rule_lock); + + ent = net_rule_list; + while (ent) { print_net_rule(&ent->r); @@ -148,8 +247,120 @@ void print_net_rule_list() count++; } printk("\nTotal of %d rules.\n", count); + + read_unlock(&net_rule_lock); +} + +/* net_find_rule - Find the destination vif according to the current rules. + * + * Apply the rules to this skbuff and return the vif id that it is bound for. + * If there is no match, VIF_DROP is returned. + */ + +int net_find_rule(u8 nproto, u8 tproto, u32 src_addr, u32 dst_addr, u16 src_port, u16 dst_port, + int src_vif) +{ + net_rule_ent_t *ent; + int dest = VIF_DROP; + + read_lock(&net_rule_lock); + + ent = net_rule_list; + + while (ent) + { + if ( ( (ent->r.src_interface == src_vif) + || (ent->r.src_interface == VIF_ANY_INTERFACE) ) + + && (!((ent->r.src_addr ^ src_addr) & ent->r.src_addr_mask )) + && (!((ent->r.dst_addr ^ dst_addr) & ent->r.dst_addr_mask )) + && (!((ent->r.src_port ^ src_port) & ent->r.src_port_mask )) + && (!((ent->r.dst_port ^ dst_port) & ent->r.dst_port_mask )) + + && ( + (ent->r.proto == NETWORK_PROTO_ANY) + || ((ent->r.proto == NETWORK_PROTO_IP) && (nproto == (u8)ETH_P_IP)) + || ((ent->r.proto == NETWORK_PROTO_ARP) && (nproto == (u8)ETH_P_ARP)) + || ((ent->r.proto == NETWORK_PROTO_TCP) && (tproto == IPPROTO_TCP)) + || ((ent->r.proto == NETWORK_PROTO_UDP) && (tproto == IPPROTO_UDP)) + ) + ) + { + break; + } + ent = ent->next; + } + + if (ent) (dest = ent->r.dst_interface); + read_unlock(&net_rule_lock); + return dest; } +/* net_get_target_vif - Find the vif that the given sk_buff is bound for. + * + * This is intended to be the main interface to the VFR rules, where + * net_find_rule (above) is a private aspect of the current matching + * implementation. All in-hypervisor routing should use this function only + * to ensure that this can be rewritten later. + * + * Currently, network rules are stored in a global linked list. New rules are + * added to the front of this list, and (at present) the first matching rule + * determines the vif that a packet is sent to. This is obviously not ideal, + * it might be more advisable to have chains, or at lest most-specific + * matching, and moreover routing latency increases linearly (for old rules) + * as new rules are added. + * + * net_get_target_vif examines the sk_buff and pulls out the relevant fields + * based on the packet type. it then calls net_find_rule to scan the rule + * list. + */ + +int net_get_target_vif(struct sk_buff *skb) +{ + 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) ) + { + 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); + 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) ) + { + 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); + 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)), + 0, + 0, + skb->src_vif); + } + break; + } + skb->dst_vif=target; + return target; + + drop: + return VIF_DROP; +} + +/* ----[ Syscall Interface ]------------------------------------------------*/ + /* * This is the hook function to handle guest-invoked traps requesting * changes to the network system. @@ -199,6 +410,7 @@ long do_network_op(network_op_t *u_network_op) void __init net_init (void) { sys_vif_count = 0; + memset(sys_vif_list, 0, sizeof(sys_vif_list)); net_rule_list = NULL; net_vif_cache = kmem_cache_create("net_vif_cache", sizeof(net_vif_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); diff --git a/xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h b/xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h index 4f4d1a2d23..9961f4b96d 100644 --- a/xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h +++ b/xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h @@ -46,21 +46,41 @@ typedef struct #define TRAP_INSTR "int $0x82" +/* Event message note: + * + * Here, as in the interrupts to the guestos, additional network interfaces + * are defined. These definitions server as placeholders for the event bits, + * however, in the code these events will allways be referred to as shifted + * offsets from the base NET events. + */ + /* Events that a guest OS may receive from the hypervisor. */ -#define EVENT_NET_TX 0x01 /* packets for transmission. */ -#define EVENT_NET_RX 0x02 /* empty buffers for receive. */ -#define EVENT_TIMER 0x04 /* a timeout has been updated. */ -#define EVENT_DIE 0x08 /* OS is about to be killed. Clean up please! */ -#define EVENT_BLK_TX 0x10 /* packets for transmission. */ -#define EVENT_BLK_RX 0x20 /* empty buffers for receive. */ +#define EVENT_BLK_TX 0x01 /* packets for transmission. */ +#define EVENT_BLK_RX 0x02 /* empty buffers for receive. */ +#define EVENT_TIMER 0x04 /* a timeout has been updated. */ +#define EVENT_DIE 0x08 /* OS is about to be killed. Clean up please! */ +#define EVENT_NET_TX 0x10 /* packets for transmission. */ +#define EVENT_NET_RX 0x20 /* empty buffers for receive. */ +#define EVENT_NET2_TX 0x40 /* packets for transmission. */ +#define EVENT_NET2_RX 0x80 /* empty buffers for receive. */ + +/* should these macros and the ones below test for range violation? */ +#define EVENT_NET_TX_FOR_VIF(x) (EVENT_NET_TX << (2 * x)) +#define EVENT_NET_RX_FOR_VIF(x) (EVENT_NET_RX << (2 * x)) + /* Bit offsets, as opposed to the above masks. */ -#define _EVENT_NET_TX 0 -#define _EVENT_NET_RX 1 -#define _EVENT_TIMER 2 -#define _EVENT_DIE 3 -#define _EVENT_BLK_TX 4 -#define _EVENT_BLK_RX 5 +#define _EVENT_BLK_TX 0 +#define _EVENT_BLK_RX 1 +#define _EVENT_TIMER 2 +#define _EVENT_DIE 3 +#define _EVENT_NET_TX 4 +#define _EVENT_NET_RX 5 +#define _EVENT_NET2_TX 6 +#define _EVENT_NET2_RX 7 + +#define _EVENT_NET_TX_FOR_VIF(x) (_EVENT_NET_TX + (2 * x)) +#define _EVENT_NET_RX_FOR_VIF(x) (_EVENT_NET_RX + (2 * x)) /* * NB. We expect that this struct is smaller than a page. @@ -72,7 +92,7 @@ typedef struct shared_info_st { /* * Hypervisor will only signal event delivery via the "callback * exception" when this value is non-zero. Hypervisor clears this when - * notiying the guest OS -- thsi prevents unbounded reentrancy and + * notiying the guest OS -- this prevents unbounded reentrancy and * stack overflow (in this way, acts as an interrupt-enable flag). */ unsigned long events_enable; diff --git a/xen-2.4.16/include/hypervisor-ifs/network.h b/xen-2.4.16/include/hypervisor-ifs/network.h index 54cb99095a..a0cfc9fa2c 100644 --- a/xen-2.4.16/include/hypervisor-ifs/network.h +++ b/xen-2.4.16/include/hypervisor-ifs/network.h @@ -52,7 +52,7 @@ typedef struct net_ring_st { } net_ring_t; /* Specify base of per-domain array. Get returned free slot in the array. */ -net_ring_t *create_net_vif(int domain); +//net_ring_t *create_net_vif(int domain); /* Packet routing/filtering code follows: */ @@ -60,10 +60,11 @@ net_ring_t *create_net_vif(int domain); #define NETWORK_ACTION_ACCEPT 0 #define NETWORK_ACTION_COUNT 1 -#define NETWORK_PROTO_IP 0 -#define NETWORK_PROTO_TCP 1 -#define NETWORK_PROTO_UDP 2 -#define NETWORK_PROTO_ARP 3 +#define NETWORK_PROTO_ANY 0 +#define NETWORK_PROTO_IP 1 +#define NETWORK_PROTO_TCP 2 +#define NETWORK_PROTO_UDP 3 +#define NETWORK_PROTO_ARP 4 typedef struct net_rule_st { @@ -77,8 +78,8 @@ typedef struct net_rule_st u16 dst_port_mask; u16 proto; - u16 src_interface; - u16 dst_interface; + int src_interface; + int dst_interface; u16 action; } net_rule_t; diff --git a/xen-2.4.16/include/xeno/in.h b/xen-2.4.16/include/xeno/in.h new file mode 100644 index 0000000000..1d5f14ad62 --- /dev/null +++ b/xen-2.4.16/include/xeno/in.h @@ -0,0 +1,190 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Definitions of the Internet Protocol. + * + * Version: @(#)in.h 1.0.1 04/21/93 + * + * Authors: Original taken from the GNU Project <netinet/in.h> file. + * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _LINUX_IN_H +#define _LINUX_IN_H + +#include <linux/types.h> + +/* Standard well-defined IP protocols. */ +enum { + IPPROTO_IP = 0, /* Dummy protocol for TCP */ + IPPROTO_ICMP = 1, /* Internet Control Message Protocol */ + IPPROTO_IGMP = 2, /* Internet Group Management Protocol */ + IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94) */ + IPPROTO_TCP = 6, /* Transmission Control Protocol */ + IPPROTO_EGP = 8, /* Exterior Gateway Protocol */ + IPPROTO_PUP = 12, /* PUP protocol */ + IPPROTO_UDP = 17, /* User Datagram Protocol */ + IPPROTO_IDP = 22, /* XNS IDP protocol */ + IPPROTO_RSVP = 46, /* RSVP protocol */ + IPPROTO_GRE = 47, /* Cisco GRE tunnels (rfc 1701,1702) */ + + IPPROTO_IPV6 = 41, /* IPv6-in-IPv4 tunnelling */ + + IPPROTO_PIM = 103, /* Protocol Independent Multicast */ + + IPPROTO_ESP = 50, /* Encapsulation Security Payload protocol */ + IPPROTO_AH = 51, /* Authentication Header protocol */ + IPPROTO_COMP = 108, /* Compression Header protocol */ + + IPPROTO_RAW = 255, /* Raw IP packets */ + IPPROTO_MAX +}; + + +/* Internet address. */ +struct in_addr { + __u32 s_addr; +}; + +#define IP_TOS 1 +#define IP_TTL 2 +#define IP_HDRINCL 3 +#define IP_OPTIONS 4 +#define IP_ROUTER_ALERT 5 +#define IP_RECVOPTS 6 +#define IP_RETOPTS 7 +#define IP_PKTINFO 8 +#define IP_PKTOPTIONS 9 +#define IP_MTU_DISCOVER 10 +#define IP_RECVERR 11 +#define IP_RECVTTL 12 +#define IP_RECVTOS 13 +#define IP_MTU 14 +#define IP_FREEBIND 15 + +/* BSD compatibility */ +#define IP_RECVRETOPTS IP_RETOPTS + +/* IP_MTU_DISCOVER values */ +#define IP_PMTUDISC_DONT 0 /* Never send DF frames */ +#define IP_PMTUDISC_WANT 1 /* Use per route hints */ +#define IP_PMTUDISC_DO 2 /* Always DF */ + +#define IP_MULTICAST_IF 32 +#define IP_MULTICAST_TTL 33 +#define IP_MULTICAST_LOOP 34 +#define IP_ADD_MEMBERSHIP 35 +#define IP_DROP_MEMBERSHIP 36 + +/* These need to appear somewhere around here */ +#define IP_DEFAULT_MULTICAST_TTL 1 +#define IP_DEFAULT_MULTICAST_LOOP 1 + +/* Request struct for multicast socket ops */ + +struct ip_mreq +{ + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_interface; /* local IP address of interface */ +}; + +struct ip_mreqn +{ + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_address; /* local IP address of interface */ + int imr_ifindex; /* Interface index */ +}; + +struct in_pktinfo +{ + int ipi_ifindex; + struct in_addr ipi_spec_dst; + struct in_addr ipi_addr; +}; + +/* Structure describing an Internet (IP) socket address. */ +#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ +struct sockaddr_in { + sa_family_t sin_family; /* Address family */ + unsigned short int sin_port; /* Port number */ + struct in_addr sin_addr; /* Internet address */ + + /* Pad to size of `struct sockaddr'. */ + unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) - + sizeof(unsigned short int) - sizeof(struct in_addr)]; +}; +#define sin_zero __pad /* for BSD UNIX comp. -FvK */ + + +/* + * Definitions of the bits in an Internet address integer. + * On subnets, host and network parts are found according + * to the subnet mask, not these masks. + */ +#define IN_CLASSA(a) ((((long int) (a)) & 0x80000000) == 0) +#define IN_CLASSA_NET 0xff000000 +#define IN_CLASSA_NSHIFT 24 +#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET) +#define IN_CLASSA_MAX 128 + +#define IN_CLASSB(a) ((((long int) (a)) & 0xc0000000) == 0x80000000) +#define IN_CLASSB_NET 0xffff0000 +#define IN_CLASSB_NSHIFT 16 +#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET) +#define IN_CLASSB_MAX 65536 + +#define IN_CLASSC(a) ((((long int) (a)) & 0xe0000000) == 0xc0000000) +#define IN_CLASSC_NET 0xffffff00 +#define IN_CLASSC_NSHIFT 8 +#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET) + +#define IN_CLASSD(a) ((((long int) (a)) & 0xf0000000) == 0xe0000000) +#define IN_MULTICAST(a) IN_CLASSD(a) +#define IN_MULTICAST_NET 0xF0000000 + +#define IN_EXPERIMENTAL(a) ((((long int) (a)) & 0xf0000000) == 0xf0000000) +#define IN_BADCLASS(a) IN_EXPERIMENTAL((a)) + +/* Address to accept any incoming messages. */ +#define INADDR_ANY ((unsigned long int) 0x00000000) + +/* Address to send to all hosts. */ +#define INADDR_BROADCAST ((unsigned long int) 0xffffffff) + +/* Address indicating an error return. */ +#define INADDR_NONE ((unsigned long int) 0xffffffff) + +/* Network number for local host loopback. */ +#define IN_LOOPBACKNET 127 + +/* Address to loopback in software to local host. */ +#define INADDR_LOOPBACK 0x7f000001 /* 127.0.0.1 */ +#define IN_LOOPBACK(a) ((((long int) (a)) & 0xff000000) == 0x7f000000) + +/* Defines for Multicast INADDR */ +#define INADDR_UNSPEC_GROUP 0xe0000000U /* 224.0.0.0 */ +#define INADDR_ALLHOSTS_GROUP 0xe0000001U /* 224.0.0.1 */ +#define INADDR_ALLRTRS_GROUP 0xe0000002U /* 224.0.0.2 */ +#define INADDR_MAX_LOCAL_GROUP 0xe00000ffU /* 224.0.0.255 */ + + +/* <asm/byteorder.h> contains the htonl type stuff.. */ +#include <asm/byteorder.h> + +#ifdef __KERNEL__ +/* Some random defines to make it easier in the kernel.. */ +#define LOOPBACK(x) (((x) & htonl(0xff000000)) == htonl(0x7f000000)) +#define MULTICAST(x) (((x) & htonl(0xf0000000)) == htonl(0xe0000000)) +#define BADCLASS(x) (((x) & htonl(0xf0000000)) == htonl(0xf0000000)) +#define ZERONET(x) (((x) & htonl(0xff000000)) == htonl(0x00000000)) +#define LOCAL_MCAST(x) (((x) & htonl(0xFFFFFF00)) == htonl(0xE0000000)) + +#endif + +#endif /* _LINUX_IN_H */ diff --git a/xen-2.4.16/include/xeno/skbuff.h b/xen-2.4.16/include/xeno/skbuff.h index 4a540d8e0b..f9c38c12bf 100644 --- a/xen-2.4.16/include/xeno/skbuff.h +++ b/xen-2.4.16/include/xeno/skbuff.h @@ -28,6 +28,12 @@ #include <linux/mm.h> //#include <linux/highmem.h> +// vif special values. +#define VIF_PHYSICAL_INTERFACE -1 +#define VIF_UNKNOWN_INTERFACE -2 +#define VIF_DROP -3 +#define VIF_ANY_INTERFACE -4 + #define HAVE_ALLOC_SKB /* For the drivers to know */ #define HAVE_ALIGNABLE_SKB /* Ditto 8) */ #define SLAB_SKB /* Slabified skbuffs */ @@ -196,6 +202,12 @@ struct sk_buff { unsigned char *end; /* End pointer */ void (*destructor)(struct sk_buff *); /* Destruct function */ + + int src_vif; /* vif we came from */ + int dst_vif; /* vif we are bound for */ + + + #ifdef CONFIG_NETFILTER /* Can be used for communication between hooks. */ unsigned long nfmark; diff --git a/xen-2.4.16/include/xeno/vif.h b/xen-2.4.16/include/xeno/vif.h index 6c1a1807a5..1bef565c32 100644 --- a/xen-2.4.16/include/xeno/vif.h +++ b/xen-2.4.16/include/xeno/vif.h @@ -1,7 +1,9 @@ /* vif.h * - * this is the hypervisor end of the network code. The net_ring structure + * This is the hypervisor end of the network code. The net_ring structure * stored in each vif is placed on a shared page to interact with the guest VM. + * + * Copyright (c) 2002, A K Warfield and K A Fraser */ /* virtual network interface struct and associated defines. */ @@ -20,18 +22,21 @@ typedef struct net_vif_st { net_ring_t *net_ring; int id; struct sk_buff_head skb_list; + unsigned int domain; // rules table goes here in next revision. } net_vif_t; /* VIF-related defines. */ #define MAX_GUEST_VIFS 2 // each VIF is a small overhead in task_struct -#define MAX_SYSTEM_VIFS 256 // trying to avoid dynamic allocation +#define MAX_SYSTEM_VIFS 256 /* vif globals */ extern int sys_vif_count; extern net_vif_t *sys_vif_list[]; /* vif prototypes */ -net_ring_t *create_net_vif(int domain); +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); +void add_default_net_rule(int vif_id, u32 ipaddr); diff --git a/xen-2.4.16/net/dev.c b/xen-2.4.16/net/dev.c index dd376df98d..5c4d999bf3 100644 --- a/xen-2.4.16/net/dev.c +++ b/xen-2.4.16/net/dev.c @@ -687,7 +687,6 @@ int netif_rx(struct sk_buff *skb) unsigned long cpu_mask; #endif struct task_struct *p; - unsigned int dest_dom; int this_cpu = smp_processor_id(); struct softnet_data *queue; unsigned long flags; @@ -704,57 +703,43 @@ int netif_rx(struct sk_buff *skb) netdev_rx_stat[this_cpu].total++; - skb->h.raw = skb->nh.raw = skb->data; + 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); - if ( skb->len < 2 ) goto drop; - switch ( ntohs(skb->mac.ethernet->h_proto) ) + if (sys_vif_list[skb->dst_vif] == NULL) { - case ETH_P_ARP: - if ( skb->len < 28 ) goto drop; - dest_dom = ntohl(*(unsigned long *) - (skb->nh.raw + 24)); - break; - case ETH_P_IP: - if ( skb->len < 20 ) goto drop; - dest_dom = ntohl(*(unsigned long *) - (skb->nh.raw + 16)); - break; - default: + // the target vif does not exist. goto drop; } + + /* This lock-and-walk of the task list isn't really necessary, and is an + * artifact of the old code. The vif contains a pointer to the skb list + * we are going to queue the packet in, so the lock and the inner loop + * could be removed. + * + * The argument against this is a possible race in which a domain is killed + * as packets are being delivered to it. This would result in the dest vif + * vanishing before we can deliver to it. + */ - if ( (dest_dom < opt_ipbase) || - (dest_dom > (opt_ipbase + 16)) ) + if ( skb->dst_vif >= VIF_PHYSICAL_INTERFACE ) + { + read_lock(&tasklist_lock); + p = &idle0_task; + do { + if ( p->domain != sys_vif_list[skb->dst_vif]->domain ) continue; + skb_queue_tail(&sys_vif_list[skb->dst_vif]->skb_list, skb); + cpu_mask = mark_hyp_event(p, _HYP_EVENT_NET_RX); + read_unlock(&tasklist_lock); + goto found; + } + while ( (p = p->next_task) != &idle0_task ); + read_unlock(&tasklist_lock); goto drop; - - dest_dom -= opt_ipbase; - - read_lock(&tasklist_lock); - p = &idle0_task; - do { - if ( p->domain != dest_dom ) continue; - skb_queue_tail(&p->net_vif_list[0]->skb_list, skb); // vfr will fix. - cpu_mask = mark_hyp_event(p, _HYP_EVENT_NET_RX); - read_unlock(&tasklist_lock); - goto found; } - while ( (p = p->next_task) != &idle0_task ); - read_unlock(&tasklist_lock); - goto drop; - - found: -#if 0 - __skb_queue_tail(&queue->input_pkt_queue,skb); - /* Runs from irqs or BH's, no need to wake BH */ - cpu_raise_softirq(this_cpu, NET_RX_SOFTIRQ); - local_irq_restore(flags); - get_sample_stats(this_cpu); - return softnet_data[this_cpu].cng_level; -#else - hyp_event_notify(cpu_mask); - local_irq_restore(flags); - return 0; -#endif drop: netdev_rx_stat[this_cpu].dropped++; @@ -762,6 +747,11 @@ drop: kfree_skb(skb); return NET_RX_DROP; + +found: + hyp_event_notify(cpu_mask); + local_irq_restore(flags); + return 0; } /* Deliver skb to an old protocol, which is not threaded well @@ -890,6 +880,18 @@ void flush_rx_queue(void) unsigned int i, nvif; rx_entry_t rx; + /* I have changed this to batch flush all vifs for a guest + * at once, whenever this is called. Since the guest is about to be + * scheduled and issued an RX interrupt for one nic, it might as well + * receive all pending traffic although it will still only get + * interrupts about rings that pass the event marker. + * + * If this doesn't make sense, _HYP_EVENT_NET_RX can be modified to + * represent individual interrups as _EVENT_NET_RX and the outer for + * loop can be replaced with a translation to the specific NET + * interrupt to serve. --akw + */ + clear_bit(_HYP_EVENT_NET_RX, ¤t->hyp_events); for (nvif = 0; nvif < current->num_net_vifs; nvif++) @@ -903,10 +905,18 @@ void flush_rx_queue(void) * of the ethernet packet. Furthermore, do the same for ARP * reply packets. This is easy because the virtual MAC address * is always 00-00-00-00-00-00. + * + * Actually, the MAC address is now all zeros, except for the + * second sixteen bits, which are the per-host vif id. + * (so eth0 should be 00-00-..., eth1 is 00-01-...) */ memset(skb->mac.ethernet->h_dest, 0, ETH_ALEN); + *(unsigned int *)(skb->mac.ethernet->h_dest + 1) = nvif; if ( ntohs(skb->mac.ethernet->h_proto) == ETH_P_ARP ) + { memset(skb->nh.raw + 18, 0, ETH_ALEN); + *(unsigned int *)(skb->nh.raw + 18 + 1) = nvif; + } i = net_ring->rx_cons; if ( i != net_ring->rx_prod ) @@ -920,7 +930,7 @@ void flush_rx_queue(void) } net_ring->rx_cons = (i+1) & (RX_RING_SIZE-1); if ( net_ring->rx_cons == net_ring->rx_event ) - set_bit(_EVENT_NET_RX, &s->events); + set_bit(_EVENT_NET_RX_FOR_VIF(nvif), &s->events); } kfree_skb(skb); } @@ -1912,20 +1922,22 @@ long do_net_update(void) { shared_info_t *shared = current->shared_info; net_ring_t *net_ring = current->net_ring_base; + net_vif_t *current_vif; unsigned int i, j; struct sk_buff *skb; tx_entry_t tx; for ( j = 0; j < current->num_net_vifs; j++) { - net_ring = current->net_vif_list[j]->net_ring; + current_vif = current->net_vif_list[j]; + net_ring = current_vif->net_ring; for ( i = net_ring->tx_cons; i != net_ring->tx_prod; i = TX_RING_INC(i) ) { if ( copy_from_user(&tx, net_ring->tx_ring+i, sizeof(tx)) ) continue; if ( TX_RING_INC(i) == net_ring->tx_event ) - set_bit(_EVENT_NET_TX, &shared->events); + set_bit(_EVENT_NET_TX_FOR_VIF(j), &shared->events); skb = alloc_skb(tx.size, GFP_KERNEL); if ( skb == NULL ) continue; @@ -1965,17 +1977,25 @@ long do_net_update(void) { skb_get(skb); /* get a reference for non-local delivery */ skb->protocol = eth_type_trans(skb, skb->dev); - if ( netif_rx(skb) == 0 ) + skb->src_vif = current_vif->id; + net_get_target_vif(skb); + if ( skb->dst_vif > VIF_PHYSICAL_INTERFACE ) { - /* Give up non-local reference. Packet delivered locally. */ - kfree_skb(skb); + if (netif_rx(skb) == 0) + /* Give up non-local reference. Packet delivered locally. */ + kfree_skb(skb); } + else if ( skb->dst_vif == VIF_PHYSICAL_INTERFACE ) + { + + skb_push(skb, skb->dev->hard_header_len); + dev_queue_xmit(skb); + } else { - /* Pass the non-local reference to the net device. */ - skb_push(skb, skb->dev->hard_header_len); - dev_queue_xmit(skb); + kfree_skb(skb); } + } } net_ring->tx_cons = i; diff --git a/xen-2.4.16/net/skbuff.c b/xen-2.4.16/net/skbuff.c index 7ed619c5ee..07896fda78 100644 --- a/xen-2.4.16/net/skbuff.c +++ b/xen-2.4.16/net/skbuff.c @@ -211,6 +211,8 @@ struct sk_buff *alloc_skb(unsigned int size,int gfp_mask) skb->len = 0; skb->cloned = 0; skb->data_len = 0; + skb->src_vif = VIF_UNKNOWN_INTERFACE; + skb->dst_vif = VIF_UNKNOWN_INTERFACE; atomic_set(&skb->users, 1); atomic_set(&(skb_shinfo(skb)->dataref), 1); diff --git a/xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/vfr.c b/xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/vfr.c index 3f22282cee..13fe25ec9c 100644 --- a/xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/vfr.c +++ b/xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/vfr.c @@ -23,6 +23,7 @@ static unsigned char readbuf[1024]; /* Helpers, implemented at the bottom. */ u32 getipaddr(const char *buff, unsigned int len); u16 antous(const char *buff, int len); +int anton(const char *buff, int len); static int vfr_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) @@ -55,6 +56,9 @@ static int vfr_read_proc(char *page, char **start, off_t off, * */ +#define isspace(_x) ( ((_x)==' ') || ((_x)=='\t') || ((_x)=='\v') || \ + ((_x)=='\f') || ((_x)=='\r') || ((_x)=='\n') ) + static int vfr_write_proc(struct file *file, const char *buffer, u_long count, void *data) { @@ -69,12 +73,12 @@ static int vfr_write_proc(struct file *file, const char *buffer, memset(&op, 0, sizeof(network_op_t)); // get the command: - while ( count && (buffer[ts] == ' ') ) { ts++; count--; } // skip spaces. + while ( count && isspace(buffer[ts]) ) { ts++; count--; } // skip spaces. te = ts; - while ( count && (buffer[te] != ' ') ) { te++; count--; } // command end + while ( count && !isspace(buffer[te]) ) { te++; count--; } // command end if ( te <= ts ) goto bad; tl = te - ts; - + if ( strncmp(&buffer[ts], "ADD", tl) == 0 ) { op.cmd = NETWORK_OP_ADDRULE; @@ -118,71 +122,74 @@ static int vfr_write_proc(struct file *file, const char *buffer, while (count) { //get field - ts = te; while ( count && (buffer[ts] == ' ') ) { ts++; count--; } + ts = te; while ( count && isspace(buffer[ts]) ) { ts++; count--; } te = ts; - while ( count && (buffer[te] != ' ') && (buffer[te] != '=') ) + while ( count && !isspace(buffer[te]) && (buffer[te] != '=') ) { te++; count--; } - if ( te <= ts ) goto bad; + if ( te <= ts ) + goto doneparsing; tl = te - ts; fs = ts; fe = te; fl = tl; // save the field markers. // skip " = " (ignores extra equals.) - while ( count && ((buffer[te] == ' ') || (buffer[te] == '=')) ) + while ( count && (isspace(buffer[te]) || (buffer[te] == '=')) ) { te++; count--; } ts = te; - while ( count && (buffer[te] != ' ') ) { te++; count--; } + while ( count && !isspace(buffer[te]) ) { te++; count--; } tl = te - ts; if ( (fl <= 0) || (tl <= 0) ) goto bad; if (strncmp(&buffer[fs], "srcaddr", fl) == 0) { - op.u.net_rule.src_addr = getipaddr(&buffer[ts], tl-1); + op.u.net_rule.src_addr = getipaddr(&buffer[ts], tl); } else if (strncmp(&buffer[fs], "dstaddr", fl) == 0) { - op.u.net_rule.dst_addr = getipaddr(&buffer[ts], tl-1); + op.u.net_rule.dst_addr = getipaddr(&buffer[ts], tl); } else if (strncmp(&buffer[fs], "srcaddrmask", fl) == 0) { - op.u.net_rule.src_addr_mask = getipaddr(&buffer[ts], tl-1); + op.u.net_rule.src_addr_mask = getipaddr(&buffer[ts], tl); } else if (strncmp(&buffer[fs], "dstaddrmask", fl) == 0) { - op.u.net_rule.dst_addr_mask = getipaddr(&buffer[ts], tl-1); + op.u.net_rule.dst_addr_mask = getipaddr(&buffer[ts], tl); } else if (strncmp(&buffer[fs], "srcport", fl) == 0) { - op.u.net_rule.src_port = antous(&buffer[ts], tl-1); + op.u.net_rule.src_port = antous(&buffer[ts], tl); } else if (strncmp(&buffer[fs], "dstport", fl) == 0) { - op.u.net_rule.dst_port = antous(&buffer[ts], tl-1); + op.u.net_rule.dst_port = antous(&buffer[ts], tl); } else if (strncmp(&buffer[fs], "srcportmask", fl) == 0) { - op.u.net_rule.src_port_mask = antous(&buffer[ts], tl-1); + op.u.net_rule.src_port_mask = antous(&buffer[ts], tl); } else if (strncmp(&buffer[fs], "dstportmask", fl) == 0) { - op.u.net_rule.dst_port_mask = antous(&buffer[ts], tl-1); + op.u.net_rule.dst_port_mask = antous(&buffer[ts], tl); } else if (strncmp(&buffer[fs], "srcint", fl) == 0) { - op.u.net_rule.src_interface = antous(&buffer[ts], tl-1); + op.u.net_rule.src_interface = anton(&buffer[ts], tl); } else if (strncmp(&buffer[fs], "dstint", fl) == 0) { - op.u.net_rule.dst_interface = antous(&buffer[ts], tl-1); + op.u.net_rule.dst_interface = anton(&buffer[ts], tl); } else if ( (strncmp(&buffer[fs], "proto", fl) == 0)) - { - if (strncmp(&buffer[ts], "ip", tl)) + { + if (strncmp(&buffer[ts], "any", tl) == 0) + op.u.net_rule.proto = NETWORK_PROTO_ANY; + if (strncmp(&buffer[ts], "ip", tl) == 0) op.u.net_rule.proto = NETWORK_PROTO_IP; - if (strncmp(&buffer[ts], "tcp", tl)) + if (strncmp(&buffer[ts], "tcp", tl) == 0) op.u.net_rule.proto = NETWORK_PROTO_TCP; - if (strncmp(&buffer[ts], "udp", tl)) + if (strncmp(&buffer[ts], "udp", tl) == 0) op.u.net_rule.proto = NETWORK_PROTO_UDP; - if (strncmp(&buffer[ts], "arp", tl)) + if (strncmp(&buffer[ts], "arp", tl) == 0) op.u.net_rule.proto = NETWORK_PROTO_ARP; } @@ -225,9 +232,31 @@ module_exit(cleanup_module); /* Helper functions start here: */ +int anton(const char *buff, int len) +{ + int ret; + char c; + int sign = 1; + + ret = 0; + + if (len == 0) return 0; + if (*buff == '-') { sign = -1; buff++; len--; } + + while ( (len) && ((c = *buff) >= '0') && (c <= '9') ) + { + ret *= 10; + ret += c - '0'; + buff++; len--; + } + + ret *= sign; + return ret; +} + u16 antous(const char *buff, int len) { - int ret; + u16 ret; char c; ret = 0; diff --git a/xenolinux-2.4.16-sparse/arch/xeno/drivers/network/network.c b/xenolinux-2.4.16-sparse/arch/xeno/drivers/network/network.c index 7e1825f873..b018e29e49 100644 --- a/xenolinux-2.4.16-sparse/arch/xeno/drivers/network/network.c +++ b/xenolinux-2.4.16-sparse/arch/xeno/drivers/network/network.c @@ -26,6 +26,9 @@ #define NET_TX_IRQ _EVENT_NET_TX #define NET_RX_IRQ _EVENT_NET_RX +#define NET_TX_IRQ_FOR_VIF(x) _EVENT_NET_TX_FOR_VIF(x) +#define NET_RX_IRQ_FOR_VIF(x) _EVENT_NET_RX_FOR_VIF(x) + #define TX_MAX_ENTRIES (TX_RING_SIZE - 2) #define RX_MAX_ENTRIES (RX_RING_SIZE - 2) @@ -62,6 +65,7 @@ struct net_private unsigned int rx_idx, tx_idx, tx_full; net_ring_t *net_ring; spinlock_t tx_lock; + unsigned int id; }; @@ -69,7 +73,15 @@ static int network_open(struct net_device *dev) { struct net_private *np = dev->priv; int error; - + char *rxlabel, *txlabel; + + // This is inevitably not the right way to allocate a couple of static strings. + rxlabel = kmalloc(sizeof("net-rx- "), GFP_KERNEL); + txlabel = kmalloc(sizeof("net-tx- "), GFP_KERNEL); + if ((rxlabel == NULL) || (txlabel == NULL)) goto fail; + sprintf(rxlabel, "net-rx-%d", np->id); + sprintf(txlabel, "net-tx-%d", np->id); + np->rx_idx = np->tx_idx = np->tx_full = 0; memset(&np->stats, 0, sizeof(np->stats)); @@ -101,7 +113,8 @@ static int network_open(struct net_device *dev) network_alloc_rx_buffers(dev); - error = request_irq(NET_RX_IRQ, network_rx_int, 0, "net-rx", dev); + error = request_irq(NET_RX_IRQ_FOR_VIF(np->id), network_rx_int, 0, + rxlabel, dev); if ( error ) { printk(KERN_WARNING "%s: Could not allocate receive interrupt\n", @@ -109,12 +122,13 @@ static int network_open(struct net_device *dev) goto fail; } - error = request_irq(NET_TX_IRQ, network_tx_int, 0, "net-tx", dev); + error = request_irq(NET_TX_IRQ_FOR_VIF(np->id), network_tx_int, 0, + txlabel, dev); if ( error ) { printk(KERN_WARNING "%s: Could not allocate transmit interrupt\n", dev->name); - free_irq(NET_RX_IRQ, dev); + free_irq(NET_RX_IRQ_FOR_VIF(np->id), dev); goto fail; } @@ -127,6 +141,8 @@ static int network_open(struct net_device *dev) return 0; fail: + if ( rxlabel ) kfree(rxlabel); + if ( txlabel ) kfree(txlabel); if ( np->net_ring->rx_ring ) kfree(np->net_ring->rx_ring); if ( np->net_ring->tx_ring ) kfree(np->net_ring->tx_ring); if ( np->rx_skb_ring ) kfree(np->rx_skb_ring); @@ -208,7 +224,7 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev) { unsigned int i; struct net_private *np = (struct net_private *)dev->priv; - + if ( np->tx_full ) { printk(KERN_WARNING "%s: full queue wasn't stopped!\n", dev->name); @@ -275,7 +291,9 @@ static void network_rx_int(int irq, void *dev_id, struct pt_regs *ptregs) /* Deal with hypervisor racing our resetting of rx_event. */ smp_mb(); - if ( np->net_ring->rx_cons != i ) goto again; + if ( np->net_ring->rx_cons != i ) { + goto again; + } } @@ -286,13 +304,13 @@ static void network_tx_int(int irq, void *dev_id, struct pt_regs *ptregs) } -static int network_close(struct net_device *dev) +int network_close(struct net_device *dev) { struct net_private *np = dev->priv; netif_stop_queue(dev); - free_irq(NET_RX_IRQ, dev); - free_irq(NET_TX_IRQ, dev); + free_irq(NET_RX_IRQ_FOR_VIF(np->id), dev); + free_irq(NET_TX_IRQ_FOR_VIF(np->id), dev); network_free_rx_buffers(dev); kfree(np->net_ring->rx_ring); kfree(np->net_ring->tx_ring); @@ -310,7 +328,7 @@ static struct net_device_stats *network_get_stats(struct net_device *dev) } -static int __init init_module(void) +int __init init_module(void) { int i, err; struct net_device *dev; @@ -336,6 +354,9 @@ static int __init init_module(void) dev->stop = network_close; dev->get_stats = network_get_stats; + memset(dev->dev_addr, 0, ETH_ALEN); + *(unsigned int *)(dev->dev_addr + 1) = i; + if ( (err = register_netdev(dev)) != 0 ) { kfree(dev); @@ -343,6 +364,7 @@ static int __init init_module(void) } np->dev = dev; + np->id = i; list_add(&np->list, &dev_list); } diff --git a/xenolinux-2.4.16-sparse/include/asm-xeno/irq.h b/xenolinux-2.4.16-sparse/include/asm-xeno/irq.h index f5f65b8b82..619353e696 100644 --- a/xenolinux-2.4.16-sparse/include/asm-xeno/irq.h +++ b/xenolinux-2.4.16-sparse/include/asm-xeno/irq.h @@ -16,6 +16,8 @@ #define NET_TX_IRQ _EVENT_NET_TX #define NET_RX_IRQ _EVENT_NET_RX +#define NET2_TX_IRQ _EVENT_NET2_TX +#define NET2_RX_IRQ _EVENT_NET2_RX #define TIMER_IRQ _EVENT_TIMER #define NR_IRQS (sizeof(HYPERVISOR_shared_info->events) * 8) |