PERFORCE change 123756 for review
Matus Harvan
mharvan at FreeBSD.org
Thu Jul 19 23:27:57 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=123756
Change 123756 by mharvan at 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
};
More information about the p4-projects
mailing list