Netdev List
 help / color / mirror / Atom feed
* Re: [RFC/PATCH 1/2] in-kernel sockets API
From: Brian F. G. Bidulock @ 2006-06-14  0:18 UTC (permalink / raw)
  To: Chase Venters
  Cc: Ben Greear, Daniel Phillips, Stephen Hemminger, Sridhar Samudrala,
	netdev, linux-kernel
In-Reply-To: <200606131906.16683.chase.venters@clientec.com>

Chase,

On Tue, 13 Jun 2006, Chase Venters wrote:
> I'm trying to imagine what kind of legitimate non-GPL modules might 
> use them.

Example: in-kernel RTP implementation derived from AT&T rtp-lib
implementation (non-GPL compatible license) utilizing this kernel
interface for UDP socket access.

^ permalink raw reply

* Re: [RFC/PATCH 1/2] in-kernel sockets API
From: Ben Greear @ 2006-06-14  0:19 UTC (permalink / raw)
  To: Chase Venters
  Cc: Brian F. G. Bidulock, Daniel Phillips, Stephen Hemminger,
	Sridhar Samudrala, netdev, linux-kernel
In-Reply-To: <200606131906.16683.chase.venters@clientec.com>

Chase Venters wrote:
> On Tuesday 13 June 2006 18:42, Ben Greear wrote:
> 
>>Chase Venters wrote:
>>
>>>At least some of us feel like stable module APIs should be explicitly
>>>discouraged, because we don't want to offer comfort for code that
>>>refuses to live in the tree (since getting said code into the tree is
>>>often a goal).
>>
>>Some of us write modules for specific features that are not wanted in
>>the mainline kernel, even though they are pure GPL.  Our life is hard
>>enough with out people setting out to deliberately make things more
>>difficult!
> 
> 
> Fair enough, but if you are doing out of tree, pure GPL modules, 
> EXPORT_SYMBOL_GPL() isn't a bad thing, is it?
> 
> Don't mistake me for actually having a big opinion specifically about this 
> socket API's usage of EXPORT_SYMBOL()... just raising some points that I 
> think apply to these decisions in general. I don't really see a compelling 
> reason for EXPORT_SYMBOL() over EXPORT_SYMBOL_GPL() on the socket APIs 
> though... I'm trying to imagine what kind of legitimate non-GPL modules might 
> use them.

I got to the flame war late and only saw your comment that stable API should
be discouraged.  That kind of thinking pisses me off because it assumes all
modules out of the tree are that way because the authors want them out of the
tree.  I also understand that sometimes API needs to change, but please don't
encourage change just to punish other authors, be they proprietary or otherwise.

As for what type of EXPORT macro to use I surely don't have anything to
say that hasn't been said multiple times before.

Ben

-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply

* Re: [RFC/PATCH 1/2] in-kernel sockets API
From: Chase Venters @ 2006-06-14  0:29 UTC (permalink / raw)
  To: bidulock
  Cc: Ben Greear, Daniel Phillips, Stephen Hemminger, Sridhar Samudrala,
	netdev, linux-kernel
In-Reply-To: <20060613181801.A8460@openss7.org>

On Tuesday 13 June 2006 19:17, Brian F. G. Bidulock wrote:
> Chase,
>
> On Tue, 13 Jun 2006, Chase Venters wrote:
> > I'm trying to imagine what kind of legitimate non-GPL modules might
> > use them.
>
> Example: in-kernel RTP implementation derived from AT&T rtp-lib
> implementation (non-GPL compatible license) utilizing this kernel
> interface for UDP socket access.

I don't mean to be obtuse, but the "Non-exclusive Non-commercial Limited-use 
Source" license seems to make something like that have limited usefulness in 
general. That is -- unless one were to obtain a commercial license from AT&T, 
but then that starts falling into the domain of what is likely prohibited by 
the GPL (some sort of proprietary work actually _derived_ off the kernel 
rather than just supporting it in some way).

But I did ask for examples...

Thanks,
Chase

^ permalink raw reply

* Re: [RFC/PATCH 1/2] in-kernel sockets API
From: Brian F. G. Bidulock @ 2006-06-14  0:31 UTC (permalink / raw)
  To: Chase Venters
  Cc: Daniel Phillips, Stephen Hemminger, Sridhar Samudrala, netdev,
	linux-kernel
In-Reply-To: <200606131859.43695.chase.venters@clientec.com>

Chase,

On Tue, 13 Jun 2006, Chase Venters wrote:
> 
> It depends on what you mean by "pure-BSD". If you're talking about the 
> 4-clause license with the advertising clause, then you are correct. Otherwise 
> (IANAL) but my understanding is that BSD code can even be relicensed GPL by a 
> third party contribution (though it is perhaps kind to ask for relicensing 
> permission anyway).

Yes, and the long list of open source licenses listed on the FSF website
as incompatible with the GPL.

> Then would offering a 'stable API in disguise' not be a disaster and an 
> irritation to these people? If the kernel doesn't specify that an in-kernel 
> interface is stable, then there is no reason to expect it to be. It might not 
> change, but there won't be too much sympathy for out-of-tree users if it 
> does. The kernel comes with big warnings about the lack of a stable API for a 
> reason.

In fact most core kernel facilities (spin lock, memory caches, character and
block device interface, even core file system) have had a very stable API
(way back to early 2.4 kernels).  An in fact most of them are derived from
some variant or precursor to UNIX.  For example, memory caches are a Sun
Solaris concept.

It is the lack of an ABI that is most frustrating to these users.

> 
> > Another thing to consider is that the first step for many organizations in
> > opening a driver under GPL is to release a proprietary module that at least
> > first works.  
> 
> If the driver is an old-tech Linux port, then it seems there isn't too much 
> stopping them from doing this today (aside from the fact that some people 
> think proprietary modules are murky anyway). In this case, we don't want a 
> stable API/ABI, because then we leave them with little incentive to open the 
> code.

"old-tech"?  No, these are high-tech drivers supported by commercial RTOS,
from which Linux stands to benefit.  And, by not allowing these organizations
to take the first step (generate a workable Linux driver) such a policy
provides them little incentive to ever move the driver to Linux, and cuts
them off from opening it.

I don't think that it is fair to say that an unstable API/ABI, in of itself,
provides an incentive to open an existing proprietary driver.

> We're not as perfect as I wish we were. But the lack of stable API (dead 
> horse) is something that is fairly well established and understood. I think 
> most people feel that the cost-benefit analysis, for Linux anyway, strongly 
> favors no stable API.

Well, the lack of a stable ABI is well known.  The API is largely stable (but
not sacrosanctly so) for the major reason that changing it within a large
code base is difficult and error prone at best.

^ permalink raw reply

* Re: PATCHv3 2.6.17-rc5 tulip free_irq() called too late
From: Jeff Garzik @ 2006-06-14  0:33 UTC (permalink / raw)
  To: Grant Grundler; +Cc: Valerie Henson, Andrew Morton, netdev
In-Reply-To: <20060613235531.GA4191@colo.lackof.org>

Grant Grundler wrote:
> o tulip_stop_rxtx() has to be called _after_ free_irq().
>   ie. v2 patch didn't fix the original race condition
>   and when under test, dies about as fast as the original code.

You made the race window smaller, but it's still there.  The chip's DMA 
engines should be stopped before you unregister the interrupt handler.

	Jeff




^ permalink raw reply

* Re: [RFC/PATCH 1/2] in-kernel sockets API
From: Brian F. G. Bidulock @ 2006-06-14  0:36 UTC (permalink / raw)
  To: Chase Venters
  Cc: Ben Greear, Daniel Phillips, Stephen Hemminger, Sridhar Samudrala,
	netdev, linux-kernel
In-Reply-To: <200606131929.41985.chase.venters@clientec.com>

Chase,

On Tue, 13 Jun 2006, Chase Venters wrote:
> 
> But I did ask for examples...

Perhaps the license isn't a good example, but there are other RTP
stacks that are non-GPL compatible.  Also, if it includes SSL code
for SRTP, SSL license happens to be non-GPL compatible.

^ permalink raw reply

* Re: [RFC/PATCH 1/2] in-kernel sockets API
From: Brian F. G. Bidulock @ 2006-06-14  0:38 UTC (permalink / raw)
  To: Ben Greear
  Cc: Chase Venters, Daniel Phillips, Stephen Hemminger,
	Sridhar Samudrala, netdev, linux-kernel
In-Reply-To: <448F561D.5080007@candelatech.com>

Ben,

On Tue, 13 Jun 2006, Ben Greear wrote:
> 
> I got to the flame war late
...

I think we're trying to have an honest open discussion here.  I certainly
don't mean to flame anyone and apologize if my remarks have been taken so.

^ permalink raw reply

* Re: [RFC/PATCH 1/2] in-kernel sockets API
From: Chase Venters @ 2006-06-14  0:53 UTC (permalink / raw)
  To: bidulock
  Cc: Daniel Phillips, Stephen Hemminger, Sridhar Samudrala, netdev,
	linux-kernel
In-Reply-To: <20060613183112.B8460@openss7.org>

On Tuesday 13 June 2006 19:30, Brian F. G. Bidulock wrote:

> Yes, and the long list of open source licenses listed on the FSF website
> as incompatible with the GPL.

Conceded, I suppose. The usage of EXPORT_SYMBOL() though tends to be for the 
reason of enabling drivers to offer functionality to the kernel -- not for 
people who want to turn the kernel into applications. (Consider for example 
how netfilter is exposed as GPL. You can build applications [routers] out of 
it, but in that case you're doing a work derived off of Linux, and you should 
be abiding by its GPL licensing terms)

> > Then would offering a 'stable API in disguise' not be a disaster and an
> > irritation to these people? If the kernel doesn't specify that an
> > in-kernel interface is stable, then there is no reason to expect it to
> > be. It might not change, but there won't be too much sympathy for
> > out-of-tree users if it does. The kernel comes with big warnings about
> > the lack of a stable API for a reason.
>
> In fact most core kernel facilities (spin lock, memory caches, character
> and block device interface, even core file system) have had a very stable
> API (way back to early 2.4 kernels).  An in fact most of them are derived
> from some variant or precursor to UNIX.  For example, memory caches are a
> Sun Solaris concept.

I'm not advocating changing the API for no reason / just to piss off out of 
tree developers. I'm just trying to make clear that in these cases, 'stable' 
is just an observation -- not something you can count on.

> It is the lack of an ABI that is most frustrating to these users.

And the presence of an ABI would be _very_ frustrating to core developers. Not 
only would these people suffer, everyone would -- developer time would be 
wasted dealing with cruft, and forward progress would be slowed.

> > > Another thing to consider is that the first step for many organizations
> > > in opening a driver under GPL is to release a proprietary module that
> > > at least first works.
> >
> > If the driver is an old-tech Linux port, then it seems there isn't too
> > much stopping them from doing this today (aside from the fact that some
> > people think proprietary modules are murky anyway). In this case, we
> > don't want a stable API/ABI, because then we leave them with little
> > incentive to open the code.
>
> "old-tech"?  No, these are high-tech drivers supported by commercial RTOS,
> from which Linux stands to benefit.  And, by not allowing these
> organizations to take the first step (generate a workable Linux driver)
> such a policy provides them little incentive to ever move the driver to
> Linux, and cuts them off from opening it.

Perhaps another term may have been more appropriate. What I mean by 'old tech' 
is more 'existing code' -- ie, something you would port. 

And these organizations _are_ afforded the opportunity to take the first step 
-- that's why interfaces critical to drivers are currently EXPORT_SYMBOL().

> I don't think that it is fair to say that an unstable API/ABI, in of
> itself, provides an incentive to open an existing proprietary driver.

Sure it does, depending on your perspective and what you're willing to 
consider. The lack of a stable API/ABI means that if you don't want to have 
to do work tracking the kernel, you should push to have your drivers merged.

> > We're not as perfect as I wish we were. But the lack of stable API (dead
> > horse) is something that is fairly well established and understood. I
> > think most people feel that the cost-benefit analysis, for Linux anyway,
> > strongly favors no stable API.
>
> Well, the lack of a stable ABI is well known.  The API is largely stable
> (but not sacrosanctly so) for the major reason that changing it within a
> large code base is difficult and error prone at best.

Perhaps, but calling it 'stable' in any sense other than idle observation is a 
disaster, because the idea leads to pain and suffering when you do have a 
major reason to change the API.

Thanks,
Chase

^ permalink raw reply

* Re: 2.6.17: networking bug??
From: John Heffner @ 2006-06-14  1:25 UTC (permalink / raw)
  To: Rick Jones; +Cc: David Miller, netdev
In-Reply-To: <448F3EF5.50701@hp.com>

Rick Jones wrote:
>> One final word about window sizes.  If you have a connection whose
>> bandwidth-delay-product needs an N byte buffer to fill, you actually
>> have to have an "N * 2" sized buffer available in order for fast
>> retransmit to work.
> 
> Is that as important in the presence of SACK?

With SACK you do need up to N * 2, but no more.  With New Reno, you 
potentially need ~ N * (number of losses) or it will time out... yuck. 
SACK is a good thing. :)

   -John

^ permalink raw reply

* Re: PATCHv3 2.6.17-rc5 tulip free_irq() called too late
From: Grant Grundler @ 2006-06-14  4:44 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Grant Grundler, Valerie Henson, Andrew Morton, netdev
In-Reply-To: <448F5952.1060201@pobox.com>

On Tue, Jun 13, 2006 at 08:33:22PM -0400, Jeff Garzik wrote:
> Grant Grundler wrote:
> >o tulip_stop_rxtx() has to be called _after_ free_irq().
> >  ie. v2 patch didn't fix the original race condition
> >  and when under test, dies about as fast as the original code.
> 
> You made the race window smaller, but it's still there.  The chip's DMA 
> engines should be stopped before you unregister the interrupt handler.

Switching the order to be:
        tulip_stop_rxtx(tp);            /* Stop DMA */
        free_irq (dev->irq, dev);       /* no more races after this */

still leaves us open to IRQs being delivered _after_ we've stopped DMA.
That in turn allows the interrupt handler to re-enable DMA again.

Or are you worried about a masked, pending interrupt causing
problems when the driver is re-opened or resumed?
If firmware left the device in a that state at boot time wouldn't
the driver be required to handle it?

thanks,
grant



> 
> 	Jeff
> 
> 

^ permalink raw reply

* Re: 2.6.17: networking bug??
From: Andi Kleen @ 2006-06-14  5:18 UTC (permalink / raw)
  To: David Miller; +Cc: lkml, jheffner, torvalds, linux-kernel, netdev
In-Reply-To: <20060613.142603.48825062.davem@davemloft.net>


> Also, as John Heffner mentioned, even if we could detect the broken
> boxes you can't just "turn off window scaling" after it's been
> negotiated.  It's immutably active for the entire connection once
> enabled.

In theory you could set a bit in the dst entry and not use it next time
you connect to that host. That would be ok for web browsing at least
when creates new connections all the time.

But it's unclear how to even detect this situation reliably

e.g. you don't want to disable it just because there was a bit of 
packet loss on a connection to a particular host earlier and there
is no clear heuristic to detect that this particular problem happened.
 
> So the broken boxes, which to be honest are few and far between these
> days, need to go, they really do.

Agreed.

-Andi

^ permalink raw reply

* Re: How can we make more use of memory for TCP properly?
From: Andi Kleen @ 2006-06-14  5:20 UTC (permalink / raw)
  To: Kumiko Ono; +Cc: netdev
In-Reply-To: <448F323A.7000005@cs.columbia.edu>

 
> Accorting to TCP man page, the kernel calculates the values of 
> sysctl_tcp_mem depending on available physical memory at boot time.
> I added 2GB RAM to a machine that had 2GB, and then it has 4GB RAM now. 
> However, the value of sysctl_tcp_mem[2] has not changed from 196608 
> (pages). The machine is running at Linux 2.6.16.5 i686 Intel(R) 
> Pentium(R) 4 CPU 3.06GHz.

TCP can only use low memory for this which is limited to around 900MB 
on 32bit systems. 64bit CPUs don't have this problem.

-Andi

^ permalink raw reply

* tcp_slow_start_after_idle
From: David Miller @ 2006-06-14  5:35 UTC (permalink / raw)
  To: netdev; +Cc: zach.brown, jheffner


Bringing back up this old topic:

	http://marc.theaimsgroup.com/?l=linux-netdev&m=114564962420171&w=2

I've decided to add this tunable to the net-2.6.18 tree, patch below.

The more I think about it, allowing it to be turned off is
reasonable, but it will be left on by default.

diff-tree 1cd14da556199b2827a92f1eaa9d3e8411c2b68d (from 2fa95182e211572e998c7d1f906aa74fb119b025)
Author: David S. Miller <davem@sunset.davemloft.net>
Date:   Tue Jun 13 22:33:04 2006 -0700

    [TCP]: Add tcp_slow_start_after_idle sysctl.
    
    A lot of people have asked for a way to disable tcp_cwnd_restart(),
    and it seems reasonable to add a sysctl to do that.
    
    Signed-off-by: David S. Miller <davem@davemloft.net>

diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index f12007b..d46338a 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -362,6 +362,13 @@ tcp_workaround_signed_windows - BOOLEAN
 	not receive a window scaling option from them.
 	Default: 0
 
+tcp_slow_start_after_idle - BOOLEAN
+	If set, provide RFC2861 behavior and time out the congestion
+	window after an idle period.  An idle period is defined at
+	the current RTO.  If unset, the congestion window will not
+	be timed out after an idle period.
+	Default: 1
+
 IP Variables:
 
 ip_local_port_range - 2 INTEGERS
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 98338ed..cee944d 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -405,6 +405,7 @@ enum
 	NET_TCP_BASE_MSS=114,
 	NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS=115,
 	NET_TCP_DMA_COPYBREAK=116,
+	NET_TCP_SLOW_START_AFTER_IDLE=117,
 };
 
 enum {
diff --git a/include/net/tcp.h b/include/net/tcp.h
index de88c54..bfc71f9 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -227,6 +227,7 @@ extern int sysctl_tcp_abc;
 extern int sysctl_tcp_mtu_probing;
 extern int sysctl_tcp_base_mss;
 extern int sysctl_tcp_workaround_signed_windows;
+extern int sysctl_tcp_slow_start_after_idle;
 
 extern atomic_t tcp_memory_allocated;
 extern atomic_t tcp_sockets_allocated;
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index e7fb665..ce4cd5f 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -690,6 +690,14 @@ ctl_table ipv4_table[] = {
 		.proc_handler	= &proc_dointvec
 	},
 #endif
+	{
+		.ctl_name	= NET_TCP_SLOW_START_AFTER_IDLE,
+		.procname	= "tcp_slow_start_after_idle",
+		.data		= &sysctl_tcp_slow_start_after_idle,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec
+	},
 	{ .ctl_name = 0 }
 };
 
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 743016b..be6d929 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -59,6 +59,9 @@ int sysctl_tcp_tso_win_divisor = 3;
 int sysctl_tcp_mtu_probing = 0;
 int sysctl_tcp_base_mss = 512;
 
+/* By default, RFC2861 behavior.  */
+int sysctl_tcp_slow_start_after_idle = 1;
+
 static void update_send_head(struct sock *sk, struct tcp_sock *tp,
 			     struct sk_buff *skb)
 {
@@ -138,7 +141,8 @@ static void tcp_event_data_sent(struct t
 	struct inet_connection_sock *icsk = inet_csk(sk);
 	const u32 now = tcp_time_stamp;
 
-	if (!tp->packets_out && (s32)(now - tp->lsndtime) > icsk->icsk_rto)
+	if (sysctl_tcp_slow_start_after_idle &&
+	    (!tp->packets_out && (s32)(now - tp->lsndtime) > icsk->icsk_rto))
 		tcp_cwnd_restart(sk, __sk_dst_get(sk));
 
 	tp->lsndtime = now;


^ permalink raw reply related

* Re: [RFC/PATCH 1/2] in-kernel sockets API
From: Brian F. G. Bidulock @ 2006-06-14  6:07 UTC (permalink / raw)
  To: Chase Venters; +Cc: netdev, linux-kernel
In-Reply-To: <200606131953.42002.chase.venters@clientec.com>

Chase,

On Tue, 13 Jun 2006, Chase Venters wrote:
> 
> > I don't think that it is fair to say that an unstable API/ABI, in of
> > itself, provides an incentive to open an existing proprietary driver.
> 
> Sure it does, depending on your perspective and what you're willing to 
> consider. The lack of a stable API/ABI means that if you don't want to have 
> to do work tracking the kernel, you should push to have your drivers merged.
> 

More work must be done to track the kernel before they are merged, thus
purposeless API changes, or unnecessary use of EXPORT_SYMBOL_GPL impedes
merging

Not all useful kernel modules will nor should be merged GPL or not.

I think that a policy that intentionally makes it hard for proprietary
modules to be developed defeats the purpose of ultimate opening and merging.
It might end up causing something like iBCS, LinuxABI, SVR D3DK, or ODI to
flourish obviating the principal goal.

The interface currently under discussion is ultimately derived from the BSD
socket-protocol interface, and IMHO should be EXPORT_SYMBOL instead of
EXPORT_SYMBOL_GPL, if only because using _GPL serves no purpose here and can
be defeated with 3 or 4 obvious (and probably existing) lines of code.  I
wrote similar wrappers for STREAMS TPI to Linux NET4 interface instead of
using pointers directly quite a few years ago.  I doubt I was the first.
There is nothing really so novel here that it deserves _GPL.


^ permalink raw reply

* [PATCH 1/2] 8139cp: fix eeprom read command length
From: Philip Craig @ 2006-06-14  6:43 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev

The read command for the 93C46/93C56 EEPROMS should be 3 bits plus
the address.  This doesn't appear to affect the operation of the
read command, but similar errors for write commands do cause failures.

Signed-off-by: Philip Craig <philipc@snapgear.com>

Index: linux-2.6.17-rc6/drivers/net/8139cp.c
===================================================================
--- linux-2.6.17-rc6.orig/drivers/net/8139cp.c	2006-06-14 16:02:00.000000000 +1000
+++ linux-2.6.17-rc6/drivers/net/8139cp.c	2006-06-14 16:03:29.000000000 +1000
@@ -1628,7 +1628,7 @@ static int read_eeprom (void __iomem *io
 	eeprom_delay ();

 	/* Shift the read command bits out. */
-	for (i = 4 + addr_len; i >= 0; i--) {
+	for (i = 3 + addr_len - 1; i >= 0; i--) {
 		int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
 		writeb (EE_ENB | dataval, ee_addr);
 		eeprom_delay ();

^ permalink raw reply

* [PATCH 2/2] 8139cp: add ethtool eeprom support
From: Philip Craig @ 2006-06-14  6:43 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev

Implement the ethtool eeprom operations for the 8139cp driver.
Tested on x86 and big-endian ARM.

Signed-off-by: Philip Craig <philipc@snapgear.com>

Index: linux-2.6.17-rc6/drivers/net/8139cp.c
===================================================================
--- linux-2.6.17-rc6.orig/drivers/net/8139cp.c	2006-06-14 15:59:26.000000000 +1000
+++ linux-2.6.17-rc6/drivers/net/8139cp.c	2006-06-14 15:59:53.000000000 +1000
@@ -401,6 +401,11 @@ static void cp_clean_rings (struct cp_pr
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void cp_poll_controller(struct net_device *dev);
 #endif
+static int cp_get_eeprom_len(struct net_device *dev);
+static int cp_get_eeprom(struct net_device *dev,
+			 struct ethtool_eeprom *eeprom, u8 *data);
+static int cp_set_eeprom(struct net_device *dev,
+			 struct ethtool_eeprom *eeprom, u8 *data);

 static struct pci_device_id cp_pci_tbl[] = {
 	{ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139,
@@ -1577,6 +1582,9 @@ static struct ethtool_ops cp_ethtool_ops
 	.get_strings		= cp_get_strings,
 	.get_ethtool_stats	= cp_get_ethtool_stats,
 	.get_perm_addr		= ethtool_op_get_perm_addr,
+	.get_eeprom_len		= cp_get_eeprom_len,
+	.get_eeprom		= cp_get_eeprom,
+	.set_eeprom		= cp_set_eeprom,
 };

 static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
@@ -1612,24 +1620,32 @@ static int cp_ioctl (struct net_device *
 #define eeprom_delay()	readl(ee_addr)

 /* The EEPROM commands include the alway-set leading bit. */
+#define EE_EXTEND_CMD	(4)
 #define EE_WRITE_CMD	(5)
 #define EE_READ_CMD		(6)
 #define EE_ERASE_CMD	(7)

-static int read_eeprom (void __iomem *ioaddr, int location, int addr_len)
-{
-	int i;
-	unsigned retval = 0;
-	void __iomem *ee_addr = ioaddr + Cfg9346;
-	int read_cmd = location | (EE_READ_CMD << addr_len);
+#define EE_EWDS_ADDR	(0)
+#define EE_WRAL_ADDR	(1)
+#define EE_ERAL_ADDR	(2)
+#define EE_EWEN_ADDR	(3)
+
+#define CP_EEPROM_MAGIC PCI_DEVICE_ID_REALTEK_8139

+static void eeprom_cmd_start(void __iomem *ee_addr)
+{
 	writeb (EE_ENB & ~EE_CS, ee_addr);
 	writeb (EE_ENB, ee_addr);
 	eeprom_delay ();
+}
+
+static void eeprom_cmd(void __iomem *ee_addr, int cmd, int cmd_len)
+{
+	int i;

-	/* Shift the read command bits out. */
-	for (i = 3 + addr_len - 1; i >= 0; i--) {
-		int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+	/* Shift the command bits out. */
+	for (i = cmd_len - 1; i >= 0; i--) {
+		int dataval = (cmd & (1 << i)) ? EE_DATA_WRITE : 0;
 		writeb (EE_ENB | dataval, ee_addr);
 		eeprom_delay ();
 		writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
@@ -1637,6 +1653,33 @@ static int read_eeprom (void __iomem *io
 	}
 	writeb (EE_ENB, ee_addr);
 	eeprom_delay ();
+}
+
+static void eeprom_cmd_end(void __iomem *ee_addr)
+{
+	writeb (~EE_CS, ee_addr);
+	eeprom_delay ();
+}
+
+static void eeprom_extend_cmd(void __iomem *ee_addr, int extend_cmd,
+			      int addr_len)
+{
+	int cmd = (EE_EXTEND_CMD << addr_len) | (extend_cmd << (addr_len - 2));
+
+	eeprom_cmd_start(ee_addr);
+	eeprom_cmd(ee_addr, cmd, 3 + addr_len);
+	eeprom_cmd_end(ee_addr);
+}
+
+static u16 read_eeprom (void __iomem *ioaddr, int location, int addr_len)
+{
+	int i;
+	u16 retval = 0;
+	void __iomem *ee_addr = ioaddr + Cfg9346;
+	int read_cmd = location | (EE_READ_CMD << addr_len);
+
+	eeprom_cmd_start(ee_addr);
+	eeprom_cmd(ee_addr, read_cmd, 3 + addr_len);

 	for (i = 16; i > 0; i--) {
 		writeb (EE_ENB | EE_SHIFT_CLK, ee_addr);
@@ -1648,13 +1691,125 @@ static int read_eeprom (void __iomem *io
 		eeprom_delay ();
 	}

-	/* Terminate the EEPROM access. */
-	writeb (~EE_CS, ee_addr);
-	eeprom_delay ();
+	eeprom_cmd_end(ee_addr);

 	return retval;
 }

+static void write_eeprom(void __iomem *ioaddr, int location, u16 val,
+			 int addr_len)
+{
+	int i;
+	void __iomem *ee_addr = ioaddr + Cfg9346;
+	int write_cmd = location | (EE_WRITE_CMD << addr_len);
+
+	eeprom_extend_cmd(ee_addr, EE_EWEN_ADDR, addr_len);
+
+	eeprom_cmd_start(ee_addr);
+	eeprom_cmd(ee_addr, write_cmd, 3 + addr_len);
+	eeprom_cmd(ee_addr, val, 16);
+	eeprom_cmd_end(ee_addr);
+
+	eeprom_cmd_start(ee_addr);
+	for (i = 0; i < 20000; i++)
+		if (readb(ee_addr) & EE_DATA_READ)
+			break;
+	eeprom_cmd_end(ee_addr);
+
+	eeprom_extend_cmd(ee_addr, EE_EWDS_ADDR, addr_len);
+}
+
+static int cp_get_eeprom_len(struct net_device *dev)
+{
+	struct cp_private *cp = netdev_priv(dev);
+	int size;
+
+	spin_lock_irq(&cp->lock);
+	size = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 256 : 128;
+	spin_unlock_irq(&cp->lock);
+
+	return size;
+}
+
+static int cp_get_eeprom(struct net_device *dev,
+			 struct ethtool_eeprom *eeprom, u8 *data)
+{
+	struct cp_private *cp = netdev_priv(dev);
+	unsigned int addr_len;
+	u16 val;
+	u32 offset = eeprom->offset >> 1;
+	u32 len = eeprom->len;
+	u32 i = 0;
+
+	eeprom->magic = CP_EEPROM_MAGIC;
+
+	spin_lock_irq(&cp->lock);
+
+	addr_len = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 8 : 6;
+
+	if (eeprom->offset & 1) {
+		val = read_eeprom(cp->regs, offset, addr_len);
+		data[i++] = (u8)(val >> 8);
+		offset++;
+	}
+
+	while (i < len - 1) {
+		val = read_eeprom(cp->regs, offset, addr_len);
+		data[i++] = (u8)val;
+		data[i++] = (u8)(val >> 8);
+		offset++;
+	}
+
+	if (i < len) {
+		val = read_eeprom(cp->regs, offset, addr_len);
+		data[i] = (u8)val;
+	}
+
+	spin_unlock_irq(&cp->lock);
+	return 0;
+}
+
+static int cp_set_eeprom(struct net_device *dev,
+			 struct ethtool_eeprom *eeprom, u8 *data)
+{
+	struct cp_private *cp = netdev_priv(dev);
+	unsigned int addr_len;
+	u16 val;
+	u32 offset = eeprom->offset >> 1;
+	u32 len = eeprom->len;
+	u32 i = 0;
+
+	if (eeprom->magic != CP_EEPROM_MAGIC)
+		return -EINVAL;
+
+	spin_lock_irq(&cp->lock);
+
+	addr_len = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 8 : 6;
+
+	if (eeprom->offset & 1) {
+		val = read_eeprom(cp->regs, offset, addr_len) & 0xff;
+		val |= (u16)data[i++] << 8;
+		write_eeprom(cp->regs, offset, val, addr_len);
+		offset++;
+	}
+
+	while (i < len - 1) {
+		val = (u16)data[i++];
+		val |= (u16)data[i++] << 8;
+		write_eeprom(cp->regs, offset, val, addr_len);
+		offset++;
+	}
+
+	if (i < len) {
+		val = read_eeprom(cp->regs, offset, addr_len) & 0xff00;
+		val |= (u16)data[i];
+		write_eeprom(cp->regs, offset, val, addr_len);
+	}
+
+	spin_unlock_irq(&cp->lock);
+	return 0;
+}
+
 /* Put the board into D3cold state and wait for WakeUp signal */
 static void cp_set_d3_state (struct cp_private *cp)
 {

^ permalink raw reply

* Re: [RFC/PATCH 1/2] in-kernel sockets API
From: Chase Venters @ 2006-06-14  7:58 UTC (permalink / raw)
  To: bidulock; +Cc: netdev, linux-kernel
In-Reply-To: <20060614000710.C7232@openss7.org>

On Wednesday 14 June 2006 01:06, Brian F. G. Bidulock wrote:
>
> The interface currently under discussion is ultimately derived from the BSD
> socket-protocol interface, and IMHO should be EXPORT_SYMBOL instead of
> EXPORT_SYMBOL_GPL, if only because using _GPL serves no purpose here and
> can be defeated with 3 or 4 obvious (and probably existing) lines of code. 
> I wrote similar wrappers for STREAMS TPI to Linux NET4 interface instead of
> using pointers directly quite a few years ago.  I doubt I was the first.
> There is nothing really so novel here that it deserves _GPL.

I mentioned that I don't have any particular opinion on the BSD socket API in 
this discussion. All that I'm speaking of here is a property of licensing. 

I've watched a lot of what has happened with binary drivers. You'll find in 
the LKML archives plenty of lengthy discussions about whether or not binary 
drivers are allowed under the GPL. If I were to guess, there is still 
disagreement. Although some hardware support could improve, we thankfully 
seem to have some kind of an equilibrium capable of supporting lots of users.

One point I remember coming up in the discussion was that the 
EXPORT_SYMBOL()/EXPORT_SYMBOL_GPL() split was a compromise of sorts. 
Interfaces that were needed to support users would reasonably be placed under 
EXPORT_SYMBOL(). By contrast, EXPORT_SYMBOL_GPL() would indicate 
functionality that would only seem to be used by derived works. It implies 
that any code using it should probably be GPL as well.

I don't raise this in an attempt to belittle anything people are working on. 
It's an observation about the ecosystem - Linux in the 2.6 series has seen a 
great amount of corporate contribution in terms of enhancing what the kernel 
is capable of doing. GPL, I believe, encourages this.

Thanks,
Chase

^ permalink raw reply

* Re: 2.6.17: networking bug??
From: Daniel Drake @ 2006-06-14  8:09 UTC (permalink / raw)
  To: Mark Lord; +Cc: John Heffner, Linus Torvalds, Linux Kernel, netdev, davem
In-Reply-To: <448F0D4B.30201@rtr.ca>

Mark Lord wrote:
> Further to this, the current behaviour is badly unpredictable.
> 
> A machine could be working perfectly, not (noticeably) affected
> by this bug.  And then the user adds another stick of RAM to it.

This "bug" already existed in 2.6.16 to a certain extent: you were 
losing out on a lot of TCP performance. Go back to 2.6.7, measure TCP 
performance, and you'll probably find it was significantly better.

Also, there aren't that many broken end-points out there. 
www.everymac.com loads fine for me and does not ignore the window scale 
factor.

The problem in your case is a broken router in the middle. I had the 
same problem: certain sites would not load, but there is absolutely 
nothing wrong with the servers that run these sites:

http://marc.theaimsgroup.com/?l=linux-netdev&m=114478312100641&w=2

I contacted my ISP and informed them of the issue. They fixed it 
nationwide within a few weeks. You might try confirming that your 
problem only applies to HTTP like mine did (ISP runs some lame 
transparent webcaches), and it was a bug in the software there (NetApp).

We already had the "some routers are broken, should we do anything" 
discussion back at the time of 2.6.8:

http://lwn.net/Articles/92727/

Daniel


^ permalink raw reply

* Re: [RFC/PATCH 1/2] in-kernel sockets API
From: Brian F. G. Bidulock @ 2006-06-14  9:28 UTC (permalink / raw)
  To: Chase Venters; +Cc: netdev, linux-kernel
In-Reply-To: <200606140258.30302.chase.venters@clientec.com>

Chase,

On Wed, 14 Jun 2006, Chase Venters wrote:
> 
> One point I remember coming up in the discussion was that the 
> EXPORT_SYMBOL()/EXPORT_SYMBOL_GPL() split was a compromise of sorts. 
> Interfaces that were needed to support users would reasonably be placed under 
> EXPORT_SYMBOL(). By contrast, EXPORT_SYMBOL_GPL() would indicate 
> functionality that would only seem to be used by derived works. It implies 
> that any code using it should probably be GPL as well.

The difficulty with EXPORT_SYMBOL_GPL() as I see it that it reached farther
than the GPL.  GPL does not impact non-derived works, which can be licensed
under any terms their authors see fit.  Whereas, EXPORT_SYMBOL_GPL() requires
a non-derived work to declare a GPL license to even use it.  If you subscribe
to the FSF view of derived work (just linking is a derivation) then I suppose
you would support the EXPORT_SYMBOL_GPL().  IANAL, but I don't believe that
TRIPS nor Berne Convention case law supports the FSF view.  Linus' statements
in the COPYING file take a different view: that simple use of a technical
interface is not necessarily (in itself) derivation.

Now, I understand the use of EXPORT_SYMBOL() vs. EXPORT_SYMBOL_GPL() to allow
authors to differ on this idea.  But, in the case in point, the function
pointers can be accessed by merely including the appropriate header files.
Changing a the wrapper access to them to EXPORT_SYMBOL_GPL() strikes me as
similar to changing kmalloc() from EXPORT_SYMBOL() to EXPORT_SYMBOL_GPL().

Understand that all exported symbols, regardless of licensing or modversions
or whatever, are available in the kernel boot image and can be linked to by
any module at any time.  That is, those that would abuse the concept of
derivation will not be impeded by EXPORT_SYMBOL_GPL().  (Rip the symbol from
the kernel image, write a thin GPL'ed module that aliases the symbol and the
exports it again as EXPORT_SYMBOL() without module versioning, copy the lines
of code into the proprietary module, reversing the order of arbitrary lines,
etc.)

In any case, all it serves to do is to punish honest non-derivative works not
published compatible with the GPL.

What I resist is the apparent attempt to change these symbols to _GPL as some
matter of general policy in this case contrary to the author's original
intentions as expressed in the original patch submission, and without the
author of the interface being wrappered jumping up an screaming that his code
was under strict FSF linking-is-derivation GPL (in which case we could have
had a good discussion on whether Linux NET4 is actually a derivative work of
BSD 4.4 Lite which was licensed under the "old" BSD license, incompatible with
the GPL ;)

As a general policy I would say make it EXPORT_SYMBOL() unless the author of
the patch (derivation) or author of the original (derived) code dictates that
it be EXPORT_SYMBOL_GPL().

Ok, I'll shut up now... ...really.

^ permalink raw reply

* [PATCH 0/2] NET: Accurate packet scheduling for ATM/ADSL
From: Jesper Dangaard Brouer @ 2006-06-14  9:40 UTC (permalink / raw)
  To: Stephen Hemminger, Jamal Hadi Salim, netdev, lartc
  Cc: russell-tcatm, hawk, hawk, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1311 bytes --]


The Linux traffic's control engine inaccurately calculates
transmission times for packets sent over ADSL links.  For
some packet sizes the error rises to over 50%.  This occurs
because ADSL uses ATM as its link layer transport, and ATM
transmits packets in fixed sized 53 byte cells.

The following patches to iproute2 and the kernel add an
option to calculate traffic transmission times over all
ATM links, including ADSL, with perfect accuracy.

A longer presentation of the patch, its rational, what it
does and how to use it can be found here:
   http://www.stuart.id.au/russell/files/tc/tc-atm/

A earlier version of the patch, and a _detailed_ empirical
investigation of its effects can be found here:
   http://www.adsl-optimizer.dk/

The patches are both backwards and forwards compatible.
This means unpatched kernels will work with a patched
version of iproute2, and an unpatched iproute2 will work
on patches kernels.


This is a combined effort of Jesper Brouer and Russell Stuart,
to get these patches into the upstream kernel.

Let the discussion start about what we need to change to get this
upstream?

We see this as a feature enhancement, as thus hope that it can be
queued in davem's net-2.6.18.git tree.

---
Regards,
 Jesper Brouer & Russell Stuart.


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 1/2] NET: Accurate packet scheduling for ATM/ADSL (kernel)
From: Jesper Dangaard Brouer @ 2006-06-14  9:40 UTC (permalink / raw)
  To: Stephen Hemminger, Jamal Hadi Salim, netdev, lartc
  Cc: russell-tcatm, hawk, hawk, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 4899 bytes --]


The Linux traffic's control engine inaccurately calculates
transmission times for packets sent over ADSL links.  For
some packet sizes the error rises to over 50%.  This occurs
because ADSL uses ATM as its link layer transport, and ATM
transmits packets in fixed sized 53 byte cells.

This changes the kernel rate table lookup, to be able to lookup
packet transmission times over all ATM links, including ADSL,
with perfect accuracy. The accuracy is dependent on the rate
table that is calculated in userspace by iproute2 command tc.

A longer presentation of the patch, its rational, what it
does and how to use it can be found here:
   http://www.stuart.id.au/russell/files/tc/tc-atm/

A earlier version of the patch, and a _detailed_ empirical
investigation of its effects can be found here:
   http://www.adsl-optimizer.dk/

Signed-off-by: Jesper Dangaard Brouer <hawk@comx.dk>
Signed-off-by: Russell Stuart <russell-tcatm@stuart.id.au>
---

diff -Nurp kernel-source-2.6.16.orig/include/linux/pkt_sched.h kernel-source-2.6.16/include/linux/pkt_sched.h
--- kernel-source-2.6.16.orig/include/linux/pkt_sched.h	2006-03-20 15:53:29.000000000 +1000
+++ kernel-source-2.6.16/include/linux/pkt_sched.h	2006-06-13 11:42:12.000000000 +1000
@@ -77,8 +77,9 @@ struct tc_ratespec
 {
 	unsigned char	cell_log;
 	unsigned char	__reserved;
-	unsigned short	feature;
-	short		addend;
+	unsigned short	feature;	/* Always 0 in pre-atm patch kernels */
+	char		cell_align;	/* Always 0 in pre-atm patch kernels */
+	unsigned char	__unused;
 	unsigned short	mpu;
 	__u32		rate;
 };
diff -Nurp kernel-source-2.6.16.orig/include/net/sch_generic.h kernel-source-2.6.16/include/net/sch_generic.h
--- kernel-source-2.6.16.orig/include/net/sch_generic.h	2006-03-20 15:53:29.000000000 +1000
+++ kernel-source-2.6.16/include/net/sch_generic.h	2006-06-13 11:42:12.000000000 +1000
@@ -307,4 +307,18 @@ drop:
 	return NET_XMIT_DROP;
 }
 
+/* Lookup a qdisc_rate_table to determine how long it will take to send a
+   packet given its size.
+ */
+static inline u32 qdisc_l2t(struct qdisc_rate_table* rtab, int pktlen)
+{
+	int slot = pktlen + rtab->rate.cell_align;
+	if (slot < 0)
+	  	slot = 0;
+	slot >>= rtab->rate.cell_log;
+	if (slot > 255)
+		return rtab->data[255] + 1;
+	return rtab->data[slot];
+}
+
 #endif
diff -Nurp kernel-source-2.6.16.orig/net/sched/act_police.c kernel-source-2.6.16/net/sched/act_police.c
--- kernel-source-2.6.16.orig/net/sched/act_police.c	2006-03-20 15:53:29.000000000 +1000
+++ kernel-source-2.6.16/net/sched/act_police.c	2006-06-13 11:42:12.000000000 +1000
@@ -33,8 +33,8 @@
 #include <net/sock.h>
 #include <net/act_api.h>
 
-#define L2T(p,L)   ((p)->R_tab->data[(L)>>(p)->R_tab->rate.cell_log])
-#define L2T_P(p,L) ((p)->P_tab->data[(L)>>(p)->P_tab->rate.cell_log])
+#define L2T(p,L)   qdisc_l2t((p)->R_tab,L)
+#define L2T_P(p,L) qdisc_l2t((p)->P_tab,L)
 #define PRIV(a) ((struct tcf_police *) (a)->priv)
 
 /* use generic hash table */
diff -Nurp kernel-source-2.6.16.orig/net/sched/sch_cbq.c kernel-source-2.6.16/net/sched/sch_cbq.c
--- kernel-source-2.6.16.orig/net/sched/sch_cbq.c	2006-03-20 15:53:29.000000000 +1000
+++ kernel-source-2.6.16/net/sched/sch_cbq.c	2006-06-13 11:42:12.000000000 +1000
@@ -193,7 +193,7 @@ struct cbq_sched_data
 };
 
 
-#define L2T(cl,len)	((cl)->R_tab->data[(len)>>(cl)->R_tab->rate.cell_log])
+#define L2T(cl,len)	qdisc_l2t((cl)->R_tab,len)
 
 
 static __inline__ unsigned cbq_hash(u32 h)
diff -Nurp kernel-source-2.6.16.orig/net/sched/sch_htb.c kernel-source-2.6.16/net/sched/sch_htb.c
--- kernel-source-2.6.16.orig/net/sched/sch_htb.c	2006-03-20 15:53:29.000000000 +1000
+++ kernel-source-2.6.16/net/sched/sch_htb.c	2006-06-13 11:42:12.000000000 +1000
@@ -206,12 +206,10 @@ struct htb_class
 static __inline__ long L2T(struct htb_class *cl,struct qdisc_rate_table *rate,
 	int size)
 { 
-    int slot = size >> rate->rate.cell_log;
-    if (slot > 255) {
+    long result = qdisc_l2t(rate, size);
+    if (result > rate->data[255])
 	cl->xstats.giants++;
-	slot = 255;
-    }
-    return rate->data[slot];
+    return result;
 }
 
 struct htb_sched
diff -Nurp kernel-source-2.6.16.orig/net/sched/sch_tbf.c kernel-source-2.6.16/net/sched/sch_tbf.c
--- kernel-source-2.6.16.orig/net/sched/sch_tbf.c	2006-03-20 15:53:29.000000000 +1000
+++ kernel-source-2.6.16/net/sched/sch_tbf.c	2006-06-13 11:42:12.000000000 +1000
@@ -132,8 +132,8 @@ struct tbf_sched_data
 	struct Qdisc	*qdisc;		/* Inner qdisc, default - bfifo queue */
 };
 
-#define L2T(q,L)   ((q)->R_tab->data[(L)>>(q)->R_tab->rate.cell_log])
-#define L2T_P(q,L) ((q)->P_tab->data[(L)>>(q)->P_tab->rate.cell_log])
+#define L2T(q,L)   qdisc_l2t((q)->R_tab,L)
+#define L2T_P(q,L) qdisc_l2t((q)->P_tab,L)
 
 static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 {



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 2/2] NET: Accurate packet scheduling for ATM/ADSL (userspace)
From: Jesper Dangaard Brouer @ 2006-06-14  9:40 UTC (permalink / raw)
  To: Stephen Hemminger, Jamal Hadi Salim, netdev, lartc
  Cc: russell-tcatm, hawk, hawk, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 22649 bytes --]


The Linux traffic's control engine inaccurately calculates
transmission times for packets sent over ADSL links.  For
some packet sizes the error rises to over 50%.  This occurs
because ADSL uses ATM as its link layer transport, and ATM
transmits packets in fixed sized 53 byte cells.

This changes the userspace tool iproute2/tc by adding an
option to calculate traffic transmission times (rate table)
over all ATM links, including ADSL, with perfect accuracy.

A longer presentation of the patch, its rational, what it
does and how to use it can be found here:
   http://www.stuart.id.au/russell/files/tc/tc-atm/

A earlier version of the patch, and a _detailed_ empirical
investigation of its effects can be found here:
   http://www.adsl-optimizer.dk/

Signed-off-by: Jesper Dangaard Brouer <hawk@comx.dk>
Signed-off-by: Russell Stuart <russell-tcatm@stuart.id.au>
---

diff -Nurp iproute2.orig/include/linux/pkt_sched.h iproute2/include/linux/pkt_sched.h
--- iproute2.orig/include/linux/pkt_sched.h	2005-12-10 09:27:44.000000000 +1000
+++ iproute2/include/linux/pkt_sched.h	2006-06-13 11:53:27.000000000 +1000
@@ -77,8 +77,9 @@ struct tc_ratespec
 {
 	unsigned char	cell_log;
 	unsigned char	__reserved;
-	unsigned short	feature;
-	short		addend;
+	unsigned short	feature;	/* Always 0 in pre-atm patch kernels */
+	char		cell_align;	/* Always 0 in pre-atm patch kernels */
+	unsigned char	__unused;
 	unsigned short	mpu;
 	__u32		rate;
 };
diff -Nurp iproute2.orig/tc/m_police.c iproute2/tc/m_police.c
--- iproute2.orig/tc/m_police.c	2005-01-19 08:11:58.000000000 +1000
+++ iproute2/tc/m_police.c	2006-06-13 11:53:27.000000000 +1000
@@ -35,7 +35,7 @@ struct action_util police_action_util = 
 static void explain(void)
 {
 	fprintf(stderr, "Usage: ... police rate BPS burst BYTES[/BYTES] [ mtu BYTES[/BYTES] ]\n");
-	fprintf(stderr, "                [ peakrate BPS ] [ avrate BPS ]\n");
+	fprintf(stderr, "                [ peakrate BPS ] [ avrate BPS ] [ overhead OVERHEAD ] [ atm ]\n");
 	fprintf(stderr, "                [ ACTIONTERM ]\n");
 	fprintf(stderr, "Old Syntax ACTIONTERM := action <EXCEEDACT>[/NOTEXCEEDACT] \n"); 
 	fprintf(stderr, "New Syntax ACTIONTERM := conform-exceed <EXCEEDACT>[/NOTEXCEEDACT] \n"); 
@@ -134,7 +134,10 @@ int act_parse_police(struct action_util 
 	__u32 ptab[256];
 	__u32 avrate = 0;
 	int presult = 0;
-	unsigned buffer=0, mtu=0, mpu=0;
+	unsigned buffer=0, mtu=0;
+	__u8 mpu=0;
+	__s8 overhead=0;
+	int atm=0;
 	int Rcell_log=-1, Pcell_log = -1; 
 	struct rtattr *tail;
 
@@ -184,7 +187,7 @@ int act_parse_police(struct action_util 
 				fprintf(stderr, "Double \"mpu\" spec\n");
 				return -1;
 			}
-			if (get_size(&mpu, *argv)) {
+			if (get_u8(&mpu, *argv, 10)) {
 				explain1("mpu");
 				return -1;
 			}
@@ -198,6 +201,18 @@ int act_parse_police(struct action_util 
 				explain1("rate");
 				return -1;
 			}
+		} else if (strcmp(*argv, "overhead") == 0) {
+			NEXT_ARG();
+			if (p.rate.rate) {
+				fprintf(stderr, "Double \"overhead\" spec\n");
+				return -1;
+			}
+			if (get_s8(&overhead, *argv, 10)) {
+				explain1("overhead");
+				return -1;
+			}
+		} else if (strcmp(*argv, "atm") == 0) {
+		  	atm = 1;
 		} else if (strcmp(*argv, "avrate") == 0) {
 			NEXT_ARG();
 			if (avrate) {
@@ -264,22 +279,12 @@ int act_parse_police(struct action_util 
 	}
 
 	if (p.rate.rate) {
-		if ((Rcell_log = tc_calc_rtable(p.rate.rate, rtab, Rcell_log, mtu, mpu)) < 0) {
-			fprintf(stderr, "TBF: failed to calculate rate table.\n");
-			return -1;
-		}
+	  	tc_calc_ratespec(&p.rate, rtab, p.rate.rate, Rcell_log, mtu, mpu, atm, overhead);
 		p.burst = tc_calc_xmittime(p.rate.rate, buffer);
-		p.rate.cell_log = Rcell_log;
-		p.rate.mpu = mpu;
 	}
 	p.mtu = mtu;
 	if (p.peakrate.rate) {
-		if ((Pcell_log = tc_calc_rtable(p.peakrate.rate, ptab, Pcell_log, mtu, mpu)) < 0) {
-			fprintf(stderr, "POLICE: failed to calculate peak rate table.\n");
-			return -1;
-		}
-		p.peakrate.cell_log = Pcell_log;
-		p.peakrate.mpu = mpu;
+	  	tc_calc_ratespec(&p.peakrate, ptab, p.peakrate.rate, Pcell_log, mtu, mpu, atm, overhead);
 	}
 
 	tail = NLMSG_TAIL(n);
diff -Nurp iproute2.orig/tc/q_cbq.c iproute2/tc/q_cbq.c
--- iproute2.orig/tc/q_cbq.c	2005-07-06 08:37:15.000000000 +1000
+++ iproute2/tc/q_cbq.c	2006-06-13 11:53:27.000000000 +1000
@@ -32,6 +32,7 @@ static void explain_class(void)
 	fprintf(stderr, "               [ prio NUMBER ] [ cell BYTES ] [ ewma LOG ]\n");
 	fprintf(stderr, "               [ estimator INTERVAL TIME_CONSTANT ]\n");
 	fprintf(stderr, "               [ split CLASSID ] [ defmap MASK/CHANGE ]\n");
+	fprintf(stderr, "               [ overhead BYTES ] [ atm ]\n");
 }
 
 static void explain(void)
@@ -52,7 +53,10 @@ static int cbq_parse_opt(struct qdisc_ut
 	struct tc_ratespec r;
 	struct tc_cbq_lssopt lss;
 	__u32 rtab[256];
-	unsigned mpu=0, avpkt=0, allot=0;
+	unsigned avpkt=0, allot=0;
+	__u8 mpu=0;
+	__s8 overhead=0;
+	int atm=0;
 	int cell_log=-1; 
 	int ewma_log=-1;
 	struct rtattr *tail;
@@ -102,7 +106,7 @@ static int cbq_parse_opt(struct qdisc_ut
 			}
 		} else if (strcmp(*argv, "mpu") == 0) {
 			NEXT_ARG();
-			if (get_size(&mpu, *argv)) {
+			if (get_u8(&mpu, *argv, 10)) {
 				explain1("mpu");
 				return -1;
 			}
@@ -113,6 +117,14 @@ static int cbq_parse_opt(struct qdisc_ut
 				explain1("allot");
 				return -1;
 			}
+		} else if (strcmp(*argv, "overhead") == 0) {
+			NEXT_ARG();
+			if (get_s8(&overhead, *argv, 10)) {
+				explain1("overhead");
+				return -1;
+			}
+		} else if (strcmp(*argv, "atm") == 0) {
+		  	atm = 1;
 		} else if (strcmp(*argv, "help") == 0) {
 			explain();
 			return -1;
@@ -137,12 +149,7 @@ static int cbq_parse_opt(struct qdisc_ut
 	if (allot < (avpkt*3)/2)
 		allot = (avpkt*3)/2;
 
-	if ((cell_log = tc_calc_rtable(r.rate, rtab, cell_log, allot, mpu)) < 0) {
-		fprintf(stderr, "CBQ: failed to calculate rate table.\n");
-		return -1;
-	}
-	r.cell_log = cell_log;
-	r.mpu = mpu;
+	tc_calc_ratespec(&r, rtab, r.rate, cell_log, allot, mpu, atm, overhead);
 
 	if (ewma_log < 0)
 		ewma_log = TC_CBQ_DEF_EWMA;
@@ -175,7 +182,9 @@ static int cbq_parse_class_opt(struct qd
 	struct tc_cbq_fopt fopt;
 	struct tc_cbq_ovl ovl;
 	__u32 rtab[256];
-	unsigned mpu=0;
+	__u8 mpu=0;
+	__s8 overhead = 0;
+	int atm = 0;
 	int cell_log=-1; 
 	int ewma_log=-1;
 	unsigned bndw = 0;
@@ -289,10 +298,18 @@ static int cbq_parse_class_opt(struct qd
 			lss.change |= TCF_CBQ_LSS_AVPKT;
 		} else if (strcmp(*argv, "mpu") == 0) {
 			NEXT_ARG();
-			if (get_size(&mpu, *argv)) {
+			if (get_u8(&mpu, *argv, 10)) {
 				explain1("mpu");
 				return -1;
 			}
+		} else if (strcmp(*argv, "overhead") == 0) {
+			NEXT_ARG();
+			if (get_s8(&overhead, *argv, 10)) {
+				explain1("overhead");
+				return -1;
+			}
+		} else if (strcmp(*argv, "atm") == 0) {
+		  	atm = 1;
 		} else if (strcmp(*argv, "weight") == 0) {
 			NEXT_ARG();
 			if (get_size(&wrr.weight, *argv)) {
@@ -336,12 +353,7 @@ static int cbq_parse_class_opt(struct qd
 		unsigned pktsize = wrr.allot;
 		if (wrr.allot < (lss.avpkt*3)/2)
 			wrr.allot = (lss.avpkt*3)/2;
-		if ((cell_log = tc_calc_rtable(r.rate, rtab, cell_log, pktsize, mpu)) < 0) {
-			fprintf(stderr, "CBQ: failed to calculate rate table.\n");
-			return -1;
-		}
-		r.cell_log = cell_log;
-		r.mpu = mpu;
+		tc_calc_ratespec(&r, rtab, r.rate, cell_log, pktsize, mpu, atm, overhead);
 	}
 	if (ewma_log < 0)
 		ewma_log = TC_CBQ_DEF_EWMA;
@@ -463,8 +475,12 @@ static int cbq_print_opt(struct qdisc_ut
 		fprintf(f, "rate %s ", buf);
 		if (show_details) {
 			fprintf(f, "cell %ub ", 1<<r->cell_log);
-			if (r->mpu)
-				fprintf(f, "mpu %ub ", r->mpu);
+			if (r->mpu & 0xff)
+				fprintf(f, "mpu %ub ", (__u8)r->mpu);
+			if ((r->mpu >> 8))
+				fprintf(f, "overhead %db ", (__s8)(r->mpu >> 8));
+			if (r->feature & 0x0001)
+				fprintf(f, "atm ");
 		}
 	}
 	if (lss && lss->flags) {
diff -Nurp iproute2.orig/tc/q_htb.c iproute2/tc/q_htb.c
--- iproute2.orig/tc/q_htb.c	2005-01-19 08:11:58.000000000 +1000
+++ iproute2/tc/q_htb.c	2006-06-13 11:53:27.000000000 +1000
@@ -34,14 +34,14 @@ static void explain(void)
 		" default  minor id of class to which unclassified packets are sent {0}\n"
 		" r2q      DRR quantums are computed as rate in Bps/r2q {10}\n"
 		" debug    string of 16 numbers each 0-3 {0}\n\n"
-		"... class add ... htb rate R1 [burst B1] [mpu B] [overhead O]\n"
+		"... class add ... htb rate R1 [burst B1] [mpu B] [overhead O] [atm]\n"
 		"                      [prio P] [slot S] [pslot PS]\n"
 		"                      [ceil R2] [cburst B2] [mtu MTU] [quantum Q]\n"
 		" rate     rate allocated to this class (class can still borrow)\n"
 		" burst    max bytes burst which can be accumulated during idle period {computed}\n"
 		" mpu      minimum packet size used in rate computations\n"
 		" overhead per-packet size overhead used in rate computations\n"
-
+		" atm      include atm cell tax in rate computations\n"
 		" ceil     definite upper class rate (no borrows) {rate}\n"
 		" cburst   burst but for ceil {computed}\n"
 		" mtu      max packet size we create rate map for {1600}\n"
@@ -107,8 +107,10 @@ static int htb_parse_class_opt(struct qd
 	__u32 rtab[256],ctab[256];
 	unsigned buffer=0,cbuffer=0;
 	int cell_log=-1,ccell_log = -1;
-	unsigned mtu, mpu;
-	unsigned char mpu8 = 0, overhead = 0;
+	unsigned mtu;
+	__u8 mpu8=0;
+	__s8 overhead=0;
+	int atm=0;
 	struct rtattr *tail;
 
 	memset(&opt, 0, sizeof(opt)); mtu = 1600; /* eth packet len */
@@ -132,9 +134,11 @@ static int htb_parse_class_opt(struct qd
 			}
 		} else if (matches(*argv, "overhead") == 0) {
 			NEXT_ARG();
-			if (get_u8(&overhead, *argv, 10)) {
+			if (get_s8(&overhead, *argv, 10)) {
 				explain1("overhead"); return -1;
 			}
+		} else if (matches(*argv, "atm") == 0) {
+			atm = 1;
 		} else if (matches(*argv, "quantum") == 0) {
 			NEXT_ARG();
 			if (get_u32(&opt.quantum, *argv, 10)) {
@@ -206,23 +210,11 @@ static int htb_parse_class_opt(struct qd
 	if (!buffer) buffer = opt.rate.rate / get_hz() + mtu;
 	if (!cbuffer) cbuffer = opt.ceil.rate / get_hz() + mtu;
 
-/* encode overhead and mpu, 8 bits each, into lower 16 bits */
-	mpu = (unsigned)mpu8 | (unsigned)overhead << 8;
-	opt.ceil.mpu = mpu; opt.rate.mpu = mpu;
-
-	if ((cell_log = tc_calc_rtable(opt.rate.rate, rtab, cell_log, mtu, mpu)) < 0) {
-		fprintf(stderr, "htb: failed to calculate rate table.\n");
-		return -1;
-	}
+	/* encode overhead and mpu, 8 bits each, into lower 16 bits */
+	tc_calc_ratespec(&opt.rate, rtab, opt.rate.rate, cell_log, mtu, mpu8, atm, overhead);
+	tc_calc_ratespec(&opt.ceil, ctab, opt.ceil.rate, cell_log, mtu, mpu8, atm, overhead);
 	opt.buffer = tc_calc_xmittime(opt.rate.rate, buffer);
-	opt.rate.cell_log = cell_log;
-	
-	if ((ccell_log = tc_calc_rtable(opt.ceil.rate, ctab, cell_log, mtu, mpu)) < 0) {
-		fprintf(stderr, "htb: failed to calculate ceil rate table.\n");
-		return -1;
-	}
 	opt.cbuffer = tc_calc_xmittime(opt.ceil.rate, cbuffer);
-	opt.ceil.cell_log = ccell_log;
 
 	tail = NLMSG_TAIL(n);
 	addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
@@ -267,12 +259,16 @@ static int htb_print_opt(struct qdisc_ut
 			sprint_size(buffer, b1),
 			1<<hopt->rate.cell_log,
 			sprint_size(hopt->rate.mpu&0xFF, b2),
-			sprint_size((hopt->rate.mpu>>8)&0xFF, b3));
+			sprint_size((__s8)(hopt->rate.mpu>>8), b3));
+		if (hopt->rate.feature & 0x0001)
+			fprintf(f, "atm ");
 		fprintf(f, "cburst %s/%u mpu %s overhead %s ",
 			sprint_size(cbuffer, b1),
 			1<<hopt->ceil.cell_log,
 			sprint_size(hopt->ceil.mpu&0xFF, b2),
-			sprint_size((hopt->ceil.mpu>>8)&0xFF, b3));
+			sprint_size((__s8)(hopt->ceil.mpu>>8), b3));
+		if (hopt->ceil.feature & 0x0001)
+			fprintf(f, "atm ");
 		fprintf(f, "level %d ", (int)hopt->level);
 	    } else {
 		fprintf(f, "burst %s ", sprint_size(buffer, b1));
diff -Nurp iproute2.orig/tc/q_tbf.c iproute2/tc/q_tbf.c
--- iproute2.orig/tc/q_tbf.c	2005-01-19 08:11:58.000000000 +1000
+++ iproute2/tc/q_tbf.c	2006-06-13 11:53:27.000000000 +1000
@@ -26,7 +26,7 @@
 static void explain(void)
 {
 	fprintf(stderr, "Usage: ... tbf limit BYTES burst BYTES[/BYTES] rate KBPS [ mtu BYTES[/BYTES] ]\n");
-	fprintf(stderr, "               [ peakrate KBPS ] [ latency TIME ]\n");
+	fprintf(stderr, "               [ peakrate KBPS ] [ latency TIME ] [ overhead OVERHEAD ] [ atm ]\n");
 }
 
 static void explain1(char *arg)
@@ -43,7 +43,10 @@ static int tbf_parse_opt(struct qdisc_ut
 	struct tc_tbf_qopt opt;
 	__u32 rtab[256];
 	__u32 ptab[256];
-	unsigned buffer=0, mtu=0, mpu=0, latency=0;
+	unsigned buffer=0, mtu=0, latency=0;
+	__u8 mpu=0;
+	__s8 overhead=0;
+	int atm=0;
 	int Rcell_log=-1, Pcell_log = -1; 
 	struct rtattr *tail;
 
@@ -103,7 +106,7 @@ static int tbf_parse_opt(struct qdisc_ut
 				fprintf(stderr, "Double \"mpu\" spec\n");
 				return -1;
 			}
-			if (get_size(&mpu, *argv)) {
+			if (get_u8(&mpu, *argv, 10)) {
 				explain1("mpu");
 				return -1;
 			}
@@ -119,6 +122,20 @@ static int tbf_parse_opt(struct qdisc_ut
 				return -1;
 			}
 			ok++;
+		} else if (strcmp(*argv, "overhead") == 0) {
+			NEXT_ARG();
+			if (overhead) {
+				fprintf(stderr, "Double \"overhead\" spec\n");
+				return -1;
+			}
+			if (get_s8(&overhead, *argv, 10)) {
+				explain1("overhead");
+				return -1;
+			}
+			ok++;
+		} else if (strcmp(*argv, "atm") == 0) {
+			atm = 1;
+			ok++;
 		} else if (matches(*argv, "peakrate") == 0) {
 			NEXT_ARG();
 			if (opt.peakrate.rate) {
@@ -170,21 +187,11 @@ static int tbf_parse_opt(struct qdisc_ut
 		opt.limit = lim;
 	}
 
-	if ((Rcell_log = tc_calc_rtable(opt.rate.rate, rtab, Rcell_log, mtu, mpu)) < 0) {
-		fprintf(stderr, "TBF: failed to calculate rate table.\n");
-		return -1;
-	}
+	tc_calc_ratespec(&opt.rate, rtab, opt.rate.rate, Rcell_log, mtu, mpu, atm, overhead);
 	opt.buffer = tc_calc_xmittime(opt.rate.rate, buffer);
-	opt.rate.cell_log = Rcell_log;
-	opt.rate.mpu = mpu;
 	if (opt.peakrate.rate) {
-		if ((Pcell_log = tc_calc_rtable(opt.peakrate.rate, ptab, Pcell_log, mtu, mpu)) < 0) {
-			fprintf(stderr, "TBF: failed to calculate peak rate table.\n");
-			return -1;
-		}
+	  	tc_calc_ratespec(&opt.peakrate, ptab, opt.peakrate.rate, Pcell_log, mtu, mpu, atm, overhead);
 		opt.mtu = tc_calc_xmittime(opt.peakrate.rate, mtu);
-		opt.peakrate.cell_log = Pcell_log;
-		opt.peakrate.mpu = mpu;
 	}
 
 	tail = NLMSG_TAIL(n);
@@ -220,8 +227,12 @@ static int tbf_print_opt(struct qdisc_ut
 	fprintf(f, "rate %s ", sprint_rate(qopt->rate.rate, b1));
 	buffer = ((double)qopt->rate.rate*tc_core_tick2usec(qopt->buffer))/1000000;
 	if (show_details) {
-		fprintf(f, "burst %s/%u mpu %s ", sprint_size(buffer, b1),
-			1<<qopt->rate.cell_log, sprint_size(qopt->rate.mpu, b2));
+		fprintf(f, "burst %s/%u mpu %s overhead %d ", sprint_size(buffer, b1),
+			1<<qopt->rate.cell_log,
+			sprint_size(qopt->rate.mpu & 0xFF, b2),
+			(__s8)(qopt->rate.mpu >> 8));
+		if (qopt->rate.feature & 0x0001)
+			fprintf(f, "atm ");
 	} else {
 		fprintf(f, "burst %s ", sprint_size(buffer, b1));
 	}
@@ -232,8 +243,12 @@ static int tbf_print_opt(struct qdisc_ut
 		if (qopt->mtu || qopt->peakrate.mpu) {
 			mtu = ((double)qopt->peakrate.rate*tc_core_tick2usec(qopt->mtu))/1000000;
 			if (show_details) {
-				fprintf(f, "mtu %s/%u mpu %s ", sprint_size(mtu, b1),
-					1<<qopt->peakrate.cell_log, sprint_size(qopt->peakrate.mpu, b2));
+				fprintf(f, "mtu %s/%u mpu %s overhead %d ", sprint_size(mtu, b1),
+					1<<qopt->peakrate.cell_log,
+					sprint_size(qopt->peakrate.mpu & 0xFF, b2),
+					(__s8)(qopt->peakrate.mpu >> 8));
+				if (qopt->peakrate.feature & 0x0001)
+					fprintf(f, "atm ");
 			} else {
 				fprintf(f, "minburst %s ", sprint_size(mtu, b1));
 			}
diff -Nurp iproute2.orig/tc/tc_core.c iproute2/tc/tc_core.c
--- iproute2.orig/tc/tc_core.c	2004-07-31 06:26:15.000000000 +1000
+++ iproute2/tc/tc_core.c	2006-06-13 11:53:27.000000000 +1000
@@ -23,6 +23,9 @@
 
 #include "tc_core.h"
 
+#define	ATM_CELL_SIZE		53
+#define	ATM_CELL_PAYLOAD	48
+
 static __u32 t2us=1;
 static __u32 us2t=1;
 static double tick_in_usec = 1;
@@ -43,33 +46,124 @@ unsigned tc_calc_xmittime(unsigned rate,
 }
 
 /*
-   rtab[pkt_len>>cell_log] = pkt_xmit_time
+ * Calculate the ATM cell overhead.  ATM sends each packet in 48 byte
+ * chunks, the last chunk being padded if necessary.  Each chunk carries
+ * an additional 5 byte overhead - the ATM header.
  */
+static int tc_align_to_cells(int size) 
+{
+	int cells;
+
+	cells = size / ATM_CELL_PAYLOAD;
+	if (size % ATM_CELL_PAYLOAD != 0)
+		cells++;
+	return cells * ATM_CELL_SIZE;
+}
 
-int tc_calc_rtable(unsigned bps, __u32 *rtab, int cell_log, unsigned mtu,
-		   unsigned mpu)
+/*
+ * The number this function calculates is subtle.  Ignore it and just believe
+ * it works if you have a choice, otherwise ..
+ *
+ * If there we are calculating the ATM cell overhead the kernel calculations
+ * will be out sometimes if the range of packet sizes spanned by one
+ * rate table element crosses an ATM cell boundary.  Consider these three
+ * senarios:
+ *    (a) the packet is sent across the ATM link without addition
+ *        overheads the kernel doesn't know about, and
+ *    (b) a packet that has 1 byte of additional overhead the kernel
+ *        doesn't know about.  Here
+ *    (c) a packet that has 2 bytes of additional overhead the
+ *        kernel doesn't know about.
+ * The table below presents what happens.  Each row is for a single rate
+ * table element.  The "Sizes" column shows what packet sizes the rate table
+ * element will be used for.  This packet size includes the "unknown to
+ * kernel" overhead, but does not include overhead incurred by breaking the
+ * packet up into ATM cells. This ATM cell overhead consists of the 5 byte
+ * header per ATM cell, plus the padding in the last cell.  The "ATM" column
+ * shows how many bytes are actually sent across the ATM link, ie it does
+ * include the ATM cell overhead.
+ *
+ *   RateTable Entry  Sizes(a) ATM(a)    Sizes(b) ATM(b)   Sizes(c) ATM(c)
+ *      ratetable[0]    0..7    53        1..8     53        2..9    53
+ *      ratetable[1]    8..15   53        9..16    53        2..17   53
+ *      ratetable[2]   16..23   53       17..24    53       18..25   53
+ *      ratetable[3]   24..31   53       25..32    53       26..33   53
+ *      ratetable[4]   32..39   53       33..40    53       34..41   53
+ *      ratetable[5]   40..47   53       41..48    53       42..49   53,106
+ *      ratetable[6]   48..55   53,106   49..56   106       50..57  106
+ *
+ * For senario (a), the ratetable[6] entry covers two cases: one were a single
+ * ATM cell is needed to transmit the data, and one where two ATM cells are
+ * required.  It can't be right for both.  Unfortunately the error is large.
+ * The same problem arises in senario (c) for ratetable[5].  The problem
+ * doesn't happen for senario (b), because the boundary between rate table
+ * entries happens to match the boundary between ATM cells.
+ *
+ * What we would like to do is ensure that ratetable boundaries always match
+ * the ATM cells.  If we do this the error goes away.  The solution is to make
+ * the kernel add a small bias to the packet size.  (Small because the bias
+ * will always be smaller than cell_log.)  Adding this small bias will in
+ * effect slide the ratetable along a bit, so the boundaries match.  The code
+ * below calculates that bias.  Provided the MTU is less than 4092, doing
+ * this can always eliminate the error.
+ *
+ * Old kernels won't add this bias, so they will have the error described above
+ * in most cases.  In the worst case senario, considering all possible ATM cell
+ * sizes (1..48), for 7 of these sizes the old kernel will calculate the rate
+ * wrongly - ie, be out by 53 bytes.
+ */
+static int tc_calc_cell_align(int atm_cell_tax, char overhead, int cell_log)
+{
+	int cell_size;
+
+  	if (!atm_cell_tax)
+	  	return 0;
+	cell_size = 1 << cell_log;
+	return (overhead + cell_size - 2) % cell_size - cell_size + 1;
+}
+
+
+/*
+ * A constructor for a tc_ratespec.
+ */
+void tc_calc_ratespec(struct tc_ratespec* spec, __u32* rtab, unsigned bps,
+	int cell_log, unsigned mtu, unsigned char mpu, int atm_cell_tax,
+	char overhead)
 {
 	int i;
-	unsigned overhead = (mpu >> 8) & 0xFF;
-	mpu = mpu & 0xFF;
 
 	if (mtu == 0)
 		mtu = 2047;
 
+	/* rtab[pkt_len>>cell_log] = pkt_xmit_time */
 	if (cell_log < 0) {
 		cell_log = 0;
 		while ((mtu>>cell_log) > 255)
 			cell_log++;
 	}
+
 	for (i=0; i<256; i++) {
-		unsigned sz = (i<<cell_log);
-		if (overhead)
-			sz += overhead;
+	  	/*
+		 * sz is the length of packet we will use for this ratetable
+		 * entry.  The time taken to send a packet of this length will
+		 * be used for all packet lengths this ratetable entry applies
+		 * to.  As underestimating how long it will take to transmit a
+		 * packet is a worse error than overestimating it, the longest
+		 * packet this rate table entry applies to is used.
+		 */
+		int sz = ((i+1)<<cell_log) - 1 + overhead;
 		if (sz < mpu)
 			sz = mpu;
-		rtab[i] = tc_core_usec2tick(1000000*((double)sz/bps));
+		if (atm_cell_tax)
+			sz = tc_align_to_cells(sz);
+		rtab[i] = tc_calc_xmittime(bps, sz);
 	}
-	return cell_log;
+
+	spec->cell_align = tc_calc_cell_align(atm_cell_tax, overhead, cell_log);
+	spec->cell_log = cell_log;
+	spec->feature = 0x8000 | (atm_cell_tax ? 1 : 0);
+	spec->mpu = mpu | (unsigned)(overhead << 8);
+	spec->rate = bps;
 }
 
 int tc_core_init()
diff -Nurp iproute2.orig/tc/tc_core.h iproute2/tc/tc_core.h
--- iproute2.orig/tc/tc_core.h	2005-03-15 05:02:41.000000000 +1000
+++ iproute2/tc/tc_core.h	2006-06-13 11:53:27.000000000 +1000
@@ -7,7 +7,9 @@
 long tc_core_usec2tick(long usec);
 long tc_core_tick2usec(long tick);
 unsigned tc_calc_xmittime(unsigned rate, unsigned size);
-int tc_calc_rtable(unsigned bps, __u32 *rtab, int cell_log, unsigned mtu, unsigned mpu);
+void tc_calc_ratespec(struct tc_ratespec* spec, __u32* rtab, unsigned bps,
+	int cell_log, unsigned mtu, unsigned char mpu, int atm_cell_tax,
+	char overhead);
 
 int tc_setup_estimator(unsigned A, unsigned time_const, struct tc_estimator *est);
 


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Your money, newspaper post
From: Abraham Mcmahon @ 2006-06-14 10:06 UTC (permalink / raw)
  To: netdev

Even if you have no erectin problems SOFT CIAzLIS 
would help you to make BETTER SE  X MORE OFTEN!
and to bring  unimagnable plesure to her.

Just disolve half a pil under your tongue 
and get ready for action in 15 minutes. 

The tests showed that the majority of men 
after taking this medic ation were able to have 
PERFECT ER ECTI ON during 36 hours!

VISIT US, AND GET OUR SPECIAL 70% DISC OUNT OFER!

http://qjomos.skinscloth.com/?88863051

=====
     It went like lightning through the Flock. Those  birds  are  Outcast!
report From the police--again, what could they know there except for my  old
or twice?"
     Damn those eggheads! Some thinking to lay the road over the dump! And I
at sea, hungry, happy, learning.
     "Shut up."

hour. He swallowed, knowing that if his wings unfolded at that speed  be'd
saying  nothing. Suddenly he  clapped his hands, rubbed his  palms together,

^ permalink raw reply

* Re: [RFC/PATCH 1/2] in-kernel sockets API
From: Alan Cox @ 2006-06-14 10:43 UTC (permalink / raw)
  To: bidulock; +Cc: Chase Venters, netdev, linux-kernel
In-Reply-To: <20060614000710.C7232@openss7.org>

Ar Mer, 2006-06-14 am 00:07 -0600, ysgrifennodd Brian F. G. Bidulock:
> I think that a policy that intentionally makes it hard for proprietary
> modules to be developed defeats the purpose of ultimate opening and merging.

It isn't "policy" its called copyright law.

> The interface currently under discussion is ultimately derived from the BSD
> socket-protocol interface, and IMHO should be EXPORT_SYMBOL instead of
> EXPORT_SYMBOL_GPL, if only because using _GPL serves no purpose here and can
> be defeated with 3 or 4 obvious (and probably existing) lines of code

You don't seem to understand copyright law either. The GPL like all
copyright licenses deals with the right to make copies and to create and
control derivative works. It's not "defeated" by four lines of code.
  I
> wrote similar wrappers for STREAMS TPI to Linux NET4 interface instead of
> using pointers directly quite a few years ago.  I doubt I was the first.

Is that a confession ;)

> There is nothing really so novel here that it deserves _GPL.

Copyright is not about novelty, you have it confused with the
theoretical (not actual) role of patents. Wrong kind of intellectual
monopoly right.

Alan


^ permalink raw reply

* Re: [RFC/PATCH 1/2] in-kernel sockets API
From: Theodore Tso @ 2006-06-14 10:36 UTC (permalink / raw)
  To: Chase Venters
  Cc: bidulock, Daniel Phillips, Stephen Hemminger, Sridhar Samudrala,
	netdev, linux-kernel
In-Reply-To: <200606131953.42002.chase.venters@clientec.com>

On Tue, Jun 13, 2006 at 07:53:19PM -0500, Chase Venters wrote:
> > It is the lack of an ABI that is most frustrating to these users.
> 
> And the presence of an ABI would be _very_ frustrating to core
> developers. Not only would these people suffer, everyone would --
> developer time would be wasted dealing with cruft, and forward
> progress would be slowed.

Note that just because an interface is EXPORT_SYMBOL doesn't mean that
the interface is guaranteed to be stable.  So folks who are aruging
that an interface shouldn't be usable by non-GPL applications because
we are therefore guaranteeing a stable API are making an unwarranted
assumption.

						- Ted

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox