mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-30 16:13:54 +08:00
9c705260fe
I found the PPP subsystem to not work properly when connecting channels with different speeds to the same bundle. Problem Description: As the "ppp_mp_explode" function fragments the sk_buff buffer evenly among the PPP channels that are connected to a certain PPP unit to make up a bundle, if we are transmitting using an upper layer protocol that requires an Ack before sending the next packet (like TCP/IP for example), we will have a bandwidth bottleneck on the slowest channel of the bundle. Let's clarify by an example. Let's consider a scenario where we have two PPP links making up a bundle: a slow link (10KB/sec) and a fast link (1000KB/sec) working at the best (full bandwidth). On the top we have a TCP/IP stack sending a 1000 Bytes sk_buff buffer down to the PPP subsystem. The "ppp_mp_explode" function will divide the buffer in two fragments of 500B each (we are neglecting all the headers, crc, flags etc?.). Before the TCP/IP stack sends out the next buffer, it will have to wait for the ACK response from the remote peer, so it will have to wait for both fragments to have been sent over the two PPP links, received by the remote peer and reconstructed. The resulting behaviour is that, rather than having a bundle working @1010KB/sec (the sum of the channels bandwidths), we'll have a bundle working @20KB/sec (the double of the slowest channels bandwidth). Problem Solution: The problem has been solved by redesigning the "ppp_mp_explode" function in such a way to make it split the sk_buff buffer according to the speeds of the underlying PPP channels (the speeds of the serial interfaces respectively attached to the PPP channels). Referring to the above example, the redesigned "ppp_mp_explode" function will now divide the 1000 Bytes buffer into two fragments whose sizes are set according to the speeds of the channels where they are going to be sent on (e.g . 10 Byets on 10KB/sec channel and 990 Bytes on 1000KB/sec channel). The reworked function grants the same performances of the original one in optimal working conditions (i.e. a bundle made up of PPP links all working at the same speed), while greatly improving performances on the bundles made up of channels working at different speeds. Signed-off-by: Gabriele Paoloni <gabriele.paoloni@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
86 lines
3.0 KiB
C
86 lines
3.0 KiB
C
#ifndef _PPP_CHANNEL_H_
|
|
#define _PPP_CHANNEL_H_
|
|
/*
|
|
* Definitions for the interface between the generic PPP code
|
|
* and a PPP channel.
|
|
*
|
|
* A PPP channel provides a way for the generic PPP code to send
|
|
* and receive packets over some sort of communications medium.
|
|
* Packets are stored in sk_buffs and have the 2-byte PPP protocol
|
|
* number at the start, but not the address and control bytes.
|
|
*
|
|
* Copyright 1999 Paul Mackerras.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
*
|
|
* ==FILEVERSION 20000322==
|
|
*/
|
|
|
|
#include <linux/list.h>
|
|
#include <linux/skbuff.h>
|
|
#include <linux/poll.h>
|
|
#include <net/net_namespace.h>
|
|
|
|
struct ppp_channel;
|
|
|
|
struct ppp_channel_ops {
|
|
/* Send a packet (or multilink fragment) on this channel.
|
|
Returns 1 if it was accepted, 0 if not. */
|
|
int (*start_xmit)(struct ppp_channel *, struct sk_buff *);
|
|
/* Handle an ioctl call that has come in via /dev/ppp. */
|
|
int (*ioctl)(struct ppp_channel *, unsigned int, unsigned long);
|
|
};
|
|
|
|
struct ppp_channel {
|
|
void *private; /* channel private data */
|
|
struct ppp_channel_ops *ops; /* operations for this channel */
|
|
int mtu; /* max transmit packet size */
|
|
int hdrlen; /* amount of headroom channel needs */
|
|
void *ppp; /* opaque to channel */
|
|
int speed; /* transfer rate (bytes/second) */
|
|
/* the following is not used at present */
|
|
int latency; /* overhead time in milliseconds */
|
|
};
|
|
|
|
#ifdef __KERNEL__
|
|
/* Called by the channel when it can send some more data. */
|
|
extern void ppp_output_wakeup(struct ppp_channel *);
|
|
|
|
/* Called by the channel to process a received PPP packet.
|
|
The packet should have just the 2-byte PPP protocol header. */
|
|
extern void ppp_input(struct ppp_channel *, struct sk_buff *);
|
|
|
|
/* Called by the channel when an input error occurs, indicating
|
|
that we may have missed a packet. */
|
|
extern void ppp_input_error(struct ppp_channel *, int code);
|
|
|
|
/* Attach a channel to a given PPP unit in specified net. */
|
|
extern int ppp_register_net_channel(struct net *, struct ppp_channel *);
|
|
|
|
/* Attach a channel to a given PPP unit. */
|
|
extern int ppp_register_channel(struct ppp_channel *);
|
|
|
|
/* Detach a channel from its PPP unit (e.g. on hangup). */
|
|
extern void ppp_unregister_channel(struct ppp_channel *);
|
|
|
|
/* Get the channel number for a channel */
|
|
extern int ppp_channel_index(struct ppp_channel *);
|
|
|
|
/* Get the unit number associated with a channel, or -1 if none */
|
|
extern int ppp_unit_number(struct ppp_channel *);
|
|
|
|
/*
|
|
* SMP locking notes:
|
|
* The channel code must ensure that when it calls ppp_unregister_channel,
|
|
* nothing is executing in any of the procedures above, for that
|
|
* channel. The generic layer will ensure that nothing is executing
|
|
* in the start_xmit and ioctl routines for the channel by the time
|
|
* that ppp_unregister_channel returns.
|
|
*/
|
|
|
|
#endif /* __KERNEL__ */
|
|
#endif
|