diff -ubdr linux-2.6.16.16-l2tp/drivers/net/ppp_generic.c linux-2.6.16.16-l2tp-mppp/drivers/net/ppp_generic.c --- linux-2.6.16.16-l2tp/drivers/net/ppp_generic.c 2006-05-11 02:56:24.000000000 +0100 +++ linux-2.6.16.16-l2tp-mppp/drivers/net/ppp_generic.c 2007-07-03 18:23:35.000000000 +0100 @@ -64,7 +64,7 @@ #define MPHDRLEN 6 /* multilink protocol header length */ #define MPHDRLEN_SSN 4 /* ditto with short sequence numbers */ -#define MIN_FRAG_SIZE 64 +#define MIN_FRAG_SIZE 256 /* * An instance of /dev/ppp can be associated with either a ppp @@ -120,6 +120,7 @@ unsigned long last_recv; /* jiffies when last pkt rcvd a0 */ struct net_device *dev; /* network interface device a4 */ #ifdef CONFIG_PPP_MULTILINK + int minfragsize; /* minimum size for a fragment */ int nxchan; /* next channel to send something on */ u32 nxseq; /* next sequence number to send */ int mrru; /* MP: max reconst. receive unit */ @@ -767,6 +768,15 @@ ppp_recv_unlock(ppp); err = 0; break; + + case PPPIOCSMINFRAG: + if (get_user(val, p)) + break; + ppp_recv_lock(ppp); + ppp->minfragsize = val < 0 ? 0 : val; + ppp_recv_unlock(ppp); + err = 0; + break; #endif /* CONFIG_PPP_MULTILINK */ default: @@ -1254,7 +1264,7 @@ int len, fragsize; int i, bits, hdrlen, mtu; int flen; - int navail, nfree; + int navail, nfree, nfrag; int nbigger; unsigned char *p, *q; struct list_head *list; @@ -1285,7 +1295,7 @@ * the channels are free. This gives much better TCP * performance if we have a lot of channels. */ - if (nfree == 0 || nfree < navail / 2) + if (nfree == 0 || (nfree < navail / 2 && ppp->minfragsize == 0)) return 0; /* can't take now, leave it in xmit_pending */ /* Do protocol field compression (XXX this should be optional) */ @@ -1302,13 +1312,24 @@ * how small they are (i.e. even 0 length) in order to minimize * the time that it will take to detect when a channel drops * a fragment. + * However, if ppp->minfragsize > 0 we try to avoid creating + * fragments smaller than ppp->minfragsize and thus do not + * always use all free channels */ + if (ppp->minfragsize > 0) { + nfrag= len / ppp->minfragsize; + if (nfrag < 1) + nfrag = 1; + else if (nfrag > nfree) + nfrag = nfree; + } else + nfrag = nfree; fragsize = len; - if (nfree > 1) - fragsize = DIV_ROUND_UP(fragsize, nfree); + if (nfrag > 1) + fragsize = DIV_ROUND_UP(fragsize, nfrag); /* nbigger channels get fragsize bytes, the rest get fragsize-1, except if nbigger==0, then they all get fragsize. */ - nbigger = len % nfree; + nbigger = len % nfrag; /* skip to the channel after the one we last used and start at that one */ @@ -1323,7 +1344,7 @@ /* create a fragment for each channel */ bits = B; - while (nfree > 0 || len > 0) { + while (len > 0 || (nfree > 0 && ppp->minfragsize == 0)) { list = list->next; if (list == &ppp->channels) { i = 0; @@ -1371,7 +1392,7 @@ mtu = 4; if (flen > mtu) flen = mtu; - if (flen == len && nfree == 0) + if (flen == len && (nfree == 0 || ppp->minfragsize != 0)) bits |= E; frag = alloc_skb(flen + hdrlen + (flen == 0), GFP_ATOMIC); if (frag == 0) @@ -2435,6 +2456,7 @@ spin_lock_init(&ppp->rlock); spin_lock_init(&ppp->wlock); #ifdef CONFIG_PPP_MULTILINK + ppp->minfragsize = MIN_FRAG_SIZE; ppp->minseq = -1; skb_queue_head_init(&ppp->mrq); #endif /* CONFIG_PPP_MULTILINK */ diff -ubdr linux-2.6.16.16-l2tp/include/linux/if_ppp.h linux-2.6.16.16-l2tp-mppp/include/linux/if_ppp.h --- linux-2.6.16.16-l2tp/include/linux/if_ppp.h 2006-05-12 13:45:00.000000000 +0100 +++ linux-2.6.16.16-l2tp-mppp/include/linux/if_ppp.h 2007-07-03 18:15:27.000000000 +0100 @@ -162,6 +162,7 @@ #define PPPIOCATTCHAN _IOW('t', 56, int) /* attach to ppp channel */ #define PPPIOCGCHAN _IOR('t', 55, int) /* get ppp channel number */ #define PPPIOCGL2TPSTATS _IOR('t', 54, struct pppol2tp_ioc_stats) +#define PPPIOCSMINFRAG _IOW('t', 53, int) /* minimum fragment size */ #define SIOCGPPPSTATS (SIOCDEVPRIVATE + 0) #define SIOCGPPPVER (SIOCDEVPRIVATE + 1) /* NEVER change this!! */