Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 19 Jul 2007 23:27:56 GMT
From:      Matus Harvan <mharvan@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 123756 for review
Message-ID:  <200707192327.l6JNRuia062812@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=123756

Change 123756 by mharvan@mharvan_twoflower on 2007/07/19 23:27:02

	fragmentation support in the common code

Affected files ...

.. //depot/projects/soc2007/mharvan-mtund/mtund.src/Makefile#6 edit
.. //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin_icmp.c#2 edit
.. //depot/projects/soc2007/mharvan-mtund/mtund.src/tunneld.c#9 edit
.. //depot/projects/soc2007/mharvan-mtund/mtund.src/tunneld.h#4 edit

Differences ...

==== //depot/projects/soc2007/mharvan-mtund/mtund.src/Makefile#6 (text+ko) ====

@@ -1,9 +1,10 @@
-LIBS+= -levent
-LIBS+=-L/usr/local/lib
 # Linux needs -ldl
-#LIBS+= -ldl -levent
+#LIBS+= -ldl
+
+LIBS+=-levent
 
-CFLAGS=-Wall -rdynamic
+LIBS=-L/usr/local/lib -levent
+CFLAGS+=-Wall -rdynamic
 CFLAGS+=-g
 CFLAGS+=-I/usr/local/include
 
@@ -11,7 +12,6 @@
 
 tunneld: tunneld.h tunneld.c tun_dev.c
 	gcc $(CFLAGS) $(LIBS) -o tunneld tunneld.c tun_dev.c
-# -ldl
 
 plugin_tcp.so: tunneld.h plugin.h plugin_tcp.c
 	gcc $(CFLAGS) -shared  -o plugin_tcp.so plugin_tcp.c

==== //depot/projects/soc2007/mharvan-mtund/mtund.src/plugin_icmp.c#2 (text+ko) ====

@@ -182,6 +182,14 @@
 	} else {
 	    data->state = PLUGIN_STATE_CONNECTED;
 	}
+	
+	if (data->server) {
+	#ifdef __FreeBSD__
+	    //system("sysctl net.ipv4.icmp_echo_ignore_all=0");
+	#else
+	    system("sysctl net.ipv4.icmp_echo_ignore_all=0");
+	#endif
+	}
 	return 0;
     } else {
 	return -1;
@@ -278,8 +286,9 @@
 /* 	} else { */
 /* 	    icmp->type = ICMP_ECHO; */
 /* 	} */
-	icmp->type = 123;
-	    
+	//icmp->type = ICMP_ECHO;
+	icmp->type = 123;	
+    
 	icmp->code = 0;
 	icmp->id = ID;
 	icmp->seq = 0;

==== //depot/projects/soc2007/mharvan-mtund/mtund.src/tunneld.c#9 (text+ko) ====

@@ -48,8 +48,15 @@
 struct event tun_ev;
 
 struct event timer_ev;
+
+/* sequence number for the echo request */
 uint echo_seq = 0;
 
+/* fragment id for the next packet to be fragmented */
+uint frag_id = 0; // TODO: randomize
+frag_llist_t *frag_list;
+
+/* server host */
 char *host;
 char *port = "12345";
     
@@ -216,6 +223,7 @@
 void timer_ev_handler(int fd, short ev_type, void *arg)
 {
     struct timeval tv;
+    frag_llist_t *p, *q;
     plugint *pl = current_pl;
 
     fprintf(stderr, "timer fired\n");
@@ -228,6 +236,18 @@
 	}
     }
 
+    /* fragment reassembly timeout */
+    // TODO: fragment reassembly timeout
+    for (p=frag_list; p;) {
+	q = p->next;
+	if (tv.tv_sec - p->tv_sec > FRAG_TIMEOUT) {
+	    free(p->bitmap);
+	    free(p->buf);
+	    free(p);
+	}
+	p = q;
+    }
+    
     /* register a timer event */
     tv.tv_sec=1;
     tv.tv_usec=0;
@@ -241,6 +261,12 @@
 void process_data_from_plugin(plugint *pl, char *data, int len)
 {
     u_int8_t dispatch = *data;
+    frag_hdr_t *frag_hdr = NULL;
+    frag_llist_t *p, *q, **pp;
+    struct timeval tv;
+    int i;
+    int dgram_reassembled;
+
     switch (dispatch) {
     case DISPATCH_DATA:
 	if (len > 0) {
@@ -248,6 +274,120 @@
 	}
 	tun_send(data+1, len-1);
 	break;
+    case DISPATCH_FRAG:
+	if (len <= sizeof(frag_hdr)) {
+	    report_plugin_error(pl, PLUGIN_ERROR_RECEIVE);
+	    return;
+	}
+
+	frag_hdr = (frag_hdr_t*) data;
+	data += sizeof(frag_hdr_t);
+	len -= sizeof(frag_hdr_t);
+
+	/* debugging output */
+	fprintf(stderr, "got a frag header: id %d, size %d, off %d, len %d\n",
+		frag_hdr->id, frag_hdr->size, frag_hdr->offset, len);
+
+	/* search frag info in list */
+	pp = &frag_list;
+	for(p = frag_list; p; p = p->next) {
+	    if (p->id == frag_hdr->id &&
+		p->size == frag_hdr->size) {
+		break;
+	    }
+	    pp = &p;
+	}
+	/* found in list */
+	if (p) {
+	    fprintf(stderr, "found frag info in list\n");
+	    /* fragment info not found in list, start a new reassembly */
+	} else {
+	    fprintf(stderr, "frag info NOT found in list\n");
+	    /* allocate memory */
+	    p = malloc(sizeof(frag_llist_t));
+	    if (!p) {
+		fprintf(stderr, "process_data_from_plugin - "
+			"fragment reassembly: out of memory\n");
+		return;
+	    }
+	    memset(p, 0, sizeof(*p));
+	    p->buf = malloc(frag_hdr->size);
+	    if (!p->buf) {
+		free(p);
+		fprintf(stderr, "process_data_from_plugin - "
+			"fragment reassembly: out of memory\n");
+		return;
+	    }
+	    p->bitmap = malloc(frag_hdr->size/8 + 1);
+	    if (!p->bitmap) {
+		free(p->buf);
+		free(p);
+		fprintf(stderr, "process_data_from_plugin - "
+			"fragment reassembly: out of memory\n");
+		return;
+	    }
+	    memset(p->bitmap, 0, sizeof(*(p->bitmap)));
+	    
+	    /* collect information about the fragments */
+	    // TODO: error checking
+	    (void) gettimeofday(&tv, NULL);
+	    p->next = frag_list;
+	    frag_list = p;
+	    p->id = frag_hdr->id;
+	    p->size = frag_hdr->size;
+	    memcpy(&p->tv_sec, &tv.tv_sec, sizeof(tv.tv_sec));
+	}
+	
+	if (frag_hdr->offset + len <= p->size) {
+	    /* copy the data */
+	    memcpy(p->buf + frag_hdr->offset, data, len);
+	    /* update the bitmap */
+	    // TODO: we ignore overlaps, but that should be caught
+	    //       by the upper layer checksum
+	    for(i = frag_hdr->offset; i<frag_hdr->offset+len; i++) {
+		p->bitmap[i/8] |= (0x1 << (i%8));
+	    }
+	} else {
+	    fprintf(stderr, "fragment outside of packet payload\n");
+	}
+	
+	/* check if the complete packet has been reassembled */
+	dgram_reassembled = 1;
+	/* examine the bitmap */
+	for(i=0; i < p->size/8 && dgram_reassembled; i++) {
+	    if (p->bitmap[i] != 0xff) {
+		dgram_reassembled = 0;
+/* 		printf("dgram_reassembled = 0 (bitmap[%d]: 0x%x)\n", */
+/* 		       i, p->bitmap[i]); */
+	    }
+	}
+	for(i=0; i < p->size%8 && dgram_reassembled; i++) {
+	    if (! (p->bitmap[p->size/8] & (1 << i))) {
+		dgram_reassembled=0;
+/* 		printf("dgram_reassembled = 0 (bitmap<<%d)\n", i); */
+/* 		printf("bitmap[%d]: 0x%x)\n", */
+/* 		       p->size/8, p->bitmap[p->size/8]); */
+	    }
+	}
+/* 	printf("bitmap: 0x"); */
+/* 	for(i=0; i < p->size/8 + 1; i++) { */
+/* 	    printf("%x",p->bitmap[i]); */
+/* 	} */
+/* 	printf("\n"); */
+	/* packet completely reassembled */
+	if (dgram_reassembled) {
+	    fprintf(stderr, "frag reassembly: packet complete\n");
+	    current_pl = pl;
+	    tun_send(p->buf, p->size);
+	    
+	    /* remove fragment info from linked list */
+	    q = p->next;
+	    free(p->buf);
+	    free(p->bitmap);
+	    free(p);
+	    *pp = q;
+	}
+	break;
     case DISPATCH_ECHO_REQUEST:
 	*data = (u_int8_t) DISPATCH_ECHO_REPLY;
 	pl->send(pl, data, len);
@@ -270,13 +410,17 @@
  */
 void process_data_from_tun(char *data, int len)
 {
-    int n;
+    int n = 0;
     char ldata[MTU+1];
+    char *ldatap = ldata;
+    frag_hdr_t frag_hdr;
+    int mtu = 100; // TODO: add mtu to plugint
 
     if (current_pl == NULL) {
 	fprintf(stderr, "no plugin connected yet, discarding tun data\n");
 	report_plugin_error(NULL, PLUGIN_ERROR_BOOTSTRAP);
     } else {
+#ifdef NO_FRAG
 	*ldata = DISPATCH_DATA;
 	memcpy(ldata+1, data, min(sizeof(ldata)-1, len));
 	n = current_pl->send(current_pl, ldata, min(sizeof(ldata), len+1));
@@ -285,6 +429,45 @@
 	    fprintf(stderr, "process_data_from_tun: plugind sent less "
 		    "bytes (%d) than requested (%d)\n", n, len);
 	}
+#else /* NO_FRAG */
+	    // mtu = current_pl->mtu;
+
+	    /* prepare the frag header */
+	    frag_hdr.dispatch = DISPATCH_FRAG;
+	    frag_hdr.id = frag_id;
+	    frag_id++;
+	    frag_hdr.size = len;
+	    frag_hdr.offset = 0;
+		
+	    /* copy the payload */
+	    memcpy(ldatap + sizeof(frag_hdr), data,
+		   min(sizeof(ldata) - sizeof(frag_hdr), len));
+	    len += sizeof(frag_hdr);
+	    
+	    while(len > sizeof(frag_hdr)) {
+		printf("process_data_from_tun: sending frag "
+		       "offset %d, send_len %d, len %d\n",
+		       frag_hdr.offset, min(mtu, len), len);
+		/* prepend the frag dispatch and header before the payload */
+		memcpy(ldatap, &frag_hdr, sizeof(frag_hdr));
+		
+		/* send it */
+		//TODO: change the logic here, we should not fragment based
+		//      on the return value from send()
+		n = min(mtu, len);
+		(void) current_pl->send(current_pl, ldatap, min(mtu, len));
+		n -= sizeof(frag_hdr);
+		if (n <= 0) {
+		    fprintf(stderr, "process_data_from_tun: failed to send"
+			    "data (%d)\n", n);
+		    report_plugin_error(current_pl, PLUGIN_ERROR_SEND);
+		    return;
+		}
+		ldatap += n;
+		frag_hdr.offset += n;
+		len -= n;
+	    }
+#endif /* NO_FRAG */
     }
 }
 
@@ -294,6 +477,7 @@
 	return;
     }
 
+    /* server */
     if (server) {
 	if (pl) {
 	    /* reinitialize the broken plugin */
@@ -302,6 +486,7 @@
 	    //pl->deinitialize(pl);
 	    //(void) pl->initialize(pl, server, host, 1234);
 	}
+    /* client */
     } else {
 	if (pl) {
 	    /* deinitialize the broken plugin */

==== //depot/projects/soc2007/mharvan-mtund/mtund.src/tunneld.h#4 (text+ko) ====

@@ -1,9 +1,32 @@
 #ifndef _TUNNELD_H
 #define _TUNNELD_H
 
-#define PACKETLEN 1400    /* encapsulated data size */
+#include <sys/types.h>
+
+#define PACKETLEN 1400   /* encapsulated data size */
 #define SOCKET_TIMEOUT 5 /* timeout for socket operations */
+#define FRAG_TIMEOUT 60  /* encapsulated data size */
+
+/* fragment header */
+typedef struct _frag_hdr_t {
+    u_int8_t dispatch;
+    uint id;   /* Id of the whole packet, same in each fragment */
+    uint size; /* length of the whole packet, same in each fragment */
+    uint offset;   /* fragment offset (in bytes) from the beginning
+		     * of the packet */
+} frag_hdr_t;
 
+typedef struct _frag_llist_t {
+    uint id;   /* Id of the whole packet, same in each fragment */
+    uint size; /* length of the whole packet, same in each fragment */
+    time_t tv_sec;   /* seconds after epoch when reassembly
+		      * of this packet started */
+    u_int8_t *bitmap;/* bitmap representing already 
+		      * received parts of the packet */
+    char *buf;       /* buffer into which the fragment is reassembled */
+    struct _frag_llist_t *next;
+} frag_llist_t;
+
 /*
  * code for setting timeout on a socket:
  * struct timeval tv;
@@ -36,6 +59,7 @@
 enum {
     DISPATCH_ECHO_REQUEST = 1,
     DISPATCH_ECHO_REPLY   = 2,
+    DISPATCH_FRAG         = 3,
     DISPATCH_DATA         = 0x42
 };
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200707192327.l6JNRuia062812>