* [PATCH 3/2] cxgb3 - Fix EEH, missing softirq blocking
From: Divy Le Ray @ 2007-12-07 2:47 UTC (permalink / raw)
To: jeff; +Cc: netdev, linux-kernel, swise
From: Divy Le Ray <divy@chelsio.com>
set_pci_drvdata() stores a pointer to the adapter,
not the net device.
Add missing softirq blocking in t3_mgmt_tx.
Signed-off-by: Divy Le Ray <divy@chlelsio.com>
---
drivers/net/cxgb3/cxgb3_main.c | 14 ++++----------
drivers/net/cxgb3/sge.c | 7 ++++++-
2 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index d1aa777..0e3dcbf 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -2408,9 +2408,7 @@ void t3_fatal_err(struct adapter *adapter)
static pci_ers_result_t t3_io_error_detected(struct pci_dev *pdev,
pci_channel_state_t state)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct port_info *pi = netdev_priv(dev);
- struct adapter *adapter = pi->adapter;
+ struct adapter *adapter = pci_get_drvdata(pdev);
int i;
/* Stop all ports */
@@ -2444,9 +2442,7 @@ static pci_ers_result_t t3_io_error_detected(struct pci_dev *pdev,
*/
static pci_ers_result_t t3_io_slot_reset(struct pci_dev *pdev)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct port_info *pi = netdev_priv(dev);
- struct adapter *adapter = pi->adapter;
+ struct adapter *adapter = pci_get_drvdata(pdev);
if (pci_enable_device(pdev)) {
dev_err(&pdev->dev,
@@ -2469,9 +2465,7 @@ static pci_ers_result_t t3_io_slot_reset(struct pci_dev *pdev)
*/
static void t3_io_resume(struct pci_dev *pdev)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct port_info *pi = netdev_priv(dev);
- struct adapter *adapter = pi->adapter;
+ struct adapter *adapter = pci_get_drvdata(pdev);
int i;
/* Restart the ports */
@@ -2491,7 +2485,7 @@ static void t3_io_resume(struct pci_dev *pdev)
if (is_offload(adapter)) {
__set_bit(OFFLOAD_DEVMAP_BIT, &adapter->registered_device_map);
- if (offload_open(dev))
+ if (offload_open(adapter->port[0]))
printk(KERN_WARNING
"Could not bring back offload capabilities\n");
}
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index cef153d..6367cee 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -1364,7 +1364,12 @@ static void restart_ctrlq(unsigned long data)
*/
int t3_mgmt_tx(struct adapter *adap, struct sk_buff *skb)
{
- return ctrl_xmit(adap, &adap->sge.qs[0].txq[TXQ_CTRL], skb);
+ int ret;
+ local_bh_disable();
+ ret = ctrl_xmit(adap, &adap->sge.qs[0].txq[TXQ_CTRL], skb);
+ local_bh_enable();
+
+ return ret;
}
/**
^ permalink raw reply related
* [PATCH 3/3] [POWERPC] MPC8349E-mITX: Vitesse 7385 PHY is not connected to the MDIO bus
From: Vitaly Bordug @ 2007-12-06 22:51 UTC (permalink / raw)
To: Paul Mackerras; +Cc: netdev, linuxppc-dev, netdev
In-Reply-To: <20071206225121.31080.86606.stgit@localhost.localdomain>
...thus use fixed-link to register proper "Fixed PHY"
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: Vitaly Bordug <vitb@kernel.crashing.org>
---
arch/powerpc/boot/dts/mpc8349emitx.dts | 11 ++---------
1 files changed, 2 insertions(+), 9 deletions(-)
diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
index 5072f6d..877ee6d 100644
--- a/arch/powerpc/boot/dts/mpc8349emitx.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
@@ -115,14 +115,6 @@
reg = <1c>;
device_type = "ethernet-phy";
};
-
- /* Vitesse 7385 */
- phy1f: ethernet-phy@1f {
- interrupt-parent = < &ipic >;
- interrupts = <12 8>;
- reg = <1f>;
- device_type = "ethernet-phy";
- };
};
ethernet@24000 {
@@ -159,7 +151,8 @@
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <23 8 24 8 25 8>;
interrupt-parent = < &ipic >;
- phy-handle = < &phy1f >;
+ /* Vitesse 7385 isn't on the MDIO bus */
+ fixed-link = <1 1 d#1000 0 0>;
linux,network-index = <1>;
};
^ permalink raw reply related
* [PATCH 2/3] [POWERPC] fsl_soc: add support for gianfar for fixed-link property
From: Vitaly Bordug @ 2007-12-06 22:51 UTC (permalink / raw)
To: Paul Mackerras; +Cc: netdev, linuxppc-dev, netdev
In-Reply-To: <20071206225121.31080.86606.stgit@localhost.localdomain>
fixed-link says: register new "Fixed/emulated PHY", i.e. PHY that
not connected to the real MDIO bus.
Signed-off-by: Vitaly Bordug <vitb@kernel.crashing.org>
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
Documentation/powerpc/booting-without-of.txt | 4 +
arch/powerpc/sysdev/fsl_soc.c | 79 ++++++++++++++++++++------
2 files changed, 66 insertions(+), 17 deletions(-)
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index e9a3cb1..9dfd308 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -1254,6 +1254,10 @@ platforms are moved over to use the flattened-device-tree model.
services interrupts for this device.
- phy-handle : The phandle for the PHY connected to this ethernet
controller.
+ - fixed-link : <a b c d e> where a is emulated phy id - choose any,
+ but unique to the all specified fixed-links, b is duplex - 0 half,
+ 1 full, c is link speed - d#10/d#100/d#1000, d is pause - 0 no
+ pause, 1 pause, e is asym_pause - 0 no asym_pause, 1 asym_pause.
Recommended properties:
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 3ace747..a008e32 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -24,6 +24,7 @@
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/phy.h>
+#include <linux/phy_fixed.h>
#include <linux/spi/spi.h>
#include <linux/fsl_devices.h>
#include <linux/fs_enet_pd.h>
@@ -130,6 +131,37 @@ u32 get_baudrate(void)
EXPORT_SYMBOL(get_baudrate);
#endif /* CONFIG_CPM2 */
+#ifdef CONFIG_FIXED_PHY
+static int __init of_add_fixed_phys(void)
+{
+ int ret;
+ struct device_node *np;
+ u32 *fixed_link;
+ struct fixed_phy_status status = {};
+
+ for_each_node_by_name(np, "ethernet") {
+ fixed_link = (u32 *)of_get_property(np, "fixed-link", NULL);
+ if (!fixed_link)
+ continue;
+
+ status.link = 1;
+ status.duplex = fixed_link[1];
+ status.speed = fixed_link[2];
+ status.pause = fixed_link[3];
+ status.asym_pause = fixed_link[4];
+
+ ret = fixed_phy_add(PHY_POLL, fixed_link[0], &status);
+ if (ret) {
+ of_node_put(np);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+arch_initcall(of_add_fixed_phys);
+#endif /* CONFIG_FIXED_PHY */
+
static int __init gfar_mdio_of_init(void)
{
struct device_node *np;
@@ -193,7 +225,6 @@ static const char *gfar_tx_intr = "tx";
static const char *gfar_rx_intr = "rx";
static const char *gfar_err_intr = "error";
-
static int __init gfar_of_init(void)
{
struct device_node *np;
@@ -277,29 +308,43 @@ static int __init gfar_of_init(void)
gfar_data.interface = PHY_INTERFACE_MODE_MII;
ph = of_get_property(np, "phy-handle", NULL);
- phy = of_find_node_by_phandle(*ph);
+ if (ph == NULL) {
+ u32 *fixed_link;
- if (phy == NULL) {
- ret = -ENODEV;
- goto unreg;
- }
+ fixed_link = (u32 *)of_get_property(np, "fixed-link",
+ NULL);
+ if (!fixed_link) {
+ ret = -ENODEV;
+ goto unreg;
+ }
- mdio = of_get_parent(phy);
+ gfar_data.bus_id = 0;
+ gfar_data.phy_id = fixed_link[0];
+ } else {
+ phy = of_find_node_by_phandle(*ph);
+
+ if (phy == NULL) {
+ ret = -ENODEV;
+ goto unreg;
+ }
+
+ mdio = of_get_parent(phy);
+
+ id = of_get_property(phy, "reg", NULL);
+ ret = of_address_to_resource(mdio, 0, &res);
+ if (ret) {
+ of_node_put(phy);
+ of_node_put(mdio);
+ goto unreg;
+ }
+
+ gfar_data.phy_id = *id;
+ gfar_data.bus_id = res.start;
- id = of_get_property(phy, "reg", NULL);
- ret = of_address_to_resource(mdio, 0, &res);
- if (ret) {
of_node_put(phy);
of_node_put(mdio);
- goto unreg;
}
- gfar_data.phy_id = *id;
- gfar_data.bus_id = res.start;
-
- of_node_put(phy);
- of_node_put(mdio);
-
ret =
platform_device_add_data(gfar_dev, &gfar_data,
sizeof(struct
^ permalink raw reply related
* [PATCH 1/3] [NET] phy/fixed.c: rework to not duplicate PHY layer functionality
From: Vitaly Bordug @ 2007-12-06 22:51 UTC (permalink / raw)
To: Paul Mackerras; +Cc: netdev, linuxppc-dev, netdev
With that patch fixed.c now fully emulates MDIO bus, thus no need
to duplicate PHY layer functionality. That, in turn, drastically
simplifies the code, and drops down line count.
As an additional bonus, now there is no need to register MDIO bus
for each PHY, all emulated PHYs placed on the platform fixed MDIO bus.
There is also no more need to pre-allocate PHYs via .config option,
this is all now handled dynamically.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: Vitaly Bordug <vitb@kernel.crashing.org>
Acked-by: Jeff Garzik <jeff@garzik.org>
---
drivers/net/phy/Kconfig | 32 +--
drivers/net/phy/fixed.c | 445 +++++++++++++++++----------------------------
include/linux/phy_fixed.h | 51 ++---
3 files changed, 195 insertions(+), 333 deletions(-)
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 54b2ba9..7fe03ce 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -61,34 +61,12 @@ config ICPLUS_PHY
Currently supports the IP175C PHY.
config FIXED_PHY
- tristate "Drivers for PHY emulation on fixed speed/link"
+ bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
---help---
- Adds the driver to PHY layer to cover the boards that do not have any PHY bound,
- but with the ability to manipulate the speed/link in software. The relevant MII
- speed/duplex parameters could be effectively handled in a user-specified function.
- Currently tested with mpc866ads.
-
-config FIXED_MII_10_FDX
- bool "Emulation for 10M Fdx fixed PHY behavior"
- depends on FIXED_PHY
-
-config FIXED_MII_100_FDX
- bool "Emulation for 100M Fdx fixed PHY behavior"
- depends on FIXED_PHY
-
-config FIXED_MII_1000_FDX
- bool "Emulation for 1000M Fdx fixed PHY behavior"
- depends on FIXED_PHY
-
-config FIXED_MII_AMNT
- int "Number of emulated PHYs to allocate "
- depends on FIXED_PHY
- default "1"
- ---help---
- Sometimes it is required to have several independent emulated
- PHYs on the bus (in case of multi-eth but phy-less HW for instance).
- This control will have specified number allocated for each fixed
- PHY type enabled.
+ Adds the platform "fixed" MDIO Bus to cover the boards that use
+ PHYs that are not connected to the real MDIO bus.
+
+ Currently tested with mpc866ads and mpc8349e-mitx.
config MDIO_BITBANG
tristate "Support for bitbanged MDIO buses"
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
index 5619182..73b6d39 100644
--- a/drivers/net/phy/fixed.c
+++ b/drivers/net/phy/fixed.c
@@ -1,362 +1,253 @@
/*
- * drivers/net/phy/fixed.c
+ * Fixed MDIO bus (MDIO bus emulation with fixed PHYs)
*
- * Driver for fixed PHYs, when transceiver is able to operate in one fixed mode.
+ * Author: Vitaly Bordug <vbordug@ru.mvista.com>
+ * Anton Vorontsov <avorontsov@ru.mvista.com>
*
- * Author: Vitaly Bordug
- *
- * Copyright (c) 2006 MontaVista Software, Inc.
+ * Copyright (c) 2006-2007 MontaVista Software, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
- *
*/
+
#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/unistd.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/mm.h>
#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
#include <linux/mii.h>
-#include <linux/ethtool.h>
#include <linux/phy.h>
#include <linux/phy_fixed.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
+#define MII_REGS_NUM 29
-/* we need to track the allocated pointers in order to free them on exit */
-static struct fixed_info *fixed_phy_ptrs[CONFIG_FIXED_MII_AMNT*MAX_PHY_AMNT];
-
-/*-----------------------------------------------------------------------------
- * If something weird is required to be done with link/speed,
- * network driver is able to assign a function to implement this.
- * May be useful for PHY's that need to be software-driven.
- *-----------------------------------------------------------------------------*/
-int fixed_mdio_set_link_update(struct phy_device *phydev,
- int (*link_update) (struct net_device *,
- struct fixed_phy_status *))
-{
- struct fixed_info *fixed;
-
- if (link_update == NULL)
- return -EINVAL;
-
- if (phydev) {
- if (phydev->bus) {
- fixed = phydev->bus->priv;
- fixed->link_update = link_update;
- return 0;
- }
- }
- return -EINVAL;
-}
-
-EXPORT_SYMBOL(fixed_mdio_set_link_update);
+struct fixed_mdio_bus {
+ int irqs[PHY_MAX_ADDR];
+ struct mii_bus mii_bus;
+ struct list_head phys;
+};
-struct fixed_info *fixed_mdio_get_phydev (int phydev_ind)
-{
- if (phydev_ind >= MAX_PHY_AMNT)
- return NULL;
- return fixed_phy_ptrs[phydev_ind];
-}
+struct fixed_phy {
+ int id;
+ u16 regs[MII_REGS_NUM];
+ struct phy_device *phydev;
+ struct fixed_phy_status status;
+ int (*link_update)(struct net_device *, struct fixed_phy_status *);
+ struct list_head node;
+};
-EXPORT_SYMBOL(fixed_mdio_get_phydev);
+static struct platform_device *pdev;
+static struct fixed_mdio_bus platform_fmb = {
+ .phys = LIST_HEAD_INIT(platform_fmb.phys),
+};
-/*-----------------------------------------------------------------------------
- * This is used for updating internal mii regs from the status
- *-----------------------------------------------------------------------------*/
-#if defined(CONFIG_FIXED_MII_100_FDX) || defined(CONFIG_FIXED_MII_10_FDX) || defined(CONFIG_FIXED_MII_1000_FDX)
-static int fixed_mdio_update_regs(struct fixed_info *fixed)
+static int fixed_phy_update_regs(struct fixed_phy *fp)
{
- u16 *regs = fixed->regs;
- u16 bmsr = 0;
+ u16 bmsr = BMSR_ANEGCAPABLE;
u16 bmcr = 0;
+ u16 lpagb = 0;
+ u16 lpa = 0;
- if (!regs) {
- printk(KERN_ERR "%s: regs not set up", __FUNCTION__);
- return -EINVAL;
- }
-
- if (fixed->phy_status.link)
- bmsr |= BMSR_LSTATUS;
-
- if (fixed->phy_status.duplex) {
+ if (fp->status.duplex) {
bmcr |= BMCR_FULLDPLX;
- switch (fixed->phy_status.speed) {
+ switch (fp->status.speed) {
+ case 1000:
+ bmsr |= BMSR_ESTATEN;
+ bmcr |= BMCR_SPEED1000;
+ lpagb |= LPA_1000FULL;
+ break;
case 100:
bmsr |= BMSR_100FULL;
bmcr |= BMCR_SPEED100;
+ lpa |= LPA_100FULL;
break;
-
case 10:
bmsr |= BMSR_10FULL;
+ lpa |= LPA_10FULL;
break;
+ default:
+ printk(KERN_WARNING "fixed phy: unknown speed\n");
+ return -EINVAL;
}
} else {
- switch (fixed->phy_status.speed) {
+ switch (fp->status.speed) {
+ case 1000:
+ bmsr |= BMSR_ESTATEN;
+ bmcr |= BMCR_SPEED1000;
+ lpagb |= LPA_1000HALF;
+ break;
case 100:
bmsr |= BMSR_100HALF;
bmcr |= BMCR_SPEED100;
+ lpa |= LPA_100HALF;
break;
-
case 10:
- bmsr |= BMSR_100HALF;
+ bmsr |= BMSR_10HALF;
+ lpa |= LPA_10HALF;
break;
+ default:
+ printk(KERN_WARNING "fixed phy: unknown speed\n");
+ return -EINVAL;
}
}
- regs[MII_BMCR] = bmcr;
- regs[MII_BMSR] = bmsr | 0x800; /*we are always capable of 10 hdx */
+ if (fp->status.link)
+ bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE;
+
+ if (fp->status.pause)
+ lpa |= LPA_PAUSE_CAP;
+
+ if (fp->status.asym_pause)
+ lpa |= LPA_PAUSE_ASYM;
+
+ fp->regs[MII_PHYSID1] = fp->id >> 16;
+ fp->regs[MII_PHYSID2] = fp->id;
+
+ fp->regs[MII_BMSR] = bmsr;
+ fp->regs[MII_BMCR] = bmcr;
+ fp->regs[MII_LPA] = lpa;
+ fp->regs[MII_STAT1000] = lpagb;
return 0;
}
-static int fixed_mii_read(struct mii_bus *bus, int phy_id, int location)
+static int fixed_mdio_read(struct mii_bus *bus, int phy_id, int reg_num)
{
- struct fixed_info *fixed = bus->priv;
-
- /* if user has registered link update callback, use it */
- if (fixed->phydev)
- if (fixed->phydev->attached_dev) {
- if (fixed->link_update) {
- fixed->link_update(fixed->phydev->attached_dev,
- &fixed->phy_status);
- fixed_mdio_update_regs(fixed);
+ struct fixed_mdio_bus *fmb = container_of(bus, struct fixed_mdio_bus,
+ mii_bus);
+ struct fixed_phy *fp;
+
+ if (reg_num >= MII_REGS_NUM)
+ return -1;
+
+ list_for_each_entry(fp, &fmb->phys, node) {
+ if (fp->id == phy_id) {
+ /* Issue callback if user registered it. */
+ if (fp->link_update) {
+ fp->link_update(fp->phydev->attached_dev,
+ &fp->status);
+ fixed_phy_update_regs(fp);
}
+ return fp->regs[reg_num];
}
+ }
- if ((unsigned int)location >= fixed->regs_num)
- return -1;
- return fixed->regs[location];
+ return 0xFFFF;
}
-static int fixed_mii_write(struct mii_bus *bus, int phy_id, int location,
- u16 val)
+static int fixed_mdio_write(struct mii_bus *bus, int phy_id, int reg_num,
+ u16 val)
{
- /* do nothing for now */
return 0;
}
-static int fixed_mii_reset(struct mii_bus *bus)
+/*
+ * If something weird is required to be done with link/speed,
+ * network driver is able to assign a function to implement this.
+ * May be useful for PHY's that need to be software-driven.
+ */
+int fixed_phy_set_link_update(struct phy_device *phydev,
+ int (*link_update)(struct net_device *,
+ struct fixed_phy_status *))
{
- /*nothing here - no way/need to reset it */
- return 0;
-}
-#endif
+ struct fixed_mdio_bus *fmb = &platform_fmb;
+ struct fixed_phy *fp;
-static int fixed_config_aneg(struct phy_device *phydev)
-{
- /* :TODO:03/13/2006 09:45:37 PM::
- The full autoneg funcionality can be emulated,
- but no need to have anything here for now
- */
- return 0;
-}
+ if (!link_update || !phydev || !phydev->bus)
+ return -EINVAL;
-/*-----------------------------------------------------------------------------
- * the manual bind will do the magic - with phy_id_mask == 0
- * match will never return true...
- *-----------------------------------------------------------------------------*/
-static struct phy_driver fixed_mdio_driver = {
- .name = "Fixed PHY",
-#ifdef CONFIG_FIXED_MII_1000_FDX
- .features = PHY_GBIT_FEATURES,
-#else
- .features = PHY_BASIC_FEATURES,
-#endif
- .config_aneg = fixed_config_aneg,
- .read_status = genphy_read_status,
- .driver = { .owner = THIS_MODULE, },
-};
+ list_for_each_entry(fp, &fmb->phys, node) {
+ if (fp->id == phydev->phy_id) {
+ fp->link_update = link_update;
+ fp->phydev = phydev;
+ return 0;
+ }
+ }
-static void fixed_mdio_release(struct device *dev)
-{
- struct phy_device *phydev = container_of(dev, struct phy_device, dev);
- struct mii_bus *bus = phydev->bus;
- struct fixed_info *fixed = bus->priv;
-
- kfree(phydev);
- kfree(bus->dev);
- kfree(bus);
- kfree(fixed->regs);
- kfree(fixed);
+ return -ENOENT;
}
+EXPORT_SYMBOL_GPL(fixed_phy_set_link_update);
-/*-----------------------------------------------------------------------------
- * This func is used to create all the necessary stuff, bind
- * the fixed phy driver and register all it on the mdio_bus_type.
- * speed is either 10 or 100 or 1000, duplex is boolean.
- * number is used to create multiple fixed PHYs, so that several devices can
- * utilize them simultaneously.
- *
- * The device on mdio bus will look like [bus_id]:[phy_id],
- * bus_id = number
- * phy_id = speed+duplex.
- *-----------------------------------------------------------------------------*/
-#if defined(CONFIG_FIXED_MII_100_FDX) || defined(CONFIG_FIXED_MII_10_FDX) || defined(CONFIG_FIXED_MII_1000_FDX)
-struct fixed_info *fixed_mdio_register_device(
- int bus_id, int speed, int duplex, u8 phy_id)
+int fixed_phy_add(unsigned int irq, int phy_id,
+ struct fixed_phy_status *status)
{
- struct mii_bus *new_bus;
- struct fixed_info *fixed;
- struct phy_device *phydev;
- int err;
+ int ret;
+ struct fixed_mdio_bus *fmb = &platform_fmb;
+ struct fixed_phy *fp;
- struct device *dev = kzalloc(sizeof(struct device), GFP_KERNEL);
+ fp = kzalloc(sizeof(*fp), GFP_KERNEL);
+ if (!fp)
+ return -ENOMEM;
- if (dev == NULL)
- goto err_dev_alloc;
+ memset(fp->regs, 0xFF, sizeof(fp->regs[0]) * MII_REGS_NUM);
- new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+ fmb->irqs[phy_id] = irq;
- if (new_bus == NULL)
- goto err_bus_alloc;
+ fp->id = phy_id;
+ fp->status = *status;
- fixed = kzalloc(sizeof(struct fixed_info), GFP_KERNEL);
+ ret = fixed_phy_update_regs(fp);
+ if (ret)
+ goto err_regs;
- if (fixed == NULL)
- goto err_fixed_alloc;
+ list_add_tail(&fp->node, &fmb->phys);
- fixed->regs = kzalloc(MII_REGS_NUM * sizeof(int), GFP_KERNEL);
- if (NULL == fixed->regs)
- goto err_fixed_regs_alloc;
+ return 0;
- fixed->regs_num = MII_REGS_NUM;
- fixed->phy_status.speed = speed;
- fixed->phy_status.duplex = duplex;
- fixed->phy_status.link = 1;
+err_regs:
+ kfree(fp);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(fixed_phy_add);
- new_bus->name = "Fixed MII Bus";
- new_bus->read = &fixed_mii_read;
- new_bus->write = &fixed_mii_write;
- new_bus->reset = &fixed_mii_reset;
- /*set up workspace */
- fixed_mdio_update_regs(fixed);
- new_bus->priv = fixed;
+static int __init fixed_mdio_bus_init(void)
+{
+ struct fixed_mdio_bus *fmb = &platform_fmb;
+ int ret;
- new_bus->dev = dev;
- dev_set_drvdata(dev, new_bus);
+ pdev = platform_device_register_simple("Fixed MDIO bus", 0, NULL, 0);
+ if (!pdev) {
+ ret = -ENOMEM;
+ goto err_pdev;
+ }
- /* create phy_device and register it on the mdio bus */
- phydev = phy_device_create(new_bus, 0, 0);
- if (phydev == NULL)
- goto err_phy_dev_create;
+ fmb->mii_bus.id = 0;
+ fmb->mii_bus.name = "Fixed MDIO Bus";
+ fmb->mii_bus.dev = &pdev->dev;
+ fmb->mii_bus.read = &fixed_mdio_read;
+ fmb->mii_bus.write = &fixed_mdio_write;
+ fmb->mii_bus.irq = fmb->irqs;
- /*
- * Put the phydev pointer into the fixed pack so that bus read/write
- * code could be able to access for instance attached netdev. Well it
- * doesn't have to do so, only in case of utilizing user-specified
- * link-update...
- */
+ ret = mdiobus_register(&fmb->mii_bus);
+ if (ret)
+ goto err_mdiobus_reg;
- fixed->phydev = phydev;
- phydev->speed = speed;
- phydev->duplex = duplex;
+ return 0;
- phydev->irq = PHY_IGNORE_INTERRUPT;
- phydev->dev.bus = &mdio_bus_type;
+err_mdiobus_reg:
+ platform_device_unregister(pdev);
+err_pdev:
+ return ret;
+}
+module_init(fixed_mdio_bus_init);
- snprintf(phydev->dev.bus_id, BUS_ID_SIZE,
- PHY_ID_FMT, bus_id, phy_id);
+static void __exit fixed_mdio_bus_exit(void)
+{
+ struct fixed_mdio_bus *fmb = &platform_fmb;
+ struct fixed_phy *fp;
- phydev->bus = new_bus;
+ mdiobus_unregister(&fmb->mii_bus);
+ platform_device_unregister(pdev);
- phydev->dev.driver = &fixed_mdio_driver.driver;
- phydev->dev.release = fixed_mdio_release;
- err = phydev->dev.driver->probe(&phydev->dev);
- if (err < 0) {
- printk(KERN_ERR "Phy %s: problems with fixed driver\n",
- phydev->dev.bus_id);
- goto err_out;
- }
- err = device_register(&phydev->dev);
- if (err) {
- printk(KERN_ERR "Phy %s failed to register\n",
- phydev->dev.bus_id);
- goto err_out;
+ list_for_each_entry(fp, &fmb->phys, node) {
+ list_del(&fp->node);
+ kfree(fp);
}
- //phydev->state = PHY_RUNNING; /* make phy go up quick, but in 10Mbit/HDX
- return fixed;
-
-err_out:
- kfree(phydev);
-err_phy_dev_create:
- kfree(fixed->regs);
-err_fixed_regs_alloc:
- kfree(fixed);
-err_fixed_alloc:
- kfree(new_bus);
-err_bus_alloc:
- kfree(dev);
-err_dev_alloc:
-
- return NULL;
-
}
-#endif
+module_exit(fixed_mdio_bus_exit);
-MODULE_DESCRIPTION("Fixed PHY device & driver for PAL");
+MODULE_DESCRIPTION("Fixed MDIO bus (MDIO bus emulation with fixed PHYs)");
MODULE_AUTHOR("Vitaly Bordug");
MODULE_LICENSE("GPL");
-
-static int __init fixed_init(void)
-{
- int cnt = 0;
- int i;
-/* register on the bus... Not expected to be matched
- * with anything there...
- *
- */
- phy_driver_register(&fixed_mdio_driver);
-
-/* We will create several mdio devices here, and will bound the upper
- * driver to them.
- *
- * Then the external software can lookup the phy bus by searching
- * for 0:101, to be connected to the virtual 100M Fdx phy.
- *
- * In case several virtual PHYs required, the bus_id will be in form
- * [num]:[duplex]+[speed], which make it able even to define
- * driver-specific link control callback, if for instance PHY is
- * completely SW-driven.
- */
- for (i=1; i <= CONFIG_FIXED_MII_AMNT; i++) {
-#ifdef CONFIG_FIXED_MII_1000_FDX
- fixed_phy_ptrs[cnt++] = fixed_mdio_register_device(0, 1000, 1, i);
-#endif
-#ifdef CONFIG_FIXED_MII_100_FDX
- fixed_phy_ptrs[cnt++] = fixed_mdio_register_device(1, 100, 1, i);
-#endif
-#ifdef CONFIG_FIXED_MII_10_FDX
- fixed_phy_ptrs[cnt++] = fixed_mdio_register_device(2, 10, 1, i);
-#endif
- }
-
- return 0;
-}
-
-static void __exit fixed_exit(void)
-{
- int i;
-
- phy_driver_unregister(&fixed_mdio_driver);
- for (i=0; i < MAX_PHY_AMNT; i++)
- if ( fixed_phy_ptrs[i] )
- device_unregister(&fixed_phy_ptrs[i]->phydev->dev);
-}
-
-module_init(fixed_init);
-module_exit(fixed_exit);
diff --git a/include/linux/phy_fixed.h b/include/linux/phy_fixed.h
index 04ba70d..509d8f5 100644
--- a/include/linux/phy_fixed.h
+++ b/include/linux/phy_fixed.h
@@ -1,38 +1,31 @@
#ifndef __PHY_FIXED_H
#define __PHY_FIXED_H
-#define MII_REGS_NUM 29
-
-/* max number of virtual phy stuff */
-#define MAX_PHY_AMNT 10
-/*
- The idea is to emulate normal phy behavior by responding with
- pre-defined values to mii BMCR read, so that read_status hook could
- take all the needed info.
-*/
-
struct fixed_phy_status {
- u8 link;
- u16 speed;
- u8 duplex;
+ int link;
+ int speed;
+ int duplex;
+ int pause;
+ int asym_pause;
};
-/*-----------------------------------------------------------------------------
- * Private information hoder for mii_bus
- *-----------------------------------------------------------------------------*/
-struct fixed_info {
- u16 *regs;
- u8 regs_num;
- struct fixed_phy_status phy_status;
- struct phy_device *phydev; /* pointer to the container */
- /* link & speed cb */
- int (*link_update) (struct net_device *, struct fixed_phy_status *);
+#ifdef CONFIG_FIXED_PHY
+extern int fixed_phy_add(unsigned int irq, int phy_id,
+ struct fixed_phy_status *status);
+#else
+static inline int fixed_phy_add(unsigned int irq, int phy_id,
+ struct fixed_phy_status *status)
+{
+ return -ENODEV;
+}
+#endif /* CONFIG_FIXED_PHY */
-};
-
-
-int fixed_mdio_set_link_update(struct phy_device *,
- int (*link_update) (struct net_device *, struct fixed_phy_status *));
-struct fixed_info *fixed_mdio_get_phydev (int phydev_ind);
+/*
+ * This function issued only by fixed_phy-aware drivers, no need
+ * protect it with #ifdef
+ */
+extern int fixed_phy_set_link_update(struct phy_device *phydev,
+ int (*link_update)(struct net_device *,
+ struct fixed_phy_status *));
#endif /* __PHY_FIXED_H */
^ permalink raw reply related
* Re: [PATCH] Reduce stack used by lib/hexdump.c
From: Joe Perches @ 2007-12-06 21:52 UTC (permalink / raw)
To: Andrew Morton
Cc: jengelh, Kyle Moffett, randy.dunlap, linux-kernel, Ted Ts'o,
Andreas Dilger, Dave Kleikamp, David Brownell, David Woodhouse,
Eric Sandeen, Greg Kroah-Hartman, James E.J. Bottomley,
Jeff Garzik, Mingming Cao, Stephen Tweedie, Zhu Yi, ipw3945-devel,
jfs-discussion, linux-ext4, linux-mtd, linux-scsi,
linux-usb-devel, linux-usb-users, linux-wireless, netdev
In-Reply-To: <20071205160133.0766c4f5.akpm@linux-foundation.org>
On Wed, 2007-12-05 at 16:01 -0800, Andrew Morton wrote:
> No, I think print_hex_dump() is too low-level to be doing allocations.
> For example, one could easily choose to call print_hex_dump() at oops time,
> and then what happens if we oops in kmalloc() (as we often do...)?
>
> You could trim linebuf[] to 80 chars or so. Extra points for making it
> very clear when someone tries to exceed that - strcpy(linebuf, "stop being
> stupid").
No extra points, but here's a revised patch to hexdump against
Linus' current:
hex_dump_to_buffer:
Removes casts to type for non-1 group sizes
Used by: fs/ext(3|4)super.c, fs/jfs
If someone really dislikes this change, please say so.
I think casting to type in a hex dump odd, especially
for mixed type structures.
If you want an array of type dumper, it probably
shouldn't be called hex_dump_to_buffer.
Groups by arbitrary size
print_hex_dump:
Removes rowsize argument
Reduces linebuf stack use to ~120 bytes
prefix:25 + address:20 + data:48 + ascii:20)
Aligns multiline ascii output
Changes return to size_t, number of bytes actually output
include/linux/kernel.h
Removes hex_asc define
Updates hex_dump prototypes
The rest are trivial conversions to new argument list.
size before:
text data bss dec hex filename
1142 0 0 1142 476 lib/hexdump.o
size after:
text data bss dec hex filename
823 0 0 823 337 lib/hexdump.o
Signed-off-by: Joe Perches <joe@perches.com>
---
include/linux/kernel.h | 13 +-
lib/hexdump.c | 164 ++++++++++++---------------
drivers/mtd/ubi/debug.c | 2 +-
drivers/mtd/ubi/io.c | 2 +-
drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 +-
drivers/net/wireless/iwlwifi/iwl4965-base.c | 4 +-
drivers/scsi/ide-scsi.c | 8 +-
drivers/usb/gadget/file_storage.c | 4 +-
fs/ext3/super.c | 6 +-
fs/ext4/super.c | 6 +-
fs/jffs2/wbuf.c | 4 +-
fs/jfs/jfs_imap.c | 2 +-
fs/jfs/jfs_logmgr.c | 6 +-
fs/jfs/jfs_metapage.c | 2 +-
fs/jfs/jfs_txnmgr.c | 8 +-
fs/jfs/xattr.c | 4 +-
16 files changed, 110 insertions(+), 129 deletions(-)
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 94bc996..ab45524 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -248,15 +248,14 @@ enum {
DUMP_PREFIX_ADDRESS,
DUMP_PREFIX_OFFSET
};
-extern void hex_dump_to_buffer(const void *buf, size_t len,
- int rowsize, int groupsize,
- char *linebuf, size_t linebuflen, bool ascii);
+extern size_t hex_dump_to_buffer(const void *buf, size_t len,
+ size_t rowsize, size_t groupsize,
+ char *linebuf, size_t linebuflen, bool ascii);
extern void print_hex_dump(const char *level, const char *prefix_str,
- int prefix_type, int rowsize, int groupsize,
- const void *buf, size_t len, bool ascii);
+ int prefix_type, size_t groupsize,
+ const void *buf, size_t len, bool ascii);
extern void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
- const void *buf, size_t len);
-#define hex_asc(x) "0123456789abcdef"[x]
+ const void *buf, size_t len);
#define pr_emerg(fmt, arg...) \
printk(KERN_EMERG fmt, ##arg)
diff --git a/lib/hexdump.c b/lib/hexdump.c
index 3435465..df82012 100644
--- a/lib/hexdump.c
+++ b/lib/hexdump.c
@@ -12,18 +12,21 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#define ROWSIZE ((size_t)16)
+#define MAX_PREFIX_LEN ((size_t)20)
+
/**
* hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
* @buf: data blob to dump
* @len: number of bytes in the @buf
- * @rowsize: number of bytes to print per line; must be 16 or 32
+ * @rowsize: maximum number of bytes to output (aligns ascii)
* @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
* @linebuf: where to put the converted data
* @linebuflen: total size of @linebuf, including space for terminating NUL
* @ascii: include ASCII after the hex output
*
* hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
- * 16 or 32 bytes of input data converted to hex + ASCII output.
+ * input data converted to hex + ASCII output.
*
* Given a buffer of u8 data, hex_dump_to_buffer() converts the input data
* to a hex + ASCII dump at the supplied memory location.
@@ -31,85 +34,54 @@
*
* E.g.:
* hex_dump_to_buffer(frame->data, frame->len, 16, 1,
- * linebuf, sizeof(linebuf), 1);
+ * linebuf, sizeof(linebuf), true);
*
* example output buffer:
* 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
*/
-void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
- int groupsize, char *linebuf, size_t linebuflen,
- bool ascii)
+size_t hex_dump_to_buffer(const void *buf, size_t len,
+ size_t rowsize, size_t groupsize,
+ char *linebuf, size_t linebuflen, bool ascii)
{
const u8 *ptr = buf;
- u8 ch;
- int j, lx = 0;
- int ascii_column;
-
- if (rowsize != 16 && rowsize != 32)
- rowsize = 16;
-
+ int i, lx = 0;
+ size_t ascii_column;
+ size_t ngroups;
if (!len)
goto nil;
- if (len > rowsize) /* limit to one line at a time */
- len = rowsize;
- if ((len % groupsize) != 0) /* no mixed size output */
- groupsize = 1;
-
- switch (groupsize) {
- case 8: {
- const u64 *ptr8 = buf;
- int ngroups = len / groupsize;
-
- for (j = 0; j < ngroups; j++)
- lx += scnprintf(linebuf + lx, linebuflen - lx,
- "%16.16llx ", (unsigned long long)*(ptr8 + j));
- ascii_column = 17 * ngroups + 2;
- break;
- }
-
- case 4: {
- const u32 *ptr4 = buf;
- int ngroups = len / groupsize;
-
- for (j = 0; j < ngroups; j++)
- lx += scnprintf(linebuf + lx, linebuflen - lx,
- "%8.8x ", *(ptr4 + j));
- ascii_column = 9 * ngroups + 2;
- break;
- }
- case 2: {
- const u16 *ptr2 = buf;
- int ngroups = len / groupsize;
+ if (groupsize == 0)
+ groupsize = 1;
+ else if (groupsize > rowsize)
+ groupsize = rowsize;
- for (j = 0; j < ngroups; j++)
- lx += scnprintf(linebuf + lx, linebuflen - lx,
- "%4.4x ", *(ptr2 + j));
- ascii_column = 5 * ngroups + 2;
- break;
- }
+ ngroups = rowsize / groupsize;
+ ascii_column = (2 * groupsize + 1) * ngroups + 2;
+ if (len > (ngroups * groupsize))
+ len = ngroups * groupsize;
- default:
- for (j = 0; (j < rowsize) && (j < len) && (lx + 4) < linebuflen;
- j++) {
- ch = ptr[j];
- linebuf[lx++] = hex_asc(ch >> 4);
- linebuf[lx++] = hex_asc(ch & 0x0f);
+ for (i = 0; i < len; i++) {
+ if (i && (i % groupsize) == 0)
linebuf[lx++] = ' ';
- }
- ascii_column = 3 * rowsize + 2;
- break;
+ lx += scnprintf(linebuf + lx, linebuflen - lx,
+ "%02x", ptr[i] & 0xff);
}
+
if (!ascii)
goto nil;
while (lx < (linebuflen - 1) && lx < (ascii_column - 1))
linebuf[lx++] = ' ';
- for (j = 0; (j < rowsize) && (j < len) && (lx + 2) < linebuflen; j++)
- linebuf[lx++] = (isascii(ptr[j]) && isprint(ptr[j])) ? ptr[j]
- : '.';
+
+ for (i = 0; i < len && (lx + 2) < linebuflen; i++) {
+ if (i > 0 && groupsize > 1 && (i % groupsize) == 0)
+ linebuf[lx++] = ' ';
+ linebuf[lx++] = (isascii(ptr[i]) && isprint(ptr[i]))
+ ? ptr[i] : '.';
+ }
nil:
- linebuf[lx++] = '\0';
+ linebuf[lx] = '\0';
+ return len;
}
EXPORT_SYMBOL(hex_dump_to_buffer);
@@ -120,7 +92,6 @@ EXPORT_SYMBOL(hex_dump_to_buffer);
* caller supplies trailing spaces for alignment if desired
* @prefix_type: controls whether prefix of an offset, address, or none
* is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
- * @rowsize: number of bytes to print per line; must be 16 or 32
* @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
* @buf: data blob to dump
* @len: number of bytes in the @buf
@@ -131,48 +102,60 @@ EXPORT_SYMBOL(hex_dump_to_buffer);
* leading prefix.
*
* print_hex_dump() works on one "line" of output at a time, i.e.,
- * 16 or 32 bytes of input data converted to hex + ASCII output.
+ * 16 bytes of input data converted to hex + ASCII output.
* print_hex_dump() iterates over the entire input @buf, breaking it into
- * "line size" chunks to format and print.
+ * groups of up to 16 byte chunks to format and print.
*
* E.g.:
- * print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS,
- * 16, 1, frame->data, frame->len, 1);
+ * print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS, 1,
+ * frame->data, frame->len, 1);
*
* Example output using %DUMP_PREFIX_OFFSET and 1-byte mode:
- * 0009ab42: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
- * Example output using %DUMP_PREFIX_ADDRESS and 4-byte mode:
- * ffffffff88089af0: 73727170 77767574 7b7a7978 7f7e7d7c pqrstuvwxyz{|}~.
+ * 00000000: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
+ * Example output using %DUMP_PREFIX_ADDRESS and 4-byte mode on BE 64 bit:
+ * ffffffff88089af0: 70717273 74757677 78797a7b 7c7d7e7f pqrs tuvw xyz{ |}~.
+ * Example output using %DUMP_PREFIX_ADDRESS and 5-byte mode on LE 32 bit:
+ * 88089af0: 7071727374 7576777879 7a7b7d7d7e pqrst uvwxy z{|}~
*/
+
void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
- int rowsize, int groupsize,
- const void *buf, size_t len, bool ascii)
+ size_t groupsize, const void *buf, size_t len, bool ascii)
{
const u8 *ptr = buf;
- int i, linelen, remaining = len;
- unsigned char linebuf[200];
-
- if (rowsize != 16 && rowsize != 32)
- rowsize = 16;
-
- for (i = 0; i < len; i += rowsize) {
- linelen = min(remaining, rowsize);
- remaining -= rowsize;
- hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
- linebuf, sizeof(linebuf), ascii);
+ size_t i;
+ size_t linelen;
+ size_t prefix_len = strlen(prefix_str);
+ unsigned char linebuf[sizeof(KERN_INFO) +
+ MAX_PREFIX_LEN +
+ (2 * sizeof(void *) + 4) +
+ (3 * ROWSIZE) +
+ (3 * ROWSIZE / 2) + 1];
+ if (prefix_len > MAX_PREFIX_LEN)
+ prefix_len = MAX_PREFIX_LEN;
+
+ i = 0;
+ while (i < len) {
+ size_t bytes;
+ linelen = min(len - i, ROWSIZE);
+ bytes = hex_dump_to_buffer(ptr + i, linelen, ROWSIZE, groupsize,
+ linebuf, sizeof(linebuf), ascii);
switch (prefix_type) {
case DUMP_PREFIX_ADDRESS:
- printk("%s%s%*p: %s\n", level, prefix_str,
- (int)(2 * sizeof(void *)), ptr + i, linebuf);
+ printk("%s%-.*s%*p: %s\n", level,
+ prefix_len, prefix_str,
+ (int)(2 * sizeof(void *)), ptr + i, linebuf);
break;
case DUMP_PREFIX_OFFSET:
- printk("%s%s%.8x: %s\n", level, prefix_str, i, linebuf);
+ printk("%s%-.*s%.8x: %s\n", level,
+ prefix_len, prefix_str, i, linebuf);
break;
default:
- printk("%s%s%s\n", level, prefix_str, linebuf);
+ printk("%s%-.*s%s\n", level,
+ prefix_len, prefix_str, linebuf);
break;
}
+ i += bytes;
}
}
EXPORT_SYMBOL(print_hex_dump);
@@ -187,12 +170,11 @@ EXPORT_SYMBOL(print_hex_dump);
* @len: number of bytes in the @buf
*
* Calls print_hex_dump(), with log level of KERN_DEBUG,
- * rowsize of 16, groupsize of 1, and ASCII output included.
+ * groupsize of 1, and ASCII output included.
*/
void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
- const void *buf, size_t len)
+ const void *buf, size_t len)
{
- print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 16, 1,
- buf, len, 1);
+ print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 1, buf, len, true);
}
EXPORT_SYMBOL(print_hex_dump_bytes);
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index 56956ec..d99c4d5 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -42,7 +42,7 @@ void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
dbg_msg("data_offset %d", be32_to_cpu(ec_hdr->data_offset));
dbg_msg("hdr_crc %#08x", be32_to_cpu(ec_hdr->hdr_crc));
dbg_msg("erase counter header hexdump:");
- print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
+ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 1,
ec_hdr, UBI_EC_HDR_SIZE, 1);
}
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 7c304ee..20cf7b2 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -1243,7 +1243,7 @@ static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset,
fail:
ubi_err("paranoid check failed for PEB %d", pnum);
dbg_msg("hex dump of the %d-%d region", offset, offset + len);
- print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
+ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 1,
ubi->dbg_peb_buf, len, 1);
err = 1;
error:
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 4bdf237..563c30f 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -184,8 +184,8 @@ static void iwl_print_hex_dump(int level, void *p, u32 len)
if (!(iwl_debug_level & level))
return;
- print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
- p, len, 1);
+ print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 1,
+ p, len, 1);
#endif
}
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 8f85564..150f6e4 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -183,8 +183,8 @@ static void iwl_print_hex_dump(int level, void *p, u32 len)
if (!(iwl_debug_level & level))
return;
- print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
- p, len, 1);
+ print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 1,
+ p, len, 1);
#endif
}
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 7a835a3..cc2da8a 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -272,7 +272,7 @@ static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_co
pc->scsi_cmd = ((idescsi_pc_t *) failed_command->special)->scsi_cmd;
if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
printk ("ide-scsi: %s: queue cmd = ", drive->name);
- print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, pc->c,
+ print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 1, pc->c,
6, 0);
}
rq->rq_disk = scsi->disk;
@@ -328,7 +328,7 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
idescsi_pc_t *opc = (idescsi_pc_t *) rq->buffer;
if (log) {
printk ("ide-scsi: %s: wrap up check %lu, rst = ", drive->name, opc->scsi_cmd->serial_number);
- print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1,
+ print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 1,
pc->buffer, 16, 0);
}
memcpy((void *) opc->scsi_cmd->sense_buffer, pc->buffer, SCSI_SENSE_BUFFERSIZE);
@@ -808,11 +808,11 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number);
- print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1,
+ print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 1,
cmd->cmnd, cmd->cmd_len, 0);
if (memcmp(pc->c, cmd->cmnd, cmd->cmd_len)) {
printk ("ide-scsi: %s: que %lu, tsl = ", drive->name, cmd->serial_number);
- print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1,
+ print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 1,
pc->c, 12, 0);
}
}
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 1d174dc..e690949 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -723,7 +723,7 @@ static void dump_msg(struct fsg_dev *fsg, const char *label,
if (length < 512) {
DBG(fsg, "%s, length %u:\n", label, length);
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET,
- 16, 1, buf, length, 0);
+ 1, buf, length, 0);
}
}
@@ -741,7 +741,7 @@ static void dump_msg(struct fsg_dev *fsg, const char *label,
static void dump_cdb(struct fsg_dev *fsg)
{
print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE,
- 16, 1, fsg->cmnd, fsg->cmnd_size, 0);
+ 1, fsg->cmnd, fsg->cmnd_size, 0);
}
#else
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index de55da9..f5022a3 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -464,9 +464,9 @@ static void ext3_destroy_inode(struct inode *inode)
if (!list_empty(&(EXT3_I(inode)->i_orphan))) {
printk("EXT3 Inode %p: orphan list check failed!\n",
EXT3_I(inode));
- print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4,
- EXT3_I(inode), sizeof(struct ext3_inode_info),
- false);
+ print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 4,
+ EXT3_I(inode), sizeof(struct ext3_inode_info),
+ false);
dump_stack();
}
kmem_cache_free(ext3_inode_cachep, EXT3_I(inode));
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 8031dc0..edd6a80 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -517,9 +517,9 @@ static void ext4_destroy_inode(struct inode *inode)
if (!list_empty(&(EXT4_I(inode)->i_orphan))) {
printk("EXT4 Inode %p: orphan list check failed!\n",
EXT4_I(inode));
- print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4,
- EXT4_I(inode), sizeof(struct ext4_inode_info),
- true);
+ print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 4,
+ EXT4_I(inode), sizeof(struct ext4_inode_info),
+ true);
dump_stack();
}
kmem_cache_free(ext4_inode_cachep, EXT4_I(inode));
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index d1d4f27..c03977e 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -248,11 +248,11 @@ static int jffs2_verify_write(struct jffs2_sb_info *c, unsigned char *buf,
printk(KERN_WARNING "Write verify error (ECC %s) at %08x. Wrote:\n",
eccstr, c->wbuf_ofs);
- print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
+ print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 1,
c->wbuf, c->wbuf_pagesize, 0);
printk(KERN_WARNING "Read back:\n");
- print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
+ print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 1,
c->wbuf_verify, c->wbuf_pagesize, 0);
return -EIO;
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index 3870ba8..c22907d 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -890,7 +890,7 @@ int diFree(struct inode *ip)
* the map.
*/
if (iagno >= imap->im_nextiag) {
- print_hex_dump(KERN_ERR, "imap: ", DUMP_PREFIX_ADDRESS, 16, 4,
+ print_hex_dump(KERN_ERR, "imap: ", DUMP_PREFIX_ADDRESS, 4,
imap, 32, 0);
jfs_error(ip->i_sb,
"diFree: inum = %d, iagno = %d, nextiag = %d",
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index 15a3974..a54e19f 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -1627,15 +1627,15 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
if (lp->xflag & COMMIT_PAGE) {
struct metapage *mp = (struct metapage *)lp;
print_hex_dump(KERN_ERR, "metapage: ",
- DUMP_PREFIX_ADDRESS, 16, 4,
+ DUMP_PREFIX_ADDRESS, 4,
mp, sizeof(struct metapage), 0);
print_hex_dump(KERN_ERR, "page: ",
- DUMP_PREFIX_ADDRESS, 16,
+ DUMP_PREFIX_ADDRESS,
sizeof(long), mp->page,
sizeof(struct page), 0);
} else
print_hex_dump(KERN_ERR, "tblock:",
- DUMP_PREFIX_ADDRESS, 16, 4,
+ DUMP_PREFIX_ADDRESS, 4,
lp, sizeof(struct tblock), 0);
}
}
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index f5cd8d3..9e5fb41 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -461,7 +461,7 @@ add_failed:
printk(KERN_ERR "JFS: bio_add_page failed unexpectedly\n");
goto skip;
dump_bio:
- print_hex_dump(KERN_ERR, "JFS: dump of bio: ", DUMP_PREFIX_ADDRESS, 16,
+ print_hex_dump(KERN_ERR, "JFS: dump of bio: ", DUMP_PREFIX_ADDRESS,
4, bio, sizeof(*bio), 0);
skip:
bio_put(bio);
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index e7c60ae..a105198 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -830,14 +830,14 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
/* assert(jfs_ip->fileset == AGGREGATE_I); */
if (jfs_ip->fileset != AGGREGATE_I) {
printk(KERN_ERR "txLock: trying to lock locked page!");
- print_hex_dump(KERN_ERR, "ip: ", DUMP_PREFIX_ADDRESS, 16, 4,
+ print_hex_dump(KERN_ERR, "ip: ", DUMP_PREFIX_ADDRESS, 4,
ip, sizeof(*ip), 0);
- print_hex_dump(KERN_ERR, "mp: ", DUMP_PREFIX_ADDRESS, 16, 4,
+ print_hex_dump(KERN_ERR, "mp: ", DUMP_PREFIX_ADDRESS, 4,
mp, sizeof(*mp), 0);
print_hex_dump(KERN_ERR, "Locker's tblock: ",
- DUMP_PREFIX_ADDRESS, 16, 4, tid_to_tblock(tid),
+ DUMP_PREFIX_ADDRESS, 4, tid_to_tblock(tid),
sizeof(struct tblock), 0);
- print_hex_dump(KERN_ERR, "Tlock: ", DUMP_PREFIX_ADDRESS, 16, 4,
+ print_hex_dump(KERN_ERR, "Tlock: ", DUMP_PREFIX_ADDRESS, 4,
tlck, sizeof(*tlck), 0);
BUG();
}
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index 9b7f2cd..43c0d70 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -590,8 +590,8 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
size_check:
if (EALIST_SIZE(ea_buf->xattr) != ea_size) {
printk(KERN_ERR "ea_get: invalid extended attribute\n");
- print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1,
- ea_buf->xattr, ea_size, 1);
+ print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 1,
+ ea_buf->xattr, ea_size, 1);
ea_release(inode, ea_buf);
rc = -EIO;
goto clean_up;
^ permalink raw reply related
* [PATCH 1/7] [TFRC]: Provide central source file and debug facility
From: Arnaldo Carvalho de Melo @ 2007-12-06 21:02 UTC (permalink / raw)
To: David S. Miller
Cc: netdev, dccp, Gerrit Renker, Ian McDonald,
Arnaldo Carvalho de Melo
In-Reply-To: <1196974974-31531-1-git-send-email-acme@redhat.com>
From: Gerrit Renker <gerrit@erg.abdn.ac.uk>
This patch changes the tfrc_lib module in the following manner:
(1) a dedicated tfrc source file to call the packet history &
loss interval init/exit functions.
(2) a dedicated tfrc_pr_debug macro with toggle switch `tfrc_debug'.
Commiter note: renamed tfrc_module.c to tfrc.c, and made CONFIG_IP_DCCP_CCID3
select IP_DCCP_TFRC_LIB.
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/Kconfig | 13 ++++++---
net/dccp/ccids/lib/Makefile | 2 +-
net/dccp/ccids/lib/packet_history.c | 27 ++-----------------
net/dccp/ccids/lib/packet_history.h | 3 +-
net/dccp/ccids/lib/tfrc.c | 48 +++++++++++++++++++++++++++++++++++
net/dccp/ccids/lib/tfrc.h | 17 +++++++++---
6 files changed, 75 insertions(+), 35 deletions(-)
create mode 100644 net/dccp/ccids/lib/tfrc.c
diff --git a/net/dccp/ccids/Kconfig b/net/dccp/ccids/Kconfig
index 3d7d867..1227594 100644
--- a/net/dccp/ccids/Kconfig
+++ b/net/dccp/ccids/Kconfig
@@ -38,6 +38,7 @@ config IP_DCCP_CCID2_DEBUG
config IP_DCCP_CCID3
tristate "CCID3 (TCP-Friendly) (EXPERIMENTAL)"
def_tristate IP_DCCP
+ select IP_DCCP_TFRC_LIB
---help---
CCID 3 denotes TCP-Friendly Rate Control (TFRC), an equation-based
rate-controlled congestion control mechanism. TFRC is designed to
@@ -63,10 +64,6 @@ config IP_DCCP_CCID3
If in doubt, say M.
-config IP_DCCP_TFRC_LIB
- depends on IP_DCCP_CCID3
- def_tristate IP_DCCP_CCID3
-
config IP_DCCP_CCID3_DEBUG
bool "CCID3 debugging messages"
depends on IP_DCCP_CCID3
@@ -110,5 +107,13 @@ config IP_DCCP_CCID3_RTO
is serious network congestion: experimenting with larger values should
therefore not be performed on WANs.
+config IP_DCCP_TFRC_LIB
+ tristate
+ default n
+
+config IP_DCCP_TFRC_DEBUG
+ bool
+ depends on IP_DCCP_TFRC_LIB
+ default y if IP_DCCP_CCID3_DEBUG
endmenu
diff --git a/net/dccp/ccids/lib/Makefile b/net/dccp/ccids/lib/Makefile
index 5f940a6..68c93e3 100644
--- a/net/dccp/ccids/lib/Makefile
+++ b/net/dccp/ccids/lib/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_IP_DCCP_TFRC_LIB) += dccp_tfrc_lib.o
-dccp_tfrc_lib-y := loss_interval.o packet_history.o tfrc_equation.o
+dccp_tfrc_lib-y := tfrc.o tfrc_equation.o packet_history.o loss_interval.o
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
index 4805de9..1d4d6ee 100644
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -35,7 +35,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/module.h>
#include <linux/string.h>
#include "packet_history.h"
@@ -277,39 +276,19 @@ void dccp_rx_hist_purge(struct dccp_rx_hist *hist, struct list_head *list)
EXPORT_SYMBOL_GPL(dccp_rx_hist_purge);
-extern int __init dccp_li_init(void);
-extern void dccp_li_exit(void);
-
-static __init int packet_history_init(void)
+__init int packet_history_init(void)
{
- if (dccp_li_init() != 0)
- goto out;
-
tfrc_tx_hist = kmem_cache_create("tfrc_tx_hist",
sizeof(struct tfrc_tx_hist_entry), 0,
SLAB_HWCACHE_ALIGN, NULL);
- if (tfrc_tx_hist == NULL)
- goto out_li_exit;
- return 0;
-out_li_exit:
- dccp_li_exit();
-out:
- return -ENOBUFS;
+ return tfrc_tx_hist == NULL ? -ENOBUFS : 0;
}
-module_init(packet_history_init);
-static __exit void packet_history_exit(void)
+void packet_history_exit(void)
{
if (tfrc_tx_hist != NULL) {
kmem_cache_destroy(tfrc_tx_hist);
tfrc_tx_hist = NULL;
}
- dccp_li_exit();
}
-module_exit(packet_history_exit);
-
-MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, "
- "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>");
-MODULE_DESCRIPTION("DCCP TFRC library");
-MODULE_LICENSE("GPL");
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h
index 0670f46..9a2642e 100644
--- a/net/dccp/ccids/lib/packet_history.h
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -39,8 +39,7 @@
#include <linux/ktime.h>
#include <linux/list.h>
#include <linux/slab.h>
-
-#include "../../dccp.h"
+#include "tfrc.h"
/* Number of later packets received before one is considered lost */
#define TFRC_RECV_NUM_LATE_LOSS 3
diff --git a/net/dccp/ccids/lib/tfrc.c b/net/dccp/ccids/lib/tfrc.c
new file mode 100644
index 0000000..3a7a183
--- /dev/null
+++ b/net/dccp/ccids/lib/tfrc.c
@@ -0,0 +1,48 @@
+/*
+ * TFRC: main module holding the pieces of the TFRC library together
+ *
+ * Copyright (c) 2007 The University of Aberdeen, Scotland, UK
+ * Copyright (c) 2007 Arnaldo Carvalho de Melo <acme@redhat.com>
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include "tfrc.h"
+
+#ifdef CONFIG_IP_DCCP_TFRC_DEBUG
+int tfrc_debug;
+module_param(tfrc_debug, bool, 0444);
+MODULE_PARM_DESC(tfrc_debug, "Enable debug messages");
+#endif
+
+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();
+ }
+
+ return rc;
+}
+
+static void __exit tfrc_module_exit(void)
+{
+ packet_history_exit();
+ dccp_li_exit();
+}
+
+module_init(tfrc_module_init);
+module_exit(tfrc_module_exit);
+
+MODULE_AUTHOR("Gerrit Renker <gerrit@erg.abdn.ac.uk>, "
+ "Ian McDonald <ian.mcdonald@jandi.co.nz>, "
+ "Arnaldo Carvalho de Melo <acme@redhat.com>");
+MODULE_DESCRIPTION("DCCP TFRC library");
+MODULE_LICENSE("GPL");
diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h
index 5a0ba86..ab8848c 100644
--- a/net/dccp/ccids/lib/tfrc.h
+++ b/net/dccp/ccids/lib/tfrc.h
@@ -3,10 +3,11 @@
/*
* net/dccp/ccids/lib/tfrc.h
*
- * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- * Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
- * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
+ * Copyright (c) 2007 The University of Aberdeen, Scotland, UK
+ * Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand.
+ * Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
+ * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
*
* 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
@@ -15,6 +16,14 @@
*/
#include <linux/types.h>
#include <asm/div64.h>
+#include "../../dccp.h"
+
+#ifdef CONFIG_IP_DCCP_TFRC_DEBUG
+extern int tfrc_debug;
+#define tfrc_pr_debug(format, a...) DCCP_PR_DEBUG(tfrc_debug, format, ##a)
+#else
+#define tfrc_pr_debug(format, a...)
+#endif
/* integer-arithmetic divisions of type (a * 1000000)/b */
static inline u64 scaled_div(u64 a, u32 b)
--
1.5.3.4
^ permalink raw reply related
* [PATCH 3/7] [TFRC]: Rename tfrc_tx_hist to tfrc_tx_hist_slab, for consistency
From: Arnaldo Carvalho de Melo @ 2007-12-06 21:02 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, dccp, Arnaldo Carvalho de Melo, Gerrit Renker
In-Reply-To: <1196974974-31531-3-git-send-email-acme@redhat.com>
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 | 20 ++++++++++----------
1 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
index 1d4d6ee..b628714 100644
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -53,7 +53,7 @@ struct tfrc_tx_hist_entry {
/*
* Transmitter History Routines
*/
-static struct kmem_cache *tfrc_tx_hist;
+static struct kmem_cache *tfrc_tx_hist_slab;
static struct tfrc_tx_hist_entry *
tfrc_tx_hist_find_entry(struct tfrc_tx_hist_entry *head, u64 seqno)
@@ -66,7 +66,7 @@ static struct tfrc_tx_hist_entry *
int tfrc_tx_hist_add(struct tfrc_tx_hist_entry **headp, u64 seqno)
{
- struct tfrc_tx_hist_entry *entry = kmem_cache_alloc(tfrc_tx_hist, gfp_any());
+ struct tfrc_tx_hist_entry *entry = kmem_cache_alloc(tfrc_tx_hist_slab, gfp_any());
if (entry == NULL)
return -ENOBUFS;
@@ -85,7 +85,7 @@ void tfrc_tx_hist_purge(struct tfrc_tx_hist_entry **headp)
while (head != NULL) {
struct tfrc_tx_hist_entry *next = head->next;
- kmem_cache_free(tfrc_tx_hist, head);
+ kmem_cache_free(tfrc_tx_hist_slab, head);
head = next;
}
@@ -278,17 +278,17 @@ EXPORT_SYMBOL_GPL(dccp_rx_hist_purge);
__init int packet_history_init(void)
{
- tfrc_tx_hist = kmem_cache_create("tfrc_tx_hist",
- sizeof(struct tfrc_tx_hist_entry), 0,
- SLAB_HWCACHE_ALIGN, NULL);
+ 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 == NULL ? -ENOBUFS : 0;
+ return tfrc_tx_hist_slab == NULL ? -ENOBUFS : 0;
}
void packet_history_exit(void)
{
- if (tfrc_tx_hist != NULL) {
- kmem_cache_destroy(tfrc_tx_hist);
- tfrc_tx_hist = NULL;
+ if (tfrc_tx_hist_slab != NULL) {
+ kmem_cache_destroy(tfrc_tx_hist_slab);
+ tfrc_tx_hist_slab = NULL;
}
}
--
1.5.3.4
^ permalink raw reply related
* [PATCHES 0/7]: DCCP patches for 2.6.25
From: Arnaldo Carvalho de Melo @ 2007-12-06 21:02 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/Kconfig | 13
b/net/dccp/ccids/ccid3.c | 35 --
b/net/dccp/ccids/ccid3.h | 14
b/net/dccp/ccids/lib/Makefile | 2
b/net/dccp/ccids/lib/loss_interval.c | 14
b/net/dccp/ccids/lib/packet_history.c | 27 -
b/net/dccp/ccids/lib/packet_history.h | 3
b/net/dccp/ccids/lib/tfrc.c | 48 +++
b/net/dccp/ccids/lib/tfrc.h | 18 -
b/net/dccp/dccp.h | 13
net/dccp/ccids/ccid3.c | 322 ++++++++--------------
net/dccp/ccids/lib/loss_interval.c | 13
net/dccp/ccids/lib/packet_history.c | 496 +++++++++++++++++++---------------
net/dccp/ccids/lib/packet_history.h | 177 ++++--------
14 files changed, 579 insertions(+), 616 deletions(-)
^ permalink raw reply
* [PATCH 7/7] [TFRC]: New rx history code
From: Arnaldo Carvalho de Melo @ 2007-12-06 21:02 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, dccp, Arnaldo Carvalho de Melo, Gerrit Renker
In-Reply-To: <1196974974-31531-7-git-send-email-acme@redhat.com>
Credit here goes to Gerrit Renker, that provided the initial implementation for
this new codebase.
I modified it just to try to make it closer to the existing API, renaming some
functions, add namespacing and fix one bug where the tfrc_rx_hist_alloc was not
freeing the allocated ring entries on the error path.
Original changeset comment from Gerrit:
-----------
This provides a new, self-contained and generic RX history service for TFRC
based protocols.
Details:
* new data structure, initialisation and cleanup routines;
* allocation of dccp_rx_hist entries local to packet_history.c,
as a service exported by the dccp_tfrc_lib module.
* interface to automatically track highest-received seqno;
* receiver-based RTT estimation (needed for instance by RFC 3448, 6.3.1);
* a generic function to test for `data packets' as per RFC 4340, sec. 7.7.
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 | 288 ++++++++++++----------------------
net/dccp/ccids/ccid3.h | 14 +-
net/dccp/ccids/lib/loss_interval.c | 13 ++-
net/dccp/ccids/lib/packet_history.c | 290 +++++++++++++++++++++--------------
net/dccp/ccids/lib/packet_history.h | 83 +++++------
5 files changed, 330 insertions(+), 358 deletions(-)
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 5ff5aab..faacffa 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -641,6 +641,15 @@ static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len,
/*
* Receiver Half-Connection Routines
*/
+
+/* CCID3 feedback types */
+enum ccid3_fback_type {
+ CCID3_FBACK_NONE = 0,
+ CCID3_FBACK_INITIAL,
+ CCID3_FBACK_PERIODIC,
+ CCID3_FBACK_PARAM_CHANGE
+};
+
#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state)
{
@@ -667,59 +676,60 @@ static void ccid3_hc_rx_set_state(struct sock *sk,
hcrx->ccid3hcrx_state = state;
}
-static inline void ccid3_hc_rx_update_s(struct ccid3_hc_rx_sock *hcrx, int len)
-{
- if (likely(len > 0)) /* don't update on empty packets (e.g. ACKs) */
- hcrx->ccid3hcrx_s = tfrc_ewma(hcrx->ccid3hcrx_s, len, 9);
-}
-
-static void ccid3_hc_rx_send_feedback(struct sock *sk)
+static void ccid3_hc_rx_send_feedback(struct sock *sk,
+ const struct sk_buff *skb,
+ enum ccid3_fback_type fbtype)
{
struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
struct dccp_sock *dp = dccp_sk(sk);
- struct tfrc_rx_hist_entry *packet;
ktime_t now;
- suseconds_t delta;
+ s64 delta = 0;
ccid3_pr_debug("%s(%p) - entry \n", dccp_role(sk), sk);
+ if (unlikely(hcrx->ccid3hcrx_state == TFRC_RSTATE_TERM))
+ return;
+
now = ktime_get_real();
- switch (hcrx->ccid3hcrx_state) {
- case TFRC_RSTATE_NO_DATA:
+ switch (fbtype) {
+ case CCID3_FBACK_INITIAL:
hcrx->ccid3hcrx_x_recv = 0;
+ hcrx->ccid3hcrx_pinv = ~0U; /* see RFC 4342, 8.5 */
break;
- case TFRC_RSTATE_DATA:
- delta = ktime_us_delta(now,
- hcrx->ccid3hcrx_tstamp_last_feedback);
- DCCP_BUG_ON(delta < 0);
- hcrx->ccid3hcrx_x_recv =
- scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);
+ case CCID3_FBACK_PARAM_CHANGE:
+ /*
+ * When parameters change (new loss or p > p_prev), we do not
+ * have a reliable estimate for R_m of [RFC 3448, 6.2] and so
+ * need to reuse the previous value of X_recv. However, when
+ * X_recv was 0 (due to early loss), this would kill X down to
+ * s/t_mbi (i.e. one packet in 64 seconds).
+ * To avoid such drastic reduction, we approximate X_recv as
+ * the number of bytes since last feedback.
+ * This is a safe fallback, since X is bounded above by X_calc.
+ */
+ if (hcrx->ccid3hcrx_x_recv > 0)
+ break;
+ /* fall through */
+ case CCID3_FBACK_PERIODIC:
+ delta = ktime_us_delta(now, hcrx->ccid3hcrx_tstamp_last_feedback);
+ if (delta <= 0)
+ DCCP_BUG("delta (%ld) <= 0", (long)delta);
+ else
+ hcrx->ccid3hcrx_x_recv =
+ scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);
break;
- case TFRC_RSTATE_TERM:
- DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
+ default:
return;
}
- packet = tfrc_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist);
- if (unlikely(packet == NULL)) {
- DCCP_WARN("%s(%p), no data packet in history!\n",
- dccp_role(sk), sk);
- return;
- }
+ ccid3_pr_debug("Interval %ldusec, X_recv=%u, 1/p=%u\n", (long)delta,
+ hcrx->ccid3hcrx_x_recv, hcrx->ccid3hcrx_pinv);
hcrx->ccid3hcrx_tstamp_last_feedback = now;
- hcrx->ccid3hcrx_ccval_last_counter = packet->tfrchrx_ccval;
+ hcrx->ccid3hcrx_last_counter = dccp_hdr(skb)->dccph_ccval;
hcrx->ccid3hcrx_bytes_recv = 0;
- if (hcrx->ccid3hcrx_p == 0)
- hcrx->ccid3hcrx_pinv = ~0U; /* see RFC 4342, 8.5 */
- else if (hcrx->ccid3hcrx_p > 1000000) {
- DCCP_WARN("p (%u) > 100%%\n", hcrx->ccid3hcrx_p);
- hcrx->ccid3hcrx_pinv = 1; /* use 100% in this case */
- } else
- hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p;
-
dp->dccps_hc_rx_insert_options = 1;
dccp_send_ack(sk);
}
@@ -750,165 +760,74 @@ static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
return 0;
}
-static int ccid3_hc_rx_detect_loss(struct sock *sk,
- struct tfrc_rx_hist_entry *packet)
-{
- struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
- struct tfrc_rx_hist_entry *rx_hist =
- tfrc_rx_hist_head(&hcrx->ccid3hcrx_hist);
- u64 seqno = packet->tfrchrx_seqno;
- u64 tmp_seqno;
- int loss = 0;
- u8 ccval;
-
-
- tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss;
-
- if (!rx_hist ||
- follows48(packet->tfrchrx_seqno, hcrx->ccid3hcrx_seqno_nonloss)) {
- hcrx->ccid3hcrx_seqno_nonloss = seqno;
- hcrx->ccid3hcrx_ccval_nonloss = packet->tfrchrx_ccval;
- goto detect_out;
- }
-
-
- while (dccp_delta_seqno(hcrx->ccid3hcrx_seqno_nonloss, seqno)
- > TFRC_RECV_NUM_LATE_LOSS) {
- loss = 1;
- dccp_li_update_li(sk,
- &hcrx->ccid3hcrx_li_hist,
- &hcrx->ccid3hcrx_hist,
- hcrx->ccid3hcrx_tstamp_last_feedback,
- hcrx->ccid3hcrx_s,
- hcrx->ccid3hcrx_bytes_recv,
- hcrx->ccid3hcrx_x_recv,
- hcrx->ccid3hcrx_seqno_nonloss,
- hcrx->ccid3hcrx_ccval_nonloss);
- tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss;
- dccp_inc_seqno(&tmp_seqno);
- hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
- dccp_inc_seqno(&tmp_seqno);
- while (tfrc_rx_hist_find_entry(&hcrx->ccid3hcrx_hist,
- tmp_seqno, &ccval)) {
- hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
- hcrx->ccid3hcrx_ccval_nonloss = ccval;
- dccp_inc_seqno(&tmp_seqno);
- }
- }
-
- /* FIXME - this code could be simplified with above while */
- /* but works at moment */
- if (follows48(packet->tfrchrx_seqno, hcrx->ccid3hcrx_seqno_nonloss)) {
- hcrx->ccid3hcrx_seqno_nonloss = seqno;
- hcrx->ccid3hcrx_ccval_nonloss = packet->tfrchrx_ccval;
- }
-
-detect_out:
- tfrc_rx_hist_add_packet(&hcrx->ccid3hcrx_hist,
- &hcrx->ccid3hcrx_li_hist, packet,
- hcrx->ccid3hcrx_seqno_nonloss);
- return loss;
-}
-
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);
- const struct dccp_options_received *opt_recv;
- struct tfrc_rx_hist_entry *packet;
- u32 p_prev, r_sample, rtt_prev;
- int loss, payload_size;
- ktime_t now;
-
- opt_recv = &dccp_sk(sk)->dccps_options_received;
-
- switch (DCCP_SKB_CB(skb)->dccpd_type) {
- case DCCP_PKT_ACK:
- if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)
- return;
- case DCCP_PKT_DATAACK:
- if (opt_recv->dccpor_timestamp_echo == 0)
- break;
- r_sample = dccp_timestamp() - opt_recv->dccpor_timestamp_echo;
- rtt_prev = hcrx->ccid3hcrx_rtt;
- r_sample = dccp_sample_rtt(sk, 10 * r_sample);
-
- if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)
- hcrx->ccid3hcrx_rtt = r_sample;
- else
- hcrx->ccid3hcrx_rtt = (hcrx->ccid3hcrx_rtt * 9) / 10 +
- r_sample / 10;
-
- if (rtt_prev != hcrx->ccid3hcrx_rtt)
- ccid3_pr_debug("%s(%p), New RTT=%uus, elapsed time=%u\n",
- dccp_role(sk), sk, hcrx->ccid3hcrx_rtt,
- opt_recv->dccpor_elapsed_time);
- break;
- case DCCP_PKT_DATA:
- break;
- default: /* We're not interested in other packet types, move along */
- return;
- }
-
- packet = tfrc_rx_hist_entry_new(opt_recv->dccpor_ndp, skb, GFP_ATOMIC);
- if (unlikely(packet == NULL)) {
- DCCP_WARN("%s(%p), Not enough mem to add rx packet "
- "to history, consider it lost!\n", dccp_role(sk), sk);
- return;
- }
-
- loss = ccid3_hc_rx_detect_loss(sk, packet);
+ enum ccid3_fback_type do_feedback = CCID3_FBACK_NONE;
+ const u32 ndp = dccp_sk(sk)->dccps_options_received.dccpor_ndp;
+ const bool is_data_packet = dccp_data_packet(skb);
+
+ if (unlikely(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)) {
+ if (is_data_packet) {
+ const u32 payload = skb->len - dccp_hdr(skb)->dccph_doff * 4;
+ do_feedback = CCID3_FBACK_INITIAL;
+ ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA);
+ hcrx->ccid3hcrx_s = payload;
+ /*
+ * Not necessary to update ccid3hcrx_bytes_recv here,
+ * since X_recv = 0 for the first feedback packet (cf.
+ * RFC 3448, 6.3) -- gerrit
+ */
+ }
+ goto update_records;
+ }
- if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK)
- return;
+ if (tfrc_rx_hist_duplicate(&hcrx->ccid3hcrx_hist, skb))
+ return; /* done receiving */
- payload_size = skb->len - dccp_hdr(skb)->dccph_doff * 4;
- ccid3_hc_rx_update_s(hcrx, payload_size);
+ if (is_data_packet) {
+ const u32 payload = skb->len - dccp_hdr(skb)->dccph_doff * 4;
+ /*
+ * Update moving-average of s and the sum of received payload bytes
+ */
+ hcrx->ccid3hcrx_s = tfrc_ewma(hcrx->ccid3hcrx_s, payload, 9);
+ hcrx->ccid3hcrx_bytes_recv += payload;
+ }
- switch (hcrx->ccid3hcrx_state) {
- case TFRC_RSTATE_NO_DATA:
- ccid3_pr_debug("%s(%p, state=%s), skb=%p, sending initial "
- "feedback\n", dccp_role(sk), sk,
- dccp_state_name(sk->sk_state), skb);
- ccid3_hc_rx_send_feedback(sk);
- ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA);
- return;
- case TFRC_RSTATE_DATA:
- hcrx->ccid3hcrx_bytes_recv += payload_size;
- if (loss)
- break;
+ /*
+ * Handle pending losses and otherwise check for new loss
+ */
+ if (tfrc_rx_hist_new_loss_indicated(&hcrx->ccid3hcrx_hist, skb, ndp))
+ goto update_records;
- now = ktime_get_real();
- if ((ktime_us_delta(now, hcrx->ccid3hcrx_tstamp_last_ack) -
- (s64)hcrx->ccid3hcrx_rtt) >= 0) {
- hcrx->ccid3hcrx_tstamp_last_ack = now;
- ccid3_hc_rx_send_feedback(sk);
- }
- return;
- case TFRC_RSTATE_TERM:
- DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
- return;
+ /*
+ * Handle data packets: RTT sampling and monitoring p
+ */
+ if (unlikely(!is_data_packet))
+ goto update_records;
+
+ if (list_empty(&hcrx->ccid3hcrx_li_hist)) { /* no loss so far: p = 0 */
+ const u32 sample = tfrc_rx_hist_sample_rtt(&hcrx->ccid3hcrx_hist, skb);
+ /*
+ * Empty loss history: no loss so far, hence p stays 0.
+ * Sample RTT values, since an RTT estimate is required for the
+ * computation of p when the first loss occurs; RFC 3448, 6.3.1.
+ */
+ if (sample != 0)
+ hcrx->ccid3hcrx_rtt = tfrc_ewma(hcrx->ccid3hcrx_rtt, sample, 9);
}
- /* Dealing with packet loss */
- ccid3_pr_debug("%s(%p, state=%s), data loss! Reacting...\n",
- dccp_role(sk), sk, dccp_state_name(sk->sk_state));
-
- p_prev = hcrx->ccid3hcrx_p;
-
- /* Calculate loss event rate */
- if (!list_empty(&hcrx->ccid3hcrx_li_hist)) {
- u32 i_mean = dccp_li_hist_calc_i_mean(&hcrx->ccid3hcrx_li_hist);
+ /*
+ * Check if the periodic once-per-RTT feedback is due; RFC 4342, 10.3
+ */
+ if (SUB16(dccp_hdr(skb)->dccph_ccval, hcrx->ccid3hcrx_last_counter) > 3)
+ do_feedback = CCID3_FBACK_PERIODIC;
- /* Scaling up by 1000000 as fixed decimal */
- if (i_mean != 0)
- hcrx->ccid3hcrx_p = 1000000 / i_mean;
- } else
- DCCP_BUG("empty loss history");
+update_records:
+ tfrc_rx_hist_add_packet(&hcrx->ccid3hcrx_hist, skb, ndp);
- if (hcrx->ccid3hcrx_p > p_prev) {
- ccid3_hc_rx_send_feedback(sk);
- return;
- }
+ if (do_feedback)
+ ccid3_hc_rx_send_feedback(sk, skb, do_feedback);
}
static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
@@ -918,11 +837,8 @@ static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
ccid3_pr_debug("entry\n");
hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
- INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);
INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist);
- hcrx->ccid3hcrx_tstamp_last_feedback =
- hcrx->ccid3hcrx_tstamp_last_ack = ktime_get_real();
- return 0;
+ return tfrc_rx_hist_alloc(&hcrx->ccid3hcrx_hist);
}
static void ccid3_hc_rx_exit(struct sock *sk)
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index b842a7d..3c33dc6 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -1,7 +1,8 @@
/*
* net/dccp/ccids/ccid3.h
*
- * Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand.
+ * Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
+ * Copyright (c) 2007 The University of Aberdeen, Scotland, UK
*
* An implementation of the DCCP protocol
*
@@ -135,9 +136,7 @@ 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_seqno_nonloss - Last received non-loss sequence number
- * @ccid3hcrx_ccval_nonloss - Last received non-loss Window CCVal
- * @ccid3hcrx_ccval_last_counter - Tracks window counter (RFC 4342, 8.1)
+ * @ccid3hcrx_last_counter - Tracks window counter (RFC 4342, 8.1)
* @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
@@ -152,14 +151,11 @@ struct ccid3_hc_rx_sock {
#define ccid3hcrx_x_recv ccid3hcrx_tfrc.tfrcrx_x_recv
#define ccid3hcrx_rtt ccid3hcrx_tfrc.tfrcrx_rtt
#define ccid3hcrx_p ccid3hcrx_tfrc.tfrcrx_p
- u64 ccid3hcrx_seqno_nonloss:48,
- ccid3hcrx_ccval_nonloss:4,
- ccid3hcrx_ccval_last_counter:4;
+ u8 ccid3hcrx_last_counter:4;
enum ccid3_hc_rx_states ccid3hcrx_state:8;
u32 ccid3hcrx_bytes_recv;
ktime_t ccid3hcrx_tstamp_last_feedback;
- ktime_t ccid3hcrx_tstamp_last_ack;
- struct list_head ccid3hcrx_hist;
+ struct tfrc_rx_hist ccid3hcrx_hist;
struct list_head ccid3hcrx_li_hist;
u16 ccid3hcrx_s;
u32 ccid3hcrx_pinv;
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c
index a5f59af..7e0714a 100644
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -129,6 +129,13 @@ static u32 dccp_li_calc_first_li(struct sock *sk,
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;
@@ -216,10 +223,10 @@ found:
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 ~0;
- else
+ if (p != 0)
return 1000000 / p;
+#endif
+ return ~0;
}
void dccp_li_update_li(struct sock *sk,
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
index 255cca1..e197389 100644
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -36,7 +36,9 @@
*/
#include <linux/string.h>
+#include <linux/slab.h>
#include "packet_history.h"
+#include "../../dccp.h"
/**
* tfrc_tx_hist_entry - Simple singly-linked TX history list
@@ -111,154 +113,214 @@ u32 tfrc_tx_hist_rtt(struct tfrc_tx_hist_entry *head, const u64 seqno,
}
EXPORT_SYMBOL_GPL(tfrc_tx_hist_rtt);
+
+/**
+ * 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)];
+}
+
/*
* Receiver History Routines
*/
static struct kmem_cache *tfrc_rx_hist_slab;
-struct tfrc_rx_hist_entry *tfrc_rx_hist_entry_new(const u32 ndp,
- const struct sk_buff *skb,
- const gfp_t prio)
+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 = kmem_cache_alloc(tfrc_rx_hist_slab,
- prio);
-
- if (entry != NULL) {
- const struct dccp_hdr *dh = dccp_hdr(skb);
-
- entry->tfrchrx_seqno = DCCP_SKB_CB(skb)->dccpd_seq;
- entry->tfrchrx_ccval = dh->dccph_ccval;
- entry->tfrchrx_type = dh->dccph_type;
- entry->tfrchrx_ndp = ndp;
- entry->tfrchrx_tstamp = ktime_get_real();
- }
-
- return entry;
+ 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;
+ entry->tfrchrx_ccval = dh->dccph_ccval;
+ entry->tfrchrx_type = dh->dccph_type;
+ entry->tfrchrx_ndp = ndp;
+ entry->tfrchrx_tstamp = ktime_get_real();
}
-EXPORT_SYMBOL_GPL(tfrc_rx_hist_entry_new);
+EXPORT_SYMBOL_GPL(tfrc_rx_hist_add_packet);
static inline void tfrc_rx_hist_entry_delete(struct tfrc_rx_hist_entry *entry)
{
kmem_cache_free(tfrc_rx_hist_slab, entry);
}
-int tfrc_rx_hist_find_entry(const struct list_head *list, const u64 seq,
- u8 *ccval)
+/**
+ * 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)
{
- struct tfrc_rx_hist_entry *packet = NULL, *entry;
+ return h->ring[tfrc_rx_hist_index(h, n)];
+}
- list_for_each_entry(entry, list, tfrchrx_node)
- if (entry->tfrchrx_seqno == seq) {
- packet = entry;
- break;
- }
+/**
+ * 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)
+{
+ const u64 seq = DCCP_SKB_CB(skb)->dccpd_seq;
+ int i;
+
+ if (dccp_delta_seqno(tfrc_rx_hist_loss_prev(h)->tfrchrx_seqno, seq) <= 0)
+ return 1;
- if (packet)
- *ccval = packet->tfrchrx_ccval;
+ for (i = 1; i <= h->loss_count; i++)
+ if (tfrc_rx_hist_entry(h, i)->tfrchrx_seqno == seq)
+ return 1;
- return packet != NULL;
+ return 0;
}
+EXPORT_SYMBOL_GPL(tfrc_rx_hist_duplicate);
-EXPORT_SYMBOL_GPL(tfrc_rx_hist_find_entry);
-struct tfrc_rx_hist_entry *
- tfrc_rx_hist_find_data_packet(const struct list_head *list)
+/* initialise loss detection and disable RTT sampling */
+static inline void tfrc_rx_hist_loss_indicated(struct tfrc_rx_hist *h)
{
- struct tfrc_rx_hist_entry *entry, *packet = NULL;
+ h->loss_count = 1;
+}
- list_for_each_entry(entry, list, tfrchrx_node)
- if (entry->tfrchrx_type == DCCP_PKT_DATA ||
- entry->tfrchrx_type == DCCP_PKT_DATAACK) {
- packet = entry;
- break;
- }
+/* 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 packet;
+ return tfrc_rx_hist_loss_pending(h);
}
+EXPORT_SYMBOL_GPL(tfrc_rx_hist_new_loss_indicated);
-EXPORT_SYMBOL_GPL(tfrc_rx_hist_find_data_packet);
+int tfrc_rx_hist_alloc(struct tfrc_rx_hist *h)
+{
+ int i;
+
+ for (i = 0; i <= TFRC_NDUPACK; i++) {
+ h->ring[i] = kmem_cache_alloc(tfrc_rx_hist_slab, GFP_ATOMIC);
+ if (h->ring[i] == NULL)
+ goto out_free;
+ }
+
+ h->loss_count = h->loss_start = 0;
+ return 0;
+
+out_free:
+ while (i-- != 0) {
+ kmem_cache_free(tfrc_rx_hist_slab, h->ring[i]);
+ h->ring[i] = NULL;
+ }
+ return -ENOBUFS;
+}
+EXPORT_SYMBOL_GPL(tfrc_rx_hist_alloc);
-void tfrc_rx_hist_add_packet(struct list_head *rx_list,
- struct list_head *li_list,
- struct tfrc_rx_hist_entry *packet,
- u64 nonloss_seqno)
+void tfrc_rx_hist_purge(struct tfrc_rx_hist *h)
{
- struct tfrc_rx_hist_entry *entry, *next;
- u8 num_later = 0;
-
- list_add(&packet->tfrchrx_node, rx_list);
-
- num_later = TFRC_RECV_NUM_LATE_LOSS + 1;
-
- if (!list_empty(li_list)) {
- list_for_each_entry_safe(entry, next, rx_list, tfrchrx_node) {
- if (num_later == 0) {
- if (after48(nonloss_seqno,
- entry->tfrchrx_seqno)) {
- list_del_init(&entry->tfrchrx_node);
- tfrc_rx_hist_entry_delete(entry);
- }
- } else if (tfrc_rx_hist_entry_data_packet(entry))
- --num_later;
- }
- } else {
- int step = 0;
- u8 win_count = 0; /* Not needed, but lets shut up gcc */
- int tmp;
- /*
- * We have no loss interval history so we need at least one
- * rtt:s of data packets to approximate rtt.
- */
- list_for_each_entry_safe(entry, next, rx_list, tfrchrx_node) {
- if (num_later == 0) {
- switch (step) {
- case 0:
- step = 1;
- /* OK, find next data packet */
- num_later = 1;
- break;
- case 1:
- step = 2;
- /* OK, find next data packet */
- num_later = 1;
- win_count = entry->tfrchrx_ccval;
- break;
- case 2:
- tmp = win_count - entry->tfrchrx_ccval;
- if (tmp < 0)
- tmp += TFRC_WIN_COUNT_LIMIT;
- if (tmp > TFRC_WIN_COUNT_PER_RTT + 1) {
- /*
- * We have found a packet older
- * than one rtt remove the rest
- */
- step = 3;
- } else /* OK, find next data packet */
- num_later = 1;
- break;
- case 3:
- list_del_init(&entry->tfrchrx_node);
- tfrc_rx_hist_entry_delete(entry);
- break;
- }
- } else if (tfrc_rx_hist_entry_data_packet(entry))
- --num_later;
+ int i;
+
+ for (i = 0; i <= TFRC_NDUPACK; ++i)
+ if (h->ring[i] != NULL) {
+ kmem_cache_free(tfrc_rx_hist_slab, h->ring[i]);
+ h->ring[i] = NULL;
}
- }
}
+EXPORT_SYMBOL_GPL(tfrc_rx_hist_purge);
-EXPORT_SYMBOL_GPL(tfrc_rx_hist_add_packet);
+/**
+ * tfrc_rx_hist_rtt_last_s - reference entry to compute RTT samples against
+ */
+static inline struct tfrc_rx_hist_entry *
+ tfrc_rx_hist_rtt_last_s(const struct tfrc_rx_hist *h)
+{
+ return h->ring[0];
+}
-void tfrc_rx_hist_purge(struct list_head *list)
+/**
+ * tfrc_rx_hist_rtt_prev_s: previously suitable (wrt rtt_last_s) RTT-sampling entry
+ */
+static inline struct tfrc_rx_hist_entry *
+ tfrc_rx_hist_rtt_prev_s(const struct tfrc_rx_hist *h)
{
- struct tfrc_rx_hist_entry *entry, *next;
+ return h->ring[h->rtt_sample_prev];
+}
- list_for_each_entry_safe(entry, next, list, tfrchrx_node) {
- list_del_init(&entry->tfrchrx_node);
- tfrc_rx_hist_entry_delete(entry);
+/**
+ * tfrc_rx_hist_sample_rtt - Sample RTT from timestamp / CCVal
+ * Based on ideas presented in RFC 4342, 8.1. Returns 0 if it was not able
+ * to compute a sample with given data - calling function should check this.
+ */
+u32 tfrc_rx_hist_sample_rtt(struct tfrc_rx_hist *h, const struct sk_buff *skb)
+{
+ u32 sample = 0,
+ delta_v = SUB16(dccp_hdr(skb)->dccph_ccval,
+ tfrc_rx_hist_rtt_last_s(h)->tfrchrx_ccval);
+
+ if (delta_v < 1 || delta_v > 4) { /* unsuitable CCVal delta */
+ if (h->rtt_sample_prev == 2) { /* previous candidate stored */
+ sample = SUB16(tfrc_rx_hist_rtt_prev_s(h)->tfrchrx_ccval,
+ tfrc_rx_hist_rtt_last_s(h)->tfrchrx_ccval);
+ if (sample)
+ sample = 4 / sample *
+ ktime_us_delta(tfrc_rx_hist_rtt_prev_s(h)->tfrchrx_tstamp,
+ tfrc_rx_hist_rtt_last_s(h)->tfrchrx_tstamp);
+ else /*
+ * FIXME: This condition is in principle not
+ * possible but occurs when CCID is used for
+ * two-way data traffic. I have tried to trace
+ * it, but the cause does not seem to be here.
+ */
+ DCCP_BUG("please report to dccp@vger.kernel.org"
+ " => prev = %u, last = %u",
+ tfrc_rx_hist_rtt_prev_s(h)->tfrchrx_ccval,
+ tfrc_rx_hist_rtt_last_s(h)->tfrchrx_ccval);
+ } else if (delta_v < 1) {
+ h->rtt_sample_prev = 1;
+ goto keep_ref_for_next_time;
+ }
+
+ } else if (delta_v == 4) /* optimal match */
+ sample = ktime_to_us(net_timedelta(tfrc_rx_hist_rtt_last_s(h)->tfrchrx_tstamp));
+ else { /* suboptimal match */
+ h->rtt_sample_prev = 2;
+ goto keep_ref_for_next_time;
}
-}
-EXPORT_SYMBOL_GPL(tfrc_rx_hist_purge);
+ if (unlikely(sample > DCCP_SANE_RTT_MAX)) {
+ DCCP_WARN("RTT sample %u too large, using max\n", sample);
+ sample = DCCP_SANE_RTT_MAX;
+ }
+
+ h->rtt_sample_prev = 0; /* use current entry as next reference */
+keep_ref_for_next_time:
+
+ return sample;
+}
+EXPORT_SYMBOL_GPL(tfrc_rx_hist_sample_rtt);
__init int packet_history_init(void)
{
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h
index 5b0b983..3dfd182 100644
--- a/net/dccp/ccids/lib/packet_history.h
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -37,15 +37,9 @@
#define _DCCP_PKT_HIST_
#include <linux/ktime.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include "tfrc.h"
+#include <linux/types.h>
-/* Number of later packets received before one is considered lost */
-#define TFRC_RECV_NUM_LATE_LOSS 3
-
-#define TFRC_WIN_COUNT_PER_RTT 4
-#define TFRC_WIN_COUNT_LIMIT 16
+struct sk_buff;
struct tfrc_tx_hist_entry;
@@ -54,11 +48,20 @@ extern void tfrc_tx_hist_purge(struct tfrc_tx_hist_entry **headp);
extern u32 tfrc_tx_hist_rtt(struct tfrc_tx_hist_entry *head,
const u64 seqno, const ktime_t now);
-/*
- * Receiver History data structures and declarations
+/* Subtraction a-b modulo-16, respects circular wrap-around */
+#define SUB16(a, b) (((a) + 16 - (b)) & 0xF)
+
+/* Number of packets to wait after a missing packet (RFC 4342, 6.1) */
+#define TFRC_NDUPACK 3
+
+/**
+ * tfrc_rx_hist_entry - Store information about a single received packet
+ * @tfrchrx_seqno: DCCP packet sequence number
+ * @tfrchrx_ccval: window counter value of packet (RFC 4342, 8.1)
+ * @tfrchrx_ndp: the NDP count (if any) of the packet
+ * @tfrchrx_tstamp: actual receive time of packet
*/
struct tfrc_rx_hist_entry {
- struct list_head tfrchrx_node;
u64 tfrchrx_seqno:48,
tfrchrx_ccval:4,
tfrchrx_type:4;
@@ -66,42 +69,30 @@ struct tfrc_rx_hist_entry {
ktime_t tfrchrx_tstamp;
};
-extern struct tfrc_rx_hist_entry *
- tfrc_rx_hist_entry_new(const u32 ndp,
- const struct sk_buff *skb,
- const gfp_t prio);
-
-static inline struct tfrc_rx_hist_entry *
- tfrc_rx_hist_head(struct list_head *list)
-{
- struct tfrc_rx_hist_entry *head = NULL;
-
- if (!list_empty(list))
- head = list_entry(list->next, struct tfrc_rx_hist_entry,
- tfrchrx_node);
- return head;
-}
-
-extern int tfrc_rx_hist_find_entry(const struct list_head *list, const u64 seq,
- u8 *ccval);
-extern struct tfrc_rx_hist_entry *
- tfrc_rx_hist_find_data_packet(const struct list_head *list);
-
-extern void tfrc_rx_hist_add_packet(struct list_head *rx_list,
- struct list_head *li_list,
- struct tfrc_rx_hist_entry *packet,
- u64 nonloss_seqno);
-
-extern void tfrc_rx_hist_purge(struct list_head *list);
+/**
+ * tfrc_rx_hist - RX history structure for TFRC-based protocols
+ *
+ * @ring: Packet history for RTT sampling and loss detection
+ * @loss_count: Number of entries in circular history
+ * @loss_start: Movable index (for loss detection)
+ * @rtt_sample_prev: Used during RTT sampling, points to candidate entry
+ */
+struct tfrc_rx_hist {
+ struct tfrc_rx_hist_entry *ring[TFRC_NDUPACK + 1];
+ u8 loss_count:2,
+ loss_start:2;
+#define rtt_sample_prev loss_start
+};
-static inline int
- tfrc_rx_hist_entry_data_packet(const struct tfrc_rx_hist_entry *entry)
-{
- return entry->tfrchrx_type == DCCP_PKT_DATA ||
- entry->tfrchrx_type == DCCP_PKT_DATAACK;
-}
+extern void tfrc_rx_hist_add_packet(struct tfrc_rx_hist *h,
+ const struct sk_buff *skb, const u32 ndp);
-extern u64 tfrc_rx_hist_detect_loss(struct list_head *rx_list,
- struct list_head *li_list, u8 *win_loss);
+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);
+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);
+extern void tfrc_rx_hist_purge(struct tfrc_rx_hist *h);
#endif /* _DCCP_PKT_HIST_ */
--
1.5.3.4
^ permalink raw reply related
* [PATCH 5/7] [TFRC]: Rename dccp_rx_ to tfrc_rx_
From: Arnaldo Carvalho de Melo @ 2007-12-06 21:02 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, dccp, Arnaldo Carvalho de Melo, Gerrit Renker
In-Reply-To: <1196974974-31531-5-git-send-email-acme@redhat.com>
This is in preparation for merging the new rx history code written by Gerrit Renker.
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 | 32 ++++++------
net/dccp/ccids/lib/loss_interval.c | 14 +++---
net/dccp/ccids/lib/packet_history.c | 90 +++++++++++++++++-----------------
net/dccp/ccids/lib/packet_history.h | 48 +++++++++---------
4 files changed, 92 insertions(+), 92 deletions(-)
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 07920bb..c95dca8 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -677,7 +677,7 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
{
struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
struct dccp_sock *dp = dccp_sk(sk);
- struct dccp_rx_hist_entry *packet;
+ struct tfrc_rx_hist_entry *packet;
ktime_t now;
suseconds_t delta;
@@ -701,7 +701,7 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
return;
}
- packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist);
+ packet = tfrc_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist);
if (unlikely(packet == NULL)) {
DCCP_WARN("%s(%p), no data packet in history!\n",
dccp_role(sk), sk);
@@ -709,7 +709,7 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
}
hcrx->ccid3hcrx_tstamp_last_feedback = now;
- hcrx->ccid3hcrx_ccval_last_counter = packet->dccphrx_ccval;
+ hcrx->ccid3hcrx_ccval_last_counter = packet->tfrchrx_ccval;
hcrx->ccid3hcrx_bytes_recv = 0;
if (hcrx->ccid3hcrx_p == 0)
@@ -752,12 +752,12 @@ static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
}
static int ccid3_hc_rx_detect_loss(struct sock *sk,
- struct dccp_rx_hist_entry *packet)
+ struct tfrc_rx_hist_entry *packet)
{
struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
- struct dccp_rx_hist_entry *rx_hist =
- dccp_rx_hist_head(&hcrx->ccid3hcrx_hist);
- u64 seqno = packet->dccphrx_seqno;
+ struct tfrc_rx_hist_entry *rx_hist =
+ tfrc_rx_hist_head(&hcrx->ccid3hcrx_hist);
+ u64 seqno = packet->tfrchrx_seqno;
u64 tmp_seqno;
int loss = 0;
u8 ccval;
@@ -766,9 +766,9 @@ static int ccid3_hc_rx_detect_loss(struct sock *sk,
tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss;
if (!rx_hist ||
- follows48(packet->dccphrx_seqno, hcrx->ccid3hcrx_seqno_nonloss)) {
+ follows48(packet->tfrchrx_seqno, hcrx->ccid3hcrx_seqno_nonloss)) {
hcrx->ccid3hcrx_seqno_nonloss = seqno;
- hcrx->ccid3hcrx_ccval_nonloss = packet->dccphrx_ccval;
+ hcrx->ccid3hcrx_ccval_nonloss = packet->tfrchrx_ccval;
goto detect_out;
}
@@ -789,7 +789,7 @@ static int ccid3_hc_rx_detect_loss(struct sock *sk,
dccp_inc_seqno(&tmp_seqno);
hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
dccp_inc_seqno(&tmp_seqno);
- while (dccp_rx_hist_find_entry(&hcrx->ccid3hcrx_hist,
+ while (tfrc_rx_hist_find_entry(&hcrx->ccid3hcrx_hist,
tmp_seqno, &ccval)) {
hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
hcrx->ccid3hcrx_ccval_nonloss = ccval;
@@ -799,13 +799,13 @@ static int ccid3_hc_rx_detect_loss(struct sock *sk,
/* FIXME - this code could be simplified with above while */
/* but works at moment */
- if (follows48(packet->dccphrx_seqno, hcrx->ccid3hcrx_seqno_nonloss)) {
+ if (follows48(packet->tfrchrx_seqno, hcrx->ccid3hcrx_seqno_nonloss)) {
hcrx->ccid3hcrx_seqno_nonloss = seqno;
- hcrx->ccid3hcrx_ccval_nonloss = packet->dccphrx_ccval;
+ hcrx->ccid3hcrx_ccval_nonloss = packet->tfrchrx_ccval;
}
detect_out:
- dccp_rx_hist_add_packet(&hcrx->ccid3hcrx_hist,
+ tfrc_rx_hist_add_packet(&hcrx->ccid3hcrx_hist,
&hcrx->ccid3hcrx_li_hist, packet,
hcrx->ccid3hcrx_seqno_nonloss);
return loss;
@@ -815,7 +815,7 @@ 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);
const struct dccp_options_received *opt_recv;
- struct dccp_rx_hist_entry *packet;
+ struct tfrc_rx_hist_entry *packet;
u32 p_prev, r_sample, rtt_prev;
int loss, payload_size;
ktime_t now;
@@ -850,7 +850,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
return;
}
- packet = dccp_rx_hist_entry_new(opt_recv->dccpor_ndp, skb, GFP_ATOMIC);
+ packet = tfrc_rx_hist_entry_new(opt_recv->dccpor_ndp, skb, GFP_ATOMIC);
if (unlikely(packet == NULL)) {
DCCP_WARN("%s(%p), Not enough mem to add rx packet "
"to history, consider it lost!\n", dccp_role(sk), sk);
@@ -933,7 +933,7 @@ static void ccid3_hc_rx_exit(struct sock *sk)
ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM);
/* Empty packet history */
- dccp_rx_hist_purge(&hcrx->ccid3hcrx_hist);
+ tfrc_rx_hist_purge(&hcrx->ccid3hcrx_hist);
/* Empty loss interval history */
dccp_li_hist_purge(&hcrx->ccid3hcrx_li_hist);
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c
index f2ca4eb..a5f59af 100644
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -129,7 +129,7 @@ static u32 dccp_li_calc_first_li(struct sock *sk,
u16 s, u32 bytes_recv,
u32 previous_x_recv)
{
- struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
+ struct tfrc_rx_hist_entry *entry, *next, *tail = NULL;
u32 x_recv, p;
suseconds_t rtt, delta;
ktime_t tstamp = ktime_set(0, 0);
@@ -138,18 +138,18 @@ static u32 dccp_li_calc_first_li(struct sock *sk,
int step = 0;
u64 fval;
- list_for_each_entry_safe(entry, next, hist_list, dccphrx_node) {
- if (dccp_rx_hist_entry_data_packet(entry)) {
+ 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->dccphrx_tstamp;
- win_count = entry->dccphrx_ccval;
+ tstamp = entry->tfrchrx_tstamp;
+ win_count = entry->tfrchrx_ccval;
step = 1;
break;
case 1:
- interval = win_count - entry->dccphrx_ccval;
+ interval = win_count - entry->tfrchrx_ccval;
if (interval < 0)
interval += TFRC_WIN_COUNT_LIMIT;
if (interval > 4)
@@ -176,7 +176,7 @@ found:
return ~0;
}
- delta = ktime_us_delta(tstamp, tail->dccphrx_tstamp);
+ delta = ktime_us_delta(tstamp, tail->tfrchrx_tstamp);
DCCP_BUG_ON(delta < 0);
rtt = delta * 4 / interval;
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
index e1ab853..255cca1 100644
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -116,58 +116,58 @@ EXPORT_SYMBOL_GPL(tfrc_tx_hist_rtt);
*/
static struct kmem_cache *tfrc_rx_hist_slab;
-struct dccp_rx_hist_entry *dccp_rx_hist_entry_new(const u32 ndp,
+struct tfrc_rx_hist_entry *tfrc_rx_hist_entry_new(const u32 ndp,
const struct sk_buff *skb,
const gfp_t prio)
{
- struct dccp_rx_hist_entry *entry = kmem_cache_alloc(tfrc_rx_hist_slab,
+ struct tfrc_rx_hist_entry *entry = kmem_cache_alloc(tfrc_rx_hist_slab,
prio);
if (entry != NULL) {
const struct dccp_hdr *dh = dccp_hdr(skb);
- entry->dccphrx_seqno = DCCP_SKB_CB(skb)->dccpd_seq;
- entry->dccphrx_ccval = dh->dccph_ccval;
- entry->dccphrx_type = dh->dccph_type;
- entry->dccphrx_ndp = ndp;
- entry->dccphrx_tstamp = ktime_get_real();
+ entry->tfrchrx_seqno = DCCP_SKB_CB(skb)->dccpd_seq;
+ entry->tfrchrx_ccval = dh->dccph_ccval;
+ entry->tfrchrx_type = dh->dccph_type;
+ entry->tfrchrx_ndp = ndp;
+ entry->tfrchrx_tstamp = ktime_get_real();
}
return entry;
}
-EXPORT_SYMBOL_GPL(dccp_rx_hist_entry_new);
+EXPORT_SYMBOL_GPL(tfrc_rx_hist_entry_new);
-static inline void dccp_rx_hist_entry_delete(struct dccp_rx_hist_entry *entry)
+static inline void tfrc_rx_hist_entry_delete(struct tfrc_rx_hist_entry *entry)
{
kmem_cache_free(tfrc_rx_hist_slab, entry);
}
-int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
+int tfrc_rx_hist_find_entry(const struct list_head *list, const u64 seq,
u8 *ccval)
{
- struct dccp_rx_hist_entry *packet = NULL, *entry;
+ struct tfrc_rx_hist_entry *packet = NULL, *entry;
- list_for_each_entry(entry, list, dccphrx_node)
- if (entry->dccphrx_seqno == seq) {
+ list_for_each_entry(entry, list, tfrchrx_node)
+ if (entry->tfrchrx_seqno == seq) {
packet = entry;
break;
}
if (packet)
- *ccval = packet->dccphrx_ccval;
+ *ccval = packet->tfrchrx_ccval;
return packet != NULL;
}
-EXPORT_SYMBOL_GPL(dccp_rx_hist_find_entry);
-struct dccp_rx_hist_entry *
- dccp_rx_hist_find_data_packet(const struct list_head *list)
+EXPORT_SYMBOL_GPL(tfrc_rx_hist_find_entry);
+struct tfrc_rx_hist_entry *
+ tfrc_rx_hist_find_data_packet(const struct list_head *list)
{
- struct dccp_rx_hist_entry *entry, *packet = NULL;
+ struct tfrc_rx_hist_entry *entry, *packet = NULL;
- list_for_each_entry(entry, list, dccphrx_node)
- if (entry->dccphrx_type == DCCP_PKT_DATA ||
- entry->dccphrx_type == DCCP_PKT_DATAACK) {
+ list_for_each_entry(entry, list, tfrchrx_node)
+ if (entry->tfrchrx_type == DCCP_PKT_DATA ||
+ entry->tfrchrx_type == DCCP_PKT_DATAACK) {
packet = entry;
break;
}
@@ -175,29 +175,29 @@ struct dccp_rx_hist_entry *
return packet;
}
-EXPORT_SYMBOL_GPL(dccp_rx_hist_find_data_packet);
+EXPORT_SYMBOL_GPL(tfrc_rx_hist_find_data_packet);
-void dccp_rx_hist_add_packet(struct list_head *rx_list,
+void tfrc_rx_hist_add_packet(struct list_head *rx_list,
struct list_head *li_list,
- struct dccp_rx_hist_entry *packet,
+ struct tfrc_rx_hist_entry *packet,
u64 nonloss_seqno)
{
- struct dccp_rx_hist_entry *entry, *next;
+ struct tfrc_rx_hist_entry *entry, *next;
u8 num_later = 0;
- list_add(&packet->dccphrx_node, rx_list);
+ list_add(&packet->tfrchrx_node, rx_list);
num_later = TFRC_RECV_NUM_LATE_LOSS + 1;
if (!list_empty(li_list)) {
- list_for_each_entry_safe(entry, next, rx_list, dccphrx_node) {
+ list_for_each_entry_safe(entry, next, rx_list, tfrchrx_node) {
if (num_later == 0) {
if (after48(nonloss_seqno,
- entry->dccphrx_seqno)) {
- list_del_init(&entry->dccphrx_node);
- dccp_rx_hist_entry_delete(entry);
+ entry->tfrchrx_seqno)) {
+ list_del_init(&entry->tfrchrx_node);
+ tfrc_rx_hist_entry_delete(entry);
}
- } else if (dccp_rx_hist_entry_data_packet(entry))
+ } else if (tfrc_rx_hist_entry_data_packet(entry))
--num_later;
}
} else {
@@ -208,7 +208,7 @@ void dccp_rx_hist_add_packet(struct list_head *rx_list,
* We have no loss interval history so we need at least one
* rtt:s of data packets to approximate rtt.
*/
- list_for_each_entry_safe(entry, next, rx_list, dccphrx_node) {
+ list_for_each_entry_safe(entry, next, rx_list, tfrchrx_node) {
if (num_later == 0) {
switch (step) {
case 0:
@@ -220,10 +220,10 @@ void dccp_rx_hist_add_packet(struct list_head *rx_list,
step = 2;
/* OK, find next data packet */
num_later = 1;
- win_count = entry->dccphrx_ccval;
+ win_count = entry->tfrchrx_ccval;
break;
case 2:
- tmp = win_count - entry->dccphrx_ccval;
+ tmp = win_count - entry->tfrchrx_ccval;
if (tmp < 0)
tmp += TFRC_WIN_COUNT_LIMIT;
if (tmp > TFRC_WIN_COUNT_PER_RTT + 1) {
@@ -236,29 +236,29 @@ void dccp_rx_hist_add_packet(struct list_head *rx_list,
num_later = 1;
break;
case 3:
- list_del_init(&entry->dccphrx_node);
- dccp_rx_hist_entry_delete(entry);
+ list_del_init(&entry->tfrchrx_node);
+ tfrc_rx_hist_entry_delete(entry);
break;
}
- } else if (dccp_rx_hist_entry_data_packet(entry))
+ } else if (tfrc_rx_hist_entry_data_packet(entry))
--num_later;
}
}
}
-EXPORT_SYMBOL_GPL(dccp_rx_hist_add_packet);
+EXPORT_SYMBOL_GPL(tfrc_rx_hist_add_packet);
-void dccp_rx_hist_purge(struct list_head *list)
+void tfrc_rx_hist_purge(struct list_head *list)
{
- struct dccp_rx_hist_entry *entry, *next;
+ struct tfrc_rx_hist_entry *entry, *next;
- list_for_each_entry_safe(entry, next, list, dccphrx_node) {
- list_del_init(&entry->dccphrx_node);
- dccp_rx_hist_entry_delete(entry);
+ list_for_each_entry_safe(entry, next, list, tfrchrx_node) {
+ list_del_init(&entry->tfrchrx_node);
+ tfrc_rx_hist_entry_delete(entry);
}
}
-EXPORT_SYMBOL_GPL(dccp_rx_hist_purge);
+EXPORT_SYMBOL_GPL(tfrc_rx_hist_purge);
__init int packet_history_init(void)
{
@@ -269,7 +269,7 @@ __init int packet_history_init(void)
goto out_err;
tfrc_rx_hist_slab = kmem_cache_create("tfrc_rx_hist",
- sizeof(struct dccp_rx_hist_entry), 0,
+ sizeof(struct tfrc_rx_hist_entry), 0,
SLAB_HWCACHE_ALIGN, NULL);
if (tfrc_rx_hist_slab == NULL)
goto out_free_tx;
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h
index 34b180b..5b0b983 100644
--- a/net/dccp/ccids/lib/packet_history.h
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -57,51 +57,51 @@ extern u32 tfrc_tx_hist_rtt(struct tfrc_tx_hist_entry *head,
/*
* Receiver History data structures and declarations
*/
-struct dccp_rx_hist_entry {
- struct list_head dccphrx_node;
- u64 dccphrx_seqno:48,
- dccphrx_ccval:4,
- dccphrx_type:4;
- u32 dccphrx_ndp; /* In fact it is from 8 to 24 bits */
- ktime_t dccphrx_tstamp;
+struct tfrc_rx_hist_entry {
+ struct list_head tfrchrx_node;
+ u64 tfrchrx_seqno:48,
+ tfrchrx_ccval:4,
+ tfrchrx_type:4;
+ u32 tfrchrx_ndp; /* In fact it is from 8 to 24 bits */
+ ktime_t tfrchrx_tstamp;
};
-extern struct dccp_rx_hist_entry *
- dccp_rx_hist_entry_new(const u32 ndp,
+extern struct tfrc_rx_hist_entry *
+ tfrc_rx_hist_entry_new(const u32 ndp,
const struct sk_buff *skb,
const gfp_t prio);
-static inline struct dccp_rx_hist_entry *
- dccp_rx_hist_head(struct list_head *list)
+static inline struct tfrc_rx_hist_entry *
+ tfrc_rx_hist_head(struct list_head *list)
{
- struct dccp_rx_hist_entry *head = NULL;
+ struct tfrc_rx_hist_entry *head = NULL;
if (!list_empty(list))
- head = list_entry(list->next, struct dccp_rx_hist_entry,
- dccphrx_node);
+ head = list_entry(list->next, struct tfrc_rx_hist_entry,
+ tfrchrx_node);
return head;
}
-extern int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
+extern int tfrc_rx_hist_find_entry(const struct list_head *list, const u64 seq,
u8 *ccval);
-extern struct dccp_rx_hist_entry *
- dccp_rx_hist_find_data_packet(const struct list_head *list);
+extern struct tfrc_rx_hist_entry *
+ tfrc_rx_hist_find_data_packet(const struct list_head *list);
-extern void dccp_rx_hist_add_packet(struct list_head *rx_list,
+extern void tfrc_rx_hist_add_packet(struct list_head *rx_list,
struct list_head *li_list,
- struct dccp_rx_hist_entry *packet,
+ struct tfrc_rx_hist_entry *packet,
u64 nonloss_seqno);
-extern void dccp_rx_hist_purge(struct list_head *list);
+extern void tfrc_rx_hist_purge(struct list_head *list);
static inline int
- dccp_rx_hist_entry_data_packet(const struct dccp_rx_hist_entry *entry)
+ tfrc_rx_hist_entry_data_packet(const struct tfrc_rx_hist_entry *entry)
{
- return entry->dccphrx_type == DCCP_PKT_DATA ||
- entry->dccphrx_type == DCCP_PKT_DATAACK;
+ return entry->tfrchrx_type == DCCP_PKT_DATA ||
+ entry->tfrchrx_type == DCCP_PKT_DATAACK;
}
-extern u64 dccp_rx_hist_detect_loss(struct list_head *rx_list,
+extern u64 tfrc_rx_hist_detect_loss(struct list_head *rx_list,
struct list_head *li_list, u8 *win_loss);
#endif /* _DCCP_PKT_HIST_ */
--
1.5.3.4
^ permalink raw reply related
* [PATCH 4/7] [TFRC]: Make the rx history slab be global
From: Arnaldo Carvalho de Melo @ 2007-12-06 21:02 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, dccp, Arnaldo Carvalho de Melo, Gerrit Renker
In-Reply-To: <1196974974-31531-4-git-send-email-acme@redhat.com>
This is in preparation for merging the new rx history code written by Gerrit Renker.
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 | 35 ++-----------
net/dccp/ccids/lib/packet_history.c | 95 ++++++++++++++++++-----------------
net/dccp/ccids/lib/packet_history.h | 43 ++--------------
3 files changed, 60 insertions(+), 113 deletions(-)
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 5dea690..07920bb 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -49,8 +49,6 @@ static int ccid3_debug;
#define ccid3_pr_debug(format, a...)
#endif
-static struct dccp_rx_hist *ccid3_rx_hist;
-
/*
* Transmitter Half-Connection Routines
*/
@@ -807,9 +805,9 @@ static int ccid3_hc_rx_detect_loss(struct sock *sk,
}
detect_out:
- dccp_rx_hist_add_packet(ccid3_rx_hist, &hcrx->ccid3hcrx_hist,
- &hcrx->ccid3hcrx_li_hist, packet,
- hcrx->ccid3hcrx_seqno_nonloss);
+ dccp_rx_hist_add_packet(&hcrx->ccid3hcrx_hist,
+ &hcrx->ccid3hcrx_li_hist, packet,
+ hcrx->ccid3hcrx_seqno_nonloss);
return loss;
}
@@ -852,8 +850,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
return;
}
- packet = dccp_rx_hist_entry_new(ccid3_rx_hist, opt_recv->dccpor_ndp,
- skb, GFP_ATOMIC);
+ packet = dccp_rx_hist_entry_new(opt_recv->dccpor_ndp, skb, GFP_ATOMIC);
if (unlikely(packet == NULL)) {
DCCP_WARN("%s(%p), Not enough mem to add rx packet "
"to history, consider it lost!\n", dccp_role(sk), sk);
@@ -936,7 +933,7 @@ static void ccid3_hc_rx_exit(struct sock *sk)
ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM);
/* Empty packet history */
- dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist);
+ dccp_rx_hist_purge(&hcrx->ccid3hcrx_hist);
/* Empty loss interval history */
dccp_li_hist_purge(&hcrx->ccid3hcrx_li_hist);
@@ -1013,33 +1010,13 @@ MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");
static __init int ccid3_module_init(void)
{
- int rc = -ENOBUFS;
-
- ccid3_rx_hist = dccp_rx_hist_new("ccid3");
- if (ccid3_rx_hist == NULL)
- goto out;
-
- rc = ccid_register(&ccid3);
- if (rc != 0)
- goto out_free_rx;
-out:
- return rc;
-
-out_free_rx:
- dccp_rx_hist_delete(ccid3_rx_hist);
- ccid3_rx_hist = NULL;
- goto out;
+ return ccid_register(&ccid3);
}
module_init(ccid3_module_init);
static __exit void ccid3_module_exit(void)
{
ccid_unregister(&ccid3);
-
- if (ccid3_rx_hist != NULL) {
- dccp_rx_hist_delete(ccid3_rx_hist);
- ccid3_rx_hist = NULL;
- }
}
module_exit(ccid3_module_exit);
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
index b628714..e1ab853 100644
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -114,48 +114,33 @@ EXPORT_SYMBOL_GPL(tfrc_tx_hist_rtt);
/*
* Receiver History Routines
*/
-struct dccp_rx_hist *dccp_rx_hist_new(const char *name)
+static struct kmem_cache *tfrc_rx_hist_slab;
+
+struct dccp_rx_hist_entry *dccp_rx_hist_entry_new(const u32 ndp,
+ const struct sk_buff *skb,
+ const gfp_t prio)
{
- struct dccp_rx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
- static const char dccp_rx_hist_mask[] = "rx_hist_%s";
- char *slab_name;
-
- if (hist == NULL)
- goto out;
-
- slab_name = kmalloc(strlen(name) + sizeof(dccp_rx_hist_mask) - 1,
- GFP_ATOMIC);
- if (slab_name == NULL)
- goto out_free_hist;
-
- sprintf(slab_name, dccp_rx_hist_mask, name);
- hist->dccprxh_slab = kmem_cache_create(slab_name,
- sizeof(struct dccp_rx_hist_entry),
- 0, SLAB_HWCACHE_ALIGN, NULL);
- if (hist->dccprxh_slab == NULL)
- goto out_free_slab_name;
-out:
- return hist;
-out_free_slab_name:
- kfree(slab_name);
-out_free_hist:
- kfree(hist);
- hist = NULL;
- goto out;
-}
+ struct dccp_rx_hist_entry *entry = kmem_cache_alloc(tfrc_rx_hist_slab,
+ prio);
-EXPORT_SYMBOL_GPL(dccp_rx_hist_new);
+ if (entry != NULL) {
+ const struct dccp_hdr *dh = dccp_hdr(skb);
-void dccp_rx_hist_delete(struct dccp_rx_hist *hist)
-{
- const char* name = kmem_cache_name(hist->dccprxh_slab);
+ entry->dccphrx_seqno = DCCP_SKB_CB(skb)->dccpd_seq;
+ entry->dccphrx_ccval = dh->dccph_ccval;
+ entry->dccphrx_type = dh->dccph_type;
+ entry->dccphrx_ndp = ndp;
+ entry->dccphrx_tstamp = ktime_get_real();
+ }
- kmem_cache_destroy(hist->dccprxh_slab);
- kfree(name);
- kfree(hist);
+ return entry;
}
+EXPORT_SYMBOL_GPL(dccp_rx_hist_entry_new);
-EXPORT_SYMBOL_GPL(dccp_rx_hist_delete);
+static inline void dccp_rx_hist_entry_delete(struct dccp_rx_hist_entry *entry)
+{
+ kmem_cache_free(tfrc_rx_hist_slab, entry);
+}
int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
u8 *ccval)
@@ -192,11 +177,10 @@ struct dccp_rx_hist_entry *
EXPORT_SYMBOL_GPL(dccp_rx_hist_find_data_packet);
-void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
- struct list_head *rx_list,
- struct list_head *li_list,
- struct dccp_rx_hist_entry *packet,
- u64 nonloss_seqno)
+void dccp_rx_hist_add_packet(struct list_head *rx_list,
+ struct list_head *li_list,
+ struct dccp_rx_hist_entry *packet,
+ u64 nonloss_seqno)
{
struct dccp_rx_hist_entry *entry, *next;
u8 num_later = 0;
@@ -211,7 +195,7 @@ void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
if (after48(nonloss_seqno,
entry->dccphrx_seqno)) {
list_del_init(&entry->dccphrx_node);
- dccp_rx_hist_entry_delete(hist, entry);
+ dccp_rx_hist_entry_delete(entry);
}
} else if (dccp_rx_hist_entry_data_packet(entry))
--num_later;
@@ -253,7 +237,7 @@ void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
break;
case 3:
list_del_init(&entry->dccphrx_node);
- dccp_rx_hist_entry_delete(hist, entry);
+ dccp_rx_hist_entry_delete(entry);
break;
}
} else if (dccp_rx_hist_entry_data_packet(entry))
@@ -264,13 +248,13 @@ void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
EXPORT_SYMBOL_GPL(dccp_rx_hist_add_packet);
-void dccp_rx_hist_purge(struct dccp_rx_hist *hist, struct list_head *list)
+void dccp_rx_hist_purge(struct list_head *list)
{
struct dccp_rx_hist_entry *entry, *next;
list_for_each_entry_safe(entry, next, list, dccphrx_node) {
list_del_init(&entry->dccphrx_node);
- kmem_cache_free(hist->dccprxh_slab, entry);
+ dccp_rx_hist_entry_delete(entry);
}
}
@@ -281,8 +265,22 @@ __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;
- return tfrc_tx_hist_slab == NULL ? -ENOBUFS : 0;
+ tfrc_rx_hist_slab = kmem_cache_create("tfrc_rx_hist",
+ sizeof(struct dccp_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)
@@ -291,4 +289,9 @@ void packet_history_exit(void)
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/packet_history.h b/net/dccp/ccids/lib/packet_history.h
index 9a2642e..34b180b 100644
--- a/net/dccp/ccids/lib/packet_history.h
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -66,34 +66,10 @@ struct dccp_rx_hist_entry {
ktime_t dccphrx_tstamp;
};
-struct dccp_rx_hist {
- struct kmem_cache *dccprxh_slab;
-};
-
-extern struct dccp_rx_hist *dccp_rx_hist_new(const char *name);
-extern void dccp_rx_hist_delete(struct dccp_rx_hist *hist);
-
-static inline struct dccp_rx_hist_entry *
- dccp_rx_hist_entry_new(struct dccp_rx_hist *hist,
- const u32 ndp,
+extern struct dccp_rx_hist_entry *
+ dccp_rx_hist_entry_new(const u32 ndp,
const struct sk_buff *skb,
- const gfp_t prio)
-{
- struct dccp_rx_hist_entry *entry = kmem_cache_alloc(hist->dccprxh_slab,
- prio);
-
- if (entry != NULL) {
- const struct dccp_hdr *dh = dccp_hdr(skb);
-
- entry->dccphrx_seqno = DCCP_SKB_CB(skb)->dccpd_seq;
- entry->dccphrx_ccval = dh->dccph_ccval;
- entry->dccphrx_type = dh->dccph_type;
- entry->dccphrx_ndp = ndp;
- entry->dccphrx_tstamp = ktime_get_real();
- }
-
- return entry;
-}
+ const gfp_t prio);
static inline struct dccp_rx_hist_entry *
dccp_rx_hist_head(struct list_head *list)
@@ -111,21 +87,12 @@ extern int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
extern struct dccp_rx_hist_entry *
dccp_rx_hist_find_data_packet(const struct list_head *list);
-extern void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
- struct list_head *rx_list,
+extern void dccp_rx_hist_add_packet(struct list_head *rx_list,
struct list_head *li_list,
struct dccp_rx_hist_entry *packet,
u64 nonloss_seqno);
-static inline void dccp_rx_hist_entry_delete(struct dccp_rx_hist *hist,
- struct dccp_rx_hist_entry *entry)
-{
- if (entry != NULL)
- kmem_cache_free(hist->dccprxh_slab, entry);
-}
-
-extern void dccp_rx_hist_purge(struct dccp_rx_hist *hist,
- struct list_head *list);
+extern void dccp_rx_hist_purge(struct list_head *list);
static inline int
dccp_rx_hist_entry_data_packet(const struct dccp_rx_hist_entry *entry)
--
1.5.3.4
^ permalink raw reply related
* [PATCH 6/7] [CCID3]: The receiver of a half-connection does not set window counter values
From: Arnaldo Carvalho de Melo @ 2007-12-06 21:02 UTC (permalink / raw)
To: David S. Miller
Cc: netdev, dccp, Gerrit Renker, Ian McDonald,
Arnaldo Carvalho de Melo
In-Reply-To: <1196974974-31531-6-git-send-email-acme@redhat.com>
From: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Only the sender sets window counters [RFC 4342, sections 5 and 8.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 | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index c95dca8..5ff5aab 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -733,7 +733,6 @@ static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
return 0;
hcrx = ccid3_hc_rx_sk(sk);
- DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_ccval_last_counter;
if (dccp_packet_without_ack(skb))
return 0;
--
1.5.3.4
^ permalink raw reply related
* [PATCH 2/7] [DCCP]: Introduce generic function to test for `data packets'
From: Arnaldo Carvalho de Melo @ 2007-12-06 21:02 UTC (permalink / raw)
To: David S. Miller
Cc: netdev, dccp, Gerrit Renker, Ian McDonald,
Arnaldo Carvalho de Melo
In-Reply-To: <1196974974-31531-2-git-send-email-acme@redhat.com>
From: Gerrit Renker <gerrit@erg.abdn.ac.uk>
as per RFC 4340, sec. 7.7.
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/dccp.h | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index ee97950..f4a5ea1 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -334,6 +334,7 @@ struct dccp_skb_cb {
#define DCCP_SKB_CB(__skb) ((struct dccp_skb_cb *)&((__skb)->cb[0]))
+/* RFC 4340, sec. 7.7 */
static inline int dccp_non_data_packet(const struct sk_buff *skb)
{
const __u8 type = DCCP_SKB_CB(skb)->dccpd_type;
@@ -346,6 +347,17 @@ static inline int dccp_non_data_packet(const struct sk_buff *skb)
type == DCCP_PKT_SYNCACK;
}
+/* RFC 4340, sec. 7.7 */
+static inline int dccp_data_packet(const struct sk_buff *skb)
+{
+ const __u8 type = DCCP_SKB_CB(skb)->dccpd_type;
+
+ return type == DCCP_PKT_DATA ||
+ type == DCCP_PKT_DATAACK ||
+ type == DCCP_PKT_REQUEST ||
+ type == DCCP_PKT_RESPONSE;
+}
+
static inline int dccp_packet_without_ack(const struct sk_buff *skb)
{
const __u8 type = DCCP_SKB_CB(skb)->dccpd_type;
--
1.5.3.4
^ permalink raw reply related
* [PATCH] s2io: fix inconsistent hardware VLAN tagging during driver init
From: Andy Gospodarek @ 2007-12-06 19:57 UTC (permalink / raw)
To: netdev; +Cc: ram.vepa, santosh.rastapur, sivakumar.subramani,
sreenivasa.honnur
The s2io driver keeps a local variable around (vlan_strip_flag) to keep
track of the current state of the hardware and whether or not it will
strip VLAN tags on incoming packets. It seems as though the hardware
default is to strip them, but that variable is not set correctly during
initialization if the default setup is used. This check ensures
vlan_strip_flag and the hardware setting are in sync.
These variables were introduced by this patch:
commit 926930b202d56c3dfb6aea0a0c6bfba2b87a8c03
Author: Sivakumar Subramani <Sivakumar.Subramani@neterion.com>
Date: Sat Feb 24 01:59:39 2007 -0500
so this problem hasn't been around forever.
Recent patches from Ramkrishna Vepa <ram.vepa@neterion.com> removed this
variable and would have worked around the problem, but they were not
accepted.
Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
---
s2io.c | 5 +++++
1 files changed, 5 insertions(+)
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 8b9f0ea..08c08de 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -2151,6 +2151,11 @@ static int start_nic(struct s2io_nic *nic)
val64 &= ~RX_PA_CFG_STRIP_VLAN_TAG;
writeq(val64, &bar0->rx_pa_cfg);
vlan_strip_flag = 0;
+ } else {
+ val64 = readq(&bar0->rx_pa_cfg);
+ val64 |= RX_PA_CFG_STRIP_VLAN_TAG;
+ writeq(val64, &bar0->rx_pa_cfg);
+ vlan_strip_flag = 1;
}
/*
^ permalink raw reply related
* Re: [PATCH] iproute2: support dotted-quad netmask notation.
From: Stephen Hemminger @ 2007-12-06 19:53 UTC (permalink / raw)
To: Andreas Henriksson; +Cc: netdev
In-Reply-To: <20071204135818.GA24419@scream.fatal.se>
On Tue, 4 Dec 2007 14:58:18 +0100
Andreas Henriksson <andreas@fatal.se> wrote:
> Suggested patch for allowing netmask to be specified in dotted quad format.
> See http://bugs.debian.org/357172
>
> (Known problem: this will not prevent some invalid syntaxes,
> ie. "255.0.255.0" will be treated as "255.255.255.0")
>
> Comments? Suggestions? Improvements?
Fix the bug you mentioned?
/* a valid netmask must be 2^n - 1 (n = 1..31) */
static int is_valid_netmask(const inet_prefix *addr)
{
uint32_t host;
if (addr->family != AF_INET)
return 0;
host = ~ntohl(addr->data[0]);
if (host == 0 || ~host == 0)
return 0;
return (host & (host + 1)) == 0;
}
^ permalink raw reply
* Re: Reproducible data corruption with sendfile+vsftp - splice regression?
From: Francois Romieu @ 2007-12-06 18:44 UTC (permalink / raw)
To: Holger Hoffstaette; +Cc: linux-kernel, netdev, torvalds
In-Reply-To: <pan.2007.12.06.09.28.08.913625@wizards.de>
Holger Hoffstaette <holger@wizards.de> :
[...]
> Maybe turning off sendfile or NAPI just lead to random success - so far it
> really looks like tso on the r8169 is the common cause.
TSO on the r8169 is the magic switch but the regression makes imvho more
sense from a VM pov:
- the corrupted file has the same size as the expected file
- the corrupted file exhibits holes which come as a multiple of 4096 bytes
(8*4k, 2 places, there may be more)
- the r8169 driver does not know what a page is
- the 8169 hardware has a small 8192 bytes Tx buffer
It would be nice if someone could do a sendfile + vsftp test with TSO on a
different hardware. While I could not reproduce the corruption when simply
downloading a file that I had copied on the server with scp, it triggered
almost immediately after I copied it locally and tried to download the copy.
--
Ueimor
^ permalink raw reply
* Re: [Patch] net/xfrm/xfrm_policy.c: Some small improvements
From: Herbert Xu @ 2007-12-06 17:40 UTC (permalink / raw)
To: Richard Knutsson; +Cc: David Miller, xiyou.wangcong, linux-kernel, akpm, netdev
In-Reply-To: <4758093A.7010608@student.ltu.se>
On Thu, Dec 06, 2007 at 03:37:46PM +0100, Richard Knutsson wrote:
>
> Is it not an improvement to distinct booleans from actual values? Do you
> use integers for ASCII characters too? It can also avoid some potential
> bugs like the 'if (i == TRUE)'...
> What is wrong with 'size_t' (since it is unsigned, compared to (some)
> 'int')?
I agree with Dave. There are so many useful things that we can do
(and need to do) in IPsec that bool/size_t conversions just add
churn without adding much value.
Thanks,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH net-2.6.25 10/11][INET] Eliminate difference in actions of sysctl and proc handler for conf.all.forwarding
From: Herbert Xu @ 2007-12-06 17:42 UTC (permalink / raw)
To: Pavel Emelyanov; +Cc: David Miller, netdev, devel
In-Reply-To: <4757EB92.4010400@openvz.org>
On Thu, Dec 06, 2007 at 03:31:14PM +0300, Pavel Emelyanov wrote:
>
> BTW, this is not 100% true. Look, in rtm_to_ifaddr()
> I see the following code flow:
>
> ipv4_devconf_setall(in_dev);
>
> ifa = inet_alloc_ifa();
> if (ifa == NULL) {
> /*
> * A potential indev allocation can be left alive, it stays
> * assigned to its device and is destroy with it.
> */
> err = -ENOBUFS;
> goto errout;
> }
>
> if we fail to allocate the ifa (hard to happen, but), we will
> make this device not to accept the default propagation.
Yes that's unintentional.
> If this is a relevant note, I can prepare the patch.
It certainly seems easy enough to fix by just swapping the order.
Please do.
Thanks,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* [PATCH] SCTP: Fix the bind_addr info during migration.
From: Vlad Yasevich @ 2007-12-06 17:48 UTC (permalink / raw)
To: davem; +Cc: netdev, lksctp-developers, Vlad Yasevich
In-Reply-To: <1196963304-32494-1-git-send-email-vladislav.yasevich@hp.com>
During accept/migrate the code attempts to copy the addresses from
the parent endpoint to the new endpoint. However, if the parent
was bound to a wildcard address, then we end up pointlessly copying
all of the current addresses on the system.
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
---
include/net/sctp/structs.h | 3 +++
net/sctp/bind_addr.c | 26 ++++++++++++++++++++++++++
net/sctp/socket.c | 12 ++----------
3 files changed, 31 insertions(+), 10 deletions(-)
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index eb3113c..002a00a 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1184,6 +1184,9 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
const struct sctp_bind_addr *src,
sctp_scope_t scope, gfp_t gfp,
int flags);
+int sctp_bind_addr_dup(struct sctp_bind_addr *dest,
+ const struct sctp_bind_addr *src,
+ gfp_t gfp);
int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
__u8 use_as_src, gfp_t gfp);
int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *);
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index cae95af..6a7d010 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -105,6 +105,32 @@ out:
return error;
}
+/* Exactly duplicate the address lists. This is necessary when doing
+ * peer-offs and accepts. We don't want to put all the current system
+ * addresses into the endpoint. That's useless. But we do want duplicat
+ * the list of bound addresses that the older endpoint used.
+ */
+int sctp_bind_addr_dup(struct sctp_bind_addr *dest,
+ const struct sctp_bind_addr *src,
+ gfp_t gfp)
+{
+ struct sctp_sockaddr_entry *addr;
+ struct list_head *pos;
+ int error = 0;
+
+ /* All addresses share the same port. */
+ dest->port = src->port;
+
+ list_for_each(pos, &src->address_list) {
+ addr = list_entry(pos, struct sctp_sockaddr_entry, list);
+ error = sctp_add_bind_addr(dest, &addr->a, 1, gfp);
+ if (error < 0)
+ break;
+ }
+
+ return error;
+}
+
/* Initialize the SCTP_bind_addr structure for either an endpoint or
* an association.
*/
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 9f5d793..ea9649c 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -6326,7 +6326,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
struct sk_buff *skb, *tmp;
struct sctp_ulpevent *event;
struct sctp_bind_hashbucket *head;
- int flags = 0;
/* Migrate socket buffer sizes and all the socket level options to the
* new socket.
@@ -6356,15 +6355,8 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
/* Copy the bind_addr list from the original endpoint to the new
* endpoint so that we can handle restarts properly
*/
- if (PF_INET6 == assoc->base.sk->sk_family)
- flags = SCTP_ADDR6_ALLOWED;
- if (assoc->peer.ipv4_address)
- flags |= SCTP_ADDR4_PEERSUPP;
- if (assoc->peer.ipv6_address)
- flags |= SCTP_ADDR6_PEERSUPP;
- sctp_bind_addr_copy(&newsp->ep->base.bind_addr,
- &oldsp->ep->base.bind_addr,
- SCTP_SCOPE_GLOBAL, GFP_KERNEL, flags);
+ sctp_bind_addr_dup(&newsp->ep->base.bind_addr,
+ &oldsp->ep->base.bind_addr, GFP_KERNEL);
/* Move any messages in the old socket's receive queue that are for the
* peeled off association to the new socket's receive queue.
--
1.5.3.5
^ permalink raw reply related
* [SCTP] Bug fixes to the migrate/accept code path.
From: Vlad Yasevich @ 2007-12-06 17:48 UTC (permalink / raw)
To: davem; +Cc: netdev, lksctp-developers
Hi Dave
The following two patches fix some bugs in the SCTP accept code path.
The first one fixes a slab corruption bug that we found during stress
testing. The second one is just a clean-up and the right way to do things.
You can also pull both from:
master.kernel.org:/pub/scm/linux/kernel/git/lksctp-dev.git pending
Thanks
-vlad
^ permalink raw reply
* [PATCH] SCTP: Add bind hash locking to the migrate code
From: Vlad Yasevich @ 2007-12-06 17:48 UTC (permalink / raw)
To: davem; +Cc: netdev, lksctp-developers, Vlad Yasevich
In-Reply-To: <1196963304-32494-1-git-send-email-vladislav.yasevich@hp.com>
SCTP accept code tries to add a newliy created socket
to a bind bucket without holding a lock. On a really
busy system, that can causes slab corruptions.
Add a lock around this code.
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
---
net/sctp/socket.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index ff8bc95..9f5d793 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -6325,6 +6325,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
struct sctp_endpoint *newep = newsp->ep;
struct sk_buff *skb, *tmp;
struct sctp_ulpevent *event;
+ struct sctp_bind_hashbucket *head;
int flags = 0;
/* Migrate socket buffer sizes and all the socket level options to the
@@ -6342,10 +6343,15 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
newsp->hmac = NULL;
/* Hook this new socket in to the bind_hash list. */
+ head = &sctp_port_hashtable[sctp_phashfn(inet_sk(oldsk)->num)];
+ sctp_local_bh_disable();
+ sctp_spin_lock(&head->lock);
pp = sctp_sk(oldsk)->bind_hash;
sk_add_bind_node(newsk, &pp->owner);
sctp_sk(newsk)->bind_hash = pp;
inet_sk(newsk)->num = inet_sk(oldsk)->num;
+ sctp_spin_unlock(&head->lock);
+ sctp_local_bh_enable();
/* Copy the bind_addr list from the original endpoint to the new
* endpoint so that we can handle restarts properly
--
1.5.3.5
^ permalink raw reply related
* Re: TCP event tracking via netlink...
From: Stephen Hemminger @ 2007-12-06 17:23 UTC (permalink / raw)
To: David Miller; +Cc: ilpo.jarvinen, netdev
In-Reply-To: <20071206.023346.256200942.davem@davemloft.net>
On Thu, 06 Dec 2007 02:33:46 -0800 (PST)
David Miller <davem@davemloft.net> wrote:
> From: "Ilpo_Järvinen" <ilpo.jarvinen@helsinki.fi>
> Date: Thu, 6 Dec 2007 01:18:28 +0200 (EET)
>
> > On Wed, 5 Dec 2007, David Miller wrote:
> >
> > > I assume you're using something like carefully crafted printk's,
> > > kprobes, or even ad-hoc statistic counters. That's what I used to do
> > > :-)
> >
> > No, that's not at all what I do :-). I usually look time-seq graphs
> > expect for the cases when I just find things out by reading code (or
> > by just thinking of it).
>
> Can you briefly detail what graph tools and command lines
> you are using?
>
> The last time I did graphing to analyze things, the tools
> were hit-or-miss.
>
> > Much of the info is available in tcpdump already, it's just hard to read
> > without graphing it first because there are some many overlapping things
> > to track in two-dimensional space.
> >
> > ...But yes, I have to admit that couple of problems come to my mind
> > where having some variable from tcp_sock would have made the problem
> > more obvious.
>
> The most important are the cwnd and ssthresh, which you could guess
> using graphs but it is important to know on a packet to packet
> basis why we might have sent a packet or not because this has
> rippling effects down the rest of the RTT.
>
> > Not sure what is the benefit of having distributions with it because
> > those people hardly report problems anyway to here, they're just too
> > happy with TCP performance unless we print something to their logs,
> > which implies that we must setup a *_ON() condition :-(.
>
> That may be true, but if we could integrate the information with
> tcpdumps, we could gather internal state using tools the user
> already has available.
>
> Imagine if tcpdump printed out:
>
> 02:26:14.865805 IP $SRC > $DEST: . 11226:12686(1460) ack 0 win 108
> ss_thresh: 129 cwnd: 133 packets_out: 132
>
> or something like that.
>
> > Some problems are simply such that things cannot be accurately verified
> > without high processing overhead until it's far too late (eg skb bits vs
> > *_out counters). Maybe we should start to build an expensive state
> > validator as well which would automatically check invariants of the write
> > queue and tcp_sock in a straight forward, unoptimized manner? That would
> > definately do a lot of work for us, just ask people to turn it on and it
> > spits out everything that went wrong :-) (unless they really depend on
> > very high-speed things and are therefore unhappy if we scan thousands of
> > packets unnecessarily per ACK :-)). ...Early enough! ...That would work
> > also for distros but there's always human judgement needed to decide
> > whether the bug reporter will be happy when his TCP processing does no
> > longer scale ;-).
>
> I think it's useful as a TCP_DEBUG config option or similar, sure.
>
> But sometimes the algorithms are working as designed, it's just that
> they provide poor pipe utilization and CWND analysis embedded inside
> of a tcpdump would be one way to see that as well as determine the
> flaw in the algorithm.
>
> > ...Hopefully you found any of my comments useful.
>
> Very much so, thanks.
>
> I put together a sample implementation anyways just to show the idea,
> against net-2.6.25 below.
>
> It is untested since I didn't write the userland app yet to see that
> proper things get logged. Basically you could run a daemon that
> writes per-connection traces into files based upon the incoming
> netlink events. Later, using the binary pcap file and these traces,
> you can piece together traces like the above using the timestamps
> etc. to match up pcap packets to ones from the TCP logger.
>
> The userland tools could do analysis and print pre-cooked state diff
> logs, like "this ACK raised CWND by one" or whatever else you wanted
> to know.
>
> It's nice that an expert like you can look at graphs and understand,
> but we'd like to create more experts and besides reading code one
> way to become an expert is to be able to extrace live real data
> from the kernel's working state and try to understand how things
> got that way. This information is permanently lost currently.
Tools and scripts for testing that generate graphs are at:
git://git.kernel.org/pub/scm/tcptest/tcptest
^ permalink raw reply
* ucc_geth 10 Mbit/s locks up CPU even though NAPI is enabled
From: Joakim Tjernlund @ 2007-12-06 17:22 UTC (permalink / raw)
To: 'linuxppc-dev Development', Netdev
Injecting a 10 MBit/s stream with 64 bytes pkgs locks up my
MPC832x CPU even though I got NAPI enabled. Kernel 2.6.23
Any ideas?
Jocke
^ permalink raw reply
* Re: [PATCH] sky2: RX lockup fix
From: Peter Tyser @ 2007-12-06 16:14 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20071205225249.0f46672c@shemminger-laptop>
> I have ways to generate errors, so I'll check
Thanks Stephen. We didn't spend a lot of time characterizing the issue,
but our test setup had two blades, each with an 88E8062. Our test
software pumped UDP and TCP traffic of varying packet sizes between the
blades in both directions (including jumbo frames - we increased the
MTU of the interfaces to 9000). The issue could generally be brought
out in about 15 minutes and almost always within an hour.
If you'd like any additional details on the test setup or would like me
to try something on my end, let me know.
^ permalink raw reply
* [PATCH 14/20] net/ipv4/cipso_ipv4.c: use LIST_HEAD instead of LIST_HEAD_INIT
From: Denis Cheng @ 2007-12-06 16:04 UTC (permalink / raw)
To: netdev; +Cc: Andrew Morton, linux-kernel
single list_head variable initialized with LIST_HEAD_INIT could almost
always can be replaced with LIST_HEAD declaration, this shrinks the code
and looks better.
Signed-off-by: Denis Cheng <crquan@gmail.com>
---
net/ipv4/cipso_ipv4.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index f18e88b..d4dc4eb 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -63,7 +63,7 @@ struct cipso_v4_domhsh_entry {
* probably be turned into a hash table or something similar so we
* can do quick lookups. */
static DEFINE_SPINLOCK(cipso_v4_doi_list_lock);
-static struct list_head cipso_v4_doi_list = LIST_HEAD_INIT(cipso_v4_doi_list);
+static LIST_HEAD(cipso_v4_doi_list);
/* Label mapping cache */
int cipso_v4_cache_enabled = 1;
--
1.5.3.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