summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2012-01-28 23:28:48 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2012-01-28 23:28:48 +0100
commit3f7ad298fd5dd80c0dc017fdd77be23e7861e547 (patch)
treebed3a33609f64e6977675de2ebb73aad9790228e
parent3496138ca428a7b2b69fe08e69fb544006a9a2cc (diff)
parenta12a10679017d89194c0dd873f44804b64f71102 (diff)
Merge branch 'master' into master-slab
-rw-r--r--Makefile.am2
-rw-r--r--i386/intel/pmap.c2
-rw-r--r--kern/sched_prim.c2
-rw-r--r--kern/strings.c19
-rw-r--r--xen/net.c74
5 files changed, 96 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am
index 0c98bfd..319b7e8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -156,7 +156,7 @@ noinst_PROGRAMS += \
gnumach.o
# This is the list of routines we decide is OK to steal from the C library.
-clib_routines := memcmp memcpy memmove memset \
+clib_routines := memcmp memcpy memmove \
strchr strstr strsep strtok \
htonl htons ntohl ntohs \
udivdi3 __udivdi3 \
diff --git a/i386/intel/pmap.c b/i386/intel/pmap.c
index 94d2e9c..d6e18e5 100644
--- a/i386/intel/pmap.c
+++ b/i386/intel/pmap.c
@@ -1587,7 +1587,7 @@ void pmap_page_protect(phys, prot)
do {
#ifdef MACH_XEN
if (!hyp_mmu_update_pte(kv_to_ma(pte), *pte & ~INTEL_PTE_WRITE))
- panic("%s:%d could not enable write on pte %p\n",__FILE__,__LINE__,pte);
+ panic("%s:%d could not disable write on pte %p\n",__FILE__,__LINE__,pte);
#else /* MACH_XEN */
*pte &= ~INTEL_PTE_WRITE;
#endif /* MACH_XEN */
diff --git a/kern/sched_prim.c b/kern/sched_prim.c
index ff942ae..9d4e8af 100644
--- a/kern/sched_prim.c
+++ b/kern/sched_prim.c
@@ -139,7 +139,7 @@ void thread_check(thread_t, run_queue_t);
* The wait event hash table declarations are as follows:
*/
-#define NUMQUEUES 59
+#define NUMQUEUES 1031
queue_head_t wait_queue[NUMQUEUES];
decl_simple_lock_data(, wait_lock[NUMQUEUES])
diff --git a/kern/strings.c b/kern/strings.c
index 80e410e..3676f98 100644
--- a/kern/strings.c
+++ b/kern/strings.c
@@ -172,3 +172,22 @@ strlen(
return string - 1 - ret;
}
+
+/*
+ * Abstract:
+ * memset writes value "c" in the "n" bytes starting at address "s".
+ * The return value is a pointer to the "s" string.
+ */
+
+void *
+memset(
+ void *_s, int c, size_t n)
+{
+ char *s = _s;
+ int i;
+
+ for (i = 0; i < n ; i++)
+ s[i] = c;
+
+ return _s;
+}
diff --git a/xen/net.c b/xen/net.c
index 8373cec..10e4bbe 100644
--- a/xen/net.c
+++ b/xen/net.c
@@ -118,6 +118,61 @@ static void enqueue_rx_buf(struct net_data *nd, int number) {
req->gref = nd->rx_buf_gnt[number] = gref;
}
+static int recompute_checksum(void *data, int len) {
+ unsigned16_t *header16 = data;
+ unsigned8_t *header8 = data;
+ unsigned length, i;
+ unsigned32_t checksum = 0;
+
+ /* IPv4 header length */
+ length = (header8[0] & 0xf) * 4;
+ if (length < 20)
+ /* Too small for an IP header16 */
+ return -1;
+ if (length > len)
+ /* Does not fit in the ethernet frame */
+ return -1;
+
+ /* Compute IP header checksum */
+ header16[5] = 0;
+ for (i = 0; i < length/2; i++)
+ checksum += ntohs(header16[i]);
+
+ while (checksum >> 16)
+ checksum = (checksum & 0xffff) + (checksum >> 16);
+
+ header16[5] = htons(~checksum);
+
+ if (header8[9] == 6) {
+ /* Need to fix TCP checksum as well */
+ unsigned16_t *tcp_header16 = header16 + length/2;
+ unsigned8_t *tcp_header8 = header8 + length;
+ unsigned tcp_length = ntohs(header16[1]) - length;
+
+ /* Pseudo IP header */
+ checksum = ntohs(header16[6]) + ntohs(header16[7]) +
+ ntohs(header16[8]) + ntohs(header16[9]) +
+ header8[9] + tcp_length;
+
+ tcp_header16[8] = 0;
+ for (i = 0; i < tcp_length / 2; i++)
+ checksum += ntohs(tcp_header16[i]);
+ if (tcp_length & 1)
+ checksum += tcp_header8[tcp_length-1] << 8;
+
+ while (checksum >> 16)
+ checksum = (checksum & 0xffff) + (checksum >> 16);
+
+ tcp_header16[8] = htons(~checksum);
+ } else if (header8[9] == 17) {
+ /* Drop any bogus checksum */
+ unsigned16_t *udp_header16 = header16 + length/2;
+ udp_header16[3] = 0;
+ }
+
+ return 0;
+}
+
static void hyp_net_intr(int unit) {
ipc_kmsg_t kmsg;
struct ether_header *eh;
@@ -173,6 +228,25 @@ static void hyp_net_intr(int unit) {
data = nd->rx_buf[number] + rx_rsp->offset;
len = rx_rsp->status;
+ if (rx_rsp->flags & NETRXF_csum_blank) {
+ struct ether_header *ether = data;
+
+ if (!(rx_rsp->flags & NETRXF_data_validated)) {
+ printf("packet with no checksum and not validated, dropping it\n");
+ goto drop_kmsg;
+ }
+
+ /* TODO: rather tell pfinet to ignore checksums */
+
+ if (ntohs(ether->ether_type) != 0x0800) {
+ printf("packet with no checksum and not IPv4, dropping it\n");
+ goto drop_kmsg;
+ }
+
+ if (recompute_checksum(data + sizeof(*ether), len - sizeof(*ether)))
+ goto drop_kmsg;
+ }
+
eh = (void*) (net_kmsg(kmsg)->header);
ph = (void*) (net_kmsg(kmsg)->packet);
memcpy(eh, data, sizeof (struct ether_header));