* Re: [PATCHES 0/7]: DCCP patches for 2.6.25
From: David Miller @ 2007-12-12 17:00 UTC (permalink / raw)
To: acme; +Cc: netdev, dccp
In-Reply-To: <1197477413-1456-1-git-send-email-acme@redhat.com>
From: Arnaldo Carvalho de Melo <acme@redhat.com>
Date: Wed, 12 Dec 2007 14:36:46 -0200
> Please consider pulling from:
>
> master.kernel.org:/pub/scm/linux/kernel/git/acme/net-2.6.25
Pulled and pushed out to net-2.6.25, thanks!
^ permalink raw reply
* Re: [PATCH 8/8] [PATCH v2] [CCID3]: Interface CCID3 code with newer Loss Intervals Database
From: Gerrit Renker @ 2007-12-12 16:56 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, dccp, netdev
In-Reply-To: <20071211172244.GF24046@ghostprotocols.net>
| This time around I'm not doing any reordering, just trying to use your
| patches as is, but adding this patch as-is produces a kernel that will
| crash, no?
|
| > The loss history and the RX/TX packet history slabs are all created in
| > tfrc.c using the three different __init routines of the dccp_tfrc_lib.
|
| Yes, the init routines are called and in turn they create the slab
| caches, but up to the patch "[PATCH 8/8] [PATCH v2] [CCID3]: Interface
| CCID3 code with newer Loss Intervals Database" the new li slab is not
| being created, no? See what I'm talking?
|
Sorry, there is some weird kind of mix-up going on. Can you please check
your patch set: it seems this email exchange refers to an older variant.
In the most recent patch set, the slab is introduced in the patch
[TFRC]: Ringbuffer to track loss interval history
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -27,6 +23,54 @@ struct dccp_li_hist_entry {
u32 dccplih_interval;
};
+static struct kmem_cache *tfrc_lh_slab __read_mostly; /* <=== */
+/* Loss Interval weights from [RFC 3448, 5.4], scaled by 10 */
+static const int tfrc_lh_weights[NINTERVAL] = { 10, 10, 10, 10, 8, 6, 4, 2 };
// ...
And this is 6/8, i.e. before 8/8, cf.
http://www.mail-archive.com/dccp@vger.kernel.org/msg03000.html
I don't know which tree you are working off, would it be possible to
check against the test tree
git://eden-feed.erg.abdn.ac.uk/dccp_exp [dccp]
^ permalink raw reply
* [RFC] ehea: kdump support using new shutdown hook
From: Thomas Klein @ 2007-12-12 16:53 UTC (permalink / raw)
To: Paul Mackerras
Cc: Christoph Raisch, Jan-Bernd Themann, linux-kernel, linux-ppc,
Marcus Eder, netdev, Stefan Roscher, Michael Ellermann,
Michael Neuling
This patch adds kdump support using the new PPC crash shutdown hook to the
ehea driver. The driver now keeps a list of firmware handles which have to
be freed in case of a crash. The crash handler does the minimum required: it
frees the firmware resource handles plus broadcast/multicast registrations.
Please comment.
Shutdown hook patches:
http://ozlabs.org/pipermail/linuxppc-dev/2007-December/048058.html
http://ozlabs.org/pipermail/linuxppc-dev/2007-December/048059.html
Signed-off-by: Thomas Klein <tklein@de.ibm.com>
---
diff -Nurp -X dontdiff linux-2.6.24-rc5/drivers/net/ehea/ehea.h patched_kernel/drivers/net/ehea/ehea.h
--- linux-2.6.24-rc5/drivers/net/ehea/ehea.h 2007-12-11 04:48:43.000000000 +0100
+++ patched_kernel/drivers/net/ehea/ehea.h 2007-12-12 17:30:53.000000000 +0100
@@ -40,7 +40,7 @@
#include <asm/io.h>
#define DRV_NAME "ehea"
-#define DRV_VERSION "EHEA_0083"
+#define DRV_VERSION "EHEA_0084"
/* eHEA capability flags */
#define DLPAR_PORT_ADD_REM 1
@@ -386,6 +386,7 @@ struct ehea_port_res {
#define EHEA_MAX_PORTS 16
+#define EHEA_MAX_RES_HANDLES (100 * EHEA_MAX_PORTS + 10)
struct ehea_adapter {
u64 handle;
struct of_device *ofdev;
@@ -397,6 +398,7 @@ struct ehea_adapter {
u64 max_mc_mac; /* max number of multicast mac addresses */
int active_ports;
struct list_head list;
+ u64 res_handles[EHEA_MAX_RES_HANDLES];
};
diff -Nurp -X dontdiff linux-2.6.24-rc5/drivers/net/ehea/ehea_main.c patched_kernel/drivers/net/ehea/ehea_main.c
--- linux-2.6.24-rc5/drivers/net/ehea/ehea_main.c 2007-12-11 04:48:43.000000000 +0100
+++ patched_kernel/drivers/net/ehea/ehea_main.c 2007-12-12 17:30:53.000000000 +0100
@@ -35,6 +35,7 @@
#include <linux/if_ether.h>
#include <linux/notifier.h>
#include <linux/reboot.h>
+#include <asm-powerpc/kexec.h>
#include <net/ip.h>
@@ -2256,6 +2257,33 @@ static int ehea_clean_all_portres(struct
return ret;
}
+static void ehea_update_adapter_handles(struct ehea_adapter *adapter)
+{
+ int i, k;
+ int j = 0;
+
+ memset(adapter->res_handles, sizeof(adapter->res_handles), 0);
+
+ for (k = 0; k < EHEA_MAX_PORTS; k++) {
+ struct ehea_port *port = adapter->port[k];
+
+ if (!port || (port->state != EHEA_PORT_UP))
+ continue;
+
+ for(i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
+ struct ehea_port_res *pr = &port->port_res[i];
+
+ adapter->res_handles[j++] = pr->qp->fw_handle;
+ adapter->res_handles[j++] = pr->send_cq->fw_handle;
+ adapter->res_handles[j++] = pr->recv_cq->fw_handle;
+ adapter->res_handles[j++] = pr->eq->fw_handle;
+ adapter->res_handles[j++] = pr->send_mr.handle;
+ adapter->res_handles[j++] = pr->recv_mr.handle;
+ }
+ adapter->res_handles[j++] = port->qp_eq->fw_handle;
+ }
+}
+
static void ehea_remove_adapter_mr(struct ehea_adapter *adapter)
{
if (adapter->active_ports)
@@ -2318,6 +2346,7 @@ static int ehea_up(struct net_device *de
ret = 0;
port->state = EHEA_PORT_UP;
+ ehea_update_adapter_handles(port->adapter);
goto out;
out_free_irqs:
@@ -2387,6 +2416,8 @@ static int ehea_down(struct net_device *
ehea_info("Failed freeing resources for %s. ret=%i",
dev->name, ret);
+ ehea_update_adapter_handles(port->adapter);
+
return ret;
}
@@ -3302,6 +3333,71 @@ static int __devexit ehea_remove(struct
return 0;
}
+void ehea_crash_deregister(void)
+{
+ struct ehea_adapter *adapter;
+ int i;
+ u64 hret;
+ u8 reg_type;
+
+ list_for_each_entry(adapter, &adapter_list, list) {
+ for (i = 0; i < EHEA_MAX_PORTS; i++) {
+ struct ehea_port *port = adapter->port[i];
+ if (port->state == EHEA_PORT_UP) {
+ struct ehea_mc_list *mc_entry = port->mc_list;
+ struct list_head *pos;
+ struct list_head *temp;
+
+ /* Undo multicast registrations */
+ list_for_each_safe(pos, temp,
+ &(port->mc_list->list)) {
+ mc_entry = list_entry(pos,
+ struct ehea_mc_list,
+ list);
+ ehea_multicast_reg_helper(port,
+ mc_entry->macaddr,
+ H_DEREG_BCMC);
+ }
+
+ /* Undo broad registration */
+ reg_type = EHEA_BCMC_BROADCAST |
+ EHEA_BCMC_UNTAGGED;
+ ehea_h_reg_dereg_bcmc(port->adapter->handle,
+ port->logical_port_id,
+ reg_type, port->mac_addr,
+ 0, H_DEREG_BCMC);
+
+ reg_type = EHEA_BCMC_BROADCAST |
+ EHEA_BCMC_VLANID_ALL;
+ ehea_h_reg_dereg_bcmc(port->adapter->handle,
+ port->logical_port_id,
+ reg_type, port->mac_addr,
+ 0, H_DEREG_BCMC);
+ }
+ }
+ for (i = 0; i < EHEA_MAX_RES_HANDLES; i++) {
+ u64 handle = adapter->res_handles[i];
+ if (handle) {
+ hret = ehea_h_free_resource(adapter->handle,
+ handle,
+ FORCE_FREE);
+ }
+ }
+
+ if (adapter->neq) {
+ hret = ehea_h_free_resource(adapter->handle,
+ adapter->neq->fw_handle,
+ FORCE_FREE);
+ }
+
+ if (adapter->mr.handle) {
+ hret = ehea_h_free_resource(adapter->handle,
+ adapter->mr.handle,
+ FORCE_FREE);
+ }
+ }
+}
+
static int ehea_reboot_notifier(struct notifier_block *nb,
unsigned long action, void *unused)
{
@@ -3373,6 +3469,9 @@ int __init ehea_module_init(void)
goto out;
register_reboot_notifier(&ehea_reboot_nb);
+ ret = crash_shutdown_register(&ehea_crash_deregister);
+ if (ret)
+ ehea_info("failed registering crash handler");
ret = ibmebus_register_driver(&ehea_driver);
if (ret) {
@@ -3386,6 +3485,7 @@ int __init ehea_module_init(void)
ehea_error("failed to register capabilities attribute, ret=%d",
ret);
unregister_reboot_notifier(&ehea_reboot_nb);
+ crash_shutdown_unregister(&ehea_crash_deregister);
ibmebus_unregister_driver(&ehea_driver);
goto out;
}
@@ -3396,10 +3496,15 @@ out:
static void __exit ehea_module_exit(void)
{
+ int ret;
+
flush_scheduled_work();
driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities);
ibmebus_unregister_driver(&ehea_driver);
unregister_reboot_notifier(&ehea_reboot_nb);
+ ret = crash_shutdown_unregister(&ehea_crash_deregister);
+ if (ret)
+ ehea_info("failed unregistering crash handler");
ehea_destroy_busmap();
}
^ permalink raw reply
* Re: "ip neigh show" not showing arp cache entries?
From: Eric Dumazet @ 2007-12-12 16:46 UTC (permalink / raw)
To: Chris Friesen; +Cc: netdev, linux-kernel
In-Reply-To: <47600A6E.8000202@nortel.com>
Chris Friesen a écrit :
> I retested it on an x86 machine and am seeing similar problems.
>
> First, "arp" gives the arp table as expected:
>
> root@typhoon-base-unit0:/tftpboot/cnp/0-0-5-0/0-0-5-0> arp -n
> Address HWtype HWaddress Flags Mask Iface
> 172.24.0.9 ether 00:03:CC:51:06:5E C bond0
> 10.41.18.101 ether 00:0E:0C:5E:95:BD C eth6
> 172.24.137.0 ether 00:C0:8B:08:E4:88 C bond0
> 172.24.136.0 ether 00:C0:8B:07:B3:7E C bond0
> 10.41.18.1 ether 00:00:5E:00:01:01 C eth6
> 172.24.0.5 ether 00:01:AF:15:E0:6A C bond0
> 172.24.0.13 ether 00:0E:0C:85:FD:D2 C bond0
> 172.24.0.3 ether 00:01:AF:14:C8:CC C bond0
> 172.24.132.1 ether 00:01:AF:14:E9:88 C bond0
> 172.24.0.7 ether 00:07:E9:41:4B:B4 C bond0
> 192.168.24.81 ether 00:01:AF:14:E9:8A C bond2
>
> "ip neigh show" gives nothing, but if I search for specific addresses
> from the arp table listing they show up:
>
> root@typhoon-base-unit0:/tftpboot/cnp/0-0-5-0/0-0-5-0> ip neigh show
> root@typhoon-base-unit0:/tftpboot/cnp/0-0-5-0/0-0-5-0> ip neigh show
> 172.24.0.9
> 172.24.0.9 dev bond0 lladdr 00:03:cc:51:06:5e DELAY
> root@typhoon-base-unit0:/tftpboot/cnp/0-0-5-0/0-0-5-0> ip neigh show
> 10.41.18.101
> 10.41.18.101 dev eth6 lladdr 00:0e:0c:5e:95:bd REACHABLE
> root@typhoon-base-unit0:/tftpboot/cnp/0-0-5-0/0-0-5-0> ip neigh show
> 172.24.137.0
> 172.24.137.0 dev bond0 lladdr 00:c0:8b:08:e4:88 REACHABLE
>
>
> Is this expected behaviour?
Probably not... Still a 2.6.14 kernel ?
Could you send the result of :
strace ip neigh show
^ permalink raw reply
* [PATCH/RFC] [POWERPC] Add fixed-phy support for fs_enet
From: Jochen Friedrich @ 2007-12-12 16:45 UTC (permalink / raw)
To: Vitaly Bordug; +Cc: Jeff Garzik, linuxppc-dev, linux-kernel, netdev, Scott Wood
This patch adds support to use the fixed-link property
of an ethernet node to fs_enet for the
CONFIG_PPC_CPM_NEW_BINDING case.
Signed-off-by: Jochen Friedrich <jochen@scram.de>
---
drivers/net/fs_enet/fs_enet-main.c | 9 ++++++++-
1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index f2a4d39..8220c70 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -1174,8 +1174,15 @@ static int __devinit find_phy(struct device_node *np,
struct device_node *phynode, *mdionode;
struct resource res;
int ret = 0, len;
+ const u32 *data;
+
+ data = of_get_property(np, "fixed-link", NULL);
+ if (data) {
+ snprintf(fpi->bus_id, 16, PHY_ID_FMT, 0, *data);
+ return 0;
+ }
- const u32 *data = of_get_property(np, "phy-handle", &len);
+ data = of_get_property(np, "phy-handle", &len);
if (!data || len != 4)
return -EINVAL;
--
1.5.3.7
^ permalink raw reply related
* Re: [PATCH] iproute2: support dotted-quad netmask notation.
From: Stephen Hemminger @ 2007-12-12 16:40 UTC (permalink / raw)
To: Andreas Henriksson; +Cc: netdev
In-Reply-To: <20071212115513.GA3394@scream.fatal.se>
On Wed, 12 Dec 2007 12:55:13 +0100
Andreas Henriksson <andreas@fatal.se> wrote:
> On Tue, Dec 11, 2007 at 05:14:06PM -0800, Stephen Hemminger wrote:
> > On Sun, 09 Dec 2007 18:10:22 +0100
> > Andreas Henriksson <andreas@fatal.se> wrote:
> > > I think both previous patches where broken on big-endian platforms.
> > > Here's an updated patch again. I'm very sorry for the inconvenience!
> [...]
> > > + *val=0;
> > > + for (mask = ntohl(addr.data[0]); mask; mask <<= 1)
> > > + (*val)++;
> [...]
> >
> > applied
> >
>
> Just to make sure.... It looks on git.kernel.org like you applied the wrong
> patch. (Maybe you just haven't pushed out the latest changes there yet.)
> Please double-check that you actually applied the latest version (which is
> the one in the mail you replied "applied" to, important part quoted above).
Actually, I took your logic and moved it to a new function:
static unsigned cidr(const inet_prefix *addr)
{
unsigned bits = 0;
u_int32_t mask;
for (mask = ntohl(addr->data[0]); mask; mask <<= 1)
++bits;
return bits;
}
--
Stephen Hemminger <shemminger@linux-foundation.org>
^ permalink raw reply
* [PATCH 3/7] [TFRC]: Ringbuffer to track loss interval history
From: Arnaldo Carvalho de Melo @ 2007-12-12 16:36 UTC (permalink / raw)
To: David S. Miller
Cc: netdev, dccp, Gerrit Renker, Ian McDonald,
Arnaldo Carvalho de Melo
In-Reply-To: <1197477413-1456-3-git-send-email-acme@redhat.com>
From: Gerrit Renker <gerrit@erg.abdn.ac.uk>
A ringbuffer-based implementation of loss interval history is easier to
maintain, allocate, and update.
The `swap' routine to keep the RX history sorted is due to and was written
by Arnaldo Carvalho de Melo, simplifying an earlier macro-based variant.
Details:
* access to the Loss Interval Records via macro wrappers (with safety checks);
* simplified, on-demand allocation of entries (no extra memory consumption on
lossless links); cache allocation is local to the module / exported as service;
* provision of RFC-compliant algorithm to re-compute average loss interval;
* provision of comprehensive, new loss detection algorithm
- support for all cases of loss, including re-ordered/duplicate packets;
- waiting for NDUPACK=3 packets to fill the hole;
- updating loss records when a late-arriving packet fills a hole.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Signed-off-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
net/dccp/ccids/lib/loss_interval.c | 161 +++++++++++++++++++++++++-
net/dccp/ccids/lib/loss_interval.h | 56 +++++++++-
net/dccp/ccids/lib/packet_history.c | 218 ++++++++++++++++++++++++++++++++++-
net/dccp/ccids/lib/packet_history.h | 11 +-
net/dccp/ccids/lib/tfrc.h | 3 +
5 files changed, 435 insertions(+), 14 deletions(-)
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c
index c0a933a..39980d1 100644
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -1,6 +1,7 @@
/*
* net/dccp/ccids/lib/loss_interval.c
*
+ * Copyright (c) 2007 The University of Aberdeen, Scotland, UK
* Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
* Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
* Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
@@ -10,12 +11,7 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
-
-#include <linux/module.h>
#include <net/sock.h>
-#include "../../dccp.h"
-#include "loss_interval.h"
-#include "packet_history.h"
#include "tfrc.h"
#define DCCP_LI_HIST_IVAL_F_LENGTH 8
@@ -27,6 +23,54 @@ struct dccp_li_hist_entry {
u32 dccplih_interval;
};
+static struct kmem_cache *tfrc_lh_slab __read_mostly;
+/* Loss Interval weights from [RFC 3448, 5.4], scaled by 10 */
+static const int tfrc_lh_weights[NINTERVAL] = { 10, 10, 10, 10, 8, 6, 4, 2 };
+
+/* implements LIFO semantics on the array */
+static inline u8 LIH_INDEX(const u8 ctr)
+{
+ return (LIH_SIZE - 1 - (ctr % LIH_SIZE));
+}
+
+/* the `counter' index always points at the next entry to be populated */
+static inline struct tfrc_loss_interval *tfrc_lh_peek(struct tfrc_loss_hist *lh)
+{
+ return lh->counter ? lh->ring[LIH_INDEX(lh->counter - 1)] : NULL;
+}
+
+/* given i with 0 <= i <= k, return I_i as per the rfc3448bis notation */
+static inline u32 tfrc_lh_get_interval(struct tfrc_loss_hist *lh, const u8 i)
+{
+ BUG_ON(i >= lh->counter);
+ return lh->ring[LIH_INDEX(lh->counter - i - 1)]->li_length;
+}
+
+/*
+ * On-demand allocation and de-allocation of entries
+ */
+static struct tfrc_loss_interval *tfrc_lh_demand_next(struct tfrc_loss_hist *lh)
+{
+ if (lh->ring[LIH_INDEX(lh->counter)] == NULL)
+ lh->ring[LIH_INDEX(lh->counter)] = kmem_cache_alloc(tfrc_lh_slab,
+ GFP_ATOMIC);
+ return lh->ring[LIH_INDEX(lh->counter)];
+}
+
+void tfrc_lh_cleanup(struct tfrc_loss_hist *lh)
+{
+ if (!tfrc_lh_is_initialised(lh))
+ return;
+
+ for (lh->counter = 0; lh->counter < LIH_SIZE; lh->counter++)
+ if (lh->ring[LIH_INDEX(lh->counter)] != NULL) {
+ kmem_cache_free(tfrc_lh_slab,
+ lh->ring[LIH_INDEX(lh->counter)]);
+ lh->ring[LIH_INDEX(lh->counter)] = NULL;
+ }
+}
+EXPORT_SYMBOL_GPL(tfrc_lh_cleanup);
+
static struct kmem_cache *dccp_li_cachep __read_mostly;
static inline struct dccp_li_hist_entry *dccp_li_hist_entry_new(const gfp_t prio)
@@ -98,6 +142,65 @@ u32 dccp_li_hist_calc_i_mean(struct list_head *list)
EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean);
+static void tfrc_lh_calc_i_mean(struct tfrc_loss_hist *lh)
+{
+ u32 i_i, i_tot0 = 0, i_tot1 = 0, w_tot = 0;
+ int i, k = tfrc_lh_length(lh) - 1; /* k is as in rfc3448bis, 5.4 */
+
+ for (i=0; i <= k; i++) {
+ i_i = tfrc_lh_get_interval(lh, i);
+
+ if (i < k) {
+ i_tot0 += i_i * tfrc_lh_weights[i];
+ w_tot += tfrc_lh_weights[i];
+ }
+ if (i > 0)
+ i_tot1 += i_i * tfrc_lh_weights[i-1];
+ }
+
+ BUG_ON(w_tot == 0);
+ lh->i_mean = max(i_tot0, i_tot1) / w_tot;
+}
+
+/**
+ * tfrc_lh_update_i_mean - Update the `open' loss interval I_0
+ * For recomputing p: returns `true' if p > p_prev <=> 1/p < 1/p_prev
+ */
+u8 tfrc_lh_update_i_mean(struct tfrc_loss_hist *lh, struct sk_buff *skb)
+{
+ struct tfrc_loss_interval *cur = tfrc_lh_peek(lh);
+ u32 old_i_mean = lh->i_mean;
+ s64 length;
+
+ if (cur == NULL) /* not initialised */
+ return 0;
+
+ length = dccp_delta_seqno(cur->li_seqno, DCCP_SKB_CB(skb)->dccpd_seq);
+
+ if (length - cur->li_length <= 0) /* duplicate or reordered */
+ return 0;
+
+ if (SUB16(dccp_hdr(skb)->dccph_ccval, cur->li_ccval) > 4)
+ /*
+ * Implements RFC 4342, 10.2:
+ * If a packet S (skb) exists whose seqno comes `after' the one
+ * starting the current loss interval (cur) and if the modulo-16
+ * distance from C(cur) to C(S) is greater than 4, consider all
+ * subsequent packets as belonging to a new loss interval. This
+ * test is necessary since CCVal may wrap between intervals.
+ */
+ cur->li_is_closed = 1;
+
+ if (tfrc_lh_length(lh) == 1) /* due to RFC 3448, 6.3.1 */
+ return 0;
+
+ cur->li_length = length;
+ tfrc_lh_calc_i_mean(lh);
+
+ return (lh->i_mean < old_i_mean);
+}
+EXPORT_SYMBOL_GPL(tfrc_lh_update_i_mean);
+
static int dccp_li_hist_interval_new(struct list_head *list,
const u64 seq_loss, const u8 win_loss)
{
@@ -284,6 +387,54 @@ void dccp_li_update_li(struct sock *sk,
EXPORT_SYMBOL_GPL(dccp_li_update_li);
+/* Determine if `new_loss' does begin a new loss interval [RFC 4342, 10.2] */
+static inline u8 tfrc_lh_is_new_loss(struct tfrc_loss_interval *cur,
+ struct tfrc_rx_hist_entry *new_loss)
+{
+ return dccp_delta_seqno(cur->li_seqno, new_loss->tfrchrx_seqno) > 0 &&
+ (cur->li_is_closed || SUB16(new_loss->tfrchrx_ccval, cur->li_ccval) > 4);
+}
+
+/** tfrc_lh_interval_add - Insert new record into the Loss Interval database
+ * @lh: Loss Interval database
+ * @rh: Receive history containing a fresh loss event
+ * @calc_first_li: Caller-dependent routine to compute length of first interval
+ * @sk: Used by @calc_first_li in caller-specific way (subtyping)
+ * Updates I_mean and returns 1 if a new interval has in fact been added to @lh.
+ */
+int tfrc_lh_interval_add(struct tfrc_loss_hist *lh, struct tfrc_rx_hist *rh,
+ u32 (*calc_first_li)(struct sock *), struct sock *sk)
+{
+ struct tfrc_loss_interval *cur = tfrc_lh_peek(lh), *new;
+
+ if (cur != NULL && !tfrc_lh_is_new_loss(cur, tfrc_rx_hist_loss_prev(rh)))
+ return 0;
+
+ new = tfrc_lh_demand_next(lh);
+ if (unlikely(new == NULL)) {
+ DCCP_CRIT("Cannot allocate/add loss record.");
+ return 0;
+ }
+
+ new->li_seqno = tfrc_rx_hist_loss_prev(rh)->tfrchrx_seqno;
+ new->li_ccval = tfrc_rx_hist_loss_prev(rh)->tfrchrx_ccval;
+ new->li_is_closed = 0;
+
+ if (++lh->counter == 1)
+ lh->i_mean = new->li_length = (*calc_first_li)(sk);
+ else {
+ cur->li_length = dccp_delta_seqno(cur->li_seqno, new->li_seqno);
+ new->li_length = dccp_delta_seqno(new->li_seqno,
+ tfrc_rx_hist_last_rcv(rh)->tfrchrx_seqno);
+ if (lh->counter > (2*LIH_SIZE))
+ lh->counter -= LIH_SIZE;
+
+ tfrc_lh_calc_i_mean(lh);
+ }
+ return 1;
+}
+EXPORT_SYMBOL_GPL(tfrc_lh_interval_add);
+
int __init dccp_li_init(void)
{
dccp_li_cachep = kmem_cache_create("dccp_li_hist",
diff --git a/net/dccp/ccids/lib/loss_interval.h b/net/dccp/ccids/lib/loss_interval.h
index 27bee92..5e3c5c5 100644
--- a/net/dccp/ccids/lib/loss_interval.h
+++ b/net/dccp/ccids/lib/loss_interval.h
@@ -3,6 +3,7 @@
/*
* net/dccp/ccids/lib/loss_interval.h
*
+ * Copyright (c) 2007 The University of Aberdeen, Scotland, UK
* Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
* Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
* Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
@@ -12,11 +13,64 @@
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
-
#include <linux/ktime.h>
#include <linux/list.h>
+#include <linux/slab.h>
+
+/*
+ * Number of loss intervals (RFC 4342, 8.6.1). The history size is one more than
+ * NINTERVAL, since the `open' interval I_0 is always stored as the first entry.
+ */
+#define NINTERVAL 8
+#define LIH_SIZE (NINTERVAL + 1)
+
+/**
+ * tfrc_loss_interval - Loss history record for TFRC-based protocols
+ * @li_seqno: Highest received seqno before the start of loss
+ * @li_ccval: The CCVal belonging to @li_seqno
+ * @li_is_closed: Whether @li_seqno is older than 1 RTT
+ * @li_length: Loss interval sequence length
+ */
+struct tfrc_loss_interval {
+ u64 li_seqno:48,
+ li_ccval:4,
+ li_is_closed:1;
+ u32 li_length;
+};
+
+/**
+ * tfrc_loss_hist - Loss record database
+ * @ring: Circular queue managed in LIFO manner
+ * @counter: Current count of entries (can be more than %LIH_SIZE)
+ * @i_mean: Current Average Loss Interval [RFC 3448, 5.4]
+ */
+struct tfrc_loss_hist {
+ struct tfrc_loss_interval *ring[LIH_SIZE];
+ u8 counter;
+ u32 i_mean;
+};
+
+static inline void tfrc_lh_init(struct tfrc_loss_hist *lh)
+{
+ memset(lh, 0, sizeof(struct tfrc_loss_hist));
+}
+
+static inline u8 tfrc_lh_is_initialised(struct tfrc_loss_hist *lh)
+{
+ return lh->counter > 0;
+}
+
+static inline u8 tfrc_lh_length(struct tfrc_loss_hist *lh)
+{
+ return min(lh->counter, (u8)LIH_SIZE);
+}
extern void dccp_li_hist_purge(struct list_head *list);
+struct tfrc_rx_hist;
+extern int tfrc_lh_interval_add(struct tfrc_loss_hist *, struct tfrc_rx_hist *,
+ u32 (*first_li)(struct sock *), struct sock *);
+extern u8 tfrc_lh_update_i_mean(struct tfrc_loss_hist *lh, struct sk_buff *);
+extern void tfrc_lh_cleanup(struct tfrc_loss_hist *lh);
extern u32 dccp_li_hist_calc_i_mean(struct list_head *list);
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
index dd2cf2d..5b10a1e 100644
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -151,11 +151,10 @@ void tfrc_rx_packet_history_exit(void)
}
}
-void tfrc_rx_hist_add_packet(struct tfrc_rx_hist *h,
- const struct sk_buff *skb,
- const u32 ndp)
+static inline void tfrc_rx_hist_entry_from_skb(struct tfrc_rx_hist_entry *entry,
+ const struct sk_buff *skb,
+ const u32 ndp)
{
- struct tfrc_rx_hist_entry *entry = tfrc_rx_hist_last_rcv(h);
const struct dccp_hdr *dh = dccp_hdr(skb);
entry->tfrchrx_seqno = DCCP_SKB_CB(skb)->dccpd_seq;
@@ -164,6 +163,15 @@ void tfrc_rx_hist_add_packet(struct tfrc_rx_hist *h,
entry->tfrchrx_ndp = ndp;
entry->tfrchrx_tstamp = ktime_get_real();
}
+
+void tfrc_rx_hist_add_packet(struct tfrc_rx_hist *h,
+ const struct sk_buff *skb,
+ const u32 ndp)
+{
+ struct tfrc_rx_hist_entry *entry = tfrc_rx_hist_last_rcv(h);
+
+ tfrc_rx_hist_entry_from_skb(entry, skb, ndp);
+}
EXPORT_SYMBOL_GPL(tfrc_rx_hist_add_packet);
/* has the packet contained in skb been seen before? */
@@ -209,6 +217,208 @@ int tfrc_rx_hist_new_loss_indicated(struct tfrc_rx_hist *h,
}
EXPORT_SYMBOL_GPL(tfrc_rx_hist_new_loss_indicated);
+static void tfrc_rx_hist_swap(struct tfrc_rx_hist *h, const u8 a, const u8 b)
+{
+ const u8 idx_a = tfrc_rx_hist_index(h, a),
+ idx_b = tfrc_rx_hist_index(h, b);
+ struct tfrc_rx_hist_entry *tmp = h->ring[idx_a];
+
+ h->ring[idx_a] = h->ring[idx_b];
+ h->ring[idx_b] = tmp;
+}
+
+/*
+ * Private helper functions for loss detection.
+ *
+ * In the descriptions, `Si' refers to the sequence number of entry number i,
+ * whose NDP count is `Ni' (lower case is used for variables).
+ * Note: All __after_loss functions expect that a test against duplicates has
+ * been performed already: the seqno of the skb must not be less than the
+ * seqno of loss_prev; and it must not equal that of any valid hist_entry.
+ */
+static void __one_after_loss(struct tfrc_rx_hist *h, struct sk_buff *skb, u32 n2)
+{
+ u64 s0 = tfrc_rx_hist_loss_prev(h)->tfrchrx_seqno,
+ s1 = tfrc_rx_hist_entry(h, 1)->tfrchrx_seqno,
+ s2 = DCCP_SKB_CB(skb)->dccpd_seq;
+ int n1 = tfrc_rx_hist_entry(h, 1)->tfrchrx_ndp,
+ d12 = dccp_delta_seqno(s1, s2), d2;
+
+ if (d12 > 0) { /* S1 < S2 */
+ h->loss_count = 2;
+ tfrc_rx_hist_entry_from_skb(tfrc_rx_hist_entry(h, 2), skb, n2);
+ return;
+ }
+
+ /* S0 < S2 < S1 */
+ d2 = dccp_delta_seqno(s0, s2);
+
+ if (d2 == 1 || n2 >= d2) { /* S2 is direct successor of S0 */
+ int d21 = -d12;
+
+ if (d21 == 1 || n1 >= d21) {
+ /* hole is filled: S0, S2, and S1 are consecutive */
+ h->loss_count = 0;
+ h->loss_start = tfrc_rx_hist_index(h, 1);
+ } else
+ /* gap between S2 and S1: just update loss_prev */
+ tfrc_rx_hist_entry_from_skb(tfrc_rx_hist_loss_prev(h), skb, n2);
+
+ } else { /* hole between S0 and S2 */
+ /*
+ * Reorder history to insert S2 between S0 and s1
+ */
+ tfrc_rx_hist_swap(h, 0, 3);
+ h->loss_start = tfrc_rx_hist_index(h, 3);
+ tfrc_rx_hist_entry_from_skb(tfrc_rx_hist_entry(h, 1), skb, n2);
+ h->loss_count = 2;
+ }
+}
+
+/* return 1 if a new loss event has been identified */
+static int __two_after_loss(struct tfrc_rx_hist *h, struct sk_buff *skb, u32 n3)
+{
+ u64 s0 = tfrc_rx_hist_loss_prev(h)->tfrchrx_seqno,
+ s1 = tfrc_rx_hist_entry(h, 1)->tfrchrx_seqno,
+ s2 = tfrc_rx_hist_entry(h, 2)->tfrchrx_seqno,
+ s3 = DCCP_SKB_CB(skb)->dccpd_seq;
+ int n1 = tfrc_rx_hist_entry(h, 1)->tfrchrx_ndp,
+ d23 = dccp_delta_seqno(s2, s3), d13, d3, d31;
+
+ if (d23 > 0) { /* S2 < S3 */
+ h->loss_count = 3;
+ tfrc_rx_hist_entry_from_skb(tfrc_rx_hist_entry(h, 3), skb, n3);
+ return 1;
+ }
+
+ /* S3 < S2 */
+ d13 = dccp_delta_seqno(s1, s3);
+
+ if (d13 > 0) {
+ /*
+ * The sequence number order is S1, S3, S2
+ * Reorder history to insert entry between S1 and S2
+ */
+ tfrc_rx_hist_swap(h, 2, 3);
+ tfrc_rx_hist_entry_from_skb(tfrc_rx_hist_entry(h, 2), skb, n3);
+ h->loss_count = 3;
+ return 1;
+ }
+
+ /* S0 < S3 < S1 */
+ d31 = -d13;
+ d3 = dccp_delta_seqno(s0, s3);
+
+ if (d3 == 1 || n3 >= d3) { /* S3 is a successor of S0 */
+
+ if (d31 == 1 || n1 >= d31) {
+ /* hole between S0 and S1 filled by S3 */
+ int d2 = dccp_delta_seqno(s1, s2),
+ n2 = tfrc_rx_hist_entry(h, 2)->tfrchrx_ndp;
+
+ if (d2 == 1 || n2 >= d2) {
+ /* entire hole filled by S0, S3, S1, S2 */
+ h->loss_start = tfrc_rx_hist_index(h, 2);
+ h->loss_count = 0;
+ } else {
+ /* gap remains between S1 and S2 */
+ h->loss_start = tfrc_rx_hist_index(h, 1);
+ h->loss_count = 1;
+ }
+
+ } else /* gap exists between S3 and S1, loss_count stays at 2 */
+ tfrc_rx_hist_entry_from_skb(tfrc_rx_hist_loss_prev(h), skb, n3);
+
+ return 0;
+ }
+
+ /*
+ * The remaining case: S3 is not a successor of S0.
+ * Sequence order is S0, S3, S1, S2; reorder to insert between S0 and S1
+ */
+ tfrc_rx_hist_swap(h, 0, 3);
+ h->loss_start = tfrc_rx_hist_index(h, 3);
+ tfrc_rx_hist_entry_from_skb(tfrc_rx_hist_entry(h, 1), skb, n3);
+ h->loss_count = 3;
+
+ return 1;
+}
+
+/* return the signed modulo-2^48 sequence number distance from entry e1 to e2 */
+static s64 tfrc_rx_hist_delta_seqno(struct tfrc_rx_hist *h, u8 e1, u8 e2)
+{
+ DCCP_BUG_ON(e1 > h->loss_count || e2 > h->loss_count);
+
+ return dccp_delta_seqno(tfrc_rx_hist_entry(h, e1)->tfrchrx_seqno,
+ tfrc_rx_hist_entry(h, e2)->tfrchrx_seqno);
+}
+
+/* recycle RX history records to continue loss detection if necessary */
+static void __three_after_loss(struct tfrc_rx_hist *h)
+{
+ /*
+ * The distance between S0 and S1 is always greater than 1 and the NDP
+ * count of S1 is smaller than this distance. Otherwise there would
+ * have been no loss. Hence it is only necessary to see whether there
+ * are further missing data packets between S1/S2 and S2/S3.
+ */
+ int d2 = tfrc_rx_hist_delta_seqno(h, 1, 2),
+ d3 = tfrc_rx_hist_delta_seqno(h, 2, 3),
+ n2 = tfrc_rx_hist_entry(h, 2)->tfrchrx_ndp,
+ n3 = tfrc_rx_hist_entry(h, 3)->tfrchrx_ndp;
+
+ if (d2 == 1 || n2 >= d2) { /* S2 is successor to S1 */
+
+ if (d3 == 1 || n3 >= d3) {
+ /* S3 is successor of S2: entire hole is filled */
+ h->loss_start = tfrc_rx_hist_index(h, 3);
+ h->loss_count = 0;
+ } else {
+ /* gap between S2 and S3 */
+ h->loss_start = tfrc_rx_hist_index(h, 2);
+ h->loss_count = 1;
+ }
+
+ } else { /* gap between S1 and S2 */
+ h->loss_start = tfrc_rx_hist_index(h, 1);
+ h->loss_count = 2;
+ }
+}
+
+/**
+ * tfrc_rx_handle_loss - Loss detection and further processing
+ * @h: The non-empty RX history object
+ * @lh: Loss Intervals database to update
+ * @skb: Currently received packet
+ * @ndp: The NDP count belonging to @skb
+ * @calc_first_li: Caller-dependent computation of first loss interval in @lh
+ * @sk: Used by @calc_first_li (see tfrc_lh_interval_add)
+ * Chooses action according to pending loss, updates LI database when a new
+ * loss was detected, and does required post-processing. Returns 1 when caller
+ * should send feedback, 0 otherwise.
+ */
+int tfrc_rx_handle_loss(struct tfrc_rx_hist *h,
+ struct tfrc_loss_hist *lh,
+ struct sk_buff *skb, u32 ndp,
+ u32 (*calc_first_li)(struct sock *), struct sock *sk)
+{
+ int is_new_loss = 0;
+
+ if (h->loss_count == 1) {
+ __one_after_loss(h, skb, ndp);
+ } else if (h->loss_count != 2) {
+ DCCP_BUG("invalid loss_count %d", h->loss_count);
+ } else if (__two_after_loss(h, skb, ndp)) {
+ /*
+ * Update Loss Interval database and recycle RX records
+ */
+ is_new_loss = tfrc_lh_interval_add(lh, h, calc_first_li, sk);
+ __three_after_loss(h);
+ }
+ return is_new_loss;
+}
+EXPORT_SYMBOL_GPL(tfrc_rx_handle_loss);
+
int tfrc_rx_hist_alloc(struct tfrc_rx_hist *h)
{
int i;
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h
index e58b0fc..24edd8d 100644
--- a/net/dccp/ccids/lib/packet_history.h
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -36,10 +36,9 @@
#ifndef _DCCP_PKT_HIST_
#define _DCCP_PKT_HIST_
-#include <linux/ktime.h>
-#include <linux/types.h>
-
-struct sk_buff;
+#include <linux/list.h>
+#include <linux/slab.h>
+#include "tfrc.h"
struct tfrc_tx_hist_entry;
@@ -125,6 +124,10 @@ extern void tfrc_rx_hist_add_packet(struct tfrc_rx_hist *h,
extern int tfrc_rx_hist_duplicate(struct tfrc_rx_hist *h, struct sk_buff *skb);
extern int tfrc_rx_hist_new_loss_indicated(struct tfrc_rx_hist *h,
const struct sk_buff *skb, u32 ndp);
+struct tfrc_loss_hist;
+extern int tfrc_rx_handle_loss(struct tfrc_rx_hist *, struct tfrc_loss_hist *,
+ struct sk_buff *skb, u32 ndp,
+ u32 (*first_li)(struct sock *), struct sock *);
extern u32 tfrc_rx_hist_sample_rtt(struct tfrc_rx_hist *h,
const struct sk_buff *skb);
extern int tfrc_rx_hist_alloc(struct tfrc_rx_hist *h);
diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h
index ab8848c..1fb1187 100644
--- a/net/dccp/ccids/lib/tfrc.h
+++ b/net/dccp/ccids/lib/tfrc.h
@@ -17,6 +17,9 @@
#include <linux/types.h>
#include <asm/div64.h>
#include "../../dccp.h"
+/* internal includes that this module exports: */
+#include "loss_interval.h"
+#include "packet_history.h"
#ifdef CONFIG_IP_DCCP_TFRC_DEBUG
extern int tfrc_debug;
--
1.5.3.4
^ permalink raw reply related
* [PATCH 7/7] [TFRC]: Remove previous loss intervals implementation
From: Arnaldo Carvalho de Melo @ 2007-12-12 16:36 UTC (permalink / raw)
To: David S. Miller
Cc: netdev, dccp, Gerrit Renker, Ian McDonald,
Arnaldo Carvalho de Melo
In-Reply-To: <1197477413-1456-7-git-send-email-acme@redhat.com>
From: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Signed-off-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
net/dccp/ccids/lib/loss_interval.c | 266 ------------------------------------
net/dccp/ccids/lib/loss_interval.h | 10 +--
2 files changed, 1 insertions(+), 275 deletions(-)
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c
index 8b962c1..849e181 100644
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -14,15 +14,6 @@
#include <net/sock.h>
#include "tfrc.h"
-#define DCCP_LI_HIST_IVAL_F_LENGTH 8
-
-struct dccp_li_hist_entry {
- struct list_head dccplih_node;
- u64 dccplih_seqno:48,
- dccplih_win_count:4;
- u32 dccplih_interval;
-};
-
static struct kmem_cache *tfrc_lh_slab __read_mostly;
/* Loss Interval weights from [RFC 3448, 5.4], scaled by 10 */
static const int tfrc_lh_weights[NINTERVAL] = { 10, 10, 10, 10, 8, 6, 4, 2 };
@@ -71,77 +62,6 @@ void tfrc_lh_cleanup(struct tfrc_loss_hist *lh)
}
EXPORT_SYMBOL_GPL(tfrc_lh_cleanup);
-static struct kmem_cache *dccp_li_cachep __read_mostly;
-
-static inline struct dccp_li_hist_entry *dccp_li_hist_entry_new(const gfp_t prio)
-{
- return kmem_cache_alloc(dccp_li_cachep, prio);
-}
-
-static inline void dccp_li_hist_entry_delete(struct dccp_li_hist_entry *entry)
-{
- if (entry != NULL)
- kmem_cache_free(dccp_li_cachep, entry);
-}
-
-void dccp_li_hist_purge(struct list_head *list)
-{
- struct dccp_li_hist_entry *entry, *next;
-
- list_for_each_entry_safe(entry, next, list, dccplih_node) {
- list_del_init(&entry->dccplih_node);
- kmem_cache_free(dccp_li_cachep, entry);
- }
-}
-
-EXPORT_SYMBOL_GPL(dccp_li_hist_purge);
-
-/* Weights used to calculate loss event rate */
-/*
- * These are integers as per section 8 of RFC3448. We can then divide by 4 *
- * when we use it.
- */
-static const int dccp_li_hist_w[DCCP_LI_HIST_IVAL_F_LENGTH] = {
- 4, 4, 4, 4, 3, 2, 1, 1,
-};
-
-u32 dccp_li_hist_calc_i_mean(struct list_head *list)
-{
- struct dccp_li_hist_entry *li_entry, *li_next;
- int i = 0;
- u32 i_tot;
- u32 i_tot0 = 0;
- u32 i_tot1 = 0;
- u32 w_tot = 0;
-
- list_for_each_entry_safe(li_entry, li_next, list, dccplih_node) {
- if (li_entry->dccplih_interval != ~0U) {
- i_tot0 += li_entry->dccplih_interval * dccp_li_hist_w[i];
- w_tot += dccp_li_hist_w[i];
- if (i != 0)
- i_tot1 += li_entry->dccplih_interval * dccp_li_hist_w[i - 1];
- }
-
-
- if (++i > DCCP_LI_HIST_IVAL_F_LENGTH)
- break;
- }
-
- if (i != DCCP_LI_HIST_IVAL_F_LENGTH)
- return 0;
-
- i_tot = max(i_tot0, i_tot1);
-
- if (!w_tot) {
- DCCP_WARN("w_tot = 0\n");
- return 1;
- }
-
- return i_tot / w_tot;
-}
-
-EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean);
-
static void tfrc_lh_calc_i_mean(struct tfrc_loss_hist *lh)
{
u32 i_i, i_tot0 = 0, i_tot1 = 0, w_tot = 0;
@@ -201,192 +121,6 @@ u8 tfrc_lh_update_i_mean(struct tfrc_loss_hist *lh, struct sk_buff *skb)
}
EXPORT_SYMBOL_GPL(tfrc_lh_update_i_mean);
-static int dccp_li_hist_interval_new(struct list_head *list,
- const u64 seq_loss, const u8 win_loss)
-{
- struct dccp_li_hist_entry *entry;
- int i;
-
- for (i = 0; i < DCCP_LI_HIST_IVAL_F_LENGTH; i++) {
- entry = dccp_li_hist_entry_new(GFP_ATOMIC);
- if (entry == NULL) {
- dccp_li_hist_purge(list);
- DCCP_BUG("loss interval list entry is NULL");
- return 0;
- }
- entry->dccplih_interval = ~0;
- list_add(&entry->dccplih_node, list);
- }
-
- entry->dccplih_seqno = seq_loss;
- entry->dccplih_win_count = win_loss;
- return 1;
-}
-
-/* calculate first loss interval
- *
- * returns estimated loss interval in usecs */
-static u32 dccp_li_calc_first_li(struct sock *sk,
- struct list_head *hist_list,
- ktime_t last_feedback,
- u16 s, u32 bytes_recv,
- u32 previous_x_recv)
-{
-/*
- * FIXME:
- * Will be rewritten in the upcoming new loss intervals code.
- * Has to be commented ou because it relies on the old rx history
- * data structures
- */
-#if 0
- struct tfrc_rx_hist_entry *entry, *next, *tail = NULL;
- u32 x_recv, p;
- suseconds_t rtt, delta;
- ktime_t tstamp = ktime_set(0, 0);
- int interval = 0;
- int win_count = 0;
- int step = 0;
- u64 fval;
-
- list_for_each_entry_safe(entry, next, hist_list, tfrchrx_node) {
- if (tfrc_rx_hist_entry_data_packet(entry)) {
- tail = entry;
-
- switch (step) {
- case 0:
- tstamp = entry->tfrchrx_tstamp;
- win_count = entry->tfrchrx_ccval;
- step = 1;
- break;
- case 1:
- interval = win_count - entry->tfrchrx_ccval;
- if (interval < 0)
- interval += TFRC_WIN_COUNT_LIMIT;
- if (interval > 4)
- goto found;
- break;
- }
- }
- }
-
- if (unlikely(step == 0)) {
- DCCP_WARN("%s(%p), packet history has no data packets!\n",
- dccp_role(sk), sk);
- return ~0;
- }
-
- if (unlikely(interval == 0)) {
- DCCP_WARN("%s(%p), Could not find a win_count interval > 0. "
- "Defaulting to 1\n", dccp_role(sk), sk);
- interval = 1;
- }
-found:
- if (!tail) {
- DCCP_CRIT("tail is null\n");
- return ~0;
- }
-
- delta = ktime_us_delta(tstamp, tail->tfrchrx_tstamp);
- DCCP_BUG_ON(delta < 0);
-
- rtt = delta * 4 / interval;
- dccp_pr_debug("%s(%p), approximated RTT to %dus\n",
- dccp_role(sk), sk, (int)rtt);
-
- /*
- * Determine the length of the first loss interval via inverse lookup.
- * Assume that X_recv can be computed by the throughput equation
- * s
- * X_recv = --------
- * R * fval
- * Find some p such that f(p) = fval; return 1/p [RFC 3448, 6.3.1].
- */
- if (rtt == 0) { /* would result in divide-by-zero */
- DCCP_WARN("RTT==0\n");
- return ~0;
- }
-
- delta = ktime_us_delta(ktime_get_real(), last_feedback);
- DCCP_BUG_ON(delta <= 0);
-
- x_recv = scaled_div32(bytes_recv, delta);
- if (x_recv == 0) { /* would also trigger divide-by-zero */
- DCCP_WARN("X_recv==0\n");
- if (previous_x_recv == 0) {
- DCCP_BUG("stored value of X_recv is zero");
- return ~0;
- }
- x_recv = previous_x_recv;
- }
-
- fval = scaled_div(s, rtt);
- fval = scaled_div32(fval, x_recv);
- p = tfrc_calc_x_reverse_lookup(fval);
-
- dccp_pr_debug("%s(%p), receive rate=%u bytes/s, implied "
- "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
-
- if (p != 0)
- return 1000000 / p;
-#endif
- return ~0;
-}
-
-void dccp_li_update_li(struct sock *sk,
- struct list_head *li_hist_list,
- struct list_head *hist_list,
- ktime_t last_feedback, u16 s, u32 bytes_recv,
- u32 previous_x_recv, u64 seq_loss, u8 win_loss)
-{
- struct dccp_li_hist_entry *head;
- u64 seq_temp;
-
- if (list_empty(li_hist_list)) {
- if (!dccp_li_hist_interval_new(li_hist_list, seq_loss,
- win_loss))
- return;
-
- head = list_entry(li_hist_list->next, struct dccp_li_hist_entry,
- dccplih_node);
- head->dccplih_interval = dccp_li_calc_first_li(sk, hist_list,
- last_feedback,
- s, bytes_recv,
- previous_x_recv);
- } else {
- struct dccp_li_hist_entry *entry;
- struct list_head *tail;
-
- head = list_entry(li_hist_list->next, struct dccp_li_hist_entry,
- dccplih_node);
- /* FIXME win count check removed as was wrong */
- /* should make this check with receive history */
- /* and compare there as per section 10.2 of RFC4342 */
-
- /* new loss event detected */
- /* calculate last interval length */
- seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss);
- entry = dccp_li_hist_entry_new(GFP_ATOMIC);
-
- if (entry == NULL) {
- DCCP_BUG("out of memory - can not allocate entry");
- return;
- }
-
- list_add(&entry->dccplih_node, li_hist_list);
-
- tail = li_hist_list->prev;
- list_del(tail);
- kmem_cache_free(dccp_li_cachep, tail);
-
- /* Create the newest interval */
- entry->dccplih_seqno = seq_loss;
- entry->dccplih_interval = seq_temp;
- entry->dccplih_win_count = win_loss;
- }
-}
-
-EXPORT_SYMBOL_GPL(dccp_li_update_li);
-
/* Determine if `new_loss' does begin a new loss interval [RFC 4342, 10.2] */
static inline u8 tfrc_lh_is_new_loss(struct tfrc_loss_interval *cur,
struct tfrc_rx_hist_entry *new_loss)
diff --git a/net/dccp/ccids/lib/loss_interval.h b/net/dccp/ccids/lib/loss_interval.h
index 5e3c5c5..246018a 100644
--- a/net/dccp/ccids/lib/loss_interval.h
+++ b/net/dccp/ccids/lib/loss_interval.h
@@ -65,19 +65,11 @@ static inline u8 tfrc_lh_length(struct tfrc_loss_hist *lh)
return min(lh->counter, (u8)LIH_SIZE);
}
-extern void dccp_li_hist_purge(struct list_head *list);
struct tfrc_rx_hist;
+
extern int tfrc_lh_interval_add(struct tfrc_loss_hist *, struct tfrc_rx_hist *,
u32 (*first_li)(struct sock *), struct sock *);
extern u8 tfrc_lh_update_i_mean(struct tfrc_loss_hist *lh, struct sk_buff *);
extern void tfrc_lh_cleanup(struct tfrc_loss_hist *lh);
-extern u32 dccp_li_hist_calc_i_mean(struct list_head *list);
-
-extern void dccp_li_update_li(struct sock *sk,
- struct list_head *li_hist_list,
- struct list_head *hist_list,
- ktime_t last_feedback, u16 s,
- u32 bytes_recv, u32 previous_x_recv,
- u64 seq_loss, u8 win_loss);
#endif /* _DCCP_LI_HIST_ */
--
1.5.3.4
^ permalink raw reply related
* [PATCH 6/7] [CCID3]: Interface CCID3 code with newer Loss Intervals Database
From: Arnaldo Carvalho de Melo @ 2007-12-12 16:36 UTC (permalink / raw)
To: David S. Miller
Cc: netdev, dccp, Gerrit Renker, Ian McDonald,
Arnaldo Carvalho de Melo
In-Reply-To: <1197477413-1456-6-git-send-email-acme@redhat.com>
From: Gerrit Renker <gerrit@erg.abdn.ac.uk>
This hooks up the TFRC Loss Interval database with CCID 3 packet reception.
In addition, it makes the CCID-specific computation of the first loss
interval (which requires access to all the guts of CCID3) local to ccid3.c.
The patch also fixes an omission in the DCCP code, that of a default /
fallback RTT value (defined in section 3.4 of RFC 4340 as 0.2 sec); while
at it, the upper bound of 4 seconds for an RTT sample has been reduced to
match the initial TCP RTO value of 3 seconds from[RFC 1122, 4.2.3.1].
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Signed-off-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
net/dccp/ccids/ccid3.c | 72 ++++++++++++++++++++++++++++++------
net/dccp/ccids/ccid3.h | 10 ++--
net/dccp/ccids/lib/loss_interval.c | 18 ++++----
net/dccp/ccids/lib/tfrc.c | 10 ++--
net/dccp/dccp.h | 7 ++-
5 files changed, 84 insertions(+), 33 deletions(-)
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index b92069b..a818a1e 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -1,6 +1,7 @@
/*
* net/dccp/ccids/ccid3.c
*
+ * Copyright (c) 2007 The University of Aberdeen, Scotland, UK
* Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
* Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
*
@@ -33,11 +34,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include "../ccid.h"
#include "../dccp.h"
-#include "lib/packet_history.h"
-#include "lib/loss_interval.h"
-#include "lib/tfrc.h"
#include "ccid3.h"
#include <asm/unaligned.h>
@@ -757,6 +754,46 @@ static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
return 0;
}
+/** ccid3_first_li - Implements [RFC 3448, 6.3.1]
+ *
+ * Determine the length of the first loss interval via inverse lookup.
+ * Assume that X_recv can be computed by the throughput equation
+ * s
+ * X_recv = --------
+ * R * fval
+ * Find some p such that f(p) = fval; return 1/p (scaled).
+ */
+static u32 ccid3_first_li(struct sock *sk)
+{
+ struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
+ u32 x_recv, p, delta;
+ u64 fval;
+
+ if (hcrx->ccid3hcrx_rtt == 0) {
+ DCCP_WARN("No RTT estimate available, using fallback RTT\n");
+ hcrx->ccid3hcrx_rtt = DCCP_FALLBACK_RTT;
+ }
+
+ delta = ktime_to_us(net_timedelta(hcrx->ccid3hcrx_tstamp_last_feedback));
+ x_recv = scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);
+ if (x_recv == 0) { /* would also trigger divide-by-zero */
+ DCCP_WARN("X_recv==0\n");
+ if ((x_recv = hcrx->ccid3hcrx_x_recv) == 0) {
+ DCCP_BUG("stored value of X_recv is zero");
+ return ~0U;
+ }
+ }
+
+ fval = scaled_div(hcrx->ccid3hcrx_s, hcrx->ccid3hcrx_rtt);
+ fval = scaled_div32(fval, x_recv);
+ p = tfrc_calc_x_reverse_lookup(fval);
+
+ ccid3_pr_debug("%s(%p), receive rate=%u bytes/s, implied "
+ "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
+
+ return p == 0 ? ~0U : scaled_div(1, p);
+}
+
static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
{
struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
@@ -794,6 +831,14 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
/*
* Handle pending losses and otherwise check for new loss
*/
+ if (tfrc_rx_hist_loss_pending(&hcrx->ccid3hcrx_hist) &&
+ tfrc_rx_handle_loss(&hcrx->ccid3hcrx_hist,
+ &hcrx->ccid3hcrx_li_hist,
+ skb, ndp, ccid3_first_li, sk) ) {
+ do_feedback = CCID3_FBACK_PARAM_CHANGE;
+ goto done_receiving;
+ }
+
if (tfrc_rx_hist_new_loss_indicated(&hcrx->ccid3hcrx_hist, skb, ndp))
goto update_records;
@@ -803,7 +848,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
if (unlikely(!is_data_packet))
goto update_records;
- if (list_empty(&hcrx->ccid3hcrx_li_hist)) { /* no loss so far: p = 0 */
+ if (!tfrc_lh_is_initialised(&hcrx->ccid3hcrx_li_hist)) {
const u32 sample = tfrc_rx_hist_sample_rtt(&hcrx->ccid3hcrx_hist, skb);
/*
* Empty loss history: no loss so far, hence p stays 0.
@@ -812,6 +857,13 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
*/
if (sample != 0)
hcrx->ccid3hcrx_rtt = tfrc_ewma(hcrx->ccid3hcrx_rtt, sample, 9);
+
+ } else if (tfrc_lh_update_i_mean(&hcrx->ccid3hcrx_li_hist, skb)) {
+ /*
+ * Step (3) of [RFC 3448, 6.1]: Recompute I_mean and, if I_mean
+ * has decreased (resp. p has increased), send feedback now.
+ */
+ do_feedback = CCID3_FBACK_PARAM_CHANGE;
}
/*
@@ -823,6 +875,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
update_records:
tfrc_rx_hist_add_packet(&hcrx->ccid3hcrx_hist, skb, ndp);
+done_receiving:
if (do_feedback)
ccid3_hc_rx_send_feedback(sk, skb, do_feedback);
}
@@ -831,10 +884,8 @@ static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
{
struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid);
- ccid3_pr_debug("entry\n");
-
hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
- INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist);
+ tfrc_lh_init(&hcrx->ccid3hcrx_li_hist);
return tfrc_rx_hist_alloc(&hcrx->ccid3hcrx_hist);
}
@@ -844,11 +895,8 @@ static void ccid3_hc_rx_exit(struct sock *sk)
ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM);
- /* Empty packet history */
tfrc_rx_hist_purge(&hcrx->ccid3hcrx_hist);
-
- /* Empty loss interval history */
- dccp_li_hist_purge(&hcrx->ccid3hcrx_li_hist);
+ tfrc_lh_cleanup(&hcrx->ccid3hcrx_li_hist);
}
static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index 6ceeb80..e9f6ff4 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -41,7 +41,7 @@
#include <linux/list.h>
#include <linux/types.h>
#include <linux/tfrc.h>
-#include "lib/packet_history.h"
+#include "lib/tfrc.h"
#include "../ccid.h"
/* Two seconds as per RFC 3448 4.2 */
@@ -141,8 +141,8 @@ enum ccid3_hc_rx_states {
* @ccid3hcrx_bytes_recv - Total sum of DCCP payload bytes
* @ccid3hcrx_tstamp_last_feedback - Time at which last feedback was sent
* @ccid3hcrx_tstamp_last_ack - Time at which last feedback was sent
- * @ccid3hcrx_hist - Packet history
- * @ccid3hcrx_li_hist - Loss Interval History
+ * @ccid3hcrx_hist - Packet history (loss detection + RTT sampling)
+ * @ccid3hcrx_li_hist - Loss Interval database
* @ccid3hcrx_s - Received packet size in bytes
* @ccid3hcrx_pinv - Inverse of Loss Event Rate (RFC 4342, sec. 8.5)
*/
@@ -156,9 +156,9 @@ struct ccid3_hc_rx_sock {
u32 ccid3hcrx_bytes_recv;
ktime_t ccid3hcrx_tstamp_last_feedback;
struct tfrc_rx_hist ccid3hcrx_hist;
- struct list_head ccid3hcrx_li_hist;
+ struct tfrc_loss_hist ccid3hcrx_li_hist;
u16 ccid3hcrx_s;
- u32 ccid3hcrx_pinv;
+#define ccid3hcrx_pinv ccid3hcrx_li_hist.i_mean
};
static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk)
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c
index 39980d1..8b962c1 100644
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -435,18 +435,18 @@ int tfrc_lh_interval_add(struct tfrc_loss_hist *lh, struct tfrc_rx_hist *rh,
}
EXPORT_SYMBOL_GPL(tfrc_lh_interval_add);
-int __init dccp_li_init(void)
+int __init tfrc_li_init(void)
{
- dccp_li_cachep = kmem_cache_create("dccp_li_hist",
- sizeof(struct dccp_li_hist_entry),
- 0, SLAB_HWCACHE_ALIGN, NULL);
- return dccp_li_cachep == NULL ? -ENOBUFS : 0;
+ tfrc_lh_slab = kmem_cache_create("tfrc_li_hist",
+ sizeof(struct tfrc_loss_interval), 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+ return tfrc_lh_slab == NULL ? -ENOBUFS : 0;
}
-void dccp_li_exit(void)
+void tfrc_li_exit(void)
{
- if (dccp_li_cachep != NULL) {
- kmem_cache_destroy(dccp_li_cachep);
- dccp_li_cachep = NULL;
+ if (tfrc_lh_slab != NULL) {
+ kmem_cache_destroy(tfrc_lh_slab);
+ tfrc_lh_slab = NULL;
}
}
diff --git a/net/dccp/ccids/lib/tfrc.c b/net/dccp/ccids/lib/tfrc.c
index 20763fa..d1dfbb8 100644
--- a/net/dccp/ccids/lib/tfrc.c
+++ b/net/dccp/ccids/lib/tfrc.c
@@ -19,12 +19,12 @@ extern void tfrc_tx_packet_history_exit(void);
extern int tfrc_rx_packet_history_init(void);
extern void tfrc_rx_packet_history_exit(void);
-extern int dccp_li_init(void);
-extern void dccp_li_exit(void);
+extern int tfrc_li_init(void);
+extern void tfrc_li_exit(void);
static int __init tfrc_module_init(void)
{
- int rc = dccp_li_init();
+ int rc = tfrc_li_init();
if (rc)
goto out;
@@ -41,7 +41,7 @@ static int __init tfrc_module_init(void)
out_free_tx_history:
tfrc_tx_packet_history_exit();
out_free_loss_intervals:
- dccp_li_exit();
+ tfrc_li_exit();
out:
return rc;
}
@@ -50,7 +50,7 @@ static void __exit tfrc_module_exit(void)
{
tfrc_rx_packet_history_exit();
tfrc_tx_packet_history_exit();
- dccp_li_exit();
+ tfrc_li_exit();
}
module_init(tfrc_module_init);
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index f4a5ea1..07dcbe7 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -74,9 +74,12 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo);
#define DCCP_RTO_MAX ((unsigned)(120 * HZ)) /* FIXME: using TCP value */
-/* bounds for sampled RTT values from packet exchanges (in usec) */
+/*
+ * RTT sampling: sanity bounds and fallback RTT value from RFC 4340, section 3.4
+ */
#define DCCP_SANE_RTT_MIN 100
-#define DCCP_SANE_RTT_MAX (4 * USEC_PER_SEC)
+#define DCCP_FALLBACK_RTT (USEC_PER_SEC / 5)
+#define DCCP_SANE_RTT_MAX (3 * USEC_PER_SEC)
/* Maximal interval between probes for local resources. */
#define DCCP_RESOURCE_PROBE_INTERVAL ((unsigned)(HZ / 2U))
--
1.5.3.4
^ permalink raw reply related
* [PATCHES 0/7]: DCCP patches for 2.6.25
From: Arnaldo Carvalho de Melo @ 2007-12-12 16:36 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, dccp
Hi David,
Please consider pulling from:
master.kernel.org:/pub/scm/linux/kernel/git/acme/net-2.6.25
Best Regards,
- Arnaldo
b/net/dccp/ccids/ccid3.c | 2
b/net/dccp/ccids/ccid3.h | 5
b/net/dccp/ccids/lib/loss_interval.c | 161 ++++++++++++++++++-
b/net/dccp/ccids/lib/loss_interval.h | 56 ++++++
b/net/dccp/ccids/lib/packet_history.c | 68 +++-----
b/net/dccp/ccids/lib/packet_history.h | 36 ++++
b/net/dccp/ccids/lib/tfrc.c | 32 ++-
b/net/dccp/ccids/lib/tfrc.h | 4
b/net/dccp/dccp.h | 8
net/dccp/ccids/ccid3.c | 72 +++++++-
net/dccp/ccids/ccid3.h | 10 -
net/dccp/ccids/lib/loss_interval.c | 284 +---------------------------------
net/dccp/ccids/lib/loss_interval.h | 11 -
net/dccp/ccids/lib/packet_history.c | 279 +++++++++++++++++++++++++--------
net/dccp/ccids/lib/packet_history.h | 47 ++++-
net/dccp/ccids/lib/tfrc.c | 10 -
16 files changed, 643 insertions(+), 442 deletions(-)
^ permalink raw reply
* [PATCH 4/7] [CCID3]: Redundant debugging output / documentation
From: Arnaldo Carvalho de Melo @ 2007-12-12 16:36 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, dccp, Gerrit Renker, Arnaldo Carvalho de Melo
In-Reply-To: <1197477413-1456-4-git-send-email-acme@redhat.com>
From: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Each time feedback is sent two lines are printed:
ccid3_hc_rx_send_feedback: client ... - entry
ccid3_hc_rx_send_feedback: Interval ...usec, X_recv=..., 1/p=...
The first line is redundant and thus removed.
Further, documentation of ccid3_hc_rx_sock (capitalisation) is made consistent.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
net/dccp/ccids/ccid3.c | 2 --
net/dccp/ccids/ccid3.h | 4 ++--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 60fcb31..b92069b 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -685,8 +685,6 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk,
ktime_t now;
s64 delta = 0;
- ccid3_pr_debug("%s(%p) - entry \n", dccp_role(sk), sk);
-
if (unlikely(hcrx->ccid3hcrx_state == TFRC_RSTATE_TERM))
return;
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index 3c33dc6..6ceeb80 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -135,9 +135,9 @@ enum ccid3_hc_rx_states {
*
* @ccid3hcrx_x_recv - Receiver estimate of send rate (RFC 3448 4.3)
* @ccid3hcrx_rtt - Receiver estimate of rtt (non-standard)
- * @ccid3hcrx_p - current loss event rate (RFC 3448 5.4)
+ * @ccid3hcrx_p - Current loss event rate (RFC 3448 5.4)
* @ccid3hcrx_last_counter - Tracks window counter (RFC 4342, 8.1)
- * @ccid3hcrx_state - receiver state, one of %ccid3_hc_rx_states
+ * @ccid3hcrx_state - Receiver state, one of %ccid3_hc_rx_states
* @ccid3hcrx_bytes_recv - Total sum of DCCP payload bytes
* @ccid3hcrx_tstamp_last_feedback - Time at which last feedback was sent
* @ccid3hcrx_tstamp_last_ack - Time at which last feedback was sent
--
1.5.3.4
^ permalink raw reply related
* [PATCH 5/7] [TFRC]: CCID3 (and CCID4) needs to access these inlines
From: Arnaldo Carvalho de Melo @ 2007-12-12 16:36 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, dccp, Gerrit Renker, Arnaldo Carvalho de Melo
In-Reply-To: <1197477413-1456-5-git-send-email-acme@redhat.com>
From: Gerrit Renker <gerrit@erg.abdn.ac.uk>
This moves two inlines back to packet_history.h: these are not private
to packet_history.c, but are needed by CCID3/4 to detect whether a new
loss is indicated, or whether a loss is already pending.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
net/dccp/ccids/lib/packet_history.c | 26 --------------------------
net/dccp/ccids/lib/packet_history.h | 35 +++++++++++++++++++++++++++++++----
2 files changed, 31 insertions(+), 30 deletions(-)
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
index 5b10a1e..20af1a6 100644
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -191,32 +191,6 @@ int tfrc_rx_hist_duplicate(struct tfrc_rx_hist *h, struct sk_buff *skb)
}
EXPORT_SYMBOL_GPL(tfrc_rx_hist_duplicate);
-/* initialise loss detection and disable RTT sampling */
-static inline void tfrc_rx_hist_loss_indicated(struct tfrc_rx_hist *h)
-{
- h->loss_count = 1;
-}
-
-/* indicate whether previously a packet was detected missing */
-static inline int tfrc_rx_hist_loss_pending(const struct tfrc_rx_hist *h)
-{
- return h->loss_count;
-}
-
-/* any data packets missing between last reception and skb ? */
-int tfrc_rx_hist_new_loss_indicated(struct tfrc_rx_hist *h,
- const struct sk_buff *skb, u32 ndp)
-{
- int delta = dccp_delta_seqno(tfrc_rx_hist_last_rcv(h)->tfrchrx_seqno,
- DCCP_SKB_CB(skb)->dccpd_seq);
-
- if (delta > 1 && ndp < delta)
- tfrc_rx_hist_loss_indicated(h);
-
- return tfrc_rx_hist_loss_pending(h);
-}
-EXPORT_SYMBOL_GPL(tfrc_rx_hist_new_loss_indicated);
-
static void tfrc_rx_hist_swap(struct tfrc_rx_hist *h, const u8 a, const u8 b)
{
const u8 idx_a = tfrc_rx_hist_index(h, a),
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h
index 24edd8d..c7eeda4 100644
--- a/net/dccp/ccids/lib/packet_history.h
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -118,16 +118,43 @@ static inline struct tfrc_rx_hist_entry *
return h->ring[h->loss_start];
}
+/* initialise loss detection and disable RTT sampling */
+static inline void tfrc_rx_hist_loss_indicated(struct tfrc_rx_hist *h)
+{
+ h->loss_count = 1;
+}
+
+/* indicate whether previously a packet was detected missing */
+static inline int tfrc_rx_hist_loss_pending(const struct tfrc_rx_hist *h)
+{
+ return h->loss_count;
+}
+
+/* any data packets missing between last reception and skb ? */
+static inline int tfrc_rx_hist_new_loss_indicated(struct tfrc_rx_hist *h,
+ const struct sk_buff *skb,
+ u32 ndp)
+{
+ int delta = dccp_delta_seqno(tfrc_rx_hist_last_rcv(h)->tfrchrx_seqno,
+ DCCP_SKB_CB(skb)->dccpd_seq);
+
+ if (delta > 1 && ndp < delta)
+ tfrc_rx_hist_loss_indicated(h);
+
+ return tfrc_rx_hist_loss_pending(h);
+}
+
extern void tfrc_rx_hist_add_packet(struct tfrc_rx_hist *h,
const struct sk_buff *skb, const u32 ndp);
extern int tfrc_rx_hist_duplicate(struct tfrc_rx_hist *h, struct sk_buff *skb);
-extern int tfrc_rx_hist_new_loss_indicated(struct tfrc_rx_hist *h,
- const struct sk_buff *skb, u32 ndp);
+
struct tfrc_loss_hist;
-extern int tfrc_rx_handle_loss(struct tfrc_rx_hist *, struct tfrc_loss_hist *,
+extern int tfrc_rx_handle_loss(struct tfrc_rx_hist *h,
+ struct tfrc_loss_hist *lh,
struct sk_buff *skb, u32 ndp,
- u32 (*first_li)(struct sock *), struct sock *);
+ u32 (*first_li)(struct sock *sk),
+ struct sock *sk);
extern u32 tfrc_rx_hist_sample_rtt(struct tfrc_rx_hist *h,
const struct sk_buff *skb);
extern int tfrc_rx_hist_alloc(struct tfrc_rx_hist *h);
--
1.5.3.4
^ permalink raw reply related
* [PATCH 1/7] [TFRC]: Put RX/TX initialisation into tfrc.c
From: Arnaldo Carvalho de Melo @ 2007-12-12 16:36 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, dccp, Gerrit Renker, Arnaldo Carvalho de Melo
In-Reply-To: <1197477413-1456-1-git-send-email-acme@redhat.com>
From: Gerrit Renker <gerrit@erg.abdn.ac.uk>
This separates RX/TX initialisation and puts all packet history / loss intervals
initialisation into tfrc.c.
The organisation is uniform: slab declaration -> {rx,tx}_init() -> {rx,tx}_exit()
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
net/dccp/ccids/lib/packet_history.c | 68 ++++++++++++++++------------------
net/dccp/ccids/lib/tfrc.c | 31 ++++++++++++----
2 files changed, 55 insertions(+), 44 deletions(-)
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
index af44082..727b17d 100644
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -57,6 +57,22 @@ struct tfrc_tx_hist_entry {
*/
static struct kmem_cache *tfrc_tx_hist_slab;
+int __init tfrc_tx_packet_history_init(void)
+{
+ tfrc_tx_hist_slab = kmem_cache_create("tfrc_tx_hist",
+ sizeof(struct tfrc_tx_hist_entry),
+ 0, SLAB_HWCACHE_ALIGN, NULL);
+ return tfrc_tx_hist_slab == NULL ? -ENOBUFS : 0;
+}
+
+void tfrc_tx_packet_history_exit(void)
+{
+ if (tfrc_tx_hist_slab != NULL) {
+ kmem_cache_destroy(tfrc_tx_hist_slab);
+ tfrc_tx_hist_slab = NULL;
+ }
+}
+
static struct tfrc_tx_hist_entry *
tfrc_tx_hist_find_entry(struct tfrc_tx_hist_entry *head, u64 seqno)
{
@@ -119,6 +135,22 @@ EXPORT_SYMBOL_GPL(tfrc_tx_hist_rtt);
*/
static struct kmem_cache *tfrc_rx_hist_slab;
+int __init tfrc_rx_packet_history_init(void)
+{
+ tfrc_rx_hist_slab = kmem_cache_create("tfrc_rxh_cache",
+ sizeof(struct tfrc_rx_hist_entry),
+ 0, SLAB_HWCACHE_ALIGN, NULL);
+ return tfrc_rx_hist_slab == NULL ? -ENOBUFS : 0;
+}
+
+void tfrc_rx_packet_history_exit(void)
+{
+ if (tfrc_rx_hist_slab != NULL) {
+ kmem_cache_destroy(tfrc_rx_hist_slab);
+ tfrc_rx_hist_slab = NULL;
+ }
+}
+
/**
* tfrc_rx_hist_index - index to reach n-th entry after loss_start
*/
@@ -316,39 +348,3 @@ keep_ref_for_next_time:
return sample;
}
EXPORT_SYMBOL_GPL(tfrc_rx_hist_sample_rtt);
-
-__init int packet_history_init(void)
-{
- tfrc_tx_hist_slab = kmem_cache_create("tfrc_tx_hist",
- sizeof(struct tfrc_tx_hist_entry), 0,
- SLAB_HWCACHE_ALIGN, NULL);
- if (tfrc_tx_hist_slab == NULL)
- goto out_err;
-
- tfrc_rx_hist_slab = kmem_cache_create("tfrc_rx_hist",
- sizeof(struct tfrc_rx_hist_entry), 0,
- SLAB_HWCACHE_ALIGN, NULL);
- if (tfrc_rx_hist_slab == NULL)
- goto out_free_tx;
-
- return 0;
-
-out_free_tx:
- kmem_cache_destroy(tfrc_tx_hist_slab);
- tfrc_tx_hist_slab = NULL;
-out_err:
- return -ENOBUFS;
-}
-
-void packet_history_exit(void)
-{
- if (tfrc_tx_hist_slab != NULL) {
- kmem_cache_destroy(tfrc_tx_hist_slab);
- tfrc_tx_hist_slab = NULL;
- }
-
- if (tfrc_rx_hist_slab != NULL) {
- kmem_cache_destroy(tfrc_rx_hist_slab);
- tfrc_rx_hist_slab = NULL;
- }
-}
diff --git a/net/dccp/ccids/lib/tfrc.c b/net/dccp/ccids/lib/tfrc.c
index 3a7a183..20763fa 100644
--- a/net/dccp/ccids/lib/tfrc.c
+++ b/net/dccp/ccids/lib/tfrc.c
@@ -14,27 +14,42 @@ module_param(tfrc_debug, bool, 0444);
MODULE_PARM_DESC(tfrc_debug, "Enable debug messages");
#endif
+extern int tfrc_tx_packet_history_init(void);
+extern void tfrc_tx_packet_history_exit(void);
+extern int tfrc_rx_packet_history_init(void);
+extern void tfrc_rx_packet_history_exit(void);
+
extern int dccp_li_init(void);
extern void dccp_li_exit(void);
-extern int packet_history_init(void);
-extern void packet_history_exit(void);
static int __init tfrc_module_init(void)
{
int rc = dccp_li_init();
- if (rc == 0) {
- rc = packet_history_init();
- if (rc != 0)
- dccp_li_exit();
- }
+ if (rc)
+ goto out;
+
+ rc = tfrc_tx_packet_history_init();
+ if (rc)
+ goto out_free_loss_intervals;
+ rc = tfrc_rx_packet_history_init();
+ if (rc)
+ goto out_free_tx_history;
+ return 0;
+
+out_free_tx_history:
+ tfrc_tx_packet_history_exit();
+out_free_loss_intervals:
+ dccp_li_exit();
+out:
return rc;
}
static void __exit tfrc_module_exit(void)
{
- packet_history_exit();
+ tfrc_rx_packet_history_exit();
+ tfrc_tx_packet_history_exit();
dccp_li_exit();
}
--
1.5.3.4
^ permalink raw reply related
* [PATCH 2/7] [TFRC]: Loss interval code needs the macros/inlines that were moved
From: Arnaldo Carvalho de Melo @ 2007-12-12 16:36 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, dccp, Gerrit Renker, Arnaldo Carvalho de Melo
In-Reply-To: <1197477413-1456-2-git-send-email-acme@redhat.com>
From: Gerrit Renker <gerrit@erg.abdn.ac.uk>
This moves the inlines (which were previously declared as macros) back into
packet_history.h since the loss detection code needs to be able to read entries
from the RX history in order to create the relevant loss entries: it needs at
least tfrc_rx_hist_loss_prev() and tfrc_rx_hist_last_rcv(), which in turn
require the definition of the other inlines (macros).
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
net/dccp/ccids/lib/packet_history.c | 35 -----------------------------------
net/dccp/ccids/lib/packet_history.h | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 35 insertions(+), 35 deletions(-)
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
index 727b17d..dd2cf2d 100644
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -151,23 +151,6 @@ void tfrc_rx_packet_history_exit(void)
}
}
-/**
- * tfrc_rx_hist_index - index to reach n-th entry after loss_start
- */
-static inline u8 tfrc_rx_hist_index(const struct tfrc_rx_hist *h, const u8 n)
-{
- return (h->loss_start + n) & TFRC_NDUPACK;
-}
-
-/**
- * tfrc_rx_hist_last_rcv - entry with highest-received-seqno so far
- */
-static inline struct tfrc_rx_hist_entry *
- tfrc_rx_hist_last_rcv(const struct tfrc_rx_hist *h)
-{
- return h->ring[tfrc_rx_hist_index(h, h->loss_count)];
-}
-
void tfrc_rx_hist_add_packet(struct tfrc_rx_hist *h,
const struct sk_buff *skb,
const u32 ndp)
@@ -183,24 +166,6 @@ void tfrc_rx_hist_add_packet(struct tfrc_rx_hist *h,
}
EXPORT_SYMBOL_GPL(tfrc_rx_hist_add_packet);
-/**
- * tfrc_rx_hist_entry - return the n-th history entry after loss_start
- */
-static inline struct tfrc_rx_hist_entry *
- tfrc_rx_hist_entry(const struct tfrc_rx_hist *h, const u8 n)
-{
- return h->ring[tfrc_rx_hist_index(h, n)];
-}
-
-/**
- * tfrc_rx_hist_loss_prev - entry with highest-received-seqno before loss was detected
- */
-static inline struct tfrc_rx_hist_entry *
- tfrc_rx_hist_loss_prev(const struct tfrc_rx_hist *h)
-{
- return h->ring[h->loss_start];
-}
-
/* has the packet contained in skb been seen before? */
int tfrc_rx_hist_duplicate(struct tfrc_rx_hist *h, struct sk_buff *skb)
{
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h
index 3dfd182..e58b0fc 100644
--- a/net/dccp/ccids/lib/packet_history.h
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -84,6 +84,41 @@ struct tfrc_rx_hist {
#define rtt_sample_prev loss_start
};
+/**
+ * tfrc_rx_hist_index - index to reach n-th entry after loss_start
+ */
+static inline u8 tfrc_rx_hist_index(const struct tfrc_rx_hist *h, const u8 n)
+{
+ return (h->loss_start + n) & TFRC_NDUPACK;
+}
+
+/**
+ * tfrc_rx_hist_last_rcv - entry with highest-received-seqno so far
+ */
+static inline struct tfrc_rx_hist_entry *
+ tfrc_rx_hist_last_rcv(const struct tfrc_rx_hist *h)
+{
+ return h->ring[tfrc_rx_hist_index(h, h->loss_count)];
+}
+
+/**
+ * tfrc_rx_hist_entry - return the n-th history entry after loss_start
+ */
+static inline struct tfrc_rx_hist_entry *
+ tfrc_rx_hist_entry(const struct tfrc_rx_hist *h, const u8 n)
+{
+ return h->ring[tfrc_rx_hist_index(h, n)];
+}
+
+/**
+ * tfrc_rx_hist_loss_prev - entry with highest-received-seqno before loss was detected
+ */
+static inline struct tfrc_rx_hist_entry *
+ tfrc_rx_hist_loss_prev(const struct tfrc_rx_hist *h)
+{
+ return h->ring[h->loss_start];
+}
+
extern void tfrc_rx_hist_add_packet(struct tfrc_rx_hist *h,
const struct sk_buff *skb, const u32 ndp);
--
1.5.3.4
^ permalink raw reply related
* Re: [PATCH 6/7] [NETDEV]: tehuti Fix possible causing oops of net_rx_action
From: Stephen Hemminger @ 2007-12-12 16:36 UTC (permalink / raw)
To: David Miller, joonwpark81; +Cc: netdev, linux-kernel, jgarzik, baum, andy
In-Reply-To: <20071212.072034.148833113.davem@davemloft.net>
On Wed, 12 Dec 2007 07:20:34 -0800 (PST)
David Miller <davem@davemloft.net> wrote:
> From: Stephen Hemminger <shemminger@linux-foundation.org>
> Date: Tue, 11 Dec 2007 21:39:39 -0800
>
> > On Wed, 12 Dec 2007 13:01:27 +0900
> > "Joonwoo Park" <joonwpark81@gmail.com> wrote:
> >
> > > [NETDEV]: tehuti Fix possible causing oops of net_rx_action
> > >
> > > Signed-off-by: Joonwoo Park <joonwpark81@gmail.com>
> > > ---
> > > drivers/net/tehuti.c | 2 ++
> > > 1 files changed, 2 insertions(+), 0 deletions(-)
> > >
> > > diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
> > > index 21230c9..955e749 100644
> > > --- a/drivers/net/tehuti.c
> > > +++ b/drivers/net/tehuti.c
> > > @@ -305,6 +305,8 @@ static int bdx_poll(struct napi_struct *napi, int budget)
> > >
> > > netif_rx_complete(dev, napi);
> > > bdx_enable_interrupts(priv);
> > > + if (unlikely(work_done == napi->weight))
> > > + return work_done - 1;
> > > }
> > > return work_done;
> > > }
> >
> > A better fix would be not going over budget in the first place.
>
> That's not the problem.
>
> They are not going over the budget, rather, they are hitting
> the budget yet doing netif_rx_complete() as well which is
> illegal.
>
> Unless you strictly process less than "weight" packets, you must
> not netif_rx_complete() and re-enable chip interrupts.
>
> I can't believe people are trying to fix this bug like this.
Sorry, I was looking at a different possible problem. The issue
is that if netdev_budget was set smaller (say 128) but device
weight was set larger (say 256). The new code would still allow
the device to do a full swipe (256) packets rather than only
128 as in earlier NAPI. I guess it is an okay behaviour change, because
we don't really guarantee that case.
The problem with the tehuti driver is the logic around priv->napi_stop.
That whole early stop concept should be removed since it just
duplicates the logic of netdev->weight but breaks the assumptions
in the calling netif_rx_action.
--
Stephen Hemminger <shemminger@linux-foundation.org>
^ permalink raw reply
* Re: [PATCH] IPIP: Allow rebinding the tunnel to another interface
From: Patrick McHardy @ 2007-12-12 16:33 UTC (permalink / raw)
To: Michal Schmidt; +Cc: netdev, David S. Miller, Marcela Maslanova
In-Reply-To: <20071212172933.178cf78e@brian.englab.brq.redhat.com>
Michal Schmidt wrote:
> On Wed, 12 Dec 2007 17:00:14 +0100
> Patrick McHardy <kaber@trash.net> wrote:
>
>> If you change dev->iflink this should trigger a rtnetlink
>> notification.
>
> OK, I've added netdev_state_change(dev). Here's the new patch.
Looks good to me, thanks.
^ permalink raw reply
* Re: [kvm-devel] [virtio-net][PATCH] Don't arm tx hrtimer with a constant 500us each transmit
From: Christian Borntraeger @ 2007-12-12 16:33 UTC (permalink / raw)
To: dor.laor; +Cc: kvm-devel, Rusty Russell, netdev, virtualization
In-Reply-To: <475FED88.7020304@qumranet.com>
Am Mittwoch, 12. Dezember 2007 schrieb Dor Laor:
> Christian Borntraeger wrote:
> >
> > Am Mittwoch, 12. Dezember 2007 schrieb Dor Laor:
> > > --- a/drivers/net/virtio_net.c
> > > +++ b/drivers/net/virtio_net.c
> > > @@ -406,10 +405,10 @@ again:
> >
> > Hmm, while I agree in general with the patch, I fail to find the proper
> > version of virtio_net where this patch applies. I tried kvm.git and
> > linux-2.6.git from kernel.org. Can you give me a pointer to the
repository
> > where you work on virtio?
> >
> Sorry for that, I added some debug prints of my one.
> Here it is: *git clone
> git*://kvm.*qumranet*.com/home/*dor*/src/linux-2.6-nv use branch 'virtio'.
Ah, ok. I will look into that branch.
> BTW: what git repository do you use?
I use Avis git from kernel.org:
git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm
Christian
^ permalink raw reply
* Re: [PATCH 4/4] sky2: rtnl_lock out of loop will be faster
From: Stephen Hemminger @ 2007-12-12 16:30 UTC (permalink / raw)
To: Wang Chen; +Cc: David S. Miller, Jeff Garzik, netdev, Wang Chen
In-Reply-To: <475FA0C1.8000701@cn.fujitsu.com>
On Wed, 12 Dec 2007 16:50:09 +0800
Wang Chen <wangchen@cn.fujitsu.com> wrote:
> [PATCH 4/4] [NETDEV] sky2: rtnl_lock out of loop will be faster
>
> Before this patch, it gets and releases the lock at each
> iteration of the loop. Changing unregister_netdev to
> unregister_netdevice and locking outside of the loop will
> be faster for this approach.
>
> Signed-off-by: Wang Chen <wangchen@cn.fujitsu.com>
> ---
> sky2.c | 4 +++-
> 1 files changed, 3 insertions(+), 1 deletion(-)
>
> --- linux-2.6.24.rc5.org/drivers/net/sky2.c 2007-12-12 10:19:43.000000000 +0800
> +++ linux-2.6.24.rc5/drivers/net/sky2.c 2007-12-12 15:23:37.000000000 +0800
> @@ -4270,8 +4270,10 @@ static void __devexit sky2_remove(struct
> del_timer_sync(&hw->watchdog_timer);
> cancel_work_sync(&hw->restart_work);
>
> + rtnl_lock();
> for (i = hw->ports-1; i >= 0; --i)
> - unregister_netdev(hw->dev[i]);
> + unregister_netdevice(hw->dev[i]);
> + rtnl_unlock();
>
> sky2_write32(hw, B0_IMSK, 0);
>
Umm, okay but it doesn't matter really, there can only be 2 ports and
90+% of the boards only have one port. So why bother??
--
Stephen Hemminger <shemminger@linux-foundation.org>
^ permalink raw reply
* Re: [PATCH] IPIP: Allow rebinding the tunnel to another interface
From: Michal Schmidt @ 2007-12-12 16:29 UTC (permalink / raw)
To: Patrick McHardy; +Cc: netdev, David S. Miller, Marcela Maslanova
In-Reply-To: <4760058E.5080403@trash.net>
On Wed, 12 Dec 2007 17:00:14 +0100
Patrick McHardy <kaber@trash.net> wrote:
> If you change dev->iflink this should trigger a rtnetlink
> notification.
OK, I've added netdev_state_change(dev). Here's the new patch.
Once created, an IP tunnel can't be bound to another device.
(reported as https://bugzilla.redhat.com/show_bug.cgi?id=419671)
To reproduce:
# create a tunnel:
ip tunnel add tunneltest0 mode ipip remote 10.0.0.1 dev eth0
# try to change the bounding device from eth0 to eth1:
ip tunnel change tunneltest0 dev eth1
# show the result:
ip tunnel show tunneltest0
tunneltest0: ip/ip remote 10.0.0.1 local any dev eth0 ttl inherit
Notice the bound device has not changed from eth0 to eth1.
This patch fixes it. When changing the binding, it also recalculates the
MTU according to the new bound device's MTU.
If the change is acceptable, I'll do the same for GRE and SIT tunnels.
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 8c2b2b0..160535b 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -651,6 +651,40 @@ tx_error:
return 0;
}
+static void ipip_tunnel_bind_dev(struct net_device *dev)
+{
+ struct net_device *tdev = NULL;
+ struct ip_tunnel *tunnel;
+ struct iphdr *iph;
+
+ tunnel = netdev_priv(dev);
+ iph = &tunnel->parms.iph;
+
+ if (iph->daddr) {
+ struct flowi fl = { .oif = tunnel->parms.link,
+ .nl_u = { .ip4_u =
+ { .daddr = iph->daddr,
+ .saddr = iph->saddr,
+ .tos = RT_TOS(iph->tos) } },
+ .proto = IPPROTO_IPIP };
+ struct rtable *rt;
+ if (!ip_route_output_key(&rt, &fl)) {
+ tdev = rt->u.dst.dev;
+ ip_rt_put(rt);
+ }
+ dev->flags |= IFF_POINTOPOINT;
+ }
+
+ if (!tdev && tunnel->parms.link)
+ tdev = __dev_get_by_index(&init_net, tunnel->parms.link);
+
+ if (tdev) {
+ dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
+ dev->mtu = tdev->mtu - sizeof(struct iphdr);
+ }
+ dev->iflink = tunnel->parms.link;
+}
+
static int
ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
{
@@ -723,6 +757,11 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
t->parms.iph.ttl = p.iph.ttl;
t->parms.iph.tos = p.iph.tos;
t->parms.iph.frag_off = p.iph.frag_off;
+ if (t->parms.link != p.link) {
+ t->parms.link = p.link;
+ ipip_tunnel_bind_dev(dev);
+ netdev_state_change(dev);
+ }
}
if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
err = -EFAULT;
@@ -791,12 +830,9 @@ static void ipip_tunnel_setup(struct net_device *dev)
static int ipip_tunnel_init(struct net_device *dev)
{
- struct net_device *tdev = NULL;
struct ip_tunnel *tunnel;
- struct iphdr *iph;
tunnel = netdev_priv(dev);
- iph = &tunnel->parms.iph;
tunnel->dev = dev;
strcpy(tunnel->parms.name, dev->name);
@@ -804,29 +840,7 @@ static int ipip_tunnel_init(struct net_device *dev)
memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
- if (iph->daddr) {
- struct flowi fl = { .oif = tunnel->parms.link,
- .nl_u = { .ip4_u =
- { .daddr = iph->daddr,
- .saddr = iph->saddr,
- .tos = RT_TOS(iph->tos) } },
- .proto = IPPROTO_IPIP };
- struct rtable *rt;
- if (!ip_route_output_key(&rt, &fl)) {
- tdev = rt->u.dst.dev;
- ip_rt_put(rt);
- }
- dev->flags |= IFF_POINTOPOINT;
- }
-
- if (!tdev && tunnel->parms.link)
- tdev = __dev_get_by_index(&init_net, tunnel->parms.link);
-
- if (tdev) {
- dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
- dev->mtu = tdev->mtu - sizeof(struct iphdr);
- }
- dev->iflink = tunnel->parms.link;
+ ipip_tunnel_bind_dev(dev);
return 0;
}
^ permalink raw reply related
* Re: "ip neigh show" not showing arp cache entries?
From: Chris Friesen @ 2007-12-12 16:21 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel
In-Reply-To: <475D7D70.5030502@nortel.com>
I retested it on an x86 machine and am seeing similar problems.
First, "arp" gives the arp table as expected:
root@typhoon-base-unit0:/tftpboot/cnp/0-0-5-0/0-0-5-0> arp -n
Address HWtype HWaddress Flags Mask
Iface
172.24.0.9 ether 00:03:CC:51:06:5E C
bond0
10.41.18.101 ether 00:0E:0C:5E:95:BD C
eth6
172.24.137.0 ether 00:C0:8B:08:E4:88 C
bond0
172.24.136.0 ether 00:C0:8B:07:B3:7E C
bond0
10.41.18.1 ether 00:00:5E:00:01:01 C
eth6
172.24.0.5 ether 00:01:AF:15:E0:6A C
bond0
172.24.0.13 ether 00:0E:0C:85:FD:D2 C
bond0
172.24.0.3 ether 00:01:AF:14:C8:CC C
bond0
172.24.132.1 ether 00:01:AF:14:E9:88 C
bond0
172.24.0.7 ether 00:07:E9:41:4B:B4 C
bond0
192.168.24.81 ether 00:01:AF:14:E9:8A C
bond2
"ip neigh show" gives nothing, but if I search for specific addresses
from the arp table listing they show up:
root@typhoon-base-unit0:/tftpboot/cnp/0-0-5-0/0-0-5-0> ip neigh show
root@typhoon-base-unit0:/tftpboot/cnp/0-0-5-0/0-0-5-0> ip neigh show
172.24.0.9
172.24.0.9 dev bond0 lladdr 00:03:cc:51:06:5e DELAY
root@typhoon-base-unit0:/tftpboot/cnp/0-0-5-0/0-0-5-0> ip neigh show
10.41.18.101
10.41.18.101 dev eth6 lladdr 00:0e:0c:5e:95:bd REACHABLE
root@typhoon-base-unit0:/tftpboot/cnp/0-0-5-0/0-0-5-0> ip neigh show
172.24.137.0
172.24.137.0 dev bond0 lladdr 00:c0:8b:08:e4:88 REACHABLE
Is this expected behaviour?
Thanks,
Chris
^ permalink raw reply
* [PATCH] [IPROUTE]: Avoid overflow for larger rto_min in print_route
From: Satoru SATOH @ 2007-12-12 15:50 UTC (permalink / raw)
To: netdev
This includes a workaround for overflow while conversion of larger
rto_min (e.g. 3s) unit.
Signed-off-by: Satoru SATOH <satoru.satoh@gmail.com>
ip/iproute.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/ip/iproute.c b/ip/iproute.c
index f4200ae..fa722c6 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -510,16 +510,16 @@ int print_route(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg)
fprintf(fp, " %u",
*(unsigned*)RTA_DATA(mxrta[i]));
else {
unsigned val = *(unsigned*)RTA_DATA(mxrta[i]);
+ unsigned hz1 = hz / 1000;
- val *= 1000;
if (i == RTAX_RTT)
val /= 8;
else if (i == RTAX_RTTVAR)
val /= 4;
- if (val >= hz)
- fprintf(fp, " %ums", val/hz);
+ if (val >= hz1)
+ fprintf(fp, " %ums", val/hz1);
else
- fprintf(fp, " %.2fms", (float)val/hz);
+ fprintf(fp, " %.2fms", (float)val/hz1);
}
}
}
^ permalink raw reply related
* Re: [PATCH] IPIP: Allow rebinding the tunnel to another interface
From: Patrick McHardy @ 2007-12-12 16:00 UTC (permalink / raw)
To: Michal Schmidt; +Cc: netdev, David S. Miller, Marcela Maslanova
In-Reply-To: <20071212163451.498b5726@brian.englab.brq.redhat.com>
Michal Schmidt wrote:
> +static void ipip_tunnel_bind_dev(struct net_device *dev)
> +{
...
> + dev->iflink = tunnel->parms.link;
> +}
> +
> static int
> ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
> {
> @@ -723,6 +757,10 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
> t->parms.iph.ttl = p.iph.ttl;
> t->parms.iph.tos = p.iph.tos;
> t->parms.iph.frag_off = p.iph.frag_off;
> + if (t->parms.link != p.link) {
> + t->parms.link = p.link;
> + ipip_tunnel_bind_dev(dev);
> + }
If you change dev->iflink this should trigger a rtnetlink
notification.
^ permalink raw reply
* Re: [kvm-devel] [PATCH resent] virtio_net: Fix stalled inbound trafficon early packets
From: Dor Laor @ 2007-12-12 15:48 UTC (permalink / raw)
To: Christian Borntraeger; +Cc: Rusty Russell, kvm-devel, netdev, virtualization
In-Reply-To: <200712121239.51435.borntraeger@de.ibm.com>
Christian Borntraeger wrote:
>
> Am Mittwoch, 12. Dezember 2007 schrieb Rusty Russell:
> > On Wednesday 12 December 2007 00:16:12 Christian Borntraeger wrote:
> > > That would also work. We already have VRING_AVAIL_F_NO_INTERRUPT in
> > > virtio_ring.c - maybe we can use that. Its hidden in callback and
> > > restart handling, what about adding an explicit startup?
> >
> > Yes, I debated whether to make this a separate hook or not; the current
> > method reduces the number of function calls without having two ways of
> > disabling callbacks.
> >
> > In this case, simply starting devices with callbacks disabled and
> > renaming 'restart' to 'enable' (or something) and calling it at the
> > beginning is probably sufficient?
>
> So you suggest something like the following patch? It seems to work but
> there is still a theoretical race at startup. Therefore, I tend to agree
> with Dor that a separate hook seems prefereable, so I am not fully sure if
> the patch is the final solution:
>
I think the change below handles the race. Otherwise please detail the
use case.
>
> ps: Its ok to answer that after your vacation.
>
> ---
> drivers/block/virtio_blk.c | 3 ++-
> drivers/net/virtio_net.c | 5 ++++-
> drivers/virtio/virtio_ring.c | 9 ++++-----
> include/linux/virtio.h | 4 ++--
> 4 files changed, 12 insertions(+), 9 deletions(-)
>
> Index: kvm/drivers/virtio/virtio_ring.c
> ===================================================================
> --- kvm.orig/drivers/virtio/virtio_ring.c
> +++ kvm/drivers/virtio/virtio_ring.c
> @@ -220,7 +220,7 @@ static void *vring_get_buf(struct virtqu
> return ret;
> }
>
> -static bool vring_restart(struct virtqueue *_vq)
> +static bool vring_enable(struct virtqueue *_vq)
> {
> struct vring_virtqueue *vq = to_vvq(_vq);
>
> @@ -264,7 +264,7 @@ static struct virtqueue_ops vring_vq_ops
> .add_buf = vring_add_buf,
> .get_buf = vring_get_buf,
> .kick = vring_kick,
> - .restart = vring_restart,
> + .enable = vring_enable,
> .shutdown = vring_shutdown,
> };
>
> @@ -299,9 +299,8 @@ struct virtqueue *vring_new_virtqueue(un
> vq->in_use = false;
> #endif
>
> - /* No callback? Tell other side not to bother us. */
> - if (!callback)
> - vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
> + /* disable interrupts until we enable them */
> + vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
>
> /* Put everything in free lists. */
> vq->num_free = num;
> Index: kvm/include/linux/virtio.h
> ===================================================================
> --- kvm.orig/include/linux/virtio.h
> +++ kvm/include/linux/virtio.h
> @@ -41,7 +41,7 @@ struct virtqueue
> * vq: the struct virtqueue we're talking about.
> * len: the length written into the buffer
> * Returns NULL or the "data" token handed to add_buf.
> - * @restart: restart callbacks after callback returned false.
> + * @enable: restart callbacks after callback returned false.
> * vq: the struct virtqueue we're talking about.
> * This returns "false" (and doesn't re-enable) if there are pending
> * buffers in the queue, to avoid a race.
> @@ -65,7 +65,7 @@ struct virtqueue_ops {
>
> void *(*get_buf)(struct virtqueue *vq, unsigned int *len);
>
> - bool (*restart)(struct virtqueue *vq);
> + bool (*enable)(struct virtqueue *vq);
>
> void (*shutdown)(struct virtqueue *vq);
> };
> Index: kvm/drivers/net/virtio_net.c
> ===================================================================
> --- kvm.orig/drivers/net/virtio_net.c
> +++ kvm/drivers/net/virtio_net.c
> @@ -201,7 +201,7 @@ again:
> /* Out of packets? */
> if (received < budget) {
> netif_rx_complete(vi->dev, napi);
> - if (unlikely(!vi->rvq->vq_ops->restart(vi->rvq))
> + if (unlikely(!vi->rvq->vq_ops->enable(vi->rvq))
> && netif_rx_reschedule(vi->dev, napi))
> goto again;
> }
> @@ -292,6 +292,9 @@ static int virtnet_open(struct net_devic
> return -ENOMEM;
>
> napi_enable(&vi->napi);
> +
> + vi->rvq->vq_ops->enable(vi->rvq);
> + vi->svq->vq_ops->enable(vi->svq);
>
If you change it to:
if (!vi->rvq->vq_ops->enable(vi->rvq))
vi->rvq->vq_ops->kick(vi->rvq);
if (!vi->rvq->vq_ops->enable(vi->svq))
vi->rvq->vq_ops->kick(vi->svq);
You solve the race of packets already waiting in the queue without
triggering the irq.
The same for the block device.
Regards,
Dor.
>
> return 0;
> }
>
> Index: kvm/drivers/block/virtio_blk.c
> ===================================================================
> --- kvm.orig/drivers/block/virtio_blk.c
> +++ kvm/drivers/block/virtio_blk.c
> @@ -183,7 +183,8 @@ static int virtblk_probe(struct virtio_d
> err = PTR_ERR(vblk->vq);
> goto out_free_vblk;
> }
> -
> + /* enable interrupts */
> + vblk->vq->vq_ops->enable(vblk->vq);
> vblk->pool = mempool_create_kmalloc_pool(1,sizeof(struct
> virtblk_req));
> if (!vblk->pool) {
> err = -ENOMEM;
>
^ permalink raw reply
* [PATCH] IPIP: Allow rebinding the tunnel to another interface
From: Michal Schmidt @ 2007-12-12 15:34 UTC (permalink / raw)
To: netdev; +Cc: David S. Miller, Marcela Maslanova
Hello,
Once created, an IP tunnel can't be bound to another device.
(reported as https://bugzilla.redhat.com/show_bug.cgi?id=419671)
To reproduce:
# create a tunnel:
ip tunnel add tunneltest0 mode ipip remote 10.0.0.1 dev eth0
# try to change the bounding device from eth0 to eth1:
ip tunnel change tunneltest0 dev eth1
# show the result:
ip tunnel show tunneltest0
tunneltest0: ip/ip remote 10.0.0.1 local any dev eth0 ttl inherit
Notice the bound device has not changed from eth0 to eth1.
This patch fixes it. When changing the binding, it also recalculates the
MTU according to the new bound device's MTU.
If the change is acceptable, I'll do the same for GRE and SIT tunnels.
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 8c2b2b0..05b267b 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -651,6 +651,40 @@ tx_error:
return 0;
}
+static void ipip_tunnel_bind_dev(struct net_device *dev)
+{
+ struct net_device *tdev = NULL;
+ struct ip_tunnel *tunnel;
+ struct iphdr *iph;
+
+ tunnel = netdev_priv(dev);
+ iph = &tunnel->parms.iph;
+
+ if (iph->daddr) {
+ struct flowi fl = { .oif = tunnel->parms.link,
+ .nl_u = { .ip4_u =
+ { .daddr = iph->daddr,
+ .saddr = iph->saddr,
+ .tos = RT_TOS(iph->tos) } },
+ .proto = IPPROTO_IPIP };
+ struct rtable *rt;
+ if (!ip_route_output_key(&rt, &fl)) {
+ tdev = rt->u.dst.dev;
+ ip_rt_put(rt);
+ }
+ dev->flags |= IFF_POINTOPOINT;
+ }
+
+ if (!tdev && tunnel->parms.link)
+ tdev = __dev_get_by_index(&init_net, tunnel->parms.link);
+
+ if (tdev) {
+ dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
+ dev->mtu = tdev->mtu - sizeof(struct iphdr);
+ }
+ dev->iflink = tunnel->parms.link;
+}
+
static int
ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
{
@@ -723,6 +757,10 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
t->parms.iph.ttl = p.iph.ttl;
t->parms.iph.tos = p.iph.tos;
t->parms.iph.frag_off = p.iph.frag_off;
+ if (t->parms.link != p.link) {
+ t->parms.link = p.link;
+ ipip_tunnel_bind_dev(dev);
+ }
}
if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
err = -EFAULT;
@@ -791,12 +829,9 @@ static void ipip_tunnel_setup(struct net_device *dev)
static int ipip_tunnel_init(struct net_device *dev)
{
- struct net_device *tdev = NULL;
struct ip_tunnel *tunnel;
- struct iphdr *iph;
tunnel = netdev_priv(dev);
- iph = &tunnel->parms.iph;
tunnel->dev = dev;
strcpy(tunnel->parms.name, dev->name);
@@ -804,29 +839,7 @@ static int ipip_tunnel_init(struct net_device *dev)
memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
- if (iph->daddr) {
- struct flowi fl = { .oif = tunnel->parms.link,
- .nl_u = { .ip4_u =
- { .daddr = iph->daddr,
- .saddr = iph->saddr,
- .tos = RT_TOS(iph->tos) } },
- .proto = IPPROTO_IPIP };
- struct rtable *rt;
- if (!ip_route_output_key(&rt, &fl)) {
- tdev = rt->u.dst.dev;
- ip_rt_put(rt);
- }
- dev->flags |= IFF_POINTOPOINT;
- }
-
- if (!tdev && tunnel->parms.link)
- tdev = __dev_get_by_index(&init_net, tunnel->parms.link);
-
- if (tdev) {
- dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
- dev->mtu = tdev->mtu - sizeof(struct iphdr);
- }
- dev->iflink = tunnel->parms.link;
+ ipip_tunnel_bind_dev(dev);
return 0;
}
--
1.5.3.3
^ permalink raw reply related
* Re: [GIT PULL] SCTP bug fixes for net-2.6
From: Vlad Yasevich @ 2007-12-12 15:30 UTC (permalink / raw)
To: Jijo Chacko; +Cc: netdev, herbert, lksctp-developers
In-Reply-To: <b7f21edd0712112229l6219c835w466d8bf43390cf3a@mail.gmail.com>
Jijo Chacko wrote:
>
> Hello experts,
>
> [ sorry if my questions are irrelevent to any one of you ].
>
> I am trying to develop a frame work, where i transport all HTTP traffic
> over SCTP. On user space, i can do this easily over SCTP, BSD-style
> sockets. If i am to write a kernel module(say in-kernel web
> client/server) using kernel version of SCTP interfaces, what are the
> available calls now supported ? I see in-kernel implementation like
> NFS/RPC make kernel version of UDP and TCP _sendmsg, i don't find
> similar interfaces for SCTP..
Look at fs/dlm/lowcomms.c
All you need to do is use IPPROTO_SCTP when creating a socket in
the kernel and then I believe you can use all the same calls as TCP/UDP.
-vlad
^ permalink raw reply
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