From 1b03e69a6e6fb26a0bc79443a3d6e92aeee1cebe Mon Sep 17 00:00:00 2001 From: Michael Blizek Date: Tue, 25 May 2010 07:25:44 +0200 Subject: [PATCH] new retransmit part 3 --- Makefile | 11 +-- net/cor/common.c | 72 +++++++++++++++++- net/cor/cor.h | 115 ++++++++++++++++------------ net/cor/kpacket_gen.c | 159 +++++++++++++++++++++++++++++++-------- net/cor/kpacket_parse.c | 94 ++++++++++++++--------- net/cor/rcv.c | 23 ++++-- net/cor/snd.c | 195 ++++++++++++++++++++++++++---------------------- 7 files changed, 450 insertions(+), 219 deletions(-) diff --git a/Makefile b/Makefile index 0d46615bffe..802fe45885d 100644 --- a/Makefile +++ b/Makefile @@ -155,11 +155,12 @@ export srctree objtree VPATH # then ARCH is assigned, getting whatever value it gets normally, and # SUBARCH is subsequently ignored. -SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ - -e s/arm.*/arm/ -e s/sa110/arm/ \ - -e s/s390x/s390/ -e s/parisc64/parisc/ \ - -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ - -e s/sh[234].*/sh/ ) +#SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ +# -e s/arm.*/arm/ -e s/sa110/arm/ \ +# -e s/s390x/s390/ -e s/parisc64/parisc/ \ +# -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ +# -e s/sh[234].*/sh/ ) +SUBARCH := $(shell echo "i386") # Cross compiling and selecting different set of gcc/bin-utils # --------------------------------------------------------------------------- diff --git a/net/cor/common.c b/net/cor/common.c index 1f5c22396a6..3f8feb22121 100644 --- a/net/cor/common.c +++ b/net/cor/common.c @@ -41,6 +41,76 @@ struct htable connid_table; struct kmem_cache *bindnode_slab; struct kmem_cache *connlistener_slab; +/* see cor.h/KP_ACK_CONN */ +static const __u32 window_sizes[] = {0, + 64, 68, 73, 77, 82, 88, 93, 99, 106, 113, 120, + 128, 136, 145, 155, 165, 175, 187, 199, 212, 226, 240, + 256, 273, 290, 309, 329, 351, 374, 398, 424, 451, 481, + 512, 545, 581, 619, 659, 702, 747, 796, 848, 903, 961, + 1024, 1091, 1162, 1237, 1318, 1403, 1495, 1592, 1695, 1805, + 1923, + 2048, 2181, 2323, 2474, 2635, 2806, 2989, 3183, 3390, 3611, + 3846, + 4096, 4362, 4646, 4948, 5270, 5613, 5978, 6367, 6781, 7222, + 7692, + 8192, 8725, 9292, 9897, 10540, 11226, 11956, 12734, 13562, + 14444, 15383, + 16384, 17450, 18585, 19793, 21081, 22452, 23912, 25467, 27124, + 28888, 30767, + 32768, 34899, 37169, 39587, 42161, 44904, 47824, 50935, 54248, + 57776, 61534, + 65536, 69799, 74338, 79173, 84323, 89807, 95648, 101870, 108495, + 115552, 123068, + 131072, 139597, 148677, 158347, 168646, 179615, 191297, 203739, + 216991, 231104, 246135, + 262144, 279194, 297353, 316693, 337291, 359229, 382594, 407478, + 433981, 462208, 492270, + 524288, 558388, 594706, 633387, 674583, 718459, 765188, 814957, + 867962, 924415, 984540, + 1048576, 1116777, 1189413, 1266774, 1349166, 1436917, 1530376, + 1629913, 1735924, 1848831, 1969081, + 2097152, 2233553, 2378826, 2533547, 2698332, 2873834, 3060752, + 3259826, 3471849, 3697662, 3938162, + 4194304, 4467106, 4757652, 5067094, 5396664, 5747669, 6121503, + 6519652, 6943698, 7395323, 7876323, + 8388608, 8934212, 9515303, 10134189, 10793327, 11495337, + 12243006, 13039305, 13887396, 14790647, + 15752647, + 16777216, 17868424, 19030606, 20268378, 21586655, 22990674, + 24486013, 26078610, 27774791, 29581294, + 31505293, + 33554432, 35736849, 38061212, 40536755, 43173310, 45981349, + 48972026, 52157220, 55549582, 59162588, + 63010587, + 67108864, 71473698, 76122425, 81073510, 86346620, 91962698, + 97944052, 104314440, 111099165, 118325175, + 126021174, + 134217728, 142947395, 152244850, 162147020, 172693239, + 183925396, 195888104, 208628880, 222198329, + 236650351, 252042347, + 268435456, 285894791, 304489699, 324294041, 345386479, + 367850791, 391776208, 417257759, 444396658, + 473300701, 504084694, + 536870912, 571789581}; + +__u8 enc_window(__u32 window_bytes) +{ + int i; + BUG_ON(window_sizes[255] != 571789581); + for (i=1;i<256;i++) { + if (window_sizes[i] > window_bytes) + break; + } + + return (__u8)(i-1); /* round down */ +} + +__u32 dec_window(__u8 window) +{ + BUG_ON(window_sizes[255] != 571789581); + return window_sizes[window]; +} + static inline int hdr_size(void) { return ((sizeof(struct cell_hdr) + sizeof(void *) - 1) / sizeof(void *) @@ -140,7 +210,7 @@ int htable_delete(struct htable *ht, __u32 key, element = get_element_nounlock(ht, key, searcheditem); BUG_ON(0 == element); - if (unlikely(0 == *element)) { + if (unlikely(*element == 0)) { /* key not in table */ rc = 1; goto out; diff --git a/net/cor/cor.h b/net/cor/cor.h index 3a03cdccd5f..921db9cf55e 100644 --- a/net/cor/cor.h +++ b/net/cor/cor.h @@ -82,45 +82,32 @@ struct cor_sockaddr { #define KP_PING 2 #define KP_PONG 3 -/* KP_ACK[1] sent_conn_id[4] seqno[4] - * - * sent_conn_id means that this is *not* the conn_id we use if we sent something - * through this conn, but the conn_id that the neighbor used to send us the - * packet - */ +/* KP_ACK[1] seqno[4] */ #define KP_ACK 4 -/* - * KP_SPEED[1] conn_id[4] speedinfo[2] +/* + * KP_ACK_CONN[1] conn_id[4] seqno[4] window[1] + * KP_ACK_CONN_OOO[1] conn_id[4] seqno[4] window[1] seqno_ooo[4] length[4] * - * speedinfo[2] = - * buffer_state_value = speedinfo % 181 - * speed_value = speedinfo / 181 - * - * buffer_state = 1024 * pow(2, buffer_state_value/3.0) - * speed = 1024 * pow(2, speed_value/12.0) - * see the .0 ... - * - * This has to be done either with floating points (which is no so nice) or - * you can calculate: - * buffer_state = pow(2, value/3) * - * 1024 * pow(pow(2, 1.0/3), buffer_state_value%3) - * where 1024 * pow(pow(2, 1.0/4), value%3) can be just a table lookup - * (the "1024" should be part of the value in the table, because it increases - * the accuracy) - * - * you can do the same with the speed - * + * conn_id is the conn_id we use if we sent something through this conn and + * *not* the conn_id that the neighbor used to send us the data + * + * seqno = the seqno which is expected in the next non-out-of-order packet + * seqno_ooo, length = in case + * + * window = amount of data which can be sent without receiving the next ack + * packets with lower seqno do not overwrite the last window size + * note: the other side may also reduce the window size + * decode: + * 0 = 0 + * 1...255 = 64*2^((value-1)/11) end result is rounded down to an integer * - * Some values have special meanings: - * if speedinfo is the highest possible value(65535), it means both values - * are inifinite - * if buffer_state_value if > 91, you have to subtract 90 and make the - * resulting buffer_state negative */ -#define KP_SPEED 5 +#define KP_ACK_CONN 5 +#define KP_ACK_CONN_OOO 6 -/* NOTE on connection ids: +/* + * NOTE on connection ids: * connection ids we send are used for the receive channel * connection ids we receive are used for the send channel */ @@ -129,7 +116,7 @@ struct cor_sockaddr { * incoming connection * KP_CONNECT[1] conn_id[4] */ -#define KP_CONNECT 6 +#define KP_CONNECT 7 /* * incoming connection successful, @@ -137,17 +124,33 @@ struct cor_sockaddr { * the second conn_id is generated by us and used for the other direction * KP_CONNECT_SUCCESS[1] conn_id[4] conn_id[4] */ -#define KP_CONNECT_SUCCESS 7 +#define KP_CONNECT_SUCCESS 8 /* KP_CONN_DATA[1] conn_id[4] seqno[4] length[2] data[length] */ -#define KP_CONN_DATA 8 +#define KP_CONN_DATA 9 + +/* KP_PING_CONN[1] conn_id[4] */ +#define KP_PING_CONN 10 + +/* + * KP_PONG_CONN[1] conn_id[4] + * conn_id is the conn_id we use if we sent something through this conn and + * *not* the conn_id that the neighbor used to send us the data + */ +#define KP_PONG_CONN 11 /* * { KP_RESET_CONN[1] conn_id[4] } * We send this, if there is an established connection we want to close. */ -#define KP_RESET_CONN 9 +#define KP_RESET_CONN 12 + +/* + * KP_CONNID_UNKNOWN[1] sent_conn_id[4] + * We send this, if we receive an invalid conn_id + */ +#define KP_CONNID_UNKNOWN 13 /* * Connection data which in interpreted when connection has no target yet @@ -495,11 +498,14 @@ struct conn{ struct neighbor *nb; /* list of all connections to this neighbor */ struct list_head nb_list; - /* protected by nb->retrans_lock */ + /* protected by nb->retrans_lock, sorted by seqno */ struct list_head retrans_list; __u32 conn_id; - __u32 seqno; + __u32 seqno_nextsend; + __u32 seqno_acked; + __u32 seqno_windowlimit; + __u32 kp_windowsetseqno; __u32 stall_timeout_ms; }out; @@ -533,6 +539,10 @@ struct skb_procstate{ /* common.c */ +extern __u8 enc_window(__u32 window_bytes); + +extern __u32 dec_window(__u8 window); + extern char *htable_get(struct htable *ht, __u32 key, void *searcheditem); extern int htable_delete(struct htable *ht, __u32 key, void *searcheditem, @@ -623,7 +633,14 @@ extern void send_reset_conn(struct control_msg_out *cm, struct neighbor *nb, __u32 conn_id); extern void send_ack(struct control_msg_out *cm, struct neighbor *nb, - __u32 conn_id, __u32 seqno); + __u32 seqno); + +extern void send_ack_conn(struct control_msg_out *cm, struct neighbor *nb, + __u32 conn_id, __u32 seqno, __u8 window); + +extern void send_ack_conn_ooo(struct control_msg_out *cm, struct neighbor *nb, + __u32 conn_id, __u32 seqno, __u8 window, __u32 seqno_ooo, + __u32 length); extern void send_connect_success(struct control_msg_out *cm, struct neighbor *nb, __u32 rcvd_conn_id, __u32 gen_conn_id); @@ -645,9 +662,9 @@ extern struct sk_buff *create_packet(struct neighbor *nb, int size, gfp_t alloc_flags, __u32 conn_id, __u32 seqno); extern void retransmit_conn_timerfunc(struct work_struct *work); - -extern void conn_ack_rcvd(struct neighbor *nb, __u32 conn_id, __u32 seqno, - __u32 length); + +extern void conn_ack_rcvd(__u32 kpacket_seqno, struct conn *rconn, __u32 seqno, + __u8 window, __u32 seqno_ooo, __u32 length); extern void flush_out(struct conn *rconn); @@ -703,10 +720,10 @@ static inline __u32 mss(struct neighbor *nb) static inline void put_u64(char *dst, __u64 value, int convbo) { char *p_value = (char *) &value; - + if (convbo) value = cpu_to_be64(value); - + dst[0] = p_value[0]; dst[1] = p_value[1]; dst[2] = p_value[2]; @@ -720,10 +737,10 @@ static inline void put_u64(char *dst, __u64 value, int convbo) static inline void put_u32(char *dst, __u32 value, int convbo) { char *p_value = (char *) &value; - + if (convbo) value = cpu_to_be32(value); - + dst[0] = p_value[0]; dst[1] = p_value[1]; dst[2] = p_value[2]; @@ -733,10 +750,10 @@ static inline void put_u32(char *dst, __u32 value, int convbo) static inline void put_u16(char *dst, __u16 value, int convbo) { char *p_value = (char *) &value; - + if (convbo) value = cpu_to_be16(value); - + dst[0] = p_value[0]; dst[1] = p_value[1]; } diff --git a/net/cor/kpacket_gen.c b/net/cor/kpacket_gen.c index fd515f1696e..ac857152827 100644 --- a/net/cor/kpacket_gen.c +++ b/net/cor/kpacket_gen.c @@ -25,10 +25,12 @@ /* not sent over the network - internal meaning only */ #define MSGTYPE_PONG 1 #define MSGTYPE_ACK 2 -#define MSGTYPE_CONNECT 3 -#define MSGTYPE_CONNECT_SUCCESS 4 -#define MSGTYPE_RESET_CONN 5 -#define MSGTYPE_CONNDATA 6 +#define MSGTYPE_ACK_CONN 3 +#define MSGTYPE_ACK_CONN_OOO 4 +#define MSGTYPE_CONNECT 5 +#define MSGTYPE_CONNECT_SUCCESS 6 +#define MSGTYPE_RESET_CONN 7 +#define MSGTYPE_CONNDATA 8 /* * lh must be first @@ -47,9 +49,22 @@ struct control_msg_out{ }pong; struct{ - __u32 conn_id; __u32 seqno; }ack; + + struct{ + __u32 conn_id; + __u32 seqno; + __u8 window; + }ack_conn; + + struct{ + __u32 conn_id; + __u32 seqno; + __u8 window; + __u32 seqno_ooo; + __u32 length; + }ack_conn_ooo; struct{ __u32 conn_id; @@ -123,7 +138,6 @@ static void free_control_retrans(struct kref *ref) free_control_msg(cm); } - kref_put(&(cr->nb->ref), neighbor_free); kmem_cache_free(controlretrans_slab, cr); } @@ -134,7 +148,7 @@ struct retransmit_matchparam { static __u32 rm_to_key(struct retransmit_matchparam *rm) { - return ((__u32) rm->nb) ^ rm->seqno; + return ((__u32)((long) rm->nb)) ^ rm->seqno; } static void set_retrans_timeout(struct control_retrans *cr, struct neighbor *nb) @@ -161,7 +175,7 @@ void retransmit_timerfunc(unsigned long arg) struct retransmit_matchparam rm; spin_lock_irqsave( &(nb->retrans_lock), iflags ); - + if (list_empty(&(nb->retrans_list))) { nb->retrans_timer_running = 0; nbput = 1; @@ -176,14 +190,15 @@ void retransmit_timerfunc(unsigned long arg) rm.seqno = cr->seqno; rm.nb = nb; - if (nbstate == NEIGHBOR_STATE_KILLED) { + list_del(&(cr->timeout_list)); + + if (unlikely(nbstate == NEIGHBOR_STATE_KILLED)) { spin_unlock_irqrestore( &(nb->retrans_lock), iflags ); htable_delete(&retransmits, rm_to_key(&rm), &rm, free_control_retrans); kref_put(&(cr->ref), free_control_retrans); continue; - } if (time_after(cr->timeout, jiffies)) { @@ -191,7 +206,7 @@ void retransmit_timerfunc(unsigned long arg) mod_timer(&(nb->retrans_timer), cr->timeout); break; } - + if (unlikely(htable_delete(&retransmits, rm_to_key(&rm), &rm, free_control_retrans))) BUG(); @@ -220,7 +235,7 @@ static void schedule_retransmit(struct control_retrans *cr, struct neighbor *nb) struct retransmit_matchparam rm; int first; - + rm.seqno = cr->seqno; rm.nb = nb; @@ -246,7 +261,7 @@ void kern_ack_rcvd(struct neighbor *nb, __u32 seqno) struct control_retrans *cr = 0; struct retransmit_matchparam rm; - + rm.seqno = seqno; rm.nb = nb; @@ -266,7 +281,7 @@ void kern_ack_rcvd(struct neighbor *nb, __u32 seqno) BUG_ON(cr->nb != nb); - list_add_tail(&(cr->timeout_list), &(nb->retrans_list)); + list_del(&(cr->timeout_list)); out: spin_unlock_irqrestore( &(nb->retrans_lock), iflags ); @@ -274,7 +289,10 @@ out: static void padding(struct sk_buff *skb, int length) { - char *dst = skb_put(skb, length); + char *dst; + if (length <= 0) + return; + dst = skb_put(skb, length); BUG_ON(0 == dst); memset(dst, KP_PADDING, length); } @@ -284,19 +302,62 @@ static int add_ack(struct sk_buff *skb, struct control_retrans *cr, { char *dst; - if (unlikely(spaceleft < 9)) + if (unlikely(spaceleft < 5)) return 0; - dst = skb_put(skb, 9); + dst = skb_put(skb, 5); BUG_ON(0 == dst); dst[0] = KP_ACK; - put_u32(dst + 1, cm->msg.ack.conn_id, 1); - put_u32(dst + 5, cm->msg.ack.seqno, 1); + put_u32(dst + 1, cm->msg.ack.seqno, 1); list_add_tail(&(cm->lh), &(cr->msgs)); - return 9; + return 5; +} + +static int add_ack_conn(struct sk_buff *skb, struct control_retrans *cr, + struct control_msg_out *cm, int spaceleft) +{ + char *dst; + + if (unlikely(spaceleft < 10)) + return 0; + + dst = skb_put(skb, 10); + BUG_ON(0 == dst); + + dst[0] = KP_ACK_CONN; + put_u32(dst + 1, cm->msg.ack_conn.conn_id, 1); + put_u32(dst + 5, cm->msg.ack_conn.seqno, 1); + dst[10] = cm->msg.ack_conn.window; + + list_add_tail(&(cm->lh), &(cr->msgs)); + + return 10; +} + +static int add_ack_conn_ooo(struct sk_buff *skb, struct control_retrans *cr, + struct control_msg_out *cm, int spaceleft) +{ + char *dst; + + if (unlikely(spaceleft < 18)) + return 0; + + dst = skb_put(skb, 18); + BUG_ON(0 == dst); + + dst[0] = KP_ACK_CONN_OOO; + put_u32(dst + 1, cm->msg.ack_conn_ooo.conn_id, 1); + put_u32(dst + 5, cm->msg.ack_conn_ooo.seqno, 1); + dst[10] = cm->msg.ack_conn_ooo.window; + put_u32(dst + 11, cm->msg.ack_conn_ooo.seqno_ooo, 1); + put_u32(dst + 15, cm->msg.ack_conn_ooo.length, 1); + + list_add_tail(&(cm->lh), &(cr->msgs)); + + return 18; } static int add_ping(struct sk_buff *skb, __u32 cookie, @@ -440,6 +501,10 @@ static int add_message(struct sk_buff *skb, struct control_retrans *cr, switch (cm->type) { case MSGTYPE_ACK: return add_ack(skb, cr, cm, spaceleft); + case MSGTYPE_ACK_CONN: + return add_ack_conn(skb, cr, cm, spaceleft); + case MSGTYPE_ACK_CONN_OOO: + return add_ack_conn_ooo(skb, cr, cm, spaceleft); case MSGTYPE_PONG: return add_pong(skb, cr, cm, spaceleft); case MSGTYPE_CONNECT: @@ -485,7 +550,7 @@ static void _send_messages(struct neighbor *nb, struct sk_buff *skb, nb->ucmlength -= cm->length; else nb->cmlength -= cm->length; - if (cm->type != MSGTYPE_ACK || cm->msg.ack.conn_id != 0) + if (cm->type != MSGTYPE_ACK) retrans = 1; mutex_unlock(&(nb->cmsg_lock)); rc = add_message(skb, cr, cm, spaceleft - length); @@ -509,11 +574,15 @@ static void _send_messages(struct neighbor *nb, struct sk_buff *skb, } mutex_unlock(&(nb->cmsg_lock)); + + if (unlikely(length > spaceleft)) + printk(KERN_ERR "error cor/kpacket_gen: length > spaceleft!?"); padding(skb, spaceleft - length); + if (retransmit) schedule_retransmit(cr, nb); - + dev_queue_xmit(skb); } @@ -554,7 +623,7 @@ static void send_messages(struct neighbor *nb, int allmsgs) struct control_retrans *cr; int size = targetmss; __u32 length; - + if (pingok && nb->noping_cnt > 3) ping = 1; if (pingok && time_before_eq(nb->last_ping_time + @@ -572,7 +641,7 @@ static void send_messages(struct neighbor *nb, int allmsgs) if (unlikely(skb == 0)) { printk(KERN_ERR "cor: send_messages: cannot allocate " "skb (out of memory?)"); - goto out; + return; } cr = kmem_cache_alloc(controlretrans_slab, GFP_KERNEL); @@ -580,7 +649,7 @@ static void send_messages(struct neighbor *nb, int allmsgs) kfree_skb(skb); printk(KERN_ERR "cor: send_messages: cannot allocate " "control_retrans (out of memory?)"); - goto out; + return; } memset(cr, 0, sizeof(struct control_retrans)); kref_init(&(cr->ref)); @@ -601,10 +670,11 @@ static void send_messages(struct neighbor *nb, int allmsgs) mutex_lock(&(nb->cmsg_lock)); } - mutex_unlock(&(nb->cmsg_lock)); -out: BUG_ON(nb->cmlength < 0); + BUG_ON(nb->ucmlength < 0); + + mutex_unlock(&(nb->cmsg_lock)); } static void controlmsg_timerfunc(struct work_struct *work) @@ -666,8 +736,7 @@ static void add_control_msg(struct control_msg_out *msg, struct neighbor *nb) mutex_lock(&(nb->cmsg_lock)); msg->nb = nb; - if (unlikely(msg->type == MSGTYPE_PONG || (msg->type == MSGTYPE_ACK && - msg->msg.ack.conn_id == 0))) { + if (unlikely(msg->type == MSGTYPE_PONG || msg->type == MSGTYPE_ACK)) { nb->ucmlength += msg->length; list_add_tail(&(msg->lh), &(nb->ucontrol_msgs_out)); } else { @@ -700,13 +769,37 @@ void send_reset_conn(struct control_msg_out *cm, struct neighbor *nb, add_control_msg(cm, nb); } -void send_ack(struct control_msg_out *cm, struct neighbor *nb, __u32 conn_id, - __u32 seqno) +void send_ack(struct control_msg_out *cm, struct neighbor *nb, __u32 seqno) { cm->type = MSGTYPE_ACK; - cm->msg.ack.conn_id = conn_id; cm->msg.ack.seqno = seqno; - cm->length = 9; + cm->length = 5; + add_control_msg(cm, nb); +} + +void send_ack_conn(struct control_msg_out *cm, struct neighbor *nb, + __u32 conn_id, __u32 seqno, __u8 window) +{ + cm->type = MSGTYPE_ACK; + cm->msg.ack_conn.conn_id = conn_id; + cm->msg.ack_conn.seqno = seqno; + cm->msg.ack_conn.window = window; + + cm->length = 10; + add_control_msg(cm, nb); +} + +void send_ack_conn_ooo(struct control_msg_out *cm, struct neighbor *nb, + __u32 conn_id, __u32 seqno, __u8 window, __u32 seqno_ooo, + __u32 length) +{ + cm->type = MSGTYPE_ACK; + cm->msg.ack_conn_ooo.conn_id = conn_id; + cm->msg.ack_conn_ooo.seqno = seqno; + cm->msg.ack_conn_ooo.window = window; + cm->msg.ack_conn_ooo.seqno_ooo = seqno_ooo; + cm->msg.ack_conn_ooo.length = length; + cm->length = 18; add_control_msg(cm, nb); } diff --git a/net/cor/kpacket_parse.c b/net/cor/kpacket_parse.c index e07c37c90be..caf627fa3db 100644 --- a/net/cor/kpacket_parse.c +++ b/net/cor/kpacket_parse.c @@ -79,24 +79,47 @@ static __u16 pull_u16(struct sk_buff *skb, int convbo) return ret; } -/* not used, avoid compiler warning - * static __u8 pull_u8(struct sk_buff *skb) +static __u8 pull_u8(struct sk_buff *skb) { char *ptr = cor_pull_skb(skb, 1); BUG_ON(0 == ptr); return *ptr; -} */ +} -static void discard_speed(struct neighbor *nb, struct sk_buff *skb) +static void discard_ack_conn(struct neighbor *nb, struct sk_buff *skb) { - pull_u32(skb, 1); /* speed */ + pull_u32(skb, 1); /* seqno */ + pull_u8(skb); /* window */ } #warning todo -static void parse_speed(struct neighbor *nb, struct sk_buff *skb, - struct conn *rconn) +static void parse_ack_conn(struct neighbor *nb, struct sk_buff *skb, + __u32 kpacket_seqno, struct conn *rconn) { - __u16 speed = pull_u32(skb, 1); + __u32 seqno = pull_u32(skb, 1); + __u8 window = pull_u8(skb); + + conn_ack_rcvd(kpacket_seqno, rconn->reversedir, seqno, window, 0, 0); +} + +static void discard_ack_conn_ooo(struct neighbor *nb, struct sk_buff *skb) +{ + pull_u32(skb, 1); /* seqno */ + pull_u8(skb); /* seqno */ + pull_u32(skb, 1); /* seqno */ + pull_u32(skb, 1); /* seqno */ +} + +static void parse_ack_conn_ooo(struct neighbor *nb, struct sk_buff *skb, + __u32 kpacket_seqno, struct conn *rconn) +{ + __u32 seqno = pull_u32(skb, 1); + __u8 window = pull_u8(skb); + __u32 seqno_ooo = pull_u32(skb, 1); + __u32 length = pull_u32(skb, 1); + + conn_ack_rcvd(kpacket_seqno, rconn->reversedir, seqno, window, + seqno_ooo, length); } static void discard_conn_success(struct neighbor *nb, struct sk_buff *skb) @@ -108,7 +131,7 @@ static void discard_conn_success(struct neighbor *nb, struct sk_buff *skb) } static void parse_conn_success(struct neighbor *nb, struct sk_buff *skb, - struct conn *rconn) + __u32 seqno, struct conn *rconn) { struct conn *sconn = rconn->reversedir; @@ -131,17 +154,18 @@ static void parse_conn_success(struct neighbor *nb, struct sk_buff *skb, mutex_unlock(&(sconn->rcv_lock)); } -static void parse_reset(struct neighbor *nb, struct sk_buff *skb, +static void parse_reset(struct neighbor *nb, struct sk_buff *skb, __u32 seqno, struct conn *rconn) { atomic_cmpxchg(&(rconn->reversedir->isreset), 0, 1); reset_conn(rconn); } -static void conn_cmd(struct neighbor *nb, struct sk_buff *skb, __u8 code, - void (*parsefunc)(struct neighbor *nb, struct sk_buff *skb, - struct conn *rconn), void (*readdiscardfunc)( - struct neighbor *nb, struct sk_buff *skb)) +static void conn_cmd(struct neighbor *nb, struct sk_buff *skb, __u32 seqno, + __u8 code, void (*parsefunc)(struct neighbor *nb, + struct sk_buff *skb, __u32 seqno, struct conn *rconn), + void (*readdiscardfunc)(struct neighbor *nb, + struct sk_buff *skb)) { __u32 conn_id = pull_u32(skb, 1); struct conn *rconn = get_conn(conn_id); @@ -155,7 +179,7 @@ static void conn_cmd(struct neighbor *nb, struct sk_buff *skb, __u8 code, if (unlikely(rconn->source.in.nb != nb)) goto err; - parsefunc(nb, skb, rconn); + parsefunc(nb, skb, seqno, rconn); if (0) { err: #warning send connid_unknown @@ -206,6 +230,7 @@ err: } } +#warning todo set window on connect/connect_success static void kernel_packet2(struct neighbor *nb, struct sk_buff *skb, __u32 seqno) { @@ -220,9 +245,6 @@ static void kernel_packet2(struct neighbor *nb, struct sk_buff *skb, __u32 cookie; __u32 respdelay; - __u32 conn_id; - __u32 seqno; - __u8 *codeptr = cor_pull_skb(skb, 1); __u8 code; @@ -248,19 +270,17 @@ static void kernel_packet2(struct neighbor *nb, struct sk_buff *skb, ack = 1; break; case KP_ACK: - conn_id = pull_u32(skb, 1); seqno = pull_u32(skb, 1); - - if (conn_id == 0) - kern_ack_rcvd(nb, seqno); - else - conn_ack_rcvd(nb, conn_id, seqno, 0); - #warning todo length - if (conn_id != 0) - ack = 1; + kern_ack_rcvd(nb, seqno); + break; + case KP_ACK_CONN: + conn_cmd(nb, skb, seqno, code, parse_ack_conn, + discard_ack_conn); + ack = 1; break; - case KP_SPEED: - conn_cmd(nb, skb, code, parse_speed, discard_speed); + case KP_ACK_CONN_OOO: + conn_cmd(nb, skb, seqno, code, parse_ack_conn_ooo, + discard_ack_conn_ooo); ack = 1; break; case KP_CONNECT: @@ -268,7 +288,7 @@ static void kernel_packet2(struct neighbor *nb, struct sk_buff *skb, ack = 1; break; case KP_CONNECT_SUCCESS: - conn_cmd(nb, skb, code, parse_conn_success, + conn_cmd(nb, skb, seqno, code, parse_conn_success, discard_conn_success); ack = 1; break; @@ -277,7 +297,7 @@ static void kernel_packet2(struct neighbor *nb, struct sk_buff *skb, ack = 1; break; case KP_RESET_CONN: - conn_cmd(nb, skb, code, parse_reset, 0); + conn_cmd(nb, skb, seqno, code, parse_reset, 0); ack = 1; break; default: @@ -286,7 +306,7 @@ static void kernel_packet2(struct neighbor *nb, struct sk_buff *skb, } if (ack) - send_ack(cm, nb, 0, seqno); + send_ack(cm, nb, seqno); else free_control_msg(cm); } @@ -318,11 +338,15 @@ void kernel_packet(struct neighbor *nb, struct sk_buff *skb, __u32 seqno) goto discard; break; case KP_ACK: - if (cor_pull_skb(skb2, 8) == 0) + if (cor_pull_skb(skb2, 4) == 0) + goto discard; + break; + case KP_ACK_CONN: + if (cor_pull_skb(skb2, 9) == 0) goto discard; break; - case KP_SPEED: - if (cor_pull_skb(skb2, 6) == 0) + case KP_ACK_CONN_OOO: + if (cor_pull_skb(skb2, 17) == 0) goto discard; break; case KP_CONNECT: diff --git a/net/cor/rcv.c b/net/cor/rcv.c index 08d8a7e5fcb..c1643a3316e 100644 --- a/net/cor/rcv.c +++ b/net/cor/rcv.c @@ -118,6 +118,8 @@ static void _conn_rcv(struct conn *rconn, struct sk_buff *skb) int in_order; int drop = 1; + __u32 len = skb->len; + BUG_ON(rconn->sourcetype != SOURCE_IN); if (unlikely(cm == 0)) { @@ -139,14 +141,23 @@ static void _conn_rcv(struct conn *rconn, struct sk_buff *skb) if (drop) { kfree_skb(skb); free_control_msg(cm); - } else { - send_ack(cm, rconn->source.in.nb, rconn->source.in.conn_id, - ps->funcstate.rcv2.seqno); + goto out; } - - if (in_order) + + #warning todo set window + if (in_order) { drain_ooo_queue(rconn); + send_ack_conn(cm, rconn->source.in.nb, + rconn->reversedir->target.out.conn_id, + rconn->source.in.next_seqno, enc_window(65536)); + } else { + send_ack_conn_ooo(cm, rconn->source.in.nb, + rconn->reversedir->target.out.conn_id, + rconn->source.in.next_seqno, enc_window(65536), + ps->funcstate.rcv2.seqno, len); + } +out: mutex_unlock(&(rconn->rcv_lock)); } @@ -220,7 +231,7 @@ static void rcv(struct work_struct *work) __u8 packet_type; char *packet_type_p; - + atomic_dec(&packets_in_workqueue); packet_type_p = cor_pull_skb(skb, 1); diff --git a/net/cor/snd.c b/net/cor/snd.c index 1579a9c0f09..b690f16baab 100644 --- a/net/cor/snd.c +++ b/net/cor/snd.c @@ -46,42 +46,6 @@ static void free_connretrans(struct kref *ref) kref_put(&(cr->rconn->ref), free_conn); } -static struct htable retransmits_conn; - -struct retransmit_matchparam { - struct neighbor *nb; - __u32 conn_id; - __u32 seqno; -}; - -static __u32 rm_to_key(struct retransmit_matchparam *rm) -{ - return rm->conn_id ^ rm->seqno; -} - -static void htable_insert_connretrans(struct conn_retrans *cr) -{ - struct retransmit_matchparam rm; - - rm.conn_id = cr->rconn->target.out.conn_id; - rm.seqno = cr->seqno; - rm.nb = cr->rconn->target.out.nb; - - htable_insert(&retransmits_conn, (char *) cr, rm_to_key(&rm)); -} - -static int htable_delete_connretrans(struct conn_retrans *cr) -{ - struct retransmit_matchparam rm; - - rm.conn_id = cr->rconn->target.out.conn_id; - rm.seqno = cr->seqno; - rm.nb = cr->rconn->target.out.nb; - - return htable_delete(&retransmits_conn, rm_to_key(&rm), &rm, - free_connretrans); -} - /* static struct sk_buff * cor_dequeue(struct Qdisc *sch) { struct sk_buff *ret; @@ -245,7 +209,6 @@ static struct conn_retrans *readd_conn_retrans(struct conn_retrans *cr, } if (ret != 0) { - htable_insert_connretrans(ret); list_add(&(ret->timeout_list), &(nb->retrans_list_conn)); list_add(&(ret->conn_list), &(cr->conn_list)); @@ -365,8 +328,6 @@ void retransmit_conn_timerfunc(struct work_struct *work) if (unlikely(unlikely(nbstate == NEIGHBOR_STATE_KILLED) || unlikely(atomic_read( &(cr->rconn->isreset)) != 0))) { - htable_delete_connretrans(cr); - list_del(&(cr->timeout_list)); list_del(&(cr->conn_list)); spin_unlock_irqrestore( &(nb->retrans_lock), iflags ); @@ -394,52 +355,116 @@ void retransmit_conn_timerfunc(struct work_struct *work) kref_put(&(nb->ref), neighbor_free); } -void conn_ack_rcvd(struct neighbor *nb, __u32 conn_id, __u32 seqno, - __u32 length) +static struct conn_retrans *search_seqno(struct conn *rconn, __u32 seqno) +{ + struct list_head *next = rconn->target.out.retrans_list.next; + + while (next != &(rconn->target.out.retrans_list)) { + struct conn_retrans *cr = container_of(next, + struct conn_retrans, conn_list); + BUG_ON(cr->rconn != rconn); + if (cr->seqno + cr->length > seqno) + return cr; + next = next->next; + } + return 0; +} + +void conn_ack_rcvd(__u32 kpacket_seqno, struct conn *rconn, __u32 seqno, + __u8 window, __u32 seqno_ooo, __u32 length) { unsigned long iflags; - struct retransmit_matchparam rm; - struct conn_retrans *cr; + struct neighbor *nb = rconn->target.out.nb; + struct conn_retrans *cr = 0; - #warning todo length - - rm.conn_id = conn_id; - rm.seqno = seqno; - rm.nb = nb; + int setwindow = 0; + + BUG_ON(rconn->targettype != TARGET_OUT); + + mutex_lock(&(rconn->rcv_lock)); + + if (unlikely(seqno - rconn->target.out.seqno_nextsend > 0)) + goto out; spin_lock_irqsave( &(nb->retrans_lock), iflags ); - cr = (struct conn_retrans *) htable_get(&retransmits_conn, - rm_to_key(&rm), &rm); + if (likely(length == 0)) + goto in_order; + + cr = search_seqno(rconn, seqno_ooo); - if (unlikely(cr == 0)) { - printk(KERN_ERR "bogus/duplicate ack received"); - goto out_err; + while (cr != 0) { + struct list_head *next = cr->conn_list.next; + struct conn_retrans *nextcr = 0; + if (next != &(rconn->target.out.retrans_list)) { + nextcr = container_of(next, struct conn_retrans, + conn_list); + } + + if (((__s32)(cr->seqno + cr->length - seqno_ooo - length)) > 0) { + __u32 newseqno = seqno_ooo + length; + cr->length -= (newseqno - cr->seqno); + cr->seqno = newseqno; + break; + } else { + list_del(&(cr->timeout_list)); + list_del(&(cr->conn_list)); + cr->ackrcvd = 1; + kref_put(&(cr->ref), free_connretrans); + } + + cr = nextcr; } - - BUG_ON(cr->rconn->targettype != TARGET_OUT); - - if (unlikely(cr->rconn->target.out.nb != nb)) { - printk(KERN_ERR "invalid neigh when receiving ack"); - goto out_err; + + if (unlikely(list_empty(&(rconn->target.out.retrans_list))) == 0) { + struct conn_retrans *cr = container_of( + rconn->target.out.retrans_list.next, + struct conn_retrans, conn_list); + if (unlikely(cr->seqno - rconn->target.out.seqno_acked > 0)) { + rconn->target.out.seqno_acked = cr->seqno; + } } - if (unlikely(htable_delete_connretrans(cr))) - BUG(); +in_order: + if (likely(seqno - rconn->target.out.seqno_acked > 0)) { + rconn->target.out.seqno_acked = seqno; + setwindow = 1; + } - list_del(&(cr->timeout_list)); - list_del(&(cr->conn_list)); - cr->ackrcvd = 1; - spin_unlock_irqrestore( &(nb->retrans_lock), iflags ); + cr = search_seqno(rconn, seqno_ooo); - #warning todo databuf_ack - - kref_put(&(cr->ref), free_connretrans); + while (cr != 0) { + struct list_head *next = cr->conn_list.next; + struct conn_retrans *nextcr = 0; + if (next != &(rconn->target.out.retrans_list)) { + nextcr = container_of(next, struct conn_retrans, + conn_list); + } + + if (((__s32)(cr->seqno + cr->length - + rconn->target.out.seqno_acked)) <= 0) { + list_del(&(cr->timeout_list)); + list_del(&(cr->conn_list)); + cr->ackrcvd = 1; + kref_put(&(cr->ref), free_connretrans); + } + + cr = nextcr; + } - return; - -out_err: spin_unlock_irqrestore( &(nb->retrans_lock), iflags ); + databuf_ack(&(rconn->buf), rconn->target.out.seqno_acked); + + setwindow = setwindow || (seqno == rconn->target.out.seqno_acked && + (kpacket_seqno - rconn->target.out.kp_windowsetseqno > + 0)); + if (setwindow) { + rconn->target.out.kp_windowsetseqno = kpacket_seqno; + rconn->target.out.seqno_windowlimit = seqno + + dec_window(window); + } +out: + mutex_unlock(&(rconn->rcv_lock)); } static int schedule_retransmit_conn(struct conn *rconn, __u32 seqno, __u32 len) @@ -466,8 +491,6 @@ static int schedule_retransmit_conn(struct conn *rconn, __u32 seqno, __u32 len) spin_lock_irqsave( &(nb->retrans_lock), iflags ); - htable_insert_connretrans(cr); - first = unlikely(list_empty(&(nb->retrans_list_conn))); list_add_tail(&(cr->timeout_list), &(nb->retrans_list_conn)); @@ -490,6 +513,8 @@ void flush_out(struct conn *rconn) int targetmss = mss(rconn->target.out.nb); __u32 seqno; + #warning todo honor window size + BUG_ON(rconn->targettype != TARGET_OUT); if (unlikely(rconn->target.out.conn_id == 0)) @@ -498,7 +523,7 @@ void flush_out(struct conn *rconn) while (rconn->buf.read_remaining >= targetmss) { struct sk_buff *skb; char *dst; - seqno = rconn->target.out.seqno; + seqno = rconn->target.out.seqno_nextsend; skb = create_packet(rconn->target.out.nb, targetmss, GFP_ATOMIC, rconn->target.out.conn_id, seqno); if (unlikely(skb == 0)) @@ -513,7 +538,7 @@ void flush_out(struct conn *rconn) kfree_skb(skb); goto oom; } - rconn->target.out.seqno += targetmss; + rconn->target.out.seqno_nextsend += targetmss; dev_queue_xmit(skb); } @@ -533,13 +558,13 @@ void flush_out(struct conn *rconn) goto oom; } - seqno = rconn->target.out.seqno; + seqno = rconn->target.out.seqno_nextsend; if (unlikely(schedule_retransmit_conn(rconn, seqno, len))) { free_control_msg(cm); goto oom; } - rconn->target.out.seqno += len; + rconn->target.out.seqno_nextsend += len; send_conndata(cm, rconn->target.out.nb, rconn->target.out.conn_id, seqno, buf, buf, @@ -555,23 +580,13 @@ oom: } } -static int matches_connretrans_connid_seqno(void *htentry, void *searcheditem) -{ - struct conn_retrans *cr = (struct conn_retrans *) htentry; - struct retransmit_matchparam *rm = (struct retransmit_matchparam *) - searcheditem; - return rm->conn_id == cr->rconn->target.out.conn_id && - rm->seqno == cr->seqno && - rm->nb == cr->rconn->target.out.nb; -} - int __init cor_snd_init(void) { connretrans_slab = kmem_cache_create("cor_connretrans", sizeof(struct conn_retrans), 8, 0, 0); - htable_init(&retransmits_conn, matches_connretrans_connid_seqno, - offsetof(struct conn_retrans, htab_entry), - offsetof(struct conn_retrans, ref)); + + if (unlikely(connretrans_slab == 0)) + return 1; return 0; } -- 2.11.4.GIT