* Re: [PATCH net-next] vlan: static functions
From: David Miller @ 2011-12-14 7:47 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev, bcrl
In-Reply-To: <1323845874.2846.22.camel@edumazet-laptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Wed, 14 Dec 2011 07:57:54 +0100
> commit 6d4cdf47d2 (vlan: add 802.1q netpoll support) forgot to declare
> as static some private functions.
>
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] rtnetlink: rtnl_link_register() sanity test
From: David Miller @ 2011-12-14 7:47 UTC (permalink / raw)
To: eric.dumazet; +Cc: alex.bluesman.smirnov, netdev
In-Reply-To: <1323812280.2846.9.camel@edumazet-laptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Tue, 13 Dec 2011 22:38:00 +0100
> Before adding a struct rtnl_link_ops into link_ops list, check it doesnt
> clash with a prior one.
>
> Based on a previous patch from Alexander Smirnov
>
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
> CC: Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
Applied.
^ permalink raw reply
* Re: [patch] vlan: add rtnl_dereference() annotations
From: Jiri Pirko @ 2011-12-14 7:34 UTC (permalink / raw)
To: Dan Carpenter; +Cc: Patrick McHardy, David S. Miller, netdev, kernel-janitors
In-Reply-To: <20111214062943.GD7499@elgon.mountain>
Wed, Dec 14, 2011 at 07:29:43AM CET, dan.carpenter@oracle.com wrote:
>The original code generates a Sparse warning:
>net/8021q/vlan_core.c:336:9:
> error: incompatible types in comparison expression (different address spaces)
>
>It's ok to dereference __rcu pointers here because we are holding the
>RTNL lock. I've added some calls to rtnl_dereference() to silence the
>warning.
>
>Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
>---
>I haven't tested this, and I'm not super familiar with this code.
>Please review it carefully.
>
>diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
>index 1414c93..4d39d80 100644
>--- a/net/8021q/vlan_core.c
>+++ b/net/8021q/vlan_core.c
>@@ -326,14 +326,16 @@ int vlan_vids_add_by_dev(struct net_device *dev,
> const struct net_device *by_dev)
> {
> struct vlan_vid_info *vid_info;
>+ struct vlan_info *vlan_info;
> int err;
>
> ASSERT_RTNL();
>
>- if (!by_dev->vlan_info)
>+ vlan_info = rtnl_dereference(by_dev->vlan_info);
>+ if (!vlan_info)
> return 0;
>
>- list_for_each_entry(vid_info, &by_dev->vlan_info->vid_list, list) {
>+ list_for_each_entry(vid_info, &vlan_info->vid_list, list) {
> err = vlan_vid_add(dev, vid_info->vid);
> if (err)
> goto unwind;
>@@ -342,7 +344,7 @@ int vlan_vids_add_by_dev(struct net_device *dev,
>
> unwind:
> list_for_each_entry_continue_reverse(vid_info,
>- &by_dev->vlan_info->vid_list,
>+ &vlan_info->vid_list,
> list) {
> vlan_vid_del(dev, vid_info->vid);
> }
>@@ -355,13 +357,15 @@ void vlan_vids_del_by_dev(struct net_device *dev,
> const struct net_device *by_dev)
> {
> struct vlan_vid_info *vid_info;
>+ struct vlan_info *vlan_info;
>
> ASSERT_RTNL();
>
>- if (!by_dev->vlan_info)
>+ vlan_info = rtnl_dereference(by_dev->vlan_info);
>+ if (!vlan_info)
> return;
>
>- list_for_each_entry(vid_info, &by_dev->vlan_info->vid_list, list)
>+ list_for_each_entry(vid_info, &vlan_info->vid_list, list)
> vlan_vid_del(dev, vid_info->vid);
> }
> EXPORT_SYMBOL(vlan_vids_del_by_dev);
Acked-by: Jiri Pirko <jpirko@redhat.com>
Thanks Dan!
^ permalink raw reply
* [PATCH 1/1] r8169.c correct MSIEnable register offset
From: Su Kang Yin @ 2011-12-14 7:13 UTC (permalink / raw)
To: linux-kernel, nic_swsd, romieu, netdev
correct MSIEnable (bit 5) register to Config1 (offset 0x52) instead of
Config2 (offset 0x53)
Signed-off-by: Su Kang Yin <cantona@cantona.net>
---
drivers/net/ethernet/realtek/r8169.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/realtek/r8169.c
b/drivers/net/ethernet/realtek/r8169.c
index 67bf078..451835c 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -3430,18 +3430,18 @@ static unsigned rtl_try_msi(struct pci_dev
*pdev, void __iomem *ioaddr,
const struct rtl_cfg_info *cfg)
{
unsigned msi = 0;
- u8 cfg2;
+ u8 cfg1;
- cfg2 = RTL_R8(Config2) & ~MSIEnable;
+ cfg1 = RTL_R8(Config1) & ~MSIEnable;
if (cfg->features & RTL_FEATURE_MSI) {
if (pci_enable_msi(pdev)) {
dev_info(&pdev->dev, "no MSI. Back to INTx.\n");
} else {
- cfg2 |= MSIEnable;
+ cfg1 |= MSIEnable;
msi = RTL_FEATURE_MSI;
}
}
- RTL_W8(Config2, cfg2);
+ RTL_W8(Config1, cfg1);
return msi;
}
--
1.7.0.4
^ permalink raw reply related
* linux-next: build failure after merge of the final tree (net-next tree related)
From: Stephen Rothwell @ 2011-12-14 7:07 UTC (permalink / raw)
To: David Miller, netdev
Cc: linux-next, linux-kernel, Glauber Costa, Tejun Heo, Andrew Morton
[-- Attachment #1: Type: text/plain, Size: 2910 bytes --]
Hi ,
After merging the final tree, today's linux-next build (powerpc
allnoconfig) failed like this:
In file included from include/linux/tcp.h:211:0,
from include/linux/ipv6.h:221,
from include/net/ipv6.h:16,
from include/linux/sunrpc/clnt.h:26,
from include/linux/nfs_fs.h:50,
from init/do_mounts.c:20:
include/net/sock.h: In function 'memcg_memory_allocated_add':
include/net/sock.h:1000:20: error: 'OVER_LIMIT' undeclared (first use in this function)
And several other similar ones.
Caused by commit e1aab161e013 ("socket: initial cgroup code") from the
net-next tree. OVER_LIMIT is only defined it CONFIG_INET is set.
I applied the following (stupid) patch for today (just because reverting
the above commit would probably be too hard - we have cgroup stuff all
over the place :-( ):
From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Wed, 14 Dec 2011 18:01:12 +1100
Subject: [PATCH] socket: bad fix for cgroup code breakage
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
include/net/sock.h | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/include/net/sock.h b/include/net/sock.h
index 6fe0dae..0603973 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -986,6 +986,7 @@ static inline long sk_prot_mem_limits(const struct sock *sk, int index)
return prot[index];
}
+#ifdef CONFIG_INET
static inline void memcg_memory_allocated_add(struct cg_proto *prot,
unsigned long amt,
int *parent_status)
@@ -999,6 +1000,7 @@ static inline void memcg_memory_allocated_add(struct cg_proto *prot,
if (ret < 0)
*parent_status = OVER_LIMIT;
}
+#endif
static inline void memcg_memory_allocated_sub(struct cg_proto *prot,
unsigned long amt)
@@ -1028,12 +1030,14 @@ sk_memory_allocated_add(struct sock *sk, int amt, int *parent_status)
{
struct proto *prot = sk->sk_prot;
+#ifdef CONFIG_INET
if (mem_cgroup_sockets_enabled && sk->sk_cgrp) {
memcg_memory_allocated_add(sk->sk_cgrp, amt, parent_status);
/* update the root cgroup regardless */
atomic_long_add_return(amt, prot->memory_allocated);
return memcg_memory_allocated_read(sk->sk_cgrp);
}
+#endif
return atomic_long_add_return(amt, prot->memory_allocated);
}
@@ -1043,9 +1047,11 @@ sk_memory_allocated_sub(struct sock *sk, int amt, int parent_status)
{
struct proto *prot = sk->sk_prot;
+#ifdef CONFIG_INET
if (mem_cgroup_sockets_enabled && sk->sk_cgrp &&
parent_status != OVER_LIMIT) /* Otherwise was uncharged already */
memcg_memory_allocated_sub(sk->sk_cgrp, amt);
+#endif
atomic_long_sub(amt, prot->memory_allocated);
}
--
1.7.7.3
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply related
* Re: [patch] vlan: add rtnl_dereference() annotations
From: Eric Dumazet @ 2011-12-14 7:01 UTC (permalink / raw)
To: Dan Carpenter
Cc: Patrick McHardy, David S. Miller, netdev, kernel-janitors,
Jiri Pirko
In-Reply-To: <20111214062943.GD7499@elgon.mountain>
Le mercredi 14 décembre 2011 à 09:29 +0300, Dan Carpenter a écrit :
> The original code generates a Sparse warning:
> net/8021q/vlan_core.c:336:9:
> error: incompatible types in comparison expression (different address spaces)
>
> It's ok to dereference __rcu pointers here because we are holding the
> RTNL lock. I've added some calls to rtnl_dereference() to silence the
> warning.
>
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
> ---
> I haven't tested this, and I'm not super familiar with this code.
> Please review it carefully.
>
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
^ permalink raw reply
* [PATCH net-next] vlan: static functions
From: Eric Dumazet @ 2011-12-14 6:57 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Benjamin LaHaise
commit 6d4cdf47d2 (vlan: add 802.1q netpoll support) forgot to declare
as static some private functions.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Benjamin LaHaise <bcrl@kvack.org>
---
net/8021q/vlan_dev.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 0390139..9988d4a 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -664,12 +664,12 @@ static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, st
}
#ifdef CONFIG_NET_POLL_CONTROLLER
-void vlan_dev_poll_controller(struct net_device *dev)
+static void vlan_dev_poll_controller(struct net_device *dev)
{
return;
}
-int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo)
+static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo)
{
struct vlan_dev_priv *info = vlan_dev_priv(dev);
struct net_device *real_dev = info->real_dev;
@@ -696,7 +696,7 @@ out:
return err;
}
-void vlan_dev_netpoll_cleanup(struct net_device *dev)
+static void vlan_dev_netpoll_cleanup(struct net_device *dev)
{
struct vlan_dev_priv *info = vlan_dev_priv(dev);
struct netpoll *netpoll = info->netpoll;
^ permalink raw reply related
* [patch] vlan: add rtnl_dereference() annotations
From: Dan Carpenter @ 2011-12-14 6:29 UTC (permalink / raw)
To: Patrick McHardy; +Cc: David S. Miller, netdev, kernel-janitors, Jiri Pirko
The original code generates a Sparse warning:
net/8021q/vlan_core.c:336:9:
error: incompatible types in comparison expression (different address spaces)
It's ok to dereference __rcu pointers here because we are holding the
RTNL lock. I've added some calls to rtnl_dereference() to silence the
warning.
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
---
I haven't tested this, and I'm not super familiar with this code.
Please review it carefully.
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 1414c93..4d39d80 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -326,14 +326,16 @@ int vlan_vids_add_by_dev(struct net_device *dev,
const struct net_device *by_dev)
{
struct vlan_vid_info *vid_info;
+ struct vlan_info *vlan_info;
int err;
ASSERT_RTNL();
- if (!by_dev->vlan_info)
+ vlan_info = rtnl_dereference(by_dev->vlan_info);
+ if (!vlan_info)
return 0;
- list_for_each_entry(vid_info, &by_dev->vlan_info->vid_list, list) {
+ list_for_each_entry(vid_info, &vlan_info->vid_list, list) {
err = vlan_vid_add(dev, vid_info->vid);
if (err)
goto unwind;
@@ -342,7 +344,7 @@ int vlan_vids_add_by_dev(struct net_device *dev,
unwind:
list_for_each_entry_continue_reverse(vid_info,
- &by_dev->vlan_info->vid_list,
+ &vlan_info->vid_list,
list) {
vlan_vid_del(dev, vid_info->vid);
}
@@ -355,13 +357,15 @@ void vlan_vids_del_by_dev(struct net_device *dev,
const struct net_device *by_dev)
{
struct vlan_vid_info *vid_info;
+ struct vlan_info *vlan_info;
ASSERT_RTNL();
- if (!by_dev->vlan_info)
+ vlan_info = rtnl_dereference(by_dev->vlan_info);
+ if (!vlan_info)
return;
- list_for_each_entry(vid_info, &by_dev->vlan_info->vid_list, list)
+ list_for_each_entry(vid_info, &vlan_info->vid_list, list)
vlan_vid_del(dev, vid_info->vid);
}
EXPORT_SYMBOL(vlan_vids_del_by_dev);
^ permalink raw reply related
* Re: [WARNING - VERY LONG] A sysadmin's understanding of HFSC and IFB
From: John A. Sullivan III @ 2011-12-14 5:58 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev
In-Reply-To: <1323817279.8451.7.camel@denise.theartistscloset.com>
On Tue, 2011-12-13 at 18:01 -0500, John A. Sullivan III wrote:
> On Fri, 2011-12-09 at 08:59 +0100, Eric Dumazet wrote:
> > Le vendredi 09 décembre 2011 à 02:17 -0500, John A. Sullivan III a
> > écrit :
> > > Hello, all. I've been trying to summarize my last week's worth of
> > > research into HFSC and IFB. Being neither a developer nor a
> > > mathematician, I found most of the existing documentation daunting and
> > > am truly grateful for the help I received on this list to understand the
> > > technologies.
> > >
> > > I do not currently have a blog to post this research and so was thinking
> > > of posting it to this list so that it could be archived and searchable
> > > for other poor sysadmin types like me to save them the days of
> > > struggling to get their practical heads around the concepts.
> > >
> > > However, since this is probably a 15 page or so document, I realized
> > > this could be quite rude to those on dial up or metered connections.
> > > Would it be appropriate to post my summary here? Thanks - John
> > >
> >
> > Please post here, thats definitely a good idea.
> >
> > I am pretty sure your contribution could serve to add a page to
> >
> > http://www.linuxfoundation.org/collaborate/workgroups/networking/group
> >
> > I believe we lack documentation. A lot.
> <snip>
> OK - it's almost ready. The only problem I know if is that, when I do
> the math based upon my explanation, I sometimes violate an rt curve when
> I should not. I posed that in an email to the list entitled "An error
> in my HFSC sysadmin documentation". If anyone can figure out where my
> error is, I will gladly change the documentation. Here's what I have.
> The graphics except the ASCII art are obviously missing. All
> corrections and suggestions very gratefully accepted - John
>
<snip>
I realize I was using an incorrect definition of backlogged (needing
more bandwidth than the guaranteed bandwidth) and have corrected (having
a packet in queue) - John
^ permalink raw reply
* Re: [PATCH net-next] igb: reset PHY after recovering from PHY power down
From: Koki Sanagi @ 2011-12-14 5:55 UTC (permalink / raw)
To: Wyborny, Carolyn
Cc: e1000-devel@lists.sourceforge.net, netdev@vger.kernel.org,
Allan, Bruce W, Brandeburg, Jesse, Ronciak, John,
davem@davemloft.net
In-Reply-To: <EDC0E76513226749BFBC9C3FB031318F01832E2C5C@orsmsx508.amr.corp.intel.com>
(2011/11/29 2:57), Wyborny, Carolyn wrote:
>
>
>> -----Original Message-----
>> From: Koki Sanagi [mailto:sanagi.koki@jp.fujitsu.com]
>> Sent: Wednesday, November 23, 2011 7:18 PM
>> To: netdev@vger.kernel.org; Kirsher, Jeffrey T; Brandeburg, Jesse;
>> Allan, Bruce W; Wyborny, Carolyn; Skidmore, Donald C; Rose, Gregory V;
>> Waskiewicz Jr, Peter P; Duyck, Alexander H; Ronciak, John; e1000-
>> devel@lists.sourceforge.net
>> Cc: davem@davemloft.net
>> Subject: [PATCH net-next] igb: reset PHY after recovering from PHY power
>> down
>>
>> According to 82576_Datasheet.pdf, PHY setting is lost after PHY power
>> down.
>> So resetting PHY is needed when recovering from PHY power down to set a
>> default
>> setting to PHY register.
>>
>> Owing to this lack, NIC doesn't link up in some rare situation.
>> The situation I encountered is following.
>>
>>
>> 1.Both ports connect to switch.
>> +---------+ +--------+
>> | |-----------| |
>> | 82576NS | | switch |
>> | |-----------| |
>> +---------+ +--------+
>>
>> 2.Detach both cables from switch.
>> +---------+ +--------+
>> | |------- | |
>> | 82576NS | | switch |
>> | |------- | |
>> +---------+ +--------+
>>
>> 3.Detach one cable from one port.
>> +---------+ +--------+
>> | |------- | |
>> | 82576NS | | switch |
>> | | | |
>> +---------+ +--------+
>>
>> 4.Attach that cable to the other port.(It means connecting directly each
>> port)
>> +---------+ +--------+
>> | |-------+ | |
>> | 82576NS | | | switch |
>> | |-------+ | |
>> +---------+ +--------+
>>
>> As a result, NIC doesn't link up sometimes.
>>
>> Signed-off-by: Koki Sanagi <sanagi.koki@jp.fujitsu.com>
>> ---
>> drivers/net/ethernet/intel/igb/igb_main.c | 1 +
>> 1 files changed, 1 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/intel/igb/igb_main.c
>> b/drivers/net/ethernet/intel/igb/igb_main.c
>> index bd9b30e..4d4f065 100644
>> --- a/drivers/net/ethernet/intel/igb/igb_main.c
>> +++ b/drivers/net/ethernet/intel/igb/igb_main.c
>> @@ -2496,6 +2496,7 @@ static int igb_open(struct net_device *netdev)
>> goto err_setup_rx;
>>
>> igb_power_up_link(adapter);
>> + igb_reset_phy(hw);
>>
>> /* before we allocate an interrupt, we must be ready to handle it.
>> * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
>
> Hello,
>
> This seems reasonable, however it would only cover cases where igb_open is being called. It would be better to integrate the phy_reset call into igb_power_up_link, so that's the default. I can provide an alternate by end of the week.
>
When will the alternate be provided ?
In addition, more general problem which this lack of reset causes is found.
Two machine have 82576NS and each NIC is connected directly each other.
+--------+ +--------+
| | | |
| +-------+ +-------+ |
| | | | | |
|machineA|82576NS|-----------|82576NS|machineB|
| | | | | |
| +-------+ +-------+ |
| | | |
+--------+ +--------+
When attaching and detaching a cable repeatedly on one side port,
that side port becomes not link up.
This is also fixed by adding resetting phy.
Thanks,
Koki Sanagi
> Thanks,
>
> Carolyn
>
> Carolyn Wyborny
> Linux Development
> LAN Access Division
> Intel Corporation
>
>
>
>
------------------------------------------------------------------------------
Cloud Computing - Latest Buzzword or a Glimpse of the Future?
This paper surveys cloud computing today: What are the benefits?
Why are businesses embracing it? What are its payoffs and pitfalls?
http://www.accelacomm.com/jaw/sdnl/114/51425149/
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel® Ethernet, visit http://communities.intel.com/community/wired
^ permalink raw reply
* Re: Latency guarantees in HFSC rt service curves
From: John A. Sullivan III @ 2011-12-14 5:24 UTC (permalink / raw)
To: Michal Soltys; +Cc: netdev
In-Reply-To: <1323839798.8451.172.camel@denise.theartistscloset.com>
On Wed, 2011-12-14 at 00:16 -0500, John A. Sullivan III wrote:
> <snip>>
> > > If you have a chance, could you look at the email I sent entitled "An
> > > error in my HFSC sysadmin documentation". That's the last piece I
> > > need to fall in place before I can share my documentation of this
> > > week's research. Thanks - John
> >
> > Yes, will do.
> I'm guessing I slightly violated the rt guarantee precisely because of
> what I described above.
<snip>
Alas, not. I just reviewed what I sent and it was calculating deadline
time with monolinear service curves so I'm still making an error
somewhere. Thanks - John
^ permalink raw reply
* Re: Latency guarantees in HFSC rt service curves
From: John A. Sullivan III @ 2011-12-14 5:16 UTC (permalink / raw)
To: Michal Soltys; +Cc: netdev
In-Reply-To: <4EE7E3E4.6070409@ziu.info>
Thanks again, Michal. I'll respond in the text - John
On Wed, 2011-12-14 at 00:46 +0100, Michal Soltys wrote:
> On 10.12.2011 19:35, John A. Sullivan III wrote:
> > On Sat, 2011-12-10 at 18:57 +0100, Michal Soltys wrote: <snip> So,
> > again, trying to wear the eminently practical hat of a sys admin, for
> > periodic traffic, i.e., protocols like VoiP and video that are sending
> > packets are regular intervals and thus likely to reset the curve after
> > each packet, m1 helps reduce latency while m2 is a way of reducing the
> > chance of overrunning the circuit under heavy load, i.e., where the
> > concave queue is backlogged.
> >
>
> Well, updated, - not "reset". The latter [kind of] implies the return to
> original form, and just so we're on the same page - the curve would have
> to be completely under the old one for that to happen. There's also no
> chance of overloading anything - except if a machine is shaping on
> behalf of something upstream with smaller uplink, and doing so without
> UL keeping LS in check.
>
> > When we start multiplexing streams of periodic traffic, we are still
> > fine as long as we are not backlogged. Once we are backlogged, we
> > drop down to the m2 curve which prevents us from overrunning the
> > circuit (assuming the sum of our rt m2 curves<= circuit size) and
> > hopefully still provides adequate latency. If we are badly
> > backlogged, we have a problem with which HFSC can't help us :) (and I
> > suppose where short queues are helpful).
> >
>
> Keep in mind that not backlogged classes are not hurt by backlogged
> ones. And you can't overrun - be it m1 or m2, or at which point any
> class activates (providing curves make sense). If everything is
> backlogged, you still get nicely multiplexed traffic as defined by
> your hierarchy.
I think I understand the technology (although I confess I did not take
the time to fully digest how the curves are updated) but I'm grappling
more with the practical application and I may be making a false
assumption here.
Once again, with my practical, "how do I use this" hat on, my
instinctive thought is that I would ensure that the sum of the rt m2
curves do not exceed ul, well, not ul literally as rt disregards ul but,
more accurately, circuit capacity so that my circuit is not
oversubscribed and my guarantees are sustainable. But, since m1 on a
concave curve is a momentary "super charge", I don't need to worry about
oversubscribing since the rate is not sustained. Thus, if all the
traffic were to be backlogged at m1 rates, we would overrun the circuit.
That's what I meant by m2 working as a circuit breaker.
As I think it through further, I realize that is not true in theory and
may be the source of the error I reference later in this email. I
suppose it may also be problematic in practice so let me walk through it
a bit further with you if I may.
Let's imagine we have five classes of service. We don't need to
identify them for this exercise but what we do know is that the sum of
their m2 curves <= circuit capacity and the sum of their m1 curves >
circuit capacity because, operating under my false assumption, this is
only for that temporary boost. If all five classes receive their first
packet at the identical moment, we will fail to meet the guarantees.
More practically, let's assume the first four are continuously
backlogged and the fifth is receiving a heavy but not backlogged stream
of periodic (as in at regular intervals) traffic such that the curve is
recalculated so that each packet is sent on the m1 curve, I think it is
possible that we once again exceed the capacity of the link. Ah, no. I
see it. Now that I've interrupted writing this email to take the time
to digest how the curve is updated, I see it more clearly.
Since the curves always take the minimum of what the data would have
been if we had kept transmitting the data at the old curve rate or what
the data would be if we reset the curve and started over again at m1 (my
practical translation of the algorithm), the sustained rate even if the
queue constantly goes idle and, as soon as it goes idle receives a new
packet will never exceed the volume of traffic that would have been
transmitted by the rt curve if it was under continuous backlog (not
taking into account any linksharing bandwidth).
I realize I am babbling in my own context so let me state in another way
in case I'm not being clear. My concern was that, if the four classes
are continuously backlogged and the fifth class with a concave rt
service curve constantly goes idle and then immediately receives a
packet, it will always be transmitting at the m1 rate and thus exceed
the capacity of the circuit (since the sum of the five m2 curves =
capacity and the m1 of the fifth class is greater than the m2 of the
fifth class). However, the curves do not recalculate to m1
automatically. They calculate to whichever would be less - the total
data transmitted as if we had continued to transmit on the rt curve as
if it was continually backlogged or the amount of data transmitted if we
were starting the curve over again. Thus the total bits dequeued if the
circuit cycles between active and passive (backlogged and not
backlogged) will never exceed the total number of bits dequeued if the
queue was continuously backlogged even for concave curves.
Here is ascii art from http://www.sonycsl.co.jp/~kjc/software/TIPS.txt
depicting what I am trying to say:
________
________--------
/ ______
/ ________--------
________---+----
/ /
/ /
total -> / + new coordinate
/
/
service curve |
of +
previous period current
time
Update Operation
______
________--------
+----
/
/
total -> + new coordinate
|
+
current
time
New Service Curve
So now I'll put my practical hat back on where practice will violate
theory but with no practical deleterious effect except in the most
extreme cases. I propose that, from a practical, system administrator
perspective, it is feasible and probably ideal to define rt service
curves so that the sum of all m2 curves <= circuit capacity and m1
curves should be specified to meet latency requirements REGARDLESS OF
EXCEEDING CIRCUIT CAPACITY.
In theory, we can exceed circuit capacity and violate our guarantees as
in the example I gave where all five queues go active at exactly the
same time. In practicality, the backlog will never exceed the sum of
the m1 curves times their duration minus the circuit capacity over that
same time period. In other words, let's say we have a 1.5 Mbps link and
we have five rt curves all with m1 of 1 Mbps for 10 ms. In 10 ms, we
will have queued 5 * 1 * .01 = 50kbits of traffic and dequeued 1.5 * .01
= 15 kbits of traffic thus, our backlog will never exceed 35kbits. This
is likely to be quickly drained at the first idle time unless we truly
have all five queues continuously backlogged.
So, my approach of ensuring the sum of m2 curves <= capacity but m1
curves are specified based solely on latency requirements even if they
overload the circuit works in practice except under the most extreme
conditions (where ALL queues are continuously backlogged and even then
the damage is limited) even though it violates the theory.
Am I accurate here?
>
> If anything briefly stops being backlogged, it will get bonus on next
> backlog period
I am assuming this assumes a concave curve and has to do with the
recalculation of the curve and that this would not be true if m1=m2?
> - while making sure, it wouldn't go with new curve above
> previous backlog period's one (and assuming its actual rate is not above
> the defined RT curve, as in such case it will get bonus from excess
> bandwidth available as specified by LS (or will get none, if LS is not
> defined)).
When I first read this, I had no clue what you meant :) Now that I've
taken time to digest the curve recalculation, I think you are saying the
exact same thing I said above only in far fewer words ;)
>
> > If you have a chance, could you look at the email I sent entitled "An
> > error in my HFSC sysadmin documentation". That's the last piece I
> > need to fall in place before I can share my documentation of this
> > week's research. Thanks - John
>
> Yes, will do.
I'm guessing I slightly violated the rt guarantee precisely because of
what I described above.
>
> Btw, have you check the manpages of recent iproute2 w.r.t. hfsc ?
> Lots of this should be explained, or at least mentioned there.
Yes, you were so kind as to give me links to them. I found them very
helpful - much more mathematical and theoretical than I am used to in a
man page but I'm not sure it would be possible to explain HFSC any other
way. Thanks again - John
^ permalink raw reply
* [PATCH 2/2] e100: power off PHY after reset when interface is down
From: Jiang Wang @ 2011-12-14 2:49 UTC (permalink / raw)
To: Jeff Kirsher, Jesse Brandeburg, Bruce Allan, Carolyn Wyborny,
Don Skidmore, Greg Rose, Peter P Waskiewicz Jr, Alex Duyck,
John Ronciak, e1000-devel, netdev, linux-kernel
Cc: Francis.St.Amant, miles.ito, clala, ppanchamukhi, Jiang Wang
In-Reply-To: <1323830996-16388-1-git-send-email-Jiang.Wang@riverbed.com>
PHYs supported by e100 re-starts auto-negotiation after writing to
BMCR_RESET bit. This patch powers down PHY when the interface is down
and reset is issued.
Signed-off-by: Jiang Wang <Jiang.Wang@riverbed.com>
---
drivers/net/ethernet/intel/e100.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
index 9824e0a..b8e4910 100644
--- a/drivers/net/ethernet/intel/e100.c
+++ b/drivers/net/ethernet/intel/e100.c
@@ -2386,6 +2386,13 @@ static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
err = mii_ethtool_sset(&nic->mii, cmd);
e100_exec_cb(nic, NULL, e100_configure);
+ if (!netif_running(netdev) && !(nic->flags & wol_magic)) {
+ uint16_t phy_data;
+ phy_data = mdio_read(nic->netdev, nic->mii.phy_id, MII_BMCR);
+ phy_data |= BMCR_PDOWN;
+ mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, phy_data);
+ }
+
return err;
}
--
1.7.1
------------------------------------------------------------------------------
Cloud Computing - Latest Buzzword or a Glimpse of the Future?
This paper surveys cloud computing today: What are the benefits?
Why are businesses embracing it? What are its payoffs and pitfalls?
http://www.accelacomm.com/jaw/sdnl/114/51425149/
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel® Ethernet, visit http://communities.intel.com/community/wired
^ permalink raw reply related
* linux-next: manual merge of the net-next tree with the net tree
From: Stephen Rothwell @ 2011-12-14 2:25 UTC (permalink / raw)
To: David Miller, netdev; +Cc: linux-next, linux-kernel, Antonio Quartulli
[-- Attachment #1: Type: text/plain, Size: 2593 bytes --]
Hi all,
Today's linux-next merge of the net-next tree got conflicts in
net/batman-adv/translation-table.c between commits 03fc3070457d
("batman-adv: in case of roaming mark the client with TT_CLIENT_ROAM")
and 797399b415b7 ("batman-adv: delete global entry in case of roaming")
from the net tree and commit 48100bac89a6 ("batman-adv: create a common
substructure for tt_global/local_entry") from the net-next tree.
I fixed it up (I think - see below) and can carry the fix as necessary.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --cc net/batman-adv/translation-table.c
index 5f09a57,cc87acf..0000000
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@@ -245,12 -242,10 +242,12 @@@ void tt_local_add(struct net_device *so
if (tt_global_entry) {
/* This node is probably going to update its tt table */
tt_global_entry->orig_node->tt_poss_change = true;
- /* The global entry has to be marked as PENDING and has to be
+ /* The global entry has to be marked as ROAMING and has to be
* kept for consistency purpose */
- tt_global_entry->flags |= TT_CLIENT_ROAM;
- tt_global_entry->common.flags |= TT_CLIENT_PENDING;
++ tt_global_entry->common.flags |= TT_CLIENT_ROAM;
+ tt_global_entry->roam_at = jiffies;
+
- send_roam_adv(bat_priv, tt_global_entry->addr,
+ send_roam_adv(bat_priv, tt_global_entry->common.addr,
tt_global_entry->orig_node);
}
out:
@@@ -704,21 -668,9 +671,21 @@@ void tt_global_del(struct bat_priv *bat
if (tt_global_entry->orig_node == orig_node) {
if (roaming) {
- tt_global_entry->common.flags |= TT_CLIENT_ROAM;
- tt_global_entry->roam_at = jiffies;
- goto out;
+ /* if we are deleting a global entry due to a roam
+ * event, there are two possibilities:
+ * 1) the client roamed from node A to node B => we mark
+ * it with TT_CLIENT_ROAM, we start a timer and we
+ * wait for node B to claim it. In case of timeout
+ * the entry is purged.
+ * 2) the client roamed to us => we can directly delete
+ * the global entry, since it is useless now. */
+ tt_local_entry = tt_local_hash_find(bat_priv,
- tt_global_entry->addr);
++ tt_global_entry->common.addr);
+ if (!tt_local_entry) {
- tt_global_entry->flags |= TT_CLIENT_ROAM;
++ tt_global_entry->common.flags |= TT_CLIENT_ROAM;
+ tt_global_entry->roam_at = jiffies;
+ goto out;
+ }
}
_tt_global_del(bat_priv, tt_global_entry, message);
}
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH] bridge: push blocking slaves to forwarding when turning stp off
From: Stephen Hemminger @ 2011-12-14 0:16 UTC (permalink / raw)
To: Vitalii Demianets; +Cc: netdev, bridge
In-Reply-To: <201112131136.25919.vitas@nppfactor.kiev.ua>
On Tue, 13 Dec 2011 11:36:25 +0200
Vitalii Demianets <vitas@nppfactor.kiev.ua> wrote:
> If there is a slave in blocking state when stp is turned off, that slave will
> remain in blocking state for indefinitely long time until interface state
> changed. We should push all blocking slaves into forwarding state after
> turning stp off.
>
> Signed-off-by: Vitalii Demianets <vitas@nppfactor.kiev.ua>
Maybe. But if the port was in the blocking state then STP must have
decided there was a loop in the network if that port was used.
Therefore blindly putting the port into forwarding state could cause
disastrous network flood.
The user can force the port back out of blocking state (via sysfs).
^ permalink raw reply
* Re: [PATCH] ipv6: Check dest prefix length on original route not copied one in rt6_alloc_cow().
From: Yan, Zheng @ 2011-12-14 0:16 UTC (permalink / raw)
To: David Miller; +Cc: netdev@vger.kernel.org
In-Reply-To: <20111213.173551.163815101446083653.davem@davemloft.net>
On 12/14/2011 06:35 AM, David Miller wrote:
>
> After commit 8e2ec639173f325977818c45011ee176ef2b11f6 ("ipv6: don't
> use inetpeer to store metrics for routes.") the test in rt6_alloc_cow()
> for setting the ANYCAST flag is now wrong.
>
> 'rt' will always now have a plen of 128, because it is set explicitly
> to 128 by ip6_rt_copy.
>
> So to restore the semantics of the test, check the destination prefix
> length of 'ort'.
>
> Signed-off-by: David S. Miller <davem@davemloft.net>
> ---
>
> Committed to 'net'.
>
> net/ipv6/route.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/net/ipv6/route.c b/net/ipv6/route.c
> index 3399dd3..b582a0a 100644
> --- a/net/ipv6/route.c
> +++ b/net/ipv6/route.c
> @@ -728,7 +728,7 @@ static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort,
> int attempts = !in_softirq();
>
> if (!(rt->rt6i_flags&RTF_GATEWAY)) {
> - if (rt->rt6i_dst.plen != 128 &&
> + if (ort->rt6i_dst.plen != 128 &&
> ipv6_addr_equal(&ort->rt6i_dst.addr, daddr))
> rt->rt6i_flags |= RTF_ANYCAST;
> ipv6_addr_copy(&rt->rt6i_gateway, daddr);
My fault, sorry!
Yan, Zheng
^ permalink raw reply
* Re: Latency guarantees in HFSC rt service curves
From: Michal Soltys @ 2011-12-13 23:46 UTC (permalink / raw)
To: John A. Sullivan III; +Cc: netdev
In-Reply-To: <1323542103.3159.148.camel@denise.theartistscloset.com>
On 10.12.2011 19:35, John A. Sullivan III wrote:
> On Sat, 2011-12-10 at 18:57 +0100, Michal Soltys wrote: <snip> So,
> again, trying to wear the eminently practical hat of a sys admin, for
> periodic traffic, i.e., protocols like VoiP and video that are sending
> packets are regular intervals and thus likely to reset the curve after
> each packet, m1 helps reduce latency while m2 is a way of reducing the
> chance of overrunning the circuit under heavy load, i.e., where the
> concave queue is backlogged.
>
Well, updated, - not "reset". The latter [kind of] implies the return to
original form, and just so we're on the same page - the curve would have
to be completely under the old one for that to happen. There's also no
chance of overloading anything - except if a machine is shaping on
behalf of something upstream with smaller uplink, and doing so without
UL keeping LS in check.
> When we start multiplexing streams of periodic traffic, we are still
> fine as long as we are not backlogged. Once we are backlogged, we
> drop down to the m2 curve which prevents us from overrunning the
> circuit (assuming the sum of our rt m2 curves<= circuit size) and
> hopefully still provides adequate latency. If we are badly
> backlogged, we have a problem with which HFSC can't help us :) (and I
> suppose where short queues are helpful).
>
Keep in mind that not backlogged classes are not hurt by backlogged
ones. And you can't overrun - be it m1 or m2, or at which point any
class activates (providing curves make sense). If everything is
backlogged, you still get nicely multiplexed traffic as defined by
your hierarchy.
If anything briefly stops being backlogged, it will get bonus on next
backlog period - while making sure, it wouldn't go with new curve above
previous backlog period's one (and assuming its actual rate is not above
the defined RT curve, as in such case it will get bonus from excess
bandwidth available as specified by LS (or will get none, if LS is not
defined)).
> If you have a chance, could you look at the email I sent entitled "An
> error in my HFSC sysadmin documentation". That's the last piece I
> need to fall in place before I can share my documentation of this
> week's research. Thanks - John
Yes, will do.
Btw, have you check the manpages of recent iproute2 w.r.t. hfsc ?
Lots of this should be explained, or at least mentioned there.
^ permalink raw reply
* Re: [WARNING - VERY LONG] A sysadmin's understanding of HFSC and IFB
From: John A. Sullivan III @ 2011-12-13 23:42 UTC (permalink / raw)
To: Julien Vehent; +Cc: netdev
In-Reply-To: <1323819331.8451.9.camel@denise.theartistscloset.com>
On Tue, 2011-12-13 at 18:35 -0500, John A. Sullivan III wrote:
> On Tue, 2011-12-13 at 18:10 -0500, Julien Vehent wrote:
> > This is an amazing email and I will definitely sit down and read it
> > carefully.
> > I've been (silently) following your discussions about HFSC because I've been
> > wanting to add a section on HFSC in the TC doc I wrote here:
> > http://wiki.linuxwall.info/doku.php/en:ressources:dossiers:networking:traffic_control
> >
> > The doc I've read so far left me staring at the wall with more questions
> > than answers. I'm hoping your text will finally bring a clear view of the
> > problem :)
> >
> > Cheers,
> > Julien
> >
> <snip>
> LOL - guess whose web site I have open in my browser as I walk through
> experimenting with tc to build a test WAN environment in our lab:
>
> http://wiki.linuxwall.info/doku.php/en:ressources:dossiers:networking:traffic_control
>
> It's wonderfully well done and I've recommended it to several of my
> peers. Thanks for putting it together - John
<snip>
I should mention this is our internal, copyrighted documentation but I
do have the authority to share it freely and, as avid consumers and
contributors to the OSS world, we will want to make it as available as
possible assuming it is accurate - John
^ permalink raw reply
* Re: [WARNING - VERY LONG] A sysadmin's understanding of HFSC and IFB
From: John A. Sullivan III @ 2011-12-13 23:35 UTC (permalink / raw)
To: Julien Vehent; +Cc: Eric Dumazet, netdev
In-Reply-To: <5f2da864419b2bd2a28c57128df418a6@njm.linuxwall.info>
On Tue, 2011-12-13 at 18:10 -0500, Julien Vehent wrote:
> This is an amazing email and I will definitely sit down and read it
> carefully.
> I've been (silently) following your discussions about HFSC because I've been
> wanting to add a section on HFSC in the TC doc I wrote here:
> http://wiki.linuxwall.info/doku.php/en:ressources:dossiers:networking:traffic_control
>
> The doc I've read so far left me staring at the wall with more questions
> than answers. I'm hoping your text will finally bring a clear view of the
> problem :)
>
> Cheers,
> Julien
>
<snip>
LOL - guess whose web site I have open in my browser as I walk through
experimenting with tc to build a test WAN environment in our lab:
http://wiki.linuxwall.info/doku.php/en:ressources:dossiers:networking:traffic_control
It's wonderfully well done and I've recommended it to several of my
peers. Thanks for putting it together - John
^ permalink raw reply
* Re: [WARNING - VERY LONG] A sysadmin's understanding of HFSC and IFB
From: Julien Vehent @ 2011-12-13 23:10 UTC (permalink / raw)
To: John A. Sullivan III; +Cc: Eric Dumazet, netdev
In-Reply-To: <1323817279.8451.7.camel@denise.theartistscloset.com>
This is an amazing email and I will definitely sit down and read it
carefully.
I've been (silently) following your discussions about HFSC because I've been
wanting to add a section on HFSC in the TC doc I wrote here:
http://wiki.linuxwall.info/doku.php/en:ressources:dossiers:networking:traffic_control
The doc I've read so far left me staring at the wall with more questions
than answers. I'm hoping your text will finally bring a clear view of the
problem :)
Cheers,
Julien
On 2011-12-13 18:01, John A. Sullivan III wrote:
> On Fri, 2011-12-09 at 08:59 +0100, Eric Dumazet wrote:
>> Le vendredi 09 décembre 2011 à 02:17 -0500, John A. Sullivan III a
>> écrit :
>> > Hello, all. I've been trying to summarize my last week's worth of
>> > research into HFSC and IFB. Being neither a developer nor a
>> > mathematician, I found most of the existing documentation daunting and
>> > am truly grateful for the help I received on this list to understand
>> the
>> > technologies.
>> >
>> > I do not currently have a blog to post this research and so was
>> thinking
>> > of posting it to this list so that it could be archived and searchable
>> > for other poor sysadmin types like me to save them the days of
>> > struggling to get their practical heads around the concepts.
>> >
>> > However, since this is probably a 15 page or so document, I realized
>> > this could be quite rude to those on dial up or metered connections.
>> > Would it be appropriate to post my summary here? Thanks - John
>> >
>>
>> Please post here, thats definitely a good idea.
>>
>> I am pretty sure your contribution could serve to add a page to
>>
>> http://www.linuxfoundation.org/collaborate/workgroups/networking/group
>>
>> I believe we lack documentation. A lot.
> <snip>
> OK - it's almost ready. The only problem I know if is that, when I do
> the math based upon my explanation, I sometimes violate an rt curve when
> I should not. I posed that in an email to the list entitled "An error
> in my HFSC sysadmin documentation". If anyone can figure out where my
> error is, I will gladly change the documentation. Here's what I have.
> The graphics except the ASCII art are obviously missing. All
> corrections and suggestions very gratefully accepted - John
>
>
> IFB
> The Intermediate Functional Block (IFB) device is a pseudo-interface to
> which traffic can be redirected by using a tc filter with the mirred
> (mirror/redirect I assume) action. The primary documentation appears to
> be at
> http://www.linuxfoundation.org/collaborate/workgroups/networking/ifb but
> I found it less than helpful. Perhaps the most helpful information was
> found in a discussion on the mirred tc filter action at
> http://www.sephidev.net/external/iproute2/doc/actions/mirred-usage and
> particularly this section:
> Remember that IFB is a very specialized case of packet redirecting
> device. Instead of redirecting it puts packets at the exact spot
> on the stack it found them from.
> In other words, we redirect or mirror traffic from an interface into the
> ifb interface and, when ifb is finished with it, it puts it right back
> onto the interface which was redirected into it. Why would one want to
> do that?
> Diagnostics are one important reason, e.g., to capture dropped packets.
> Packets may be dropped on the interface either because of an iptables
> rule or a traffic limiting rule. The packets can be mirrored onto an
> ifb interface which will see them before they are dropped allowing
> packet analysis on them. Another would be in a Linux based switch to
> port mirror traffic from one port to another.
> Another reason is for applying identical traffic shaping rules to
> multiple interfaces. Let's say one is using complicated traffic shaping
> rules with several qdiscs (queue disciplines), classes, and filters and
> the same set applies to many interfaces. Rather than defining and
> maintaining this complex set for multiple interfaces, one could set a
> filter for each of those interfaces to redirect into an ifb interface
> and apply the complex traffic shaping there.
> A final reason is both complex and critically important, especially for
> SimplicITy and Firepipes (or anyone using VDI across the Internet):
> ingress traffic shaping. Normal Linux ingress traffic shaping can only
> police. Policing cannot really shape packets. It can edit them, drop
> them, pass them, or do nothing. One of the important goals of either
> policing or shaping ingress traffic is to give us a fighting chance to
> shape inbound traffic from the Internet when we have no control over the
> upstream router.
> For example, we may prioritize NX/RDP/Citrix and VoIP traffic outbound
> to the Internet so that it is prioritized over web browsing and sending
> huge email attachments or FTP transfers. But, if someone starts pulling
> down a huge file and consumes all the inbound bandwidth, our desktop
> sessions can slow to a crawl and our VoIP calls become unintelligible.
> We might face a similar problem if we host our own web servers; our web
> servers could slow to a crawl in the public perception if their ability
> to respond to queries is being blocked by monster downloads into our
> network. How can we keep the bulk traffic internal users are
> downloading from mangling our time critical traffic?
> The basic idea is to use the flow control mechanisms of traffic flow.
> This is built in to any TCP transmission and may or may not be in the
> upper layers of a UDP stream. If we start dropping inbound packets, the
> other side should get the point and start throttling its flow.
> The recommended way to do this is to place an egress filter on the
> internal interface of the firewall, i.e., we only let the firewall place
> traffic on the internal network at a particular rate. Egress traffic
> shaping can be very powerful so we can use something like HTB
> (Hierarchical Token Bucket) to reserve bandwidth for time sensitive
> traffic but allow that bandwidth to be used for bulk traffic it is not
> needed for time sensitive traffic. We can also distinguish between well
> behaved traffic (like most TCP traffic) and most poorly behaved traffic
> which won't throttle (like most UDP traffic) and not allow UDP traffic
> to use extra bandwidth if available.
> This is fine if the firewall has only a single internal interface. The
> bulk traffic can only be output at the traffic shaping speed and, when
> the inbound buffer overflows, packets will drop and the well behaved
> application on the other end should throttle. But what if we have a DMZ
> or, as we often do with Firepipes, multiple internal interfaces?
> Throttling the egress of the internal interface would also throttle
> traffic flowing to it from the DMZ or other internal interfaces; that
> would be very bad.
> In these cases, it is better to create an ingress filter, i.e., filter
> the traffic coming in off the Internet. As mentioned, an ingress filter
> can only police so the only way we can throttle download traffic is to
> drop the packets. We could create several bands to reserve bandwidth
> for different types of traffic and drop packets which exceed those
> bandwidth limits but we have no ability to do complex traffic shaping
> such as allowing bulk traffic to use available bandwidth from higher
> priority traffic if it is available.
> This is where IFB comes into play. We can redirect the inbound traffic
> into an IFB interface and then apply an egress filter with full traffic
> shaping to the IFB. This will shape the traffic before it is placed
> back onto the inbound interface.
> This would allow us to use something like HTB on the inbound traffic so
> that we could reserve bandwidth for time sensitive traffic, limit
> bandwidth for bulk traffic, yet allow the bulk traffic to use the time
> sensitive bandwidth when it is available. But what happens if the bulk
> traffic is using the bandwidth and a time sensitive packet arrives? It
> is now queued behind the bulk packets and can suffer intolerable delay.
> This is where HFSC steps in.
> HFSC
> HFSC (Hierarchical Fair Service Curve) is an incredibly powerful but,
> again, poorly documented qdisc. Its outstanding feature over qdiscs
> like HTB is that it separates latency guarantees from bandwidth
> guarantees. In other queue disciplines, the only way to guarantee lower
> latency is to allocate more bandwidth. This is counter productive with
> technologies such as VoIP which require low latency but send very small
> packets and typically require far less bandwidth per flow than bulk
> applications. HFSC has three goals:
> 1. Decouple latency requirements from bandwidth requirements
> 2. Provide guaranteed bandwidth when specified
> 3. Fairly share available extra bandwidth
> It recognizes it cannot always achieve all three goals and will preserve
> guaranteed bandwidth over fair sharing when there is a conflict.
> The paper describing HFSC is at
> http://www.cs.cmu.edu/~istoica/hfsc_extended.ps.gz (with a note that
> says, "You might need to treat it first with: sed "s|\[FontBBox
> \]|/FontBBox load |" as it was generated with a little bit old (ancient)
> idraw version." It is highly technical and mathematical but has some
> excellent graphics to illustrate the principles.
> A related site is http://www.cs.cmu.edu/~hzhang/HFSC/main.html
> The latest man pages are a little less mathematical but still pretty
> dense with the references to functions to describe the service curves.
> I've downloaded the latest man pages
>
> (http://git.kernel.org/?p=linux/kernel/git/shemminger/iproute2.git;a=blob_plain;f=man/man7/tc-hfsc.7;hb=HEAD
> and
>
> http://git.kernel.org/?p=linux/kernel/git/shemminger/iproute2.git;a=blob_plain;f=man/man8/tc-hfsc.8;hb=HEAD)
> to Tech/Equipment/Endian; they can be read with:
> nroff -mandoc -rLL=<width>n <page> | less
> A commonly reference resource is http://linux-ip.net/articles/hfsc.en/
> I also found http://www.sonycsl.co.jp/~kjc/software/TIPS.txt helpful.
> However, many articles attempting to explain HFSC didn't seem to really
> get it - especially the part about decoupling latency and bandwidth
> requirements. It is all quite confusing and not well understood. In
> fact, as I'm thinking about how to record what I have learned, I'm
> really struggling because there is no simple way to describe HFSC!
> Let's break down the terms. It is hierarchical because bandwidth can be
> allocated and controlled on a hierarchical basis. For example, the top
> level of the hierarchy might be our overall available bandwidth. The
> next level of the hierarchy might be gold level customers who get 70% of
> the available bandwidth and regular customers who get 30%. The next
> level might be individual customers or groups of customers who divide
> the 70% or 30% allocated to their parent. The final hierarchy might be
> groups of traffic like VoIP, interactive, web, or bulk. These end nodes
> are called leaf nodes. There is an important distinction between leaf
> nodes and container nodes. Bandwidth guarantees are only made at the
> leaf node level. Containers are only used for link sharing, i.e., how
> excess bandwidth is shared when it is available. Remember that we said
> HFSC enforces guarantees even if it means bandwidth is not shared
> evenly. Bandwidth guarantees are always honored (if physically
> possible) regardless of the bandwidth allocated to the higher layers of
> the hierarchy. Thus one must be careful to not overallocate bandwidth
> at the leaves.
> Moreover, the fair sharing of bandwidth only happens between peers. In
> other words, using our example, only two peers contend for the overall
> bandwidth - Gold and Regular. If the second level hierarchy of Gold has
> clients A, B, and C and the second level of Regular has D and E, D and E
> contend for Regular's share of the bandwidth and A, B, and C contend for
> Gold's share of the bandwidth but, for example, D never contends with B
> because they are in different parts of the tree. Only peers contend for
> available bandwidth.
> So that explains "hierarchical." What do we mean by fair? This refers
> to how available extra bandwidth is allocated between those groups which
> need it. Let's say that we have 100Mbps of bandwidth divided into four
> groups of traffic - Gold (40%), Silver (30%), Bronze (20%), and Regular
> (10%). Let's say that no Gold or Bronze users are active so 60% of our
> bandwidth is unallocated but both Silver and Regular could use as much
> bandwidth as we can give them. How do we fairly share that 60% between
> Silver and Regular? HFSC uses a concept called virtual time to which we
> will return later. In effect, it will divide the 60% in proportion to
> the traffic allocated to each group asking for more. Specifically, in
> this case, three shares of bandwidth will be allocated to Silver for
> every one allocated to Regular (30:10).
> This is another area where HFSC is brilliant over other queue
> disciplines. For example, what if we have a stream of traffic that
> doesn't require much bandwidth but, when it needs more, we need to
> prioritize it over bulk traffic? If our service guarantees are that VoIP
> gets a guaranteed 10% of the bandwidth, web traffic gets 30% and bulk
> gets 60%, when web is inactive and both VoIP and bulk need more, the
> excess would be allocated to bulk in a 6:1 ratio. That's not good. But
> remember we said that guaranteeing bandwidth and sharing bandwidth are
> two separate and sometimes conflicting functions in HFSC. Thus, we can
> say that VoIP is guaranteed 10% but, when it comes to sharing available
> bandwidth, VoIP should get 70%, web gets 20%, and bulk gets 10%.
> Brilliant! This is done by means of service curves, the last part of
> Hierarchical Fair Service Curve traffic shaping.
> A service curve is a mathematical way of describing how much service a
> process is given over time. The use of the term curve can throw us
> non-mathematicians for a "curve" until we remember that, in strict
> mathematical terms, a straight line is a curve - a curve which
> represents a linear function. To translate all that: a service curve is
> the allocated bandwidth. The y axis is the amount of data transferred
> (service given) and the x axis is time. The greater the bandwidth, the
> steeper the slope of the curve (line). Another brilliant thing about
> HFSC is that a service curve can have two lines, i.e., for a certain
> period of time one bandwidth can be allocated and after that time
> period, a different bandwidth can be allocated. I'll refer to this as a
> "di-linear" curve. This is how HFSC decouples bandwidth from latency
> but we'll come back to that.
> A service curve can be defined using tc with a single parameter if we
> only need one line or with three parameters if we need two lines. There
> are two ways the parameters can be given to tc. The mathematically
> oriented way is "m1 <value> d <value> m2 <value>" where m1 is the slope
> of the first curve (line for the non-mathematicians - translate: the
> initial bandwidth), m2 is the slope of the second curve (translate: the
> second bandwidth setting) and d is the intersection of the two curves
> (translate how long we use the first bandwidth before switching to the
> second bandwidth).
> The second, more system administrator oriented syntax is "umax <value>
> dmax <value> rate <value>". This syntax makes it a little easier to see
> how HFSC separates guarantees for latency from guarantees for bandwidth.
> The rate parameter is the second curve. In practical terms, this is the
> guaranteed bandwidth. The umax parameter is the size of some unit of
> data. It will often be the size of a data packet, e.g., 1514 bytes
> (does not need to include CRC, preamble, or inter-frame gap) but it
> could be some other unit. For example, some have suggested that one
> could use this so that the text portion of web pages are delivered with
> low latency and the rest of the non-text, typically larger data
> transmissions, will follow at a slower pace. If the typical text page
> size is 10KB, we might set umax to 10KB. Of course, this assumes that
> text is always sent first. The dmax parameter is the maximum delay that
> umax can tolerate. So we might say that the first 1514 byte packet must
> be delayed no more than 20ms, or the first 10KB of web page transmission
> should be delayed no more than 100ms. This is how bandwidth and latency
> guarantees are separated.
> Let's illustrate this a little further. Let's say we have an FTP
> transfer which is running as fast as its guaranteed bandwidth. We also
> have a VoIP traffic stream also running within its guaranteed bandwidth.
> The classic problem is that my VoIP packet which must be delivered on
> time is sitting behind my much larger FTP packet which is allowed to be
> sent because it is within the guaranteed bandwidth for FTP. How do I
> jump the VoIP packet ahead of the FTP packet?
> HFSC will see that both packets are eligible to be sent because both are
> within the bandwidth limits set for their kind of traffic. It then sees
> that the FTP traffic only has a bandwidth guarantee, i.e., it can meet
> its obligations to the FTP traffic as long as the packet is delivered
> within the time frame necessary to meet the bandwidth requirements
> regardless of how much the packet is delayed (as long as the delay is
> not so long as to violate the bandwidth requirements). It then looks at
> the equally eligible VoIP packet and sees that, not only does it have an
> obligation for bandwidth but it also must not delay this packet for more
> than, say, 20ms. In effect, it looks at the deadline for delivering the
> FTP packet and compares it to the deadline for delivering the VoIP
> packet and if the deadline for the VoIP packet is sooner than the
> deadline for the FTP packet, it will service the VoIP packet first.
> But how, exactly, does it work? It is done by the interplay of service
> curves and timers. In fact, we will come to see that eligible and
> deadline are actually technical terms to describe some of the timers but
> first, let's step back and explain a little more about service curves.
> Service curves
> There are actually three service curves used by HFSC. They are:
> 1. The real-time service curve (rt)
> 2. The link-sharing service curve (ls)
> 3. The upper limit service curve (ul)
> The abbreviations are used to specify which service curve we are
> describing in the tc syntax, e.g.,
> tc add class dev <device> parent parentID classid <ID> hfsc [ [ rt SC ]
> [ ls SC ] | [ sc SC ] ] [ ul SC ]
> SC is the description of the curve as described above using m1 d m2 or
> umax dmax rate, e.g.,
> tc add class dev <device> parent parentID classid <ID> hfsc rt 1514b
> 20ms 200kbits
> If we are not using two curves, we only need the last parameter, e.g.,
> tc add class dev <device> parent parentID classid <ID> hfsc ls 500kbits
> The sc parameter is used when rt and ls are the same, i.e., one can
> specify them both in one definition rather than needing to write two.
> It is not usual to specify all three curves in the same class. The rt
> parameter is only used on leaves. The ul parameter is usually not used
> leaves.
> Real-time service curve
> Real-time service curves can only be applied to leaf nodes (remember
> this is Hierarchical Fair Service Curve). Using our previous example,
> rt curve would not be applied to "Gold Clients" but to "Web traffic".
> The rt curves can have either one curve (line) or two. In fact, it is
> usually only rt curves which have two curves; ls and ul curves generally
> do not. If the first curve is steeper than the second curve
> (translated: if the initial bandwidth guarantee is greater than the
> sustained bandwidth guarantee), the curve is called concave in HFSC
> terminology. If the opposite is true, it is called convex. This is
> illustrated by the below graphic copied from
> http://www.cs.cmu.edu/~hzhang/HFSC/main.html
> One must be careful when specifying rt curves because they will be
> honored above all other curves (remember we said that, when it is
> impossible to satisfy the requirements for both guaranteed bandwidth and
> fair sharing, guaranteed bandwidth wins). This will be more
> understandable when we discuss the upper limit (ul) curve. To jump
> ahead a little bit, the ul is typically though not exclusively used to
> describe the maximum bandwidth available, e.g., a T1 circuit or a cable
> connection. We said that rt is honored above all other curves. If the
> ul curve says the maximum bandwidth available is 10 Mbps and the sum of
> all our rt curves is 20 Mbps, the system will try to guarantee 20 Mbps
> which, of course, means it will fail to meet its guarantees under
> maximum load.
> Jumping ahead once more, rt curves override ls curves, too. The ls
> curves are used to share extra bandwidth fairly. So, if the ls curve
> dictates that class A should have 2 Mbps of our 10 Mbps link and class B
> should have 8 Mbps but the rt curve says that class A is guaranteed 3
> Mbps, class A will get 3 Mbps and class B only 7 Mbps. The rt curve
> will always be honored whenever it is physically possible. The bottom
> line is that the rt service curve always "wins."
> An important point to remember is that the rt curve determines the
> bandwidth and latency guarantees, is the only curve which determines
> bandwidth and latency guarantees, and has nothing to do with how
> bandwidth is fairly shared (other than to override that sharing if
> necessary!). To put it another way, the function of the rt service
> curve is independent of the ul and ls service curves. They handle two
> completely separate characteristics of HFSC.
> Upper limit service curve
> As mentioned above, the ul curve is often used to describe the maximum
> bandwidth available. More specifically, it sets an upper boundary to
> the bandwidth which can be allocated by the ls curve. As we will see,
> the ls curve is used to determine how the excess available bandwidth is
> fairly shared. The ul service curve sets limits on that sharing.
> Let's get some vocabulary defined. Link sharing is the term used by
> HFSC to describe how the bandwidth not actively used by the rt service
> curve is fairly allocated among the rest of the network sessions which
> are requesting bandwidth. Let's connect the dots again as a way of
> review. Remember, the rt curve defines the guaranteed amounts of
> bandwidth. Let's go back to our 10 Mbps circuit and say we have VoIP
> with an rt service curve rate of 1 Mbps, interactive traffic with an rt
> service curve rate of 5 Mbps, web traffic with an rt service curve rate
> of 2 Mbps, and bulk traffic with an rt service curve rate of 1 Mbps.
> Note that the sum of the rt curves does not need to equal the total
> bandwidth. Now let's say it's the middle of the night so the phones are
> not in use and no one is generating interactive traffic however web
> traffic to our internal web servers is going at full speed as are our
> overnight off site backups and FTP transfers. Web is guaranteed 2 Mbps,
> bulk is guaranteed 1 Mbps and link sharing will figure out how to divide
> up the remaining 7 Mbps. However, the ul curve could override the way
> link sharing divides that 7 Mbps.
> Let's illustrate how and learn more about ul at the same time. The ul
> service curve is normally specified at the top of the hierarchy and is
> set to the maximum bandwidth available. Think way back to when we said
> that link sharing only happened between peers. Classes lower in the
> hierarchy can only contend for the bandwidth allocated to their parent
> and not for bandwidth allocated to classes at the same level but under a
> different parent. Once again, I will copy a graphic from
> http://www.cs.cmu.edu/~hzhang/HFSC/main.html to illustrate this:
> Since children can only contend for the bandwidth allocated to their
> parents, the ul limit on bandwidth flows down through the entire tree
> under it. If the parent with the ul limitation cannot receive the
> bandwidth, its children cannot contend for it. Thus, by placing the ul
> at the top of the hierarchy and setting it to the maximum bandwidth
> available, it flows down through the entire tree and we do not need to
> define it in every descendant class. That is, unless we want to
> override it further down the tree.
> Let's go back to our illustration. If we had set ul rate 10240kbits (10
> Mbps), the web traffic and the bulk traffic will be sharing the 7 Mbps
> available bandwidth in whatever ratio was specified in their ls service
> curves. If no ls curves were specified, they will divide the bandwidth
> according to their rt curves - in this case a 2:1 split. For now, let's
> assume that the ls curve is the same as the rt curve, that is 2 Mbps for
> web and 1 Mbps for bulk. Remember that the ul curve sets a limit on the
> ls curve. What if, for some reason, we wanted to make sure that bulk
> traffic never exceeds 3 Mbps even if there is more available? We would
> create a second ul service curve for the bulk traffic on the bulk
> traffic class with ul rate 3072bkits.
> Link sharing will try to allocate an extra 2.33 Mbps to bulk traffic
> (7 / 3). When this link sharing bandwidth is added to the guaranteed
> bandwidth of 1 Mbps, we come out to 3.33 Mbps. Since this is exceeds
> the ul service curve set specifically for bulk traffic, link sharing
> will not be able to service bulk traffic at 3.33 Mbps. It will only be
> able to provide service at 3 Mbps. The rest will go to the web service.
> So, to summarize, the ul service curve is not used to guarantee
> bandwidth or latency. That is the job of the rt service curve.
> Allocated bandwidth can exceed the ul service curve if the sum of the rt
> service curves is greater than the ul service curve and the circuit can
> support the higher rt bandwidth allocation. This is another way of
> saying the rt guaranteed bandwidth always takes precedence. The ul
> service curve is used to determine the link sharing bandwidth, i.e., the
> bandwidth allocated to classes of traffic from the unused portion of the
> available bandwidth. It is specifically used to limit how much
> bandwidth can be allocated through link sharing, is typically set to the
> maximum bandwidth of the circuit, and is normally set at the top of th
> hierarchy because its affect is to flow down to all classes underneath
> it.
> Link-sharing service curve
> The ls service curve is not used to guarantee bandwidth or latency. Its
> sole purpose is to determine the proportions in which unused bandwidth
> is allocated to classes which are requesting more than their guaranteed
> bandwidth, that is link sharing. Although it is good practice to use
> service curves with numbers that are realistic for the available
> bandwidth, technically, only the ratio is important.
> Let's illustrate by returning to our previous example. The ul is set to
> a rate of 10 Mbps. We would expect the web ls service curve to use a
> rate of 2 Mbps and the bulk ls service curve to use a rate of 1 Mbps.
> However, we could say the web ls sc is 200 Mbps and the bulk ls sc is
> 100 Mbps and it would not break and not be illegal - just confusing.
> The ratios are the same (2:1) and it is only the ratios which are
> important.
> The discussion about ul service curves has "stolen the thunder" from the
> ls service curve discussion, i.e., there is not much left to say. The
> ls service curves determine how link sharing works, i.e., how the
> bandwidth with is not being used to satisfy the guarantees of the rt
> service curves is fairly allocated among all the other network traffic
> flows who would like more bandwidth than they are guaranteed.
> The Linux and BSD implementation of HFSC go beyond the original
> specification by allowing us to specify the ls service curve separately
> from the rt service curve. This gives us some powerful flexibility as
> we are about to illustrate.
> Let's extend our previous example. Remember we have a 10 Mbps circuit
> and thus have set the ul service curve rate at the top of the hierarchy
> to 10 Mbps. We have four classes of traffic, VoIP, interactive, web,
> and bulk. The rt rate for VoIP is 1 Mbps, for interactive 5 Mbps, for
> web 2 Mbps, and for bulk 1 Mbps. That accurately reflects our desire
> for guaranteed bandwidth but those proportions may not accurately
> reflect how we want any available excess bandwidth distributed.
> For our purposes, link sharing should have the following
> characteristics. Bulk should be able to use all the bandwidth if it is
> available and uncontended. However, if the VoIP traffic needs extra
> bandwidth and there is available bandwidth, it should be granted that
> extra bandwidth with priority since we do not want to starve our voice
> traffic. Furthermore, we want visitors to our web site to have a
> positive experience and not one with substantial delays so, if there is
> contention between bulk and web traffic, we want web traffic to take
> more than a 2:1 ration of available bandwidth. Thus, we might setup our
> tc classes as follows:
> VoIP:
> tc add class dev eth0 parent 1:1 classid 1:10 hfsc rt rate1024kbits ls
> rate 7168kbits
> We first thought this should be rt umax 222b dmax 5ms rate 1024kbits
> because the maximum sized VoIP packet is typically 222 bytes (ulaw/alaw
> at 64Kbps = 8KB/s * 0.020s (20 ms per packet) = 160 Bytes + 8 (UDP
> header) + 40 (IP header) + 14 (Ethernet header) = 222 Bytes) and we want
> it delayed in the router for no more than 5ms. However, to guarantee 1
> Mbps bandwidth, a 222 byte packet needs to be sent within roughly 1.7ms
> (222 * 8 = 1776 bits / (1024 * 1024)bits/s = 0.0017s). Thus, our rate
> is sufficient and we do not need to jump the delivery of VoIP packets by
> specifying a larger initial bandwidth.
> Interactive
> tc add class dev eth0 parent 1:1 classid 1:11 hfsc sc rate5120kbits
> We use sc since we want rt and ls to be the same
> Web:
> tc add class dev eth0 parent 1:1 classid 1:12 hfsc rt rate 2048kbits ls
> rate 3072kbits
> Bulk:
> tc add class dev eth0 parent 1:1 classid 1:12 hfsc sc rate 1024kbits
> Note that the sum of our ls service curves exceeds the ul service curve.
> This is not a problem. Remember it is only the ls service curve ratios
> which are meaningful. So what have we done? Even though our guarantees
> can be met with a proportion of 1:5:2:1, we have specified that, if
> there is extra bandwidth available and, if there is contention for it,
> distribute it in the ratio of 7:5:3:1. In other words, if interactive
> and web are idle and VoIP and bulk can use more bandwidth than their
> guarantees (backlogged in HFSC terminology), the bandwidth will be
> allocated between VoIP and bulk at a 7:1 ration and not a 1:1 ratio.
> Likewise, if VoIP and interactive are idle and web and bulk are
> backlogged, the extra bandwidth will be allocated at a 3:1 ratio rather
> than a 2:1 ratio. Can we see the value of having separate rt and ls
> service curves?
> Timers
> However, service curves are not the whole story. In fact, it is not
> really the service curves which determine which packet is sent when.
> The service curves are used to set the timers and it is the timers which
> determine which packet is sent when.
> While service curves are quite understandable to system administrator
> types once we translate the vocabulary (curves = bandwidth, umax and
> dmax = latency (technically bandwidth I suppose but, latency in
> practicality)), timers are they mysterious art of programmers and
> mathematicians - an impenetrable black box. Let's see if we can pry
> open that black box and make it at least a little understandable to us
> sysadmin types.
> HFSC uses four separate timers to work its wonders:
> 1. Fit time
> 2. Virtual time
> 3. Eligible time
> 4. Deadline time
> Virtual time
> Let's start with virtual time. Virtual time is used by link sharing to
> determine which queue should be serviced to keep things fair, that is to
> keep the bandwidth in proportion to the ls service curve ratios.
> Virtual time appears to be a very complicated topic addressing
> mind-bending issues like how to preserve fairness among several
> backlogged queues when a new queue becomes backlogged as well and to
> preserve this fairness without starving one of the queues while the
> others catch up. Thus my explanation will be a dramatic
> oversimplification but hopefully enough to give fellow sysadmins a
> toehold to ascend this seemingly sheer rock face.
> Virtual time is a measure of how much time has been spent servicing the
> queue and how much it will take to service the next packet. Here is a
> very good ascii art representation copied from
> http://www.sonycsl.co.jp/~kjc/software/TIPS.txt :
> bytes
> | /
> | /service curve
> | /
> next -->+ +----------------+
> packet | | /|
> length | | / |
> | | / |
> total --> + +------------+ |
> bytes | /| |
> already | / | |
> sent | / | |
> / | |
> | |
> | |
> --------+---+--------------> time
> vt for next packet
> vt for previous packet
>
> Not surprisingly, this makes a great deal of sense when we digest it.
> Remember, the service curve we are using is the ls service curve, i.e.,
> the one for link sharing. The more the bandwidth allocated to the ls
> service curve, the steeper the slope of the line. The steeper the slope
> of the line, the shorter the time to transmit the packet = the more
> bandwidth, the shorter the time to transmit the packet. Thus, the
> change in virtual time for the same sized packet is less for a faster
> queue than for a slower queue. We'll see why that is important in a
> second.
> Remember that link sharing is used only among peers. Only peers can
> contend for available extra bandwidth. Fairness is achieved in HFSC by
> trying to keep the virtual time of all peers equal. When a queue
> becomes backlogged, i.e., needing more than its guaranteed bandwidth, it
> starts accumulating virtual time. The more it has been serviced while
> backlogged, the more virtual time it accumulates.
> When HFSC looks at the various backlogged queues, how does it determine
> which one to service? Look again at the above diagram. Each queue will
> have its current virtual time and the virtual time that it will have
> after it sends its next packet. HFSC will choose the next packet which
> will have the lowest virtual time. Let's make this more understandable
> with some real illustrations. Let's say we have two backlogged queues
> with identical ls service curves and each has a full sized Ethernet
> packet pending. Queue A has accumulated virtual time of 1000ms and
> Queue B has accumulated virtual time of 999ms. Let's say that sending
> the full sized Ethernet packet will take 2ms. The virtual time after
> Queue A sends its packet would be 1002 whereas Queue B would be 1001ms
> so HFSC sends Queue B's packet. Now Queue B has VT (virtual time) of
> 1001ms and the next packet would bring it to 1003ms. Queue A has VT of
> 1000ms and sending the next packet would bring it to 1002ms. HFSC
> chooses the packet which will result in the lowest VT thus it sends the
> packet in Queue A. See how it tries to keep the virtual times equal and
> thus produces fairness.
> Now let's alter the scenario. Let's keep the virtual time the same,
> 1000ms for Queue A and 999ms for Queue B but Queue A is handling small
> packets which only take 0.5ms to send. Queue A has one of these packets
> ready to send while Queue B has one of its full sized packets to send.
> VT for Queue A after sending its packet would be 1000.5ms and for Queue
> B would be 1001ms so, even though Queue A has already received more
> service, it is services again because its final virtual time would be
> smaller.
> More importantly, let's go back to the idea that both Queue A and Queue
> B use full sized packets but this time the ls service curves are not
> equal. Let's say the ls service curve rate for Queue A is 5120kbits and
> for Queue B is 1024kbits. Thus, a packet that would take Queue B 2ms to
> transmit would take Queue A 0.4ms to transmit. Both queues are
> continually backlogged so they always have packets to send. HFSC takes
> a look and calculates the next VT for Queue A as 1000.4 and Queue B as
> 1001 so it sends Queue A. It calculates again and A is 1000.8 and B
> 1001 so it sends A again. The next calculation of VT puts A at 1001.2
> and B at 1001 so it sends B. The next calculation puts A at 1001.2 and
> B at 1003 so A is sent. Then 1001.6 versus 1003, then 1002 vs. 1003,
> then 1002.4 vs. 1003, then 1002.8 vs. 1003, then 1003.2 vs. 1003. Can
> you see how the virtual time calculation is allocating service to Queue
> A at a 5:1 ratio with Queue B - just the fairness we requested via the
> ls service curves.
> So, in summary, virtual time used to produce fairness when distributing
> available excess bandwidth to backlogged queues in the ratio of the ls
> service curves. It does this by trying to keep virtual times for all
> peers in the hierarchy equal and it does this by always choosing the
> packet to send which will result in the smallest virtual time.
> Fit time
> Fit time is pretty simple to understand. Recall that we said the ls
> service curve was bounded by the ul service curve, i.e., even if a queue
> should get say 10 Mbps according to link sharing, if the ul (Upper
> Limit) service curve says we can use 8 Mpbs maximum, we are only going
> to get 8 Mbps. Fit time takes into account the ul service curve.
> In effect, fit time looks at what the clock time would be to send the
> packet based upon the ul service curve rate, i.e., what the time would
> be to send the pending packet at the maximum transmission rate. If that
> time is later than the current clock time, the packet will not be sent
> not matter what virtual time says. If the current clock time is later
> than fit time, i.e., we would not have exceeded out bandwidth
> limitation, then the decision is made based upon virtual time.
> As a reminder, this is all for traffic over and above the guaranteed
> rate, i.e., the rt service curve rate. Packets are always sent to
> preserve the rt service curve rate as long as it is physically possible
> regardless of fit time or virtual time. This is the same as saying that
> the rt service curve always wins or, to phrase it yet another way, to
> meet the HFSC design criterion that, if there is a conflict between link
> sharing and guaranteed bandwidth, choose guaranteed bandwidth.
> Eligible time
> The rt service curve uses two timers: eligible time and deadline time.
> Recall, we used referred to eligible and deadline time toward the
> beginning of this discussion when observed how HFSC provides decoupled
> guarantees for both bandwidth and latency. Like fit time, eligible time
> is relative to clock time. In other words, HFSC calculates what the
> clock time would be to send the queued packet at the guaranteed rate,
> i.e., the rt service curve rate. If that time is later than the current
> clock time, that packet's time has not come yet and it cannot be sent
> based upon its real time guarantee. I do believe it can be sent based
> upon virtual time assuming that fit time allows it. After all, that is
> what link sharing is about - being able to exceed the guaranteed
> bandwidth if there is extra bandwidth available. On the other hand, if
> current clock time is later than eligible time, then this packet had
> better get moving because it is potentially running behind schedule.
> So, eligible time is just as then name implies; it is the time the
> packet becomes eligible for sending based upon the real-time service
> curve, i.e., the guaranteed bandwidth/latency.
> An important point to understand the difference between eligible time
> and deadline time is that eligible time is measured from the beginning
> or head of the packet, i.e., is HFSC ready to begin sending this packet.
> But what happens when more than one queue has packets whose eligible
> time has come? That's where deadline time comes into play.
> Deadline time
> Deadline time is closely related to eligible time and is likewise
> measured against clock time. However, deadline time is measured against
> the end or tail of the packet, i.e., by when must we have finished
> sending this packet at the specified bandwidth in order to meet our
> packet delivery guarantees for bandwidth and latency. Once again,
> http://www.sonycsl.co.jp/~kjc/software/TIPS.txt has an excellent ASCII
> graphic for illustrating the relationship between eligible time measured
> at the beginning of the packet and deadline time measured from the end:
> bytes
> | /
> | /service curve
> | /
> next -->+ +----------------+
> packet | | /|
> length | | / |
> | | / |
> cumulative --> + +------------+ |
> bytes | /| |
> already | / | |
> sent | / | |
> / | |
> | |
> | |
> --------+---+--------------> time
> eligible deadline
> time
>
> This time, the slope is the rt service curve. The way in which HFSC
> chooses from among several different queues all with packets whose
> eligible time is greater than current clock time is almost identical to
> the way it chooses among backlogged queues with virtual time, viz., it
> chooses the packet with the lowest deadline time. Remember that the
> steeper the curve, the greater the bandwidth and the shorter the
> distance between eligible time and deadline time for the same sized
> packet.
> Let's walk through a real example. We have Queue A with VoIP traffic -
> small, 222 byte packets and an rt service curve bandwidth such that it
> takes 0.2ms to send its packets; that equates to roughly 8.88 Mbps ((222
> * 8)bits/0.0002s). Let's also assume that we have so much VoIP traffic
> that the queue is filled so we always have a VoIP packet asking to be
> dequeued. Queue B is sending FTP with large packets and an rt service
> curve rate such that each packet takes 2ms to send; this equates to
> 6.056 Mbps ((1514 * 8)bits/0.002s). Queue B is also completely full.
> Let's assume that the maximum bandwidth available is the sum of the
> guaranteed bandwidths, viz., 14.936 Mbps. This will allow us to
> calculated the progress of clock time, i.e., how long it actually takes
> to send each packet. Also remember that each packet has a 4 byte CRC,
> and 8 byte preamble, and a 12 byte interframe gap time at least in
> traditional Ethernet. Thus to transmit a packet in Queue A, we really
> need to transmit 246 bytes and, to transmit one in Queue B, we need to
> transmit 1538 bytes. Thus, the elapsed time to send a Queue A packet is
> (246 * 8)bits / 14,936,000(b/s) = 0.132ms and the time to transmit a
> Queue B packet is (1538 * 8)bits / 14,936,000(b/s) = 0.824ms. Sorry for
> all the math but this is what is inside the black box (and a very
> simplified version!).
> Let's assume that clock time (CT - the actual time) is 1000ms (not
> realistic but it makes the explanation easier!). The next packet queued
> in Queue A has an ET (eligible time) of 1000ms and the next packet in
> Queue B has an ET of 999ms, i.e., both are eligible to be sent. A less
> sophisticated traffic shaping algorithm would send the FTP packet first.
> However, HFSC calculates the deadline time (DT) for the packet in Queue
> A at 1000.2 (1000 + 0.2) and the deadline time for the packet in Queue B
> at 1001ms (999 + 2) so it sends A instead since it has the smaller DT.
> 0.132ms has elapsed in real time so CT is now 1000.132. The
> eligible/deadline times (ET/DT) for A and B respectively are
> 1000.2/1000.4 and 999/1001. Notice that A is no longer eligible to send
> because its ET > CT so B is serviced. 0.824ms has elapsed to send B's
> packet so CT is now 1000.956. ET/DT for A is still 1000.2/1000.4 but B
> has changed to 1001/1003. B just misses being eligible to send but A is
> eligible so A is sent. Elapsed time is 0.132, CT is now 1001.088, ET/DT
> for A is 1000.4/1000.6. Both A and B are eligible at the same time
> again as both their ETs <= CT. A's DT is less than B's DT so A is
> serviced.
> In fact, A will send 11 packets. Let's see the result after A sends 11
> packets. Elapsed time is 11* 0.132 = 1.452ms so clock time is 1002.54.
> A's ET/DT have incremented by 11 * 0.2 so they are 1002.6/1002.8. B's
> ET/DT have remained at 1001/1003. A is no longer eligible so the fact
> that its DT is less than B's DT is irrelevant. B is serviced.
> Pulling it all together
> To this point, almost all of our discussion have involved rt service
> curves based solely upon rate and we have been using some fairly large
> circuits to illustrate. What happens when our bandwidth really is
> constrained such as a T1 circuit or the upload bandwidth of an
> asymmetric DSL or cable connection and we need to balance time sensitive
> traffic with bulk traffic? This is where di-linear curves save the day.
> The best illustration I have found is from the SIGCOM97 paper on HFSC:
>
> The results might not be obvious at first. The packets arriving, e.g.,
> coming from the internal network and heading toward the constricted T1
> circuit (well, in this specific example, it is a 10 Mbps circuit) are
> shown in the second level of graphics from the top. The resulting
> output of those packets is shown in the very bottom set of graphics.
> The illustrations on the left show a mono-linear curve, i.e., just based
> upon bandwidth. The video and FTP packets are flooding in, are being
> lined up and scheduled for dequeueing based upon the bandwidth only.
> Thus, the initial video packet sits in queue behind the FTP packets as
> there is no need to rush to meet its bandwidth requirements. Here is
> how the authors describe what is happening:
> "To illustrate the advantage of decoupling delay and bandwidth
> allocation with non-linear service curves, consider the example in
> Figure 2, where a video and a FTP session share a 10 Mbps link . . . .
> Let the video source sends 30 8KB frames per second, which corresponds
> to a required bandwidth of 2 Mbps. The remaining 8 Mbps is reserved by a
> continuously backlogged FTP session. For simplicity, let all packets be
> of size 8 KB. Thus, it takes roughly 6.5 ms to transmit a packet."
> "As can be seen, the deadlines of the video packets occur every 33 ms,
> while the deadlines of the FTP packets occur every 8.2 ms. This results
> in a delay of approximately 26 ms for a video packet."
> Let's work through the math to make that more understandable. HFSC is
> committed to deliver 2 Mbps to video and each packet is 8KB long. Thus,
> HFSC's commitment to deliver that packet is within (8000 * 8)bits /
> 2,000,000(b/s) = 32ms. I'm not quite sure why I come up with 32 and
> they say 33 but we'll use 33. In other words, to meet the deadline
> based solely upon the rate, the bandwidth part of the rt service curve,
> the packet needs to be finished dequeueing at 33ms. Since it only takes
> 6.5ms to send the packet, HFSC can sit on the packet it received for 33
> - 6.5 = 26.5ms if it needs to in order to meet the guarantees for other
> traffic. This adds unnecessary latency to the video stream.
> In the second scenario, we introduce an initial, elevated bandwidth
> guarantee for the first 10ms. The bandwidth for the first 10ms is now
> 6.6 Mbps instead of 2 Mbps. We do the math again and HFSC's commitment
> to video to maintain 6.6 Mbps is to finish dequeueing the packet within
> (8000 * 8)bits / 6,600,000(b/s) = 10ms. Since it takes 6.5 ms to send
> the packet, HFSC can sit on the packet for no more than 10 - 6.5 = 3.5
> ms. Quite a difference!
> I assume for simplicity's sake, the graphic leaves out an important
> point. The rt service curve either fully or partially resets when the
> queue has been drained. Fully or partially depends on how much time has
> elapsed since the last service rendered and the new service requested
> when the queue becomes active again. Thanks for Michal Soltys on the
> netdev kernel mail list for clarifying this for me.
> Without this reset, the first part of the service curve (the m1 portion
> if you recall the earlier discussion about how service curves can be
> defined) would not have much practical value because once traffic
> activates the queue, only the first packet or first few packets would be
> guaranteed the latency of the first, accelerated part of the curve.
> Everything else would use the second part of the curve (the m2 portion -
> we'll use the terms m1 and m2 for the rest of the discussion).
> So let's re-examine the above example in more detail. The video packet
> arrives, uses the m1 curve, is jumped ahead of the FTP packets because
> of the low latency guarantee of the m1 curve, is dequeued, and now the
> queue is empty for 33.33ms (remember the video is playing at 30 frames
> per second, well, 32.69ms when you account for transmission time on a
> 100 Mbps circuit) which allows the curve to reset. The next video
> packet comes in and it is treated according to m1 and not m2 because we
> have reset the curve. Thus, each video packet is jumped in front of any
> queued FTP packets.
> We can even multiplex several video streams. As long as the queue is
> allowed to go idle long enough, each of those streams will be treated
> with very low latency and jumped in front of the FTP packets, i.e.,
> until we have so many video streams that the queue starts to backlog.
> Then they will use the m2 curve.
> This is not a bad thing; it is a good thing and allows us a new
> perspective on the m1 and m2 curves. Hopefully, we have allocated
> enough bandwidth in our m2 curve to properly service our video or VoiP
> or whatever we are pushing through this queue. Thus, even if we are not
> receiving the accelerated treatment, we are still experiencing
> sufficient service. If our queue is badly backlogged and overflowing,
> then we have a different problem and need more raw bandwidth!
> In this way, we can think of the m2 curve, the second level of service
> in a concave service curve (remember a concave service curve is where we
> start out with a higher bandwidth and then change to a lower bandwidth),
> as a circuit breaker preventing overload. In other words, we are saying
> to this prioritized traffic that we will deliver it with a lower than
> normal latency (and thus higher short term bandwidth) while we can but,
> if it becomes too much (as determined by the system administrator who
> defined the HFSC qdisc), we will drop it down to a more sustainable rate
> that will not exceed the physical capabilities of the circuit. This
> assumes we have designed our traffic shaping so that the sum of all the
> m2 portions of all the rt service curves do not exceed the capabilities
> of the circuit.
> Another way of saying this with familiar terminology is that we can
> burst at the m1 rate as long as the queue doesn't backlog but, when it
> does, we drop to our sustainable rate. Thus, concave rt service curves
> are very well suited to periodic traffic, i.e., traffic which sends
> packets on a recurring interval with space in between like VoIP or
> video. It may be less effective on burstable traffic such as the
> example of using it to accelerate the delivery of text on a web site
> unless the traffic is low enough that the queue has a chance to drain
> regularly.
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: iwlagn regression in v3.1.5
From: wwguy @ 2011-12-13 23:20 UTC (permalink / raw)
To: Udo Steinberg
Cc: Andrej Gelenberg, Intel Linux Wireless, John W. Linville,
linux-wireless@vger.kernel.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <20111213230443.2c12caeb@x220.fritz.box>
On Tue, 2011-12-13 at 14:04 -0800, Udo Steinberg wrote:
> Hi,
>
> Glad to hear it works for you now. In the patch, the following piece of code
>
> + if ((iwl_is_associated_ctx(ctx) &&
> + !ctx->ht.is_40mhz) ||
> + !iwl_is_associated_ctx(ctx))
>
> can be simplified to:
>
> if (!iwl_is_associated_ctx(ctx) || !ctx->ht.is_40mhz)
>
right, looks better this way :-)
Thanks
Wey
^ permalink raw reply
* Re: [WARNING - VERY LONG] A sysadmin's understanding of HFSC and IFB
From: John A. Sullivan III @ 2011-12-13 23:01 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev
In-Reply-To: <1323417599.2529.18.camel@edumazet-laptop>
On Fri, 2011-12-09 at 08:59 +0100, Eric Dumazet wrote:
> Le vendredi 09 décembre 2011 à 02:17 -0500, John A. Sullivan III a
> écrit :
> > Hello, all. I've been trying to summarize my last week's worth of
> > research into HFSC and IFB. Being neither a developer nor a
> > mathematician, I found most of the existing documentation daunting and
> > am truly grateful for the help I received on this list to understand the
> > technologies.
> >
> > I do not currently have a blog to post this research and so was thinking
> > of posting it to this list so that it could be archived and searchable
> > for other poor sysadmin types like me to save them the days of
> > struggling to get their practical heads around the concepts.
> >
> > However, since this is probably a 15 page or so document, I realized
> > this could be quite rude to those on dial up or metered connections.
> > Would it be appropriate to post my summary here? Thanks - John
> >
>
> Please post here, thats definitely a good idea.
>
> I am pretty sure your contribution could serve to add a page to
>
> http://www.linuxfoundation.org/collaborate/workgroups/networking/group
>
> I believe we lack documentation. A lot.
<snip>
OK - it's almost ready. The only problem I know if is that, when I do
the math based upon my explanation, I sometimes violate an rt curve when
I should not. I posed that in an email to the list entitled "An error
in my HFSC sysadmin documentation". If anyone can figure out where my
error is, I will gladly change the documentation. Here's what I have.
The graphics except the ASCII art are obviously missing. All
corrections and suggestions very gratefully accepted - John
IFB
The Intermediate Functional Block (IFB) device is a pseudo-interface to
which traffic can be redirected by using a tc filter with the mirred
(mirror/redirect I assume) action. The primary documentation appears to
be at
http://www.linuxfoundation.org/collaborate/workgroups/networking/ifb but
I found it less than helpful. Perhaps the most helpful information was
found in a discussion on the mirred tc filter action at
http://www.sephidev.net/external/iproute2/doc/actions/mirred-usage and
particularly this section:
Remember that IFB is a very specialized case of packet redirecting
device. Instead of redirecting it puts packets at the exact spot
on the stack it found them from.
In other words, we redirect or mirror traffic from an interface into the
ifb interface and, when ifb is finished with it, it puts it right back
onto the interface which was redirected into it. Why would one want to
do that?
Diagnostics are one important reason, e.g., to capture dropped packets.
Packets may be dropped on the interface either because of an iptables
rule or a traffic limiting rule. The packets can be mirrored onto an
ifb interface which will see them before they are dropped allowing
packet analysis on them. Another would be in a Linux based switch to
port mirror traffic from one port to another.
Another reason is for applying identical traffic shaping rules to
multiple interfaces. Let's say one is using complicated traffic shaping
rules with several qdiscs (queue disciplines), classes, and filters and
the same set applies to many interfaces. Rather than defining and
maintaining this complex set for multiple interfaces, one could set a
filter for each of those interfaces to redirect into an ifb interface
and apply the complex traffic shaping there.
A final reason is both complex and critically important, especially for
SimplicITy and Firepipes (or anyone using VDI across the Internet):
ingress traffic shaping. Normal Linux ingress traffic shaping can only
police. Policing cannot really shape packets. It can edit them, drop
them, pass them, or do nothing. One of the important goals of either
policing or shaping ingress traffic is to give us a fighting chance to
shape inbound traffic from the Internet when we have no control over the
upstream router.
For example, we may prioritize NX/RDP/Citrix and VoIP traffic outbound
to the Internet so that it is prioritized over web browsing and sending
huge email attachments or FTP transfers. But, if someone starts pulling
down a huge file and consumes all the inbound bandwidth, our desktop
sessions can slow to a crawl and our VoIP calls become unintelligible.
We might face a similar problem if we host our own web servers; our web
servers could slow to a crawl in the public perception if their ability
to respond to queries is being blocked by monster downloads into our
network. How can we keep the bulk traffic internal users are
downloading from mangling our time critical traffic?
The basic idea is to use the flow control mechanisms of traffic flow.
This is built in to any TCP transmission and may or may not be in the
upper layers of a UDP stream. If we start dropping inbound packets, the
other side should get the point and start throttling its flow.
The recommended way to do this is to place an egress filter on the
internal interface of the firewall, i.e., we only let the firewall place
traffic on the internal network at a particular rate. Egress traffic
shaping can be very powerful so we can use something like HTB
(Hierarchical Token Bucket) to reserve bandwidth for time sensitive
traffic but allow that bandwidth to be used for bulk traffic it is not
needed for time sensitive traffic. We can also distinguish between well
behaved traffic (like most TCP traffic) and most poorly behaved traffic
which won't throttle (like most UDP traffic) and not allow UDP traffic
to use extra bandwidth if available.
This is fine if the firewall has only a single internal interface. The
bulk traffic can only be output at the traffic shaping speed and, when
the inbound buffer overflows, packets will drop and the well behaved
application on the other end should throttle. But what if we have a DMZ
or, as we often do with Firepipes, multiple internal interfaces?
Throttling the egress of the internal interface would also throttle
traffic flowing to it from the DMZ or other internal interfaces; that
would be very bad.
In these cases, it is better to create an ingress filter, i.e., filter
the traffic coming in off the Internet. As mentioned, an ingress filter
can only police so the only way we can throttle download traffic is to
drop the packets. We could create several bands to reserve bandwidth
for different types of traffic and drop packets which exceed those
bandwidth limits but we have no ability to do complex traffic shaping
such as allowing bulk traffic to use available bandwidth from higher
priority traffic if it is available.
This is where IFB comes into play. We can redirect the inbound traffic
into an IFB interface and then apply an egress filter with full traffic
shaping to the IFB. This will shape the traffic before it is placed
back onto the inbound interface.
This would allow us to use something like HTB on the inbound traffic so
that we could reserve bandwidth for time sensitive traffic, limit
bandwidth for bulk traffic, yet allow the bulk traffic to use the time
sensitive bandwidth when it is available. But what happens if the bulk
traffic is using the bandwidth and a time sensitive packet arrives? It
is now queued behind the bulk packets and can suffer intolerable delay.
This is where HFSC steps in.
HFSC
HFSC (Hierarchical Fair Service Curve) is an incredibly powerful but,
again, poorly documented qdisc. Its outstanding feature over qdiscs
like HTB is that it separates latency guarantees from bandwidth
guarantees. In other queue disciplines, the only way to guarantee lower
latency is to allocate more bandwidth. This is counter productive with
technologies such as VoIP which require low latency but send very small
packets and typically require far less bandwidth per flow than bulk
applications. HFSC has three goals:
1. Decouple latency requirements from bandwidth requirements
2. Provide guaranteed bandwidth when specified
3. Fairly share available extra bandwidth
It recognizes it cannot always achieve all three goals and will preserve
guaranteed bandwidth over fair sharing when there is a conflict.
The paper describing HFSC is at
http://www.cs.cmu.edu/~istoica/hfsc_extended.ps.gz (with a note that
says, "You might need to treat it first with: sed "s|\[FontBBox
\]|/FontBBox load |" as it was generated with a little bit old (ancient)
idraw version." It is highly technical and mathematical but has some
excellent graphics to illustrate the principles.
A related site is http://www.cs.cmu.edu/~hzhang/HFSC/main.html
The latest man pages are a little less mathematical but still pretty
dense with the references to functions to describe the service curves.
I've downloaded the latest man pages
(http://git.kernel.org/?p=linux/kernel/git/shemminger/iproute2.git;a=blob_plain;f=man/man7/tc-hfsc.7;hb=HEAD and http://git.kernel.org/?p=linux/kernel/git/shemminger/iproute2.git;a=blob_plain;f=man/man8/tc-hfsc.8;hb=HEAD) to Tech/Equipment/Endian; they can be read with:
nroff -mandoc -rLL=<width>n <page> | less
A commonly reference resource is http://linux-ip.net/articles/hfsc.en/
I also found http://www.sonycsl.co.jp/~kjc/software/TIPS.txt helpful.
However, many articles attempting to explain HFSC didn't seem to really
get it - especially the part about decoupling latency and bandwidth
requirements. It is all quite confusing and not well understood. In
fact, as I'm thinking about how to record what I have learned, I'm
really struggling because there is no simple way to describe HFSC!
Let's break down the terms. It is hierarchical because bandwidth can be
allocated and controlled on a hierarchical basis. For example, the top
level of the hierarchy might be our overall available bandwidth. The
next level of the hierarchy might be gold level customers who get 70% of
the available bandwidth and regular customers who get 30%. The next
level might be individual customers or groups of customers who divide
the 70% or 30% allocated to their parent. The final hierarchy might be
groups of traffic like VoIP, interactive, web, or bulk. These end nodes
are called leaf nodes. There is an important distinction between leaf
nodes and container nodes. Bandwidth guarantees are only made at the
leaf node level. Containers are only used for link sharing, i.e., how
excess bandwidth is shared when it is available. Remember that we said
HFSC enforces guarantees even if it means bandwidth is not shared
evenly. Bandwidth guarantees are always honored (if physically
possible) regardless of the bandwidth allocated to the higher layers of
the hierarchy. Thus one must be careful to not overallocate bandwidth
at the leaves.
Moreover, the fair sharing of bandwidth only happens between peers. In
other words, using our example, only two peers contend for the overall
bandwidth - Gold and Regular. If the second level hierarchy of Gold has
clients A, B, and C and the second level of Regular has D and E, D and E
contend for Regular's share of the bandwidth and A, B, and C contend for
Gold's share of the bandwidth but, for example, D never contends with B
because they are in different parts of the tree. Only peers contend for
available bandwidth.
So that explains "hierarchical." What do we mean by fair? This refers
to how available extra bandwidth is allocated between those groups which
need it. Let's say that we have 100Mbps of bandwidth divided into four
groups of traffic - Gold (40%), Silver (30%), Bronze (20%), and Regular
(10%). Let's say that no Gold or Bronze users are active so 60% of our
bandwidth is unallocated but both Silver and Regular could use as much
bandwidth as we can give them. How do we fairly share that 60% between
Silver and Regular? HFSC uses a concept called virtual time to which we
will return later. In effect, it will divide the 60% in proportion to
the traffic allocated to each group asking for more. Specifically, in
this case, three shares of bandwidth will be allocated to Silver for
every one allocated to Regular (30:10).
This is another area where HFSC is brilliant over other queue
disciplines. For example, what if we have a stream of traffic that
doesn't require much bandwidth but, when it needs more, we need to
prioritize it over bulk traffic? If our service guarantees are that VoIP
gets a guaranteed 10% of the bandwidth, web traffic gets 30% and bulk
gets 60%, when web is inactive and both VoIP and bulk need more, the
excess would be allocated to bulk in a 6:1 ratio. That's not good. But
remember we said that guaranteeing bandwidth and sharing bandwidth are
two separate and sometimes conflicting functions in HFSC. Thus, we can
say that VoIP is guaranteed 10% but, when it comes to sharing available
bandwidth, VoIP should get 70%, web gets 20%, and bulk gets 10%.
Brilliant! This is done by means of service curves, the last part of
Hierarchical Fair Service Curve traffic shaping.
A service curve is a mathematical way of describing how much service a
process is given over time. The use of the term curve can throw us
non-mathematicians for a "curve" until we remember that, in strict
mathematical terms, a straight line is a curve - a curve which
represents a linear function. To translate all that: a service curve is
the allocated bandwidth. The y axis is the amount of data transferred
(service given) and the x axis is time. The greater the bandwidth, the
steeper the slope of the curve (line). Another brilliant thing about
HFSC is that a service curve can have two lines, i.e., for a certain
period of time one bandwidth can be allocated and after that time
period, a different bandwidth can be allocated. I'll refer to this as a
"di-linear" curve. This is how HFSC decouples bandwidth from latency
but we'll come back to that.
A service curve can be defined using tc with a single parameter if we
only need one line or with three parameters if we need two lines. There
are two ways the parameters can be given to tc. The mathematically
oriented way is "m1 <value> d <value> m2 <value>" where m1 is the slope
of the first curve (line for the non-mathematicians - translate: the
initial bandwidth), m2 is the slope of the second curve (translate: the
second bandwidth setting) and d is the intersection of the two curves
(translate how long we use the first bandwidth before switching to the
second bandwidth).
The second, more system administrator oriented syntax is "umax <value>
dmax <value> rate <value>". This syntax makes it a little easier to see
how HFSC separates guarantees for latency from guarantees for bandwidth.
The rate parameter is the second curve. In practical terms, this is the
guaranteed bandwidth. The umax parameter is the size of some unit of
data. It will often be the size of a data packet, e.g., 1514 bytes
(does not need to include CRC, preamble, or inter-frame gap) but it
could be some other unit. For example, some have suggested that one
could use this so that the text portion of web pages are delivered with
low latency and the rest of the non-text, typically larger data
transmissions, will follow at a slower pace. If the typical text page
size is 10KB, we might set umax to 10KB. Of course, this assumes that
text is always sent first. The dmax parameter is the maximum delay that
umax can tolerate. So we might say that the first 1514 byte packet must
be delayed no more than 20ms, or the first 10KB of web page transmission
should be delayed no more than 100ms. This is how bandwidth and latency
guarantees are separated.
Let's illustrate this a little further. Let's say we have an FTP
transfer which is running as fast as its guaranteed bandwidth. We also
have a VoIP traffic stream also running within its guaranteed bandwidth.
The classic problem is that my VoIP packet which must be delivered on
time is sitting behind my much larger FTP packet which is allowed to be
sent because it is within the guaranteed bandwidth for FTP. How do I
jump the VoIP packet ahead of the FTP packet?
HFSC will see that both packets are eligible to be sent because both are
within the bandwidth limits set for their kind of traffic. It then sees
that the FTP traffic only has a bandwidth guarantee, i.e., it can meet
its obligations to the FTP traffic as long as the packet is delivered
within the time frame necessary to meet the bandwidth requirements
regardless of how much the packet is delayed (as long as the delay is
not so long as to violate the bandwidth requirements). It then looks at
the equally eligible VoIP packet and sees that, not only does it have an
obligation for bandwidth but it also must not delay this packet for more
than, say, 20ms. In effect, it looks at the deadline for delivering the
FTP packet and compares it to the deadline for delivering the VoIP
packet and if the deadline for the VoIP packet is sooner than the
deadline for the FTP packet, it will service the VoIP packet first.
But how, exactly, does it work? It is done by the interplay of service
curves and timers. In fact, we will come to see that eligible and
deadline are actually technical terms to describe some of the timers but
first, let's step back and explain a little more about service curves.
Service curves
There are actually three service curves used by HFSC. They are:
1. The real-time service curve (rt)
2. The link-sharing service curve (ls)
3. The upper limit service curve (ul)
The abbreviations are used to specify which service curve we are
describing in the tc syntax, e.g.,
tc add class dev <device> parent parentID classid <ID> hfsc [ [ rt SC ]
[ ls SC ] | [ sc SC ] ] [ ul SC ]
SC is the description of the curve as described above using m1 d m2 or
umax dmax rate, e.g.,
tc add class dev <device> parent parentID classid <ID> hfsc rt 1514b
20ms 200kbits
If we are not using two curves, we only need the last parameter, e.g.,
tc add class dev <device> parent parentID classid <ID> hfsc ls 500kbits
The sc parameter is used when rt and ls are the same, i.e., one can
specify them both in one definition rather than needing to write two.
It is not usual to specify all three curves in the same class. The rt
parameter is only used on leaves. The ul parameter is usually not used
leaves.
Real-time service curve
Real-time service curves can only be applied to leaf nodes (remember
this is Hierarchical Fair Service Curve). Using our previous example,
rt curve would not be applied to "Gold Clients" but to "Web traffic".
The rt curves can have either one curve (line) or two. In fact, it is
usually only rt curves which have two curves; ls and ul curves generally
do not. If the first curve is steeper than the second curve
(translated: if the initial bandwidth guarantee is greater than the
sustained bandwidth guarantee), the curve is called concave in HFSC
terminology. If the opposite is true, it is called convex. This is
illustrated by the below graphic copied from
http://www.cs.cmu.edu/~hzhang/HFSC/main.html
One must be careful when specifying rt curves because they will be
honored above all other curves (remember we said that, when it is
impossible to satisfy the requirements for both guaranteed bandwidth and
fair sharing, guaranteed bandwidth wins). This will be more
understandable when we discuss the upper limit (ul) curve. To jump
ahead a little bit, the ul is typically though not exclusively used to
describe the maximum bandwidth available, e.g., a T1 circuit or a cable
connection. We said that rt is honored above all other curves. If the
ul curve says the maximum bandwidth available is 10 Mbps and the sum of
all our rt curves is 20 Mbps, the system will try to guarantee 20 Mbps
which, of course, means it will fail to meet its guarantees under
maximum load.
Jumping ahead once more, rt curves override ls curves, too. The ls
curves are used to share extra bandwidth fairly. So, if the ls curve
dictates that class A should have 2 Mbps of our 10 Mbps link and class B
should have 8 Mbps but the rt curve says that class A is guaranteed 3
Mbps, class A will get 3 Mbps and class B only 7 Mbps. The rt curve
will always be honored whenever it is physically possible. The bottom
line is that the rt service curve always "wins."
An important point to remember is that the rt curve determines the
bandwidth and latency guarantees, is the only curve which determines
bandwidth and latency guarantees, and has nothing to do with how
bandwidth is fairly shared (other than to override that sharing if
necessary!). To put it another way, the function of the rt service
curve is independent of the ul and ls service curves. They handle two
completely separate characteristics of HFSC.
Upper limit service curve
As mentioned above, the ul curve is often used to describe the maximum
bandwidth available. More specifically, it sets an upper boundary to
the bandwidth which can be allocated by the ls curve. As we will see,
the ls curve is used to determine how the excess available bandwidth is
fairly shared. The ul service curve sets limits on that sharing.
Let's get some vocabulary defined. Link sharing is the term used by
HFSC to describe how the bandwidth not actively used by the rt service
curve is fairly allocated among the rest of the network sessions which
are requesting bandwidth. Let's connect the dots again as a way of
review. Remember, the rt curve defines the guaranteed amounts of
bandwidth. Let's go back to our 10 Mbps circuit and say we have VoIP
with an rt service curve rate of 1 Mbps, interactive traffic with an rt
service curve rate of 5 Mbps, web traffic with an rt service curve rate
of 2 Mbps, and bulk traffic with an rt service curve rate of 1 Mbps.
Note that the sum of the rt curves does not need to equal the total
bandwidth. Now let's say it's the middle of the night so the phones are
not in use and no one is generating interactive traffic however web
traffic to our internal web servers is going at full speed as are our
overnight off site backups and FTP transfers. Web is guaranteed 2 Mbps,
bulk is guaranteed 1 Mbps and link sharing will figure out how to divide
up the remaining 7 Mbps. However, the ul curve could override the way
link sharing divides that 7 Mbps.
Let's illustrate how and learn more about ul at the same time. The ul
service curve is normally specified at the top of the hierarchy and is
set to the maximum bandwidth available. Think way back to when we said
that link sharing only happened between peers. Classes lower in the
hierarchy can only contend for the bandwidth allocated to their parent
and not for bandwidth allocated to classes at the same level but under a
different parent. Once again, I will copy a graphic from
http://www.cs.cmu.edu/~hzhang/HFSC/main.html to illustrate this:
Since children can only contend for the bandwidth allocated to their
parents, the ul limit on bandwidth flows down through the entire tree
under it. If the parent with the ul limitation cannot receive the
bandwidth, its children cannot contend for it. Thus, by placing the ul
at the top of the hierarchy and setting it to the maximum bandwidth
available, it flows down through the entire tree and we do not need to
define it in every descendant class. That is, unless we want to
override it further down the tree.
Let's go back to our illustration. If we had set ul rate 10240kbits (10
Mbps), the web traffic and the bulk traffic will be sharing the 7 Mbps
available bandwidth in whatever ratio was specified in their ls service
curves. If no ls curves were specified, they will divide the bandwidth
according to their rt curves - in this case a 2:1 split. For now, let's
assume that the ls curve is the same as the rt curve, that is 2 Mbps for
web and 1 Mbps for bulk. Remember that the ul curve sets a limit on the
ls curve. What if, for some reason, we wanted to make sure that bulk
traffic never exceeds 3 Mbps even if there is more available? We would
create a second ul service curve for the bulk traffic on the bulk
traffic class with ul rate 3072bkits.
Link sharing will try to allocate an extra 2.33 Mbps to bulk traffic
(7 / 3). When this link sharing bandwidth is added to the guaranteed
bandwidth of 1 Mbps, we come out to 3.33 Mbps. Since this is exceeds
the ul service curve set specifically for bulk traffic, link sharing
will not be able to service bulk traffic at 3.33 Mbps. It will only be
able to provide service at 3 Mbps. The rest will go to the web service.
So, to summarize, the ul service curve is not used to guarantee
bandwidth or latency. That is the job of the rt service curve.
Allocated bandwidth can exceed the ul service curve if the sum of the rt
service curves is greater than the ul service curve and the circuit can
support the higher rt bandwidth allocation. This is another way of
saying the rt guaranteed bandwidth always takes precedence. The ul
service curve is used to determine the link sharing bandwidth, i.e., the
bandwidth allocated to classes of traffic from the unused portion of the
available bandwidth. It is specifically used to limit how much
bandwidth can be allocated through link sharing, is typically set to the
maximum bandwidth of the circuit, and is normally set at the top of th
hierarchy because its affect is to flow down to all classes underneath
it.
Link-sharing service curve
The ls service curve is not used to guarantee bandwidth or latency. Its
sole purpose is to determine the proportions in which unused bandwidth
is allocated to classes which are requesting more than their guaranteed
bandwidth, that is link sharing. Although it is good practice to use
service curves with numbers that are realistic for the available
bandwidth, technically, only the ratio is important.
Let's illustrate by returning to our previous example. The ul is set to
a rate of 10 Mbps. We would expect the web ls service curve to use a
rate of 2 Mbps and the bulk ls service curve to use a rate of 1 Mbps.
However, we could say the web ls sc is 200 Mbps and the bulk ls sc is
100 Mbps and it would not break and not be illegal - just confusing.
The ratios are the same (2:1) and it is only the ratios which are
important.
The discussion about ul service curves has "stolen the thunder" from the
ls service curve discussion, i.e., there is not much left to say. The
ls service curves determine how link sharing works, i.e., how the
bandwidth with is not being used to satisfy the guarantees of the rt
service curves is fairly allocated among all the other network traffic
flows who would like more bandwidth than they are guaranteed.
The Linux and BSD implementation of HFSC go beyond the original
specification by allowing us to specify the ls service curve separately
from the rt service curve. This gives us some powerful flexibility as
we are about to illustrate.
Let's extend our previous example. Remember we have a 10 Mbps circuit
and thus have set the ul service curve rate at the top of the hierarchy
to 10 Mbps. We have four classes of traffic, VoIP, interactive, web,
and bulk. The rt rate for VoIP is 1 Mbps, for interactive 5 Mbps, for
web 2 Mbps, and for bulk 1 Mbps. That accurately reflects our desire
for guaranteed bandwidth but those proportions may not accurately
reflect how we want any available excess bandwidth distributed.
For our purposes, link sharing should have the following
characteristics. Bulk should be able to use all the bandwidth if it is
available and uncontended. However, if the VoIP traffic needs extra
bandwidth and there is available bandwidth, it should be granted that
extra bandwidth with priority since we do not want to starve our voice
traffic. Furthermore, we want visitors to our web site to have a
positive experience and not one with substantial delays so, if there is
contention between bulk and web traffic, we want web traffic to take
more than a 2:1 ration of available bandwidth. Thus, we might setup our
tc classes as follows:
VoIP:
tc add class dev eth0 parent 1:1 classid 1:10 hfsc rt rate1024kbits ls
rate 7168kbits
We first thought this should be rt umax 222b dmax 5ms rate 1024kbits
because the maximum sized VoIP packet is typically 222 bytes (ulaw/alaw
at 64Kbps = 8KB/s * 0.020s (20 ms per packet) = 160 Bytes + 8 (UDP
header) + 40 (IP header) + 14 (Ethernet header) = 222 Bytes) and we want
it delayed in the router for no more than 5ms. However, to guarantee 1
Mbps bandwidth, a 222 byte packet needs to be sent within roughly 1.7ms
(222 * 8 = 1776 bits / (1024 * 1024)bits/s = 0.0017s). Thus, our rate
is sufficient and we do not need to jump the delivery of VoIP packets by
specifying a larger initial bandwidth.
Interactive
tc add class dev eth0 parent 1:1 classid 1:11 hfsc sc rate5120kbits
We use sc since we want rt and ls to be the same
Web:
tc add class dev eth0 parent 1:1 classid 1:12 hfsc rt rate 2048kbits ls
rate 3072kbits
Bulk:
tc add class dev eth0 parent 1:1 classid 1:12 hfsc sc rate 1024kbits
Note that the sum of our ls service curves exceeds the ul service curve.
This is not a problem. Remember it is only the ls service curve ratios
which are meaningful. So what have we done? Even though our guarantees
can be met with a proportion of 1:5:2:1, we have specified that, if
there is extra bandwidth available and, if there is contention for it,
distribute it in the ratio of 7:5:3:1. In other words, if interactive
and web are idle and VoIP and bulk can use more bandwidth than their
guarantees (backlogged in HFSC terminology), the bandwidth will be
allocated between VoIP and bulk at a 7:1 ration and not a 1:1 ratio.
Likewise, if VoIP and interactive are idle and web and bulk are
backlogged, the extra bandwidth will be allocated at a 3:1 ratio rather
than a 2:1 ratio. Can we see the value of having separate rt and ls
service curves?
Timers
However, service curves are not the whole story. In fact, it is not
really the service curves which determine which packet is sent when.
The service curves are used to set the timers and it is the timers which
determine which packet is sent when.
While service curves are quite understandable to system administrator
types once we translate the vocabulary (curves = bandwidth, umax and
dmax = latency (technically bandwidth I suppose but, latency in
practicality)), timers are they mysterious art of programmers and
mathematicians - an impenetrable black box. Let's see if we can pry
open that black box and make it at least a little understandable to us
sysadmin types.
HFSC uses four separate timers to work its wonders:
1. Fit time
2. Virtual time
3. Eligible time
4. Deadline time
Virtual time
Let's start with virtual time. Virtual time is used by link sharing to
determine which queue should be serviced to keep things fair, that is to
keep the bandwidth in proportion to the ls service curve ratios.
Virtual time appears to be a very complicated topic addressing
mind-bending issues like how to preserve fairness among several
backlogged queues when a new queue becomes backlogged as well and to
preserve this fairness without starving one of the queues while the
others catch up. Thus my explanation will be a dramatic
oversimplification but hopefully enough to give fellow sysadmins a
toehold to ascend this seemingly sheer rock face.
Virtual time is a measure of how much time has been spent servicing the
queue and how much it will take to service the next packet. Here is a
very good ascii art representation copied from
http://www.sonycsl.co.jp/~kjc/software/TIPS.txt :
bytes
| /
| /service curve
| /
next -->+ +----------------+
packet | | /|
length | | / |
| | / |
total --> + +------------+ |
bytes | /| |
already | / | |
sent | / | |
/ | |
| |
| |
--------+---+--------------> time
vt for next packet
vt for previous packet
Not surprisingly, this makes a great deal of sense when we digest it.
Remember, the service curve we are using is the ls service curve, i.e.,
the one for link sharing. The more the bandwidth allocated to the ls
service curve, the steeper the slope of the line. The steeper the slope
of the line, the shorter the time to transmit the packet = the more
bandwidth, the shorter the time to transmit the packet. Thus, the
change in virtual time for the same sized packet is less for a faster
queue than for a slower queue. We'll see why that is important in a
second.
Remember that link sharing is used only among peers. Only peers can
contend for available extra bandwidth. Fairness is achieved in HFSC by
trying to keep the virtual time of all peers equal. When a queue
becomes backlogged, i.e., needing more than its guaranteed bandwidth, it
starts accumulating virtual time. The more it has been serviced while
backlogged, the more virtual time it accumulates.
When HFSC looks at the various backlogged queues, how does it determine
which one to service? Look again at the above diagram. Each queue will
have its current virtual time and the virtual time that it will have
after it sends its next packet. HFSC will choose the next packet which
will have the lowest virtual time. Let's make this more understandable
with some real illustrations. Let's say we have two backlogged queues
with identical ls service curves and each has a full sized Ethernet
packet pending. Queue A has accumulated virtual time of 1000ms and
Queue B has accumulated virtual time of 999ms. Let's say that sending
the full sized Ethernet packet will take 2ms. The virtual time after
Queue A sends its packet would be 1002 whereas Queue B would be 1001ms
so HFSC sends Queue B's packet. Now Queue B has VT (virtual time) of
1001ms and the next packet would bring it to 1003ms. Queue A has VT of
1000ms and sending the next packet would bring it to 1002ms. HFSC
chooses the packet which will result in the lowest VT thus it sends the
packet in Queue A. See how it tries to keep the virtual times equal and
thus produces fairness.
Now let's alter the scenario. Let's keep the virtual time the same,
1000ms for Queue A and 999ms for Queue B but Queue A is handling small
packets which only take 0.5ms to send. Queue A has one of these packets
ready to send while Queue B has one of its full sized packets to send.
VT for Queue A after sending its packet would be 1000.5ms and for Queue
B would be 1001ms so, even though Queue A has already received more
service, it is services again because its final virtual time would be
smaller.
More importantly, let's go back to the idea that both Queue A and Queue
B use full sized packets but this time the ls service curves are not
equal. Let's say the ls service curve rate for Queue A is 5120kbits and
for Queue B is 1024kbits. Thus, a packet that would take Queue B 2ms to
transmit would take Queue A 0.4ms to transmit. Both queues are
continually backlogged so they always have packets to send. HFSC takes
a look and calculates the next VT for Queue A as 1000.4 and Queue B as
1001 so it sends Queue A. It calculates again and A is 1000.8 and B
1001 so it sends A again. The next calculation of VT puts A at 1001.2
and B at 1001 so it sends B. The next calculation puts A at 1001.2 and
B at 1003 so A is sent. Then 1001.6 versus 1003, then 1002 vs. 1003,
then 1002.4 vs. 1003, then 1002.8 vs. 1003, then 1003.2 vs. 1003. Can
you see how the virtual time calculation is allocating service to Queue
A at a 5:1 ratio with Queue B - just the fairness we requested via the
ls service curves.
So, in summary, virtual time used to produce fairness when distributing
available excess bandwidth to backlogged queues in the ratio of the ls
service curves. It does this by trying to keep virtual times for all
peers in the hierarchy equal and it does this by always choosing the
packet to send which will result in the smallest virtual time.
Fit time
Fit time is pretty simple to understand. Recall that we said the ls
service curve was bounded by the ul service curve, i.e., even if a queue
should get say 10 Mbps according to link sharing, if the ul (Upper
Limit) service curve says we can use 8 Mpbs maximum, we are only going
to get 8 Mbps. Fit time takes into account the ul service curve.
In effect, fit time looks at what the clock time would be to send the
packet based upon the ul service curve rate, i.e., what the time would
be to send the pending packet at the maximum transmission rate. If that
time is later than the current clock time, the packet will not be sent
not matter what virtual time says. If the current clock time is later
than fit time, i.e., we would not have exceeded out bandwidth
limitation, then the decision is made based upon virtual time.
As a reminder, this is all for traffic over and above the guaranteed
rate, i.e., the rt service curve rate. Packets are always sent to
preserve the rt service curve rate as long as it is physically possible
regardless of fit time or virtual time. This is the same as saying that
the rt service curve always wins or, to phrase it yet another way, to
meet the HFSC design criterion that, if there is a conflict between link
sharing and guaranteed bandwidth, choose guaranteed bandwidth.
Eligible time
The rt service curve uses two timers: eligible time and deadline time.
Recall, we used referred to eligible and deadline time toward the
beginning of this discussion when observed how HFSC provides decoupled
guarantees for both bandwidth and latency. Like fit time, eligible time
is relative to clock time. In other words, HFSC calculates what the
clock time would be to send the queued packet at the guaranteed rate,
i.e., the rt service curve rate. If that time is later than the current
clock time, that packet's time has not come yet and it cannot be sent
based upon its real time guarantee. I do believe it can be sent based
upon virtual time assuming that fit time allows it. After all, that is
what link sharing is about - being able to exceed the guaranteed
bandwidth if there is extra bandwidth available. On the other hand, if
current clock time is later than eligible time, then this packet had
better get moving because it is potentially running behind schedule.
So, eligible time is just as then name implies; it is the time the
packet becomes eligible for sending based upon the real-time service
curve, i.e., the guaranteed bandwidth/latency.
An important point to understand the difference between eligible time
and deadline time is that eligible time is measured from the beginning
or head of the packet, i.e., is HFSC ready to begin sending this packet.
But what happens when more than one queue has packets whose eligible
time has come? That's where deadline time comes into play.
Deadline time
Deadline time is closely related to eligible time and is likewise
measured against clock time. However, deadline time is measured against
the end or tail of the packet, i.e., by when must we have finished
sending this packet at the specified bandwidth in order to meet our
packet delivery guarantees for bandwidth and latency. Once again,
http://www.sonycsl.co.jp/~kjc/software/TIPS.txt has an excellent ASCII
graphic for illustrating the relationship between eligible time measured
at the beginning of the packet and deadline time measured from the end:
bytes
| /
| /service curve
| /
next -->+ +----------------+
packet | | /|
length | | / |
| | / |
cumulative --> + +------------+ |
bytes | /| |
already | / | |
sent | / | |
/ | |
| |
| |
--------+---+--------------> time
eligible deadline
time
This time, the slope is the rt service curve. The way in which HFSC
chooses from among several different queues all with packets whose
eligible time is greater than current clock time is almost identical to
the way it chooses among backlogged queues with virtual time, viz., it
chooses the packet with the lowest deadline time. Remember that the
steeper the curve, the greater the bandwidth and the shorter the
distance between eligible time and deadline time for the same sized
packet.
Let's walk through a real example. We have Queue A with VoIP traffic -
small, 222 byte packets and an rt service curve bandwidth such that it
takes 0.2ms to send its packets; that equates to roughly 8.88 Mbps ((222
* 8)bits/0.0002s). Let's also assume that we have so much VoIP traffic
that the queue is filled so we always have a VoIP packet asking to be
dequeued. Queue B is sending FTP with large packets and an rt service
curve rate such that each packet takes 2ms to send; this equates to
6.056 Mbps ((1514 * 8)bits/0.002s). Queue B is also completely full.
Let's assume that the maximum bandwidth available is the sum of the
guaranteed bandwidths, viz., 14.936 Mbps. This will allow us to
calculated the progress of clock time, i.e., how long it actually takes
to send each packet. Also remember that each packet has a 4 byte CRC,
and 8 byte preamble, and a 12 byte interframe gap time at least in
traditional Ethernet. Thus to transmit a packet in Queue A, we really
need to transmit 246 bytes and, to transmit one in Queue B, we need to
transmit 1538 bytes. Thus, the elapsed time to send a Queue A packet is
(246 * 8)bits / 14,936,000(b/s) = 0.132ms and the time to transmit a
Queue B packet is (1538 * 8)bits / 14,936,000(b/s) = 0.824ms. Sorry for
all the math but this is what is inside the black box (and a very
simplified version!).
Let's assume that clock time (CT - the actual time) is 1000ms (not
realistic but it makes the explanation easier!). The next packet queued
in Queue A has an ET (eligible time) of 1000ms and the next packet in
Queue B has an ET of 999ms, i.e., both are eligible to be sent. A less
sophisticated traffic shaping algorithm would send the FTP packet first.
However, HFSC calculates the deadline time (DT) for the packet in Queue
A at 1000.2 (1000 + 0.2) and the deadline time for the packet in Queue B
at 1001ms (999 + 2) so it sends A instead since it has the smaller DT.
0.132ms has elapsed in real time so CT is now 1000.132. The
eligible/deadline times (ET/DT) for A and B respectively are
1000.2/1000.4 and 999/1001. Notice that A is no longer eligible to send
because its ET > CT so B is serviced. 0.824ms has elapsed to send B's
packet so CT is now 1000.956. ET/DT for A is still 1000.2/1000.4 but B
has changed to 1001/1003. B just misses being eligible to send but A is
eligible so A is sent. Elapsed time is 0.132, CT is now 1001.088, ET/DT
for A is 1000.4/1000.6. Both A and B are eligible at the same time
again as both their ETs <= CT. A's DT is less than B's DT so A is
serviced.
In fact, A will send 11 packets. Let's see the result after A sends 11
packets. Elapsed time is 11* 0.132 = 1.452ms so clock time is 1002.54.
A's ET/DT have incremented by 11 * 0.2 so they are 1002.6/1002.8. B's
ET/DT have remained at 1001/1003. A is no longer eligible so the fact
that its DT is less than B's DT is irrelevant. B is serviced.
Pulling it all together
To this point, almost all of our discussion have involved rt service
curves based solely upon rate and we have been using some fairly large
circuits to illustrate. What happens when our bandwidth really is
constrained such as a T1 circuit or the upload bandwidth of an
asymmetric DSL or cable connection and we need to balance time sensitive
traffic with bulk traffic? This is where di-linear curves save the day.
The best illustration I have found is from the SIGCOM97 paper on HFSC:
The results might not be obvious at first. The packets arriving, e.g.,
coming from the internal network and heading toward the constricted T1
circuit (well, in this specific example, it is a 10 Mbps circuit) are
shown in the second level of graphics from the top. The resulting
output of those packets is shown in the very bottom set of graphics.
The illustrations on the left show a mono-linear curve, i.e., just based
upon bandwidth. The video and FTP packets are flooding in, are being
lined up and scheduled for dequeueing based upon the bandwidth only.
Thus, the initial video packet sits in queue behind the FTP packets as
there is no need to rush to meet its bandwidth requirements. Here is
how the authors describe what is happening:
"To illustrate the advantage of decoupling delay and bandwidth
allocation with non-linear service curves, consider the example in
Figure 2, where a video and a FTP session share a 10 Mbps link . . . .
Let the video source sends 30 8KB frames per second, which corresponds
to a required bandwidth of 2 Mbps. The remaining 8 Mbps is reserved by a
continuously backlogged FTP session. For simplicity, let all packets be
of size 8 KB. Thus, it takes roughly 6.5 ms to transmit a packet."
"As can be seen, the deadlines of the video packets occur every 33 ms,
while the deadlines of the FTP packets occur every 8.2 ms. This results
in a delay of approximately 26 ms for a video packet."
Let's work through the math to make that more understandable. HFSC is
committed to deliver 2 Mbps to video and each packet is 8KB long. Thus,
HFSC's commitment to deliver that packet is within (8000 * 8)bits /
2,000,000(b/s) = 32ms. I'm not quite sure why I come up with 32 and
they say 33 but we'll use 33. In other words, to meet the deadline
based solely upon the rate, the bandwidth part of the rt service curve,
the packet needs to be finished dequeueing at 33ms. Since it only takes
6.5ms to send the packet, HFSC can sit on the packet it received for 33
- 6.5 = 26.5ms if it needs to in order to meet the guarantees for other
traffic. This adds unnecessary latency to the video stream.
In the second scenario, we introduce an initial, elevated bandwidth
guarantee for the first 10ms. The bandwidth for the first 10ms is now
6.6 Mbps instead of 2 Mbps. We do the math again and HFSC's commitment
to video to maintain 6.6 Mbps is to finish dequeueing the packet within
(8000 * 8)bits / 6,600,000(b/s) = 10ms. Since it takes 6.5 ms to send
the packet, HFSC can sit on the packet for no more than 10 - 6.5 = 3.5
ms. Quite a difference!
I assume for simplicity's sake, the graphic leaves out an important
point. The rt service curve either fully or partially resets when the
queue has been drained. Fully or partially depends on how much time has
elapsed since the last service rendered and the new service requested
when the queue becomes active again. Thanks for Michal Soltys on the
netdev kernel mail list for clarifying this for me.
Without this reset, the first part of the service curve (the m1 portion
if you recall the earlier discussion about how service curves can be
defined) would not have much practical value because once traffic
activates the queue, only the first packet or first few packets would be
guaranteed the latency of the first, accelerated part of the curve.
Everything else would use the second part of the curve (the m2 portion -
we'll use the terms m1 and m2 for the rest of the discussion).
So let's re-examine the above example in more detail. The video packet
arrives, uses the m1 curve, is jumped ahead of the FTP packets because
of the low latency guarantee of the m1 curve, is dequeued, and now the
queue is empty for 33.33ms (remember the video is playing at 30 frames
per second, well, 32.69ms when you account for transmission time on a
100 Mbps circuit) which allows the curve to reset. The next video
packet comes in and it is treated according to m1 and not m2 because we
have reset the curve. Thus, each video packet is jumped in front of any
queued FTP packets.
We can even multiplex several video streams. As long as the queue is
allowed to go idle long enough, each of those streams will be treated
with very low latency and jumped in front of the FTP packets, i.e.,
until we have so many video streams that the queue starts to backlog.
Then they will use the m2 curve.
This is not a bad thing; it is a good thing and allows us a new
perspective on the m1 and m2 curves. Hopefully, we have allocated
enough bandwidth in our m2 curve to properly service our video or VoiP
or whatever we are pushing through this queue. Thus, even if we are not
receiving the accelerated treatment, we are still experiencing
sufficient service. If our queue is badly backlogged and overflowing,
then we have a different problem and need more raw bandwidth!
In this way, we can think of the m2 curve, the second level of service
in a concave service curve (remember a concave service curve is where we
start out with a higher bandwidth and then change to a lower bandwidth),
as a circuit breaker preventing overload. In other words, we are saying
to this prioritized traffic that we will deliver it with a lower than
normal latency (and thus higher short term bandwidth) while we can but,
if it becomes too much (as determined by the system administrator who
defined the HFSC qdisc), we will drop it down to a more sustainable rate
that will not exceed the physical capabilities of the circuit. This
assumes we have designed our traffic shaping so that the sum of all the
m2 portions of all the rt service curves do not exceed the capabilities
of the circuit.
Another way of saying this with familiar terminology is that we can
burst at the m1 rate as long as the queue doesn't backlog but, when it
does, we drop to our sustainable rate. Thus, concave rt service curves
are very well suited to periodic traffic, i.e., traffic which sends
packets on a recurring interval with space in between like VoIP or
video. It may be less effective on burstable traffic such as the
example of using it to accelerate the delivery of text on a web site
unless the traffic is low enough that the queue has a chance to drain
regularly.
^ permalink raw reply
* Re: bayom_epp patch
From: Thomas Sailer @ 2011-12-13 22:29 UTC (permalink / raw)
To: netdev
In-Reply-To: <4EE748BA.5080807@suse.cz>
This is a resubmission with fixed whitespace:
baycom_epp: Improve parport handling, fix multi-core support
Parallel port settings no longer require an IO address value,
because addresses are automatically assigned by the PCI BIOS
nowadays and may change rather frequently.
Instead, the parport number is used (e.g. modprobe baycom_epp parport=0)
EPP transfers now utilize block IO transfers, thus significantly
reducing CPU load. Furthermore, EPP RX data transfer handling of the
conventional EPP modem (without FPGA) has been improved to assure
a minimum block transfer size increasing the effective data rate.
Spin-locks have been introduced for better multi-core compatibility.
The x86_64 exclusion has been removed from Kconfig because no problems
where observed on several test systems. To achieve this, several x86
architecture specific debug statements had to be removed.
Whitespace has been fixed.
Signed-off-by: Thomas Sailer <sailer@ife.ee.ethz.ch>
Signed-off-by: Steffen Koehler <steffen.koehler@tu-dresden.de>
diff --git a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfig
index 95dbcfd..9a736f0 100644
--- a/drivers/net/hamradio/Kconfig
+++ b/drivers/net/hamradio/Kconfig
@@ -166,7 +166,7 @@ config BAYCOM_PAR
config BAYCOM_EPP
tristate "BAYCOM epp driver for AX.25"
- depends on PARPORT && AX25 && !64BIT
+ depends on PARPORT && AX25
select CRC_CCITT
---help---
This is a driver for Baycom style simple amateur radio modems that
diff --git a/drivers/net/hamradio/baycom_epp.c
b/drivers/net/hamradio/baycom_epp.c
index 9537aaa..32b5da5 100644
--- a/drivers/net/hamradio/baycom_epp.c
+++ b/drivers/net/hamradio/baycom_epp.c
@@ -3,8 +3,9 @@
/*
* baycom_epp.c -- baycom epp radio modem driver.
*
- * Copyright (C) 1998-2000
+ * Copyright (C) 1998-2000, 2010
* Thomas Sailer (sailer@ife.ee.ethz.ch)
+ * Steffen Koehler (steffen.koehler@tu-dresden.de)
*
* 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
@@ -33,8 +34,12 @@
* 0.4 26.07.1999 Adapted to new lowlevel parport driver interface
* 0.5 03.08.1999 adapt to Linus' new __setup/__initcall
* removed some pre-2.2 kernel compatibility cruft
- * 0.6 10.08.1999 Check if parport can do SPP and is safe to access
during interrupt contexts
+ * 0.6 10.08.1999 Check if parport can do SPP and is safe to access
during
+ * interrupt contexts
* 0.7 12.02.2000 adapted to softnet driver interface
+ * 0.8 12.01.2010 added spinlocks for multi-cpu safety, changed
interface
+ * enumeration according to the parport number, some
minor
+ * bug fixes
*
*/
@@ -54,22 +59,21 @@
#include <linux/baycom.h>
#include <linux/jiffies.h>
#include <linux/random.h>
-#include <net/ax25.h>
+#include <net/ax25.h>
#include <asm/uaccess.h>
/*
--------------------------------------------------------------------- */
-#define BAYCOM_DEBUG
#define BAYCOM_MAGIC 19730510
/*
--------------------------------------------------------------------- */
-static const char paranoia_str[] = KERN_ERR
+static const char paranoia_str[] = KERN_ERR
"baycom_epp: bad magic number for hdlcdrv_state struct in routine %s
\n";
static const char bc_drvname[] = "baycom_epp";
-static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-2000
Thomas Sailer, HB9JNX/AE4WA\n"
-"baycom_epp: version 0.7\n";
+static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-2010
Thomas Sailer, HB9JNX/AE4WA\n"
+"baycom_epp: version 0.8\n";
/*
--------------------------------------------------------------------- */
@@ -94,72 +98,13 @@ static struct net_device *baycom_device[NR_PORTS];
#define EPP_RX_FIFO_ENABLE 0x08
#define EPP_MODEM_ENABLE 0x20
#define EPP_LEDS 0xC0
-#define EPP_IRQ_ENABLE 0x10
-
-/* LPT registers */
-#define LPTREG_ECONTROL 0x402
-#define LPTREG_CONFIGB 0x401
-#define LPTREG_CONFIGA 0x400
-#define LPTREG_EPPDATA 0x004
-#define LPTREG_EPPADDR 0x003
-#define LPTREG_CONTROL 0x002
-#define LPTREG_STATUS 0x001
-#define LPTREG_DATA 0x000
-
-/* LPT control register */
-#define LPTCTRL_PROGRAM 0x04 /* 0 to reprogram */
-#define LPTCTRL_WRITE 0x01
-#define LPTCTRL_ADDRSTB 0x08
-#define LPTCTRL_DATASTB 0x02
-#define LPTCTRL_INTEN 0x10
-
-/* LPT status register */
-#define LPTSTAT_SHIFT_NINTR 6
-#define LPTSTAT_WAIT 0x80
-#define LPTSTAT_NINTR (1<<LPTSTAT_SHIFT_NINTR)
-#define LPTSTAT_PE 0x20
-#define LPTSTAT_DONE 0x10
-#define LPTSTAT_NERROR 0x08
-#define LPTSTAT_EPPTIMEOUT 0x01
-
-/* LPT data register */
-#define LPTDATA_SHIFT_TDI 0
-#define LPTDATA_SHIFT_TMS 2
-#define LPTDATA_TDI (1<<LPTDATA_SHIFT_TDI)
-#define LPTDATA_TCK 0x02
-#define LPTDATA_TMS (1<<LPTDATA_SHIFT_TMS)
-#define LPTDATA_INITBIAS 0x80
-
-
-/* EPP modem config/status bits */
-#define EPP_DCDBIT 0x80
-#define EPP_PTTBIT 0x08
-#define EPP_RXEBIT 0x01
-#define EPP_RXAEBIT 0x02
-#define EPP_RXHFULL 0x04
-
-#define EPP_NTHF 0x20
-#define EPP_NTAEF 0x10
-#define EPP_NTEF EPP_PTTBIT
-
-#define EPP_TX_FIFO_ENABLE 0x10
-#define EPP_RX_FIFO_ENABLE 0x08
-#define EPP_MODEM_ENABLE 0x20
-#define EPP_LEDS 0xC0
-#define EPP_IRQ_ENABLE 0x10
-
-/* Xilinx 4k JTAG instructions */
-#define XC4K_IRLENGTH 3
-#define XC4K_EXTEST 0
-#define XC4K_PRELOAD 1
-#define XC4K_CONFIGURE 5
-#define XC4K_BYPASS 7
#define EPP_CONVENTIONAL 0
#define EPP_FPGA 1
-#define EPP_FPGAEXTSTATUS 2
-#define TXBUFFER_SIZE ((HDLCDRV_MAXFLEN*6/5)+8)
+#define EPP_XFER_FLAGS PARPORT_EPP_FAST
+
+#define TXBUFFER_SIZE ((HDLCDRV_MAXFLEN*6/5)+8)
/*
----------------------------------------------------------------------
*/
/*
@@ -171,7 +116,6 @@ struct baycom_state {
struct pardevice *pdev;
struct net_device *dev;
- unsigned int work_running;
struct delayed_work run_work;
unsigned int modem;
unsigned int bitrate;
@@ -186,6 +130,7 @@ struct baycom_state {
} cfg;
struct hdlcdrv_channel_params ch_params;
+ enum { rx_idle = 0, rx_receive, rx_flush } rx_state;
struct {
unsigned int bitbuf, bitstream, numbits, state;
@@ -206,18 +151,7 @@ struct baycom_state {
unsigned int ptt_keyed;
struct sk_buff *skb; /* next transmit packet */
-
-#ifdef BAYCOM_DEBUG
- struct debug_vals {
- unsigned long last_jiffies;
- unsigned cur_intcnt;
- unsigned last_intcnt;
- int cur_pllcorr;
- int last_pllcorr;
- unsigned int mod_cycles;
- unsigned int demod_cycles;
- } debug_vals;
-#endif /* BAYCOM_DEBUG */
+ spinlock_t lock;
};
/*
--------------------------------------------------------------------- */
@@ -243,21 +177,6 @@ struct baycom_state {
/*---------------------------------------------------------------------------*/
-#if 0
-static inline void append_crc_ccitt(unsigned char *buffer, int len)
-{
- unsigned int crc = 0xffff;
-
- for (;len>0;len--)
- crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ *buffer++) & 0xff];
- crc ^= 0xffff;
- *buffer++ = crc;
- *buffer++ = crc >> 8;
-}
-#endif
-
-/*---------------------------------------------------------------------------*/
-
static inline int check_crc_ccitt(const unsigned char *buf, int cnt)
{
return (crc_ccitt(0xffff, buf, cnt) & 0xffff) == 0xf0b8;
@@ -274,26 +193,6 @@ static inline int calc_crc_ccitt(const unsigned
char *buf, int cnt)
#define tenms_to_flags(bc,tenms) ((tenms * bc->bitrate) / 800)
-/*
--------------------------------------------------------------------- */
-
-static inline void baycom_int_freq(struct baycom_state *bc)
-{
-#ifdef BAYCOM_DEBUG
- unsigned long cur_jiffies = jiffies;
- /*
- * measure the interrupt frequency
- */
- bc->debug_vals.cur_intcnt++;
- if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {
- bc->debug_vals.last_jiffies = cur_jiffies;
- bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
- bc->debug_vals.cur_intcnt = 0;
- bc->debug_vals.last_pllcorr = bc->debug_vals.cur_pllcorr;
- bc->debug_vals.cur_pllcorr = 0;
- }
-#endif /* BAYCOM_DEBUG */
-}
-
/*
----------------------------------------------------------------------
*/
/*
* eppconfig_path should be setable via /proc/sys.
@@ -331,36 +230,38 @@ static inline void do_kiss_params(struct
baycom_state *bc,
#ifdef KISS_VERBOSE
#define PKP(a,b) printk(KERN_INFO "baycomm_epp: channel params: " a
"\n", b)
-#else /* KISS_VERBOSE */
-#define PKP(a,b)
-#endif /* KISS_VERBOSE */
+#else /* KISS_VERBOSE */
+#define PKP(a,b)
+#endif /* KISS_VERBOSE */
if (len < 2)
return;
+ spin_lock_bh(&bc->lock);
switch(data[0]) {
case PARAM_TXDELAY:
bc->ch_params.tx_delay = data[1];
PKP("TX delay = %ums", 10 * bc->ch_params.tx_delay);
break;
- case PARAM_PERSIST:
+ case PARAM_PERSIST:
bc->ch_params.ppersist = data[1];
PKP("p persistence = %u", bc->ch_params.ppersist);
break;
- case PARAM_SLOTTIME:
+ case PARAM_SLOTTIME:
bc->ch_params.slottime = data[1];
PKP("slot time = %ums", bc->ch_params.slottime);
break;
- case PARAM_TXTAIL:
+ case PARAM_TXTAIL:
bc->ch_params.tx_tail = data[1];
PKP("TX tail = %ums", bc->ch_params.tx_tail);
break;
- case PARAM_FULLDUP:
+ case PARAM_FULLDUP:
bc->ch_params.fulldup = !!data[1];
PKP("%s duplex", bc->ch_params.fulldup ? "full" : "half");
break;
default:
break;
}
+ spin_unlock_bh(&bc->lock);
#undef PKP
}
@@ -374,7 +275,7 @@ static void encode_hdlc(struct baycom_state *bc)
unsigned bitstream, notbitstream, bitbuf, numbit, crc;
unsigned char crcarr[2];
int j;
-
+
if (bc->hdlctx.bufcnt > 0)
return;
skb = bc->skb;
@@ -401,7 +302,7 @@ static void encode_hdlc(struct baycom_state *bc)
for (j = 0; j < 8; j++)
if (unlikely(!(notbitstream & (0x1f0 << j)))) {
bitstream &= ~(0x100 << j);
- bitbuf = (bitbuf & (((2 << j) << numbit) - 1)) |
+ bitbuf = (bitbuf & (((2 << j) << numbit) - 1)) |
((bitbuf & ~(((2 << j) << numbit) - 1)) << 1);
numbit++;
notbitstream = ~bitstream;
@@ -442,7 +343,7 @@ static int transmit(struct baycom_state *bc, int
cnt, unsigned char stat)
if (bc->hdlctx.bufcnt <= 0)
return 0;
if (!bc->ch_params.fulldup) {
- if (!(stat & EPP_DCDBIT)) {
+ if (!(stat & EPP_DCDBIT) || (bc->rx_state != rx_idle)) {
bc->hdlctx.slotcnt = bc->ch_params.slottime;
return 0;
}
@@ -469,7 +370,7 @@ static int transmit(struct baycom_state *bc, int
cnt, unsigned char stat)
memset(tmp, 0x7e, sizeof(tmp));
while (i > 0) {
j = (i > sizeof(tmp)) ? sizeof(tmp) : i;
- if (j != pp->ops->epp_write_data(pp, tmp, j, 0))
+ if (j != pp->ops->epp_write_data(pp, tmp, j, EPP_XFER_FLAGS))
return -1;
i -= j;
}
@@ -487,11 +388,11 @@ static int transmit(struct baycom_state *bc, int
cnt, unsigned char stat)
i = min_t(int, cnt, bc->hdlctx.bufcnt);
bc->hdlctx.bufcnt -= i;
cnt -= i;
- if (i != pp->ops->epp_write_data(pp, bc->hdlctx.bufptr, i, 0))
+ if (i != pp->ops->epp_write_data(pp, bc->hdlctx.bufptr, i,
EPP_XFER_FLAGS))
return -1;
bc->hdlctx.bufptr += i;
break;
-
+
case tx_tail:
encode_hdlc(bc);
if (bc->hdlctx.bufcnt > 0) {
@@ -505,7 +406,7 @@ static int transmit(struct baycom_state *bc, int
cnt, unsigned char stat)
memset(tmp, 0x7e, sizeof(tmp));
while (i > 0) {
j = (i > sizeof(tmp)) ? sizeof(tmp) : i;
- if (j != pp->ops->epp_write_data(pp, tmp, j, 0))
+ if (j != pp->ops->epp_write_data(pp, tmp, j, EPP_XFER_FLAGS))
return -1;
i -= j;
}
@@ -521,7 +422,7 @@ static int transmit(struct baycom_state *bc, int
cnt, unsigned char stat)
memset(tmp, 0, sizeof(tmp));
while (i > 0) {
j = (i > sizeof(tmp)) ? sizeof(tmp) : i;
- if (j != pp->ops->epp_write_data(pp, tmp, j, 0))
+ if (j != pp->ops->epp_write_data(pp, tmp, j, EPP_XFER_FLAGS))
return -1;
i -= j;
}
@@ -540,9 +441,9 @@ static void do_rxpacket(struct net_device *dev)
unsigned char *cp;
unsigned pktlen;
- if (bc->hdlcrx.bufcnt < 4)
+ if (bc->hdlcrx.bufcnt < 4)
return;
- if (!check_crc_ccitt(bc->hdlcrx.buf, bc->hdlcrx.bufcnt))
+ if (!check_crc_ccitt(bc->hdlcrx.buf, bc->hdlcrx.bufcnt))
return;
pktlen = bc->hdlcrx.bufcnt-2+1; /* KISS kludge */
if (!(skb = dev_alloc_skb(pktlen))) {
@@ -567,7 +468,7 @@ static int receive(struct net_device *dev, int cnt)
unsigned char *cp;
int cnt2, ret = 0;
int j;
-
+
numbits = bc->hdlcrx.numbits;
state = bc->hdlcrx.state;
bitstream = bc->hdlcrx.bitstream;
@@ -575,7 +476,7 @@ static int receive(struct net_device *dev, int cnt)
while (cnt > 0) {
cnt2 = (cnt > sizeof(tmp)) ? sizeof(tmp) : cnt;
cnt -= cnt2;
- if (cnt2 != pp->ops->epp_read_data(pp, tmp, cnt2, 0)) {
+ if (cnt2 != pp->ops->epp_read_data(pp, tmp, cnt2, EPP_XFER_FLAGS)) {
ret = -1;
break;
}
@@ -633,17 +534,6 @@ static int receive(struct net_device *dev, int cnt)
/*
--------------------------------------------------------------------- */
-#ifdef __i386__
-#include <asm/msr.h>
-#define GETTICK(x) \
-({ \
- if (cpu_has_tsc) \
- rdtscl(x); \
-})
-#else /* __i386__ */
-#define GETTICK(x)
-#endif /* __i386__ */
-
static void epp_bh(struct work_struct *work)
{
struct net_device *dev;
@@ -651,22 +541,17 @@ static void epp_bh(struct work_struct *work)
struct parport *pp;
unsigned char stat;
unsigned char tmp[2];
- unsigned int time1 = 0, time2 = 0, time3 = 0;
int cnt, cnt2;
bc = container_of(work, struct baycom_state, run_work.work);
+ spin_lock_bh(&bc->lock);
dev = bc->dev;
- if (!bc->work_running)
- return;
- baycom_int_freq(bc);
pp = bc->pdev->port;
/* update status */
if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1)
goto epptimeout;
bc->stat = stat;
- bc->debug_vals.last_pllcorr = stat;
- GETTICK(time1);
- if (bc->modem == EPP_FPGAEXTSTATUS) {
+ if (bc->modem == EPP_FPGA) {
/* get input count */
tmp[0] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE|1;
if (pp->ops->epp_write_addr(pp, tmp, 1, 0) != 1)
@@ -689,36 +574,52 @@ static void epp_bh(struct work_struct *work)
goto epptimeout;
if (transmit(bc, cnt2, stat))
goto epptimeout;
- GETTICK(time2);
if (receive(dev, cnt))
goto epptimeout;
- if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1)
- goto epptimeout;
- bc->stat = stat;
} else {
- /* try to tx */
+ /* try to TX */
switch (stat & (EPP_NTAEF|EPP_NTHF)) {
case EPP_NTHF:
cnt = 2048 - 256;
break;
-
+
case EPP_NTAEF:
cnt = 2048 - 1793;
break;
-
+
case 0:
cnt = 0;
break;
-
+
default:
cnt = 2048 - 1025;
break;
}
if (transmit(bc, cnt, stat))
goto epptimeout;
- GETTICK(time2);
/* do receiver */
while ((stat & (EPP_NRAEF|EPP_NRHF)) != EPP_NRHF) {
+ /* FIFO fill state accuracy work-around: */
+ /* When the channel is free, we further read */
+ /* one block to assure that the last frame has */
+ /* been completely flushed before we tell the */
+ /* TX that the channel is free */
+ if (stat & EPP_DCDBIT) {
+ switch (bc->rx_state) {
+ case rx_receive:
+ bc->rx_state = rx_flush;
+ break;
+
+ case rx_flush:
+ bc->rx_state = rx_idle;
+ break;
+
+ case rx_idle:
+ break;
+ }
+ } else
+ bc->rx_state = rx_receive;
+ /* guess RX block size */
switch (stat & (EPP_NRAEF|EPP_NRHF)) {
case EPP_NRAEF:
cnt = 1025;
@@ -737,29 +638,15 @@ static void epp_bh(struct work_struct *work)
if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1)
goto epptimeout;
}
- cnt = 0;
- if (bc->bitrate < 50000)
- cnt = 256;
- else if (bc->bitrate < 100000)
- cnt = 128;
- while (cnt > 0 && stat & EPP_NREF) {
- if (receive(dev, 1))
- goto epptimeout;
- cnt--;
- if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1)
- goto epptimeout;
- }
}
- GETTICK(time3);
-#ifdef BAYCOM_DEBUG
- bc->debug_vals.mod_cycles = time2 - time1;
- bc->debug_vals.demod_cycles = time3 - time2;
-#endif /* BAYCOM_DEBUG */
- schedule_delayed_work(&bc->run_work, 1);
if (!bc->skb)
netif_wake_queue(dev);
+ schedule_delayed_work(&bc->run_work, 1);
+ spin_unlock_bh(&bc->lock);
return;
+
epptimeout:
+ spin_unlock_bh(&bc->lock);
printk(KERN_ERR "%s: EPP timeout!\n", bc_drvname);
}
@@ -777,15 +664,19 @@ static int baycom_send_packet(struct sk_buff *skb,
struct net_device *dev)
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
+
if (bc->skb)
return NETDEV_TX_LOCKED;
+
/* strip KISS byte */
if (skb->len >= HDLCDRV_MAXFLEN+1 || skb->len < 3) {
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
+ spin_lock_bh(&bc->lock);
netif_stop_queue(dev);
bc->skb = skb;
+ spin_unlock_bh(&bc->lock);
return NETDEV_TX_OK;
}
@@ -796,8 +687,8 @@ static int baycom_set_mac_address(struct net_device
*dev, void *addr)
struct sockaddr *sa = (struct sockaddr *)addr;
/* addr is an AX.25 shifted ASCII mac address */
- memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
- return 0;
+ memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
+ return 0;
}
/*
--------------------------------------------------------------------- */
@@ -831,26 +722,18 @@ static int epp_open(struct net_device *dev)
unsigned char tmp[128];
unsigned char stat;
unsigned long tstart;
-
+
if (!pp) {
printk(KERN_ERR "%s: parport at 0x%lx unknown\n",
bc_drvname, dev->base_addr);
return -ENXIO;
}
-#if 0
- if (pp->irq < 0) {
- printk(KERN_ERR "%s: parport at 0x%lx has no irq\n",
bc_drvname, pp->base);
- parport_put_port(pp);
- return -ENXIO;
- }
-#endif
if ((~pp->modes) & (PARPORT_MODE_TRISTATE | PARPORT_MODE_PCSPP |
PARPORT_MODE_SAFEININT)) {
printk(KERN_ERR "%s: parport at 0x%lx cannot be used
\n",
bc_drvname, pp->base);
parport_put_port(pp);
return -EIO;
}
- memset(&bc->modem, 0, sizeof(bc->modem));
- bc->pdev = parport_register_device(pp, dev->name, NULL,
epp_wakeup,
+ bc->pdev = parport_register_device(pp, dev->name, NULL,
epp_wakeup,
NULL, PARPORT_DEV_EXCL, dev);
parport_put_port(pp);
if (!bc->pdev) {
@@ -862,15 +745,13 @@ static int epp_open(struct net_device *dev)
parport_unregister_device(bc->pdev);
return -EBUSY;
}
- dev->irq = /*pp->irq*/ 0;
- INIT_DELAYED_WORK(&bc->run_work, epp_bh);
- bc->work_running = 1;
bc->modem = EPP_CONVENTIONAL;
if (eppconfig(bc))
printk(KERN_INFO "%s: no FPGA detected, assuming conventional EPP
modem\n", bc_drvname);
else
- bc->modem = /*EPP_FPGA*/ EPP_FPGAEXTSTATUS;
- parport_write_control(pp, LPTCTRL_PROGRAM); /* prepare EPP mode; we
aren't using interrupts */
+ bc->modem = EPP_FPGA;
+ /* prepare EPP mode; we aren't using interrupts */
+ parport_write_control(pp, PARPORT_CONTROL_INIT);
/* reset the modem */
tmp[0] = 0;
tmp[1] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE;
@@ -886,9 +767,9 @@ static int epp_open(struct net_device *dev)
schedule();
continue;
}
- if (pp->ops->epp_read_data(pp, tmp, 128, 0) != 128)
+ if (pp->ops->epp_read_data(pp, tmp, 128, EPP_XFER_FLAGS) != 128)
goto epptimeout;
- if (pp->ops->epp_read_data(pp, tmp, 128, 0) != 128)
+ if (pp->ops->epp_read_data(pp, tmp, 128, EPP_XFER_FLAGS) != 128)
goto epptimeout;
i += 256;
}
@@ -909,14 +790,14 @@ static int epp_open(struct net_device *dev)
j++;
i >>= 1;
}
- printk(KERN_INFO "%s: autoprobed bitrate: %d int divider: %d int
rate: %d\n",
+ printk(KERN_INFO "%s: autoprobed bitrate: %d int divider: %d int
rate: %d\n",
bc_drvname, bc->bitrate, j, bc->bitrate >> (j+2));
tmp[0] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE/*|j*/;
if (pp->ops->epp_write_addr(pp, tmp, 1, 0) != 1)
goto epptimeout;
- /*
- * initialise hdlc variables
- */
+ /* reset RX buffer handling */
+ bc->rx_state = rx_idle;
+ /* initialise hdlc variables */
bc->hdlcrx.state = 0;
bc->hdlcrx.numbits = 0;
bc->hdlctx.state = tx_idle;
@@ -924,8 +805,9 @@ static int epp_open(struct net_device *dev)
bc->hdlctx.slotcnt = bc->ch_params.slottime;
bc->hdlctx.calibrate = 0;
/* start the bottom half stuff */
- schedule_delayed_work(&bc->run_work, 1);
netif_start_queue(dev);
+ INIT_DELAYED_WORK(&bc->run_work, epp_bh);
+ schedule_delayed_work(&bc->run_work, 1);
return 0;
epptimeout:
@@ -944,19 +826,20 @@ static int epp_close(struct net_device *dev)
struct parport *pp = bc->pdev->port;
unsigned char tmp[1];
- bc->work_running = 0;
+ spin_lock_bh(&bc->lock);
cancel_delayed_work_sync(&bc->run_work);
+ if (bc->skb)
+ dev_kfree_skb(bc->skb);
+ bc->skb = NULL;
bc->stat = EPP_DCDBIT;
+ spin_unlock_bh(&bc->lock);
tmp[0] = 0;
pp->ops->epp_write_addr(pp, tmp, 1, 0);
parport_write_control(pp, 0); /* reset the adapter */
parport_release(bc->pdev);
parport_unregister_device(bc->pdev);
- if (bc->skb)
- dev_kfree_skb(bc->skb);
- bc->skb = NULL;
- printk(KERN_INFO "%s: close epp at iobase 0x%lx irq %u\n",
- bc_drvname, dev->base_addr, dev->irq);
+ printk(KERN_INFO "%s: close parport at 0x%lx\n",
+ bc_drvname, dev->base_addr);
return 0;
}
@@ -966,6 +849,7 @@ static int baycom_setmode(struct baycom_state *bc,
const char *modestr)
{
const char *cp;
+ spin_lock_bh(&bc->lock);
if (strstr(modestr,"intclk"))
bc->cfg.intclk = 1;
if (strstr(modestr,"extclk"))
@@ -992,6 +876,7 @@ static int baycom_setmode(struct baycom_state *bc,
const char *modestr)
if (bc->cfg.bps > 1500000)
bc->cfg.bps = 1500000;
}
+ spin_unlock_bh(&bc->lock);
return 0;
}
@@ -1012,28 +897,32 @@ static int baycom_ioctl(struct net_device *dev,
struct ifreq *ifr, int cmd)
return -ENOIOCTLCMD;
case HDLCDRVCTL_GETCHANNELPAR:
+ spin_lock_bh(&bc->lock);
hi.data.cp.tx_delay = bc->ch_params.tx_delay;
hi.data.cp.tx_tail = bc->ch_params.tx_tail;
hi.data.cp.slottime = bc->ch_params.slottime;
hi.data.cp.ppersist = bc->ch_params.ppersist;
hi.data.cp.fulldup = bc->ch_params.fulldup;
+ spin_unlock_bh(&bc->lock);
break;
case HDLCDRVCTL_SETCHANNELPAR:
if (!capable(CAP_NET_ADMIN))
return -EACCES;
+ spin_lock_bh(&bc->lock);
bc->ch_params.tx_delay = hi.data.cp.tx_delay;
bc->ch_params.tx_tail = hi.data.cp.tx_tail;
bc->ch_params.slottime = hi.data.cp.slottime;
bc->ch_params.ppersist = hi.data.cp.ppersist;
bc->ch_params.fulldup = hi.data.cp.fulldup;
bc->hdlctx.slotcnt = 1;
+ spin_unlock_bh(&bc->lock);
return 0;
-
+
case HDLCDRVCTL_GETMODEMPAR:
hi.data.mp.iobase = dev->base_addr;
- hi.data.mp.irq = dev->irq;
- hi.data.mp.dma = dev->dma;
+ hi.data.mp.irq = 0;
+ hi.data.mp.dma = 0;
hi.data.mp.dma2 = 0;
hi.data.mp.seriobase = 0;
hi.data.mp.pariobase = 0;
@@ -1041,14 +930,12 @@ static int baycom_ioctl(struct net_device *dev,
struct ifreq *ifr, int cmd)
break;
case HDLCDRVCTL_SETMODEMPAR:
- if ((!capable(CAP_SYS_RAWIO)) || netif_running(dev))
+ if (!capable(CAP_SYS_RAWIO))
return -EACCES;
- dev->base_addr = hi.data.mp.iobase;
- dev->irq = /*hi.data.mp.irq*/0;
- dev->dma = /*hi.data.mp.dma*/0;
- return 0;
-
+ return 0;
+
case HDLCDRVCTL_GETSTAT:
+ spin_lock_bh(&bc->lock);
hi.data.cs.ptt = !!(bc->stat & EPP_PTTBIT);
hi.data.cs.dcd = !(bc->stat & EPP_DCDBIT);
hi.data.cs.ptt_keyed = bc->ptt_keyed;
@@ -1056,26 +943,31 @@ static int baycom_ioctl(struct net_device *dev,
struct ifreq *ifr, int cmd)
hi.data.cs.tx_errors = dev->stats.tx_errors;
hi.data.cs.rx_packets = dev->stats.rx_packets;
hi.data.cs.rx_errors = dev->stats.rx_errors;
- break;
+ spin_unlock_bh(&bc->lock);
+ break;
case HDLCDRVCTL_OLDGETSTAT:
+ spin_lock_bh(&bc->lock);
hi.data.ocs.ptt = !!(bc->stat & EPP_PTTBIT);
hi.data.ocs.dcd = !(bc->stat & EPP_DCDBIT);
hi.data.ocs.ptt_keyed = bc->ptt_keyed;
- break;
+ spin_unlock_bh(&bc->lock);
+ break;
case HDLCDRVCTL_CALIBRATE:
if (!capable(CAP_SYS_RAWIO))
return -EACCES;
+ spin_lock_bh(&bc->lock);
bc->hdlctx.calibrate = hi.data.calibrate * bc->bitrate / 8;
+ spin_unlock_bh(&bc->lock);
return 0;
case HDLCDRVCTL_DRIVERNAME:
strncpy(hi.data.drivername, "baycom_epp",
sizeof(hi.data.drivername));
break;
-
+
case HDLCDRVCTL_GETMODE:
- sprintf(hi.data.modename, "%sclk,%smodem,fclk=%d,bps=%d%s",
+ sprintf(hi.data.modename, "%sclk,%smodem,fclk=%d,bps=%d%s",
bc->cfg.intclk ? "int" : "ext",
bc->cfg.extmodem ? "ext" : "int", bc->cfg.fclk, bc->cfg.bps,
bc->cfg.loopback ? ",loopback" : "");
@@ -1104,73 +996,27 @@ static int baycom_ioctl(struct net_device *dev,
struct ifreq *ifr, int cmd)
/*
--------------------------------------------------------------------- */
static const struct net_device_ops baycom_netdev_ops = {
- .ndo_open = epp_open,
- .ndo_stop = epp_close,
- .ndo_do_ioctl = baycom_ioctl,
+ .ndo_open = epp_open,
+ .ndo_stop = epp_close,
+ .ndo_do_ioctl = baycom_ioctl,
.ndo_start_xmit = baycom_send_packet,
.ndo_set_mac_address = baycom_set_mac_address,
};
-/*
- * Check for a network adaptor of this type, and return '0' if one
exists.
- * If dev->base_addr == 0, probe all likely locations.
- * If dev->base_addr == 1, always return failure.
- * If dev->base_addr == 2, allocate space for the device and return
success
- * (detachable devices only).
- */
-static void baycom_probe(struct net_device *dev)
-{
- const struct hdlcdrv_channel_params dflt_ch_params = {
- 20, 2, 10, 40, 0
- };
- struct baycom_state *bc;
-
- /*
- * not a real probe! only initialize data structures
- */
- bc = netdev_priv(dev);
- /*
- * initialize the baycom_state struct
- */
- bc->ch_params = dflt_ch_params;
- bc->ptt_keyed = 0;
-
- /*
- * initialize the device struct
- */
-
- /* Fill in the fields of the device structure */
- bc->skb = NULL;
-
- dev->netdev_ops = &baycom_netdev_ops;
- dev->header_ops = &ax25_header_ops;
-
- dev->type = ARPHRD_AX25; /* AF_AX25 device */
- dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
- dev->mtu = AX25_DEF_PACLEN; /* eth_mtu is the default */
- dev->addr_len = AX25_ADDR_LEN; /* sizeof an ax.25 address */
- memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
- memcpy(dev->dev_addr, &null_ax25_address, AX25_ADDR_LEN);
- dev->tx_queue_len = 16;
-
- /* New style flags */
- dev->flags = 0;
-}
-
/*
--------------------------------------------------------------------- */
/*
* command line settable parameters
*/
-static const char *mode[NR_PORTS] = { "", };
-static int iobase[NR_PORTS] = { 0x378, };
+static const char *mode[NR_PORTS] = { "", "", "", "", };
+static int parport[NR_PORTS] = { 0, 1, 2, 3, };
module_param_array(mode, charp, NULL, 0);
MODULE_PARM_DESC(mode, "baycom operating mode");
-module_param_array(iobase, int, NULL, 0);
-MODULE_PARM_DESC(iobase, "baycom io base address");
+module_param_array(parport, int, NULL, 0);
+MODULE_PARM_DESC(parport, "baycom parport number");
-MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch,
hb9jnx@hb9w.che.eu");
+MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch");
MODULE_DESCRIPTION("Baycom epp amateur radio modem driver");
MODULE_LICENSE("GPL");
@@ -1178,6 +1024,9 @@ MODULE_LICENSE("GPL");
static void __init baycom_epp_dev_setup(struct net_device *dev)
{
+ const struct hdlcdrv_channel_params dflt_ch_params = {
+ 20, 2, 10, 40, 0
+ };
struct baycom_state *bc = netdev_priv(dev);
/*
@@ -1187,10 +1036,30 @@ static void __init baycom_epp_dev_setup(struct
net_device *dev)
bc->magic = BAYCOM_MAGIC;
bc->cfg.fclk = 19666600;
bc->cfg.bps = 9600;
+ bc->ch_params = dflt_ch_params;
+ bc->ptt_keyed = 0;
+
/*
- * initialize part of the device struct
+ * initialize the device struct
*/
- baycom_probe(dev);
+ spin_lock_init(&bc->lock);
+
+ /* Fill in the fields of the device structure */
+ bc->skb = NULL;
+
+ dev->header_ops = &ax25_header_ops;
+ dev->netdev_ops = &baycom_netdev_ops;
+
+ dev->type = ARPHRD_AX25; /* AF_AX25 device */
+ dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
+ dev->mtu = AX25_DEF_PACLEN; /* eth_mtu is the default */
+ dev->addr_len = AX25_ADDR_LEN; /* sizeof an ax.25 address */
+ memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
+ memcpy(dev->dev_addr, &null_ax25_address, AX25_ADDR_LEN);
+ dev->tx_queue_len = 16;
+
+ /* New style flags */
+ dev->flags = 0;
}
static int __init init_baycomepp(void)
@@ -1203,8 +1072,9 @@ static int __init init_baycomepp(void)
* register net devices
*/
for (i = 0; i < NR_PORTS; i++) {
+ struct parport *pp = parport_find_number(parport[i]);
struct net_device *dev;
-
+
dev = alloc_netdev(sizeof(struct baycom_state), "bce%d",
baycom_epp_dev_setup);
@@ -1212,14 +1082,12 @@ static int __init init_baycomepp(void)
printk(KERN_WARNING "bce%d : out of memory\n", i);
return found ? 0 : -ENOMEM;
}
-
+
sprintf(dev->name, "bce%d", i);
- dev->base_addr = iobase[i];
+ dev->base_addr = pp ? pp->base : 0;
- if (!mode[i])
+ if (!pp || !mode[i])
set_hw = 0;
- if (!set_hw)
- iobase[i] = 0;
if (register_netdev(dev)) {
printk(KERN_WARNING "%s: cannot register net device %s\n",
bc_drvname, dev->name);
@@ -1261,7 +1129,7 @@ module_exit(cleanup_baycomepp);
#ifndef MODULE
/*
- * format: baycom_epp=io,mode
+ * format: baycom_epp=parport,mode
* mode: fpga config options
*/
@@ -1272,11 +1140,11 @@ static int __init baycom_epp_setup(char *str)
if (nr_dev >= NR_PORTS)
return 0;
- str = get_options(str, 2, ints);
+ str = get_options(str, ARRAY_SIZE(ints), ints);
if (ints[0] < 1)
return 0;
mode[nr_dev] = str;
- iobase[nr_dev] = ints[1];
+ parport[nr_dev] = ints[1];
nr_dev++;
return 1;
}
^ permalink raw reply related
* [PATCH 2/2] ipv6: If neigh lookup fails during icmp6 dst allocation, propagate error.
From: David Miller @ 2011-12-13 22:38 UTC (permalink / raw)
To: netdev
Don't just succeed with a route that has a NULL neighbour attached.
This follows the behavior of addrconf_dst_alloc().
Allowing this kind of route to end up with a NULL neigh attached will
result in packet drops on output until the route is somehow
invalidated, since nothing will meanwhile try to lookup the neigh
again.
A statistic is bumped for the case where we see a neigh-less route on
output, but the resulting packet drop is otherwise silent in nature,
and frankly it's a hard error for this to happen and ipv6 should do
what ipv4 does which is say something in the kernel logs.
Signed-off-by: David S. Miller <davem@davemloft.net>
---
net/ipv6/route.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index d98cf41..4bf362b 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1089,8 +1089,10 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
neigh_hold(neigh);
else {
neigh = __neigh_lookup_errno(&nd_tbl, &fl6->daddr, dev);
- if (IS_ERR(neigh))
- neigh = NULL;
+ if (IS_ERR(neigh)) {
+ dst_free(&rt->dst);
+ return ERR_CAST(neigh);
+ }
}
rt->dst.flags |= DST_HOST;
--
1.7.7.4
^ permalink raw reply related
* [PATCH 1/2] net: Remove unused neighbour layer ops.
From: David Miller @ 2011-12-13 22:38 UTC (permalink / raw)
To: netdev
It's simpler to just keep these things out until there is a real user
of them, so we can see what the needs actually are, rather than keep
these things around as useless overhead.
Signed-off-by: David S. Miller <davem@davemloft.net>
---
include/linux/netdevice.h | 1 -
include/net/neighbour.h | 1 -
net/core/neighbour.c | 10 ----------
3 files changed, 0 insertions(+), 12 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 6037308..6b9d4ed 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -974,7 +974,6 @@ struct net_device_ops {
int (*ndo_set_features)(struct net_device *dev,
netdev_features_t features);
int (*ndo_neigh_construct)(struct neighbour *n);
- void (*ndo_neigh_destroy)(struct neighbour *n);
};
/*
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index e31f0a8..6814c4d 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -43,7 +43,6 @@ struct neigh_parms {
#endif
struct net_device *dev;
struct neigh_parms *next;
- int (*neigh_setup)(struct neighbour *);
void (*neigh_cleanup)(struct neighbour *);
struct neigh_table *tbl;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 4af151e..d57a40a 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -497,13 +497,6 @@ struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey,
}
}
- /* Device specific setup. */
- if (n->parms->neigh_setup &&
- (error = n->parms->neigh_setup(n)) < 0) {
- rc = ERR_PTR(error);
- goto out_neigh_release;
- }
-
n->confirmed = jiffies - (n->parms->base_reachable_time << 1);
write_lock_bh(&tbl->lock);
@@ -717,9 +710,6 @@ void neigh_destroy(struct neighbour *neigh)
skb_queue_purge(&neigh->arp_queue);
neigh->arp_queue_len_bytes = 0;
- if (dev->netdev_ops->ndo_neigh_destroy)
- dev->netdev_ops->ndo_neigh_destroy(neigh);
-
dev_put(dev);
neigh_parms_put(neigh->parms);
--
1.7.7.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox