--- drivers/net/ppp_generic.c.orig 2010-03-25 16:56:05.000000000 +0100 +++ drivers/net/ppp_generic.c 2010-03-30 19:56:15.000000000 +0200 @@ -129,6 +129,7 @@ u32 nextseq; /* MP: seq no of next packet */ u32 minseq; /* MP: min of most recent seqnos */ struct sk_buff_head mrq; /* MP: receive reconstruction queue */ + int rrsched; /* round robin scheduler for packet distribution */ #endif /* CONFIG_PPP_MULTILINK */ #ifdef CONFIG_PPP_FILTER struct sock_filter *pass_filter; /* filter for packets to pass */ @@ -227,6 +228,17 @@ #define B 0x80 /* this fragment begins a packet */ #define E 0x40 /* this fragment ends a packet */ +#ifdef CONFIG_PPP_MULTILINK +/* alternate fragmentation algorithm and multilink behaviour options added by uli.staerk@globalways.net */ +static int ppp_ml_noexplode = 0; +module_param(ppp_ml_noexplode, int, 0600); +MODULE_PARM_DESC(ppp_ml_noexplode, "Set this to any other values than zero to avoid fragmentation over connected channels"); + +static int ppp_ml_noheader = 0; +module_param(ppp_ml_noheader, int, 0600); +MODULE_PARM_DESC(ppp_ml_noheader, "Set this to any other value than zero to remove the ppp-multilink protocol header (pppoes.protocol not 0x003d) which enables fragmentation and reordering"); +#endif /* CONFIG_PPP_MULTILINK */ + /* Compare multilink sequence numbers (assumed to be 32 bits wide) */ #define seq_before(a, b) ((s32)((a) - (b)) < 0) #define seq_after(a, b) ((s32)((a) - (b)) > 0) @@ -250,6 +262,7 @@ static void ppp_mp_insert(struct ppp *ppp, struct sk_buff *skb); static struct sk_buff *ppp_mp_reconstruct(struct ppp *ppp); static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb); +static void ppp_mp_roundrobin(struct ppp *ppp, struct sk_buff *skb); #endif /* CONFIG_PPP_MULTILINK */ static int ppp_set_compress(struct ppp *ppp, unsigned long arg); static void ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound); @@ -1292,10 +1305,18 @@ } #ifdef CONFIG_PPP_MULTILINK - /* Multilink: fragment the packet over as many links - as can take the packet at the moment. */ - if (!ppp_mp_explode(ppp, skb)) + /* send packet without multilink header */ + if(ppp_ml_noheader) { + ppp_mp_roundrobin(ppp, skb); return; + } + else { + /* Multilink: fragment the packet over as many links + as can take the packet at the moment. */ + if (!ppp_mp_explode(ppp, skb)) { + return; + } + } #endif /* CONFIG_PPP_MULTILINK */ ppp->xmit_pending = NULL; @@ -1304,6 +1325,38 @@ #ifdef CONFIG_PPP_MULTILINK /* + * Send packet through the next channel (round robin) + */ +static void ppp_mp_roundrobin(struct ppp *ppp, struct sk_buff *skb) +{ + int i; + struct channel *pch; + + ppp->rrsched++; + i = 0; + list_for_each_entry(pch, &ppp->channels, clist) { + if(pch->chan == NULL) continue; + + if (ppp->rrsched % ppp->n_channels == i) { + spin_lock_bh(&pch->downl); + if (pch->chan) { + if (pch->chan->ops->start_xmit(pch->chan, skb)) { + ppp->xmit_pending = NULL; + } + } else { + /* channel got unregistered */ + kfree_skb(skb); + ppp->xmit_pending = NULL; + } + spin_unlock_bh(&pch->downl); + return; + } + i++; + } + return; +} + +/* * Divide a packet to be transmitted into fragments and * send them out the individual links. */ @@ -1352,13 +1405,21 @@ } ++i; } - /* - * Don't start sending this packet unless at least half of - * the channels are free. This gives much better TCP - * performance if we have a lot of channels. - */ - if (nfree == 0 || nfree < navail / 2) - return 0; /* can't take now, leave it in xmit_pending */ + + + if(ppp_ml_noexplode) { + } + else { + /* + * Don't start sending this packet unless at least half of + * the channels are free. This gives much better TCP + * performance if we have a lot of channels. + */ + if (nfree == 0 || nfree < navail / 2) { + return 0; /* can't take now, leave it in xmit_pending */ + + } + } /* Do protocol field compression (XXX this should be optional) */ p = skb->data; @@ -1371,6 +1432,7 @@ totlen = len; nbigger = len % nfree; + /* skip to the channel after the one we last used and start at that one */ list = &ppp->channels; @@ -1432,33 +1494,40 @@ *of the channel we are going to transmit on */ flen = len; - if (nfree > 0) { - if (pch->speed == 0) { - flen = totlen/nfree ; - if (nbigger > 0) { - flen++; - nbigger--; - } - } else { - flen = (((totfree - nzero)*(totlen + hdrlen*totfree)) / - ((totspeed*totfree)/pch->speed)) - hdrlen; - if (nbigger > 0) { - flen += ((totfree - nzero)*pch->speed)/totspeed; - nbigger -= ((totfree - nzero)*pch->speed)/ - totspeed; + + if(ppp_ml_noexplode) { + nfree--; + } + else { + if (nfree > 0) { + if (pch->speed == 0) { + flen = totlen/nfree ; + if (nbigger > 0) { + flen++; + nbigger--; + } + } else { + flen = (((totfree - nzero)*(totlen + hdrlen*totfree)) / + ((totspeed*totfree)/pch->speed)) - hdrlen; + if (nbigger > 0) { + flen += ((totfree - nzero)*pch->speed)/totspeed; + nbigger -= ((totfree - nzero)*pch->speed)/ + totspeed; + } } + nfree--; } - nfree--; + /* + *check if we are on the last channel or + *we exceded the lenght of the data to + *fragment + */ + if ((nfree <= 0) || (flen > len)) + flen = len; + } /* - *check if we are on the last channel or - *we exceded the lenght of the data to - *fragment - */ - if ((nfree <= 0) || (flen > len)) - flen = len; - /* *it is not worth to tx on slow channels: *in that case from the resulting flen according to the *above formula will be equal or less than zero.