aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.rootkeys1
-rw-r--r--BitKeeper/etc/logging_ok1
-rw-r--r--xen-2.4.16/Makefile1
-rw-r--r--xen-2.4.16/common/domain.c5
-rw-r--r--xen-2.4.16/common/kernel.c1
-rw-r--r--xen-2.4.16/common/network.c268
-rw-r--r--xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h46
-rw-r--r--xen-2.4.16/include/hypervisor-ifs/network.h15
-rw-r--r--xen-2.4.16/include/xeno/in.h190
-rw-r--r--xen-2.4.16/include/xeno/skbuff.h12
-rw-r--r--xen-2.4.16/include/xeno/vif.h13
-rw-r--r--xen-2.4.16/net/dev.c128
-rw-r--r--xen-2.4.16/net/skbuff.c2
-rw-r--r--xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/vfr.c77
-rw-r--r--xenolinux-2.4.16-sparse/arch/xeno/drivers/network/network.c42
-rw-r--r--xenolinux-2.4.16-sparse/include/asm-xeno/irq.h2
16 files changed, 663 insertions, 141 deletions
diff --git a/.rootkeys b/.rootkeys
index 6be5ce965f..05dda51e57 100644
--- a/.rootkeys
+++ b/.rootkeys
@@ -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, &current->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)