* [PATCH net-next v2 09/12] net: dsa: b53: Wire-up EEE
From: Florian Fainelli @ 2017-09-19 2:19 UTC (permalink / raw)
To: netdev; +Cc: andrew, vivien.didelot, davem, Florian Fainelli
In-Reply-To: <20170919021947.8971-1-f.fainelli@gmail.com>
Add support for enabling and disabling EEE, as well as re-negotiating it in
.adjust_link() and in .port_enable().
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/dsa/b53/b53_common.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 491e4ffa8a0e..4e37ec27e496 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -523,6 +523,10 @@ static int b53_enable_port(struct dsa_switch *ds, int port,
b53_imp_vlan_setup(ds, cpu_port);
+ /* If EEE was enabled, restore it */
+ if (dev->ports[port].eee.eee_enabled)
+ b53_eee_enable_set(ds, port, true);
+
return 0;
}
@@ -879,6 +883,7 @@ static void b53_adjust_link(struct dsa_switch *ds, int port,
struct phy_device *phydev)
{
struct b53_device *dev = ds->priv;
+ struct ethtool_eee *p = &dev->ports[port].eee;
u8 rgmii_ctrl = 0, reg = 0, off;
if (!phy_is_pseudo_fixed_link(phydev))
@@ -1000,6 +1005,9 @@ static void b53_adjust_link(struct dsa_switch *ds, int port,
b53_write8(dev, B53_CTRL_PAGE, po_reg, gmii_po);
}
}
+
+ /* Re-negotiate EEE if it was enabled already */
+ p->eee_enabled = b53_eee_init(ds, port, phydev);
}
int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
@@ -1605,6 +1613,8 @@ static const struct dsa_switch_ops b53_switch_ops = {
.adjust_link = b53_adjust_link,
.port_enable = b53_enable_port,
.port_disable = b53_disable_port,
+ .get_mac_eee = b53_get_mac_eee,
+ .set_mac_eee = b53_set_mac_eee,
.port_bridge_join = b53_br_join,
.port_bridge_leave = b53_br_leave,
.port_stp_state_set = b53_br_set_stp_state,
--
2.9.3
^ permalink raw reply related
* [PATCH net-next v2 08/12] net: dsa: b53: Move EEE functions to b53
From: Florian Fainelli @ 2017-09-19 2:19 UTC (permalink / raw)
To: netdev; +Cc: andrew, vivien.didelot, davem, Florian Fainelli
In-Reply-To: <20170919021947.8971-1-f.fainelli@gmail.com>
Move the bcm_sf2 EEE-related functions to the b53 driver because this is shared
code amongst Gigabit capable switch, only 5325 and 5365 are too old to support
that.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/dsa/b53/b53_common.c | 63 ++++++++++++++++++++++++++++++++++++++
drivers/net/dsa/b53/b53_priv.h | 5 +++
drivers/net/dsa/bcm_sf2.c | 66 ++++------------------------------------
drivers/net/dsa/bcm_sf2.h | 2 --
drivers/net/dsa/bcm_sf2_regs.h | 3 --
5 files changed, 74 insertions(+), 65 deletions(-)
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index aa2187c71ea5..491e4ffa8a0e 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -1531,6 +1531,69 @@ void b53_mirror_del(struct dsa_switch *ds, int port,
}
EXPORT_SYMBOL(b53_mirror_del);
+void b53_eee_enable_set(struct dsa_switch *ds, int port, bool enable)
+{
+ struct b53_device *dev = ds->priv;
+ u16 reg;
+
+ b53_read16(dev, B53_EEE_PAGE, B53_EEE_EN_CTRL, ®);
+ if (enable)
+ reg |= BIT(port);
+ else
+ reg &= ~BIT(port);
+ b53_write16(dev, B53_EEE_PAGE, B53_EEE_EN_CTRL, reg);
+}
+EXPORT_SYMBOL(b53_eee_enable_set);
+
+
+/* Returns 0 if EEE was not enabled, or 1 otherwise
+ */
+int b53_eee_init(struct dsa_switch *ds, int port, struct phy_device *phy)
+{
+ int ret;
+
+ ret = phy_init_eee(phy, 0);
+ if (ret)
+ return 0;
+
+ b53_eee_enable_set(ds, port, true);
+
+ return 1;
+}
+EXPORT_SYMBOL(b53_eee_init);
+
+int b53_get_mac_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)
+{
+ struct b53_device *dev = ds->priv;
+ struct ethtool_eee *p = &dev->ports[port].eee;
+ u16 reg;
+
+ if (is5325(dev) || is5365(dev))
+ return -EOPNOTSUPP;
+
+ b53_read16(dev, B53_EEE_PAGE, B53_EEE_LPI_INDICATE, ®);
+ e->eee_enabled = p->eee_enabled;
+ e->eee_active = !!(reg & BIT(port));
+
+ return 0;
+}
+EXPORT_SYMBOL(b53_get_mac_eee);
+
+int b53_set_mac_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)
+{
+ struct b53_device *dev = ds->priv;
+ struct ethtool_eee *p = &dev->ports[port].eee;
+
+ if (is5325(dev) || is5365(dev))
+ return -EOPNOTSUPP;
+
+ p->eee_enabled = e->eee_enabled;
+ b53_eee_enable_set(ds, port, e->eee_enabled);
+
+ return 0;
+}
+EXPORT_SYMBOL(b53_set_mac_eee);
+
static const struct dsa_switch_ops b53_switch_ops = {
.get_tag_protocol = b53_get_tag_protocol,
.setup = b53_setup,
diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h
index 44297b7c3795..0ed59672ef07 100644
--- a/drivers/net/dsa/b53/b53_priv.h
+++ b/drivers/net/dsa/b53/b53_priv.h
@@ -70,6 +70,7 @@ enum {
struct b53_port {
u16 vlan_ctl_mask;
+ struct ethtool_eee eee;
};
struct b53_vlan {
@@ -310,5 +311,9 @@ int b53_mirror_add(struct dsa_switch *ds, int port,
void b53_mirror_del(struct dsa_switch *ds, int port,
struct dsa_mall_mirror_tc_entry *mirror);
void b53_brcm_hdr_setup(struct dsa_switch *ds, int port);
+void b53_eee_enable_set(struct dsa_switch *ds, int port, bool enable);
+int b53_eee_init(struct dsa_switch *ds, int port, struct phy_device *phy);
+int b53_get_mac_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e);
+int b53_set_mac_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e);
#endif
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 49cb51223f70..4e8ef4c07eab 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -107,19 +107,6 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
core_writel(priv, reg, offset);
}
-static void bcm_sf2_eee_enable_set(struct dsa_switch *ds, int port, bool enable)
-{
- struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
- u32 reg;
-
- reg = core_readl(priv, CORE_EEE_EN_CTRL);
- if (enable)
- reg |= 1 << port;
- else
- reg &= ~(1 << port);
- core_writel(priv, reg, CORE_EEE_EN_CTRL);
-}
-
static void bcm_sf2_gphy_enable_set(struct dsa_switch *ds, bool enable)
{
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
@@ -256,8 +243,8 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port,
bcm_sf2_imp_vlan_setup(ds, cpu_port);
/* If EEE was enabled, restore it */
- if (priv->port_sts[port].eee.eee_enabled)
- bcm_sf2_eee_enable_set(ds, port, true);
+ if (priv->dev->ports[port].eee.eee_enabled)
+ b53_eee_enable_set(ds, port, true);
return 0;
}
@@ -292,47 +279,6 @@ static void bcm_sf2_port_disable(struct dsa_switch *ds, int port,
core_writel(priv, reg, CORE_MEM_PSM_VDD_CTRL);
}
-/* Returns 0 if EEE was not enabled, or 1 otherwise
- */
-static int bcm_sf2_eee_init(struct dsa_switch *ds, int port,
- struct phy_device *phy)
-{
- int ret;
-
- ret = phy_init_eee(phy, 0);
- if (ret)
- return 0;
-
- bcm_sf2_eee_enable_set(ds, port, true);
-
- return 1;
-}
-
-static int bcm_sf2_sw_get_mac_eee(struct dsa_switch *ds, int port,
- struct ethtool_eee *e)
-{
- struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
- struct ethtool_eee *p = &priv->port_sts[port].eee;
- u32 reg;
-
- reg = core_readl(priv, CORE_EEE_LPI_INDICATE);
- e->eee_enabled = p->eee_enabled;
- e->eee_active = !!(reg & (1 << port));
-
- return 0;
-}
-
-static int bcm_sf2_sw_set_mac_eee(struct dsa_switch *ds, int port,
- struct ethtool_eee *e)
-{
- struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
- struct ethtool_eee *p = &priv->port_sts[port].eee;
-
- p->eee_enabled = e->eee_enabled;
- bcm_sf2_eee_enable_set(ds, port, e->eee_enabled);
-
- return 0;
-}
static int bcm_sf2_sw_indir_rw(struct bcm_sf2_priv *priv, int op, int addr,
int regnum, u16 val)
@@ -567,7 +513,7 @@ static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port,
struct phy_device *phydev)
{
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
- struct ethtool_eee *p = &priv->port_sts[port].eee;
+ struct ethtool_eee *p = &priv->dev->ports[port].eee;
u32 id_mode_dis = 0, port_mode;
const char *str = NULL;
u32 reg, offset;
@@ -649,7 +595,7 @@ static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port,
core_writel(priv, reg, offset);
if (!phydev->is_pseudo_fixed_link)
- p->eee_enabled = bcm_sf2_eee_init(ds, port, phydev);
+ p->eee_enabled = b53_eee_init(ds, port, phydev);
}
static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port,
@@ -978,8 +924,8 @@ static const struct dsa_switch_ops bcm_sf2_ops = {
.set_wol = bcm_sf2_sw_set_wol,
.port_enable = bcm_sf2_port_setup,
.port_disable = bcm_sf2_port_disable,
- .get_mac_eee = bcm_sf2_sw_get_mac_eee,
- .set_mac_eee = bcm_sf2_sw_set_mac_eee,
+ .get_mac_eee = b53_get_mac_eee,
+ .set_mac_eee = b53_set_mac_eee,
.port_bridge_join = b53_br_join,
.port_bridge_leave = b53_br_leave,
.port_stp_state_set = b53_br_set_stp_state,
diff --git a/drivers/net/dsa/bcm_sf2.h b/drivers/net/dsa/bcm_sf2.h
index 02c499f9c56b..1922e027ff59 100644
--- a/drivers/net/dsa/bcm_sf2.h
+++ b/drivers/net/dsa/bcm_sf2.h
@@ -48,8 +48,6 @@ struct bcm_sf2_hw_params {
struct bcm_sf2_port_status {
unsigned int link;
-
- struct ethtool_eee eee;
};
struct bcm_sf2_cfp_priv {
diff --git a/drivers/net/dsa/bcm_sf2_regs.h b/drivers/net/dsa/bcm_sf2_regs.h
index 788361ad68a0..d8b8074a47b9 100644
--- a/drivers/net/dsa/bcm_sf2_regs.h
+++ b/drivers/net/dsa/bcm_sf2_regs.h
@@ -244,9 +244,6 @@ enum bcm_sf2_reg_offs {
#define CORE_JOIN_ALL_VLAN_EN 0xd140
-#define CORE_EEE_EN_CTRL 0x24800
-#define CORE_EEE_LPI_INDICATE 0x24810
-
#define CORE_CFP_ACC 0x28000
#define OP_STR_DONE (1 << 0)
#define OP_SEL_SHIFT 1
--
2.9.3
^ permalink raw reply related
* Re: [PATCH net-next] net_sched: sch_htb: add per class overlimits counter
From: David Miller @ 2017-09-19 2:23 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev, nuclearcat, jhs, xiyou.wangcong, jiri
In-Reply-To: <1505763382.29839.27.camel@edumazet-glaptop3.roam.corp.google.com>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Mon, 18 Sep 2017 12:36:22 -0700
> From: Eric Dumazet <edumazet@google.com>
>
> HTB qdisc overlimits counter is properly increased, but we have no per
> class counter, meaning it is difficult to diagnose HTB problems.
>
> This patch adds this counter, visible in "tc -s class show dev eth0",
> with current iproute2.
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Reported-by: Denys Fedoryshchenko <nuclearcat@nuclearcat.com>
Applied, thanks Eric.
^ permalink raw reply
* [PATCH net-next v2 04/12] net: dsa: bcm_sf2: Defer port enabling to calling port_enable
From: Florian Fainelli @ 2017-09-19 2:19 UTC (permalink / raw)
To: netdev; +Cc: andrew, vivien.didelot, davem, Florian Fainelli
In-Reply-To: <20170919021947.8971-1-f.fainelli@gmail.com>
There is no need to configure the enabled ports once in bcm_sf2_sw_setup() and
then a second time around when dsa_switch_ops::port_enable is called, just do
it when port_enable is called which is better in terms of power consumption and
correctness.
Reviewed-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/dsa/bcm_sf2.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index d7b53d53c116..8acbd17bc1fd 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -890,14 +890,11 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds)
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
unsigned int port;
- /* Enable all valid ports and disable those unused */
+ /* Disable unused ports and configure IMP port */
for (port = 0; port < priv->hw_params.num_ports; port++) {
- /* IMP port receives special treatment */
- if ((1 << port) & ds->enabled_port_mask)
- bcm_sf2_port_setup(ds, port, NULL);
- else if (dsa_is_cpu_port(ds, port))
+ if (dsa_is_cpu_port(ds, port))
bcm_sf2_imp_setup(ds, port);
- else
+ else if (!((1 << port) & ds->enabled_port_mask))
bcm_sf2_port_disable(ds, port, NULL);
}
--
2.9.3
^ permalink raw reply related
* [PATCH net-next v2 03/12] net: dsa: b53: Defer port enabling to calling port_enable
From: Florian Fainelli @ 2017-09-19 2:19 UTC (permalink / raw)
To: netdev; +Cc: andrew, vivien.didelot, davem, Florian Fainelli
In-Reply-To: <20170919021947.8971-1-f.fainelli@gmail.com>
There is no need to configure the enabled ports once in b53_setup() and then a
second time around when dsa_switch_ops::port_enable is called, just do it when
port_enable is called which is better in terms of power consumption and
correctness.
Reviewed-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/dsa/b53/b53_common.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index d8bc54cfcfbe..3297af6aab8a 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -815,12 +815,13 @@ static int b53_setup(struct dsa_switch *ds)
if (ret)
dev_err(ds->dev, "failed to apply configuration\n");
+ /* Configure IMP/CPU port, disable unused ports. Enabled
+ * ports will be configured with .port_enable
+ */
for (port = 0; port < dev->num_ports; port++) {
- if (BIT(port) & ds->enabled_port_mask)
- b53_enable_port(ds, port, NULL);
- else if (dsa_is_cpu_port(ds, port))
+ if (dsa_is_cpu_port(ds, port))
b53_enable_cpu_port(dev, port);
- else
+ else if (!(BIT(port) & ds->enabled_port_mask))
b53_disable_port(ds, port, NULL);
}
--
2.9.3
^ permalink raw reply related
* [PATCH net-next v2 02/12] net: dsa: b53: Make b53_enable_cpu_port() take a port argument
From: Florian Fainelli @ 2017-09-19 2:19 UTC (permalink / raw)
To: netdev; +Cc: andrew, vivien.didelot, davem, Florian Fainelli
In-Reply-To: <20170919021947.8971-1-f.fainelli@gmail.com>
In preparation for future changes allowing the configuring of multiple
CPU ports, make b53_enable_cpu_port() take a port argument.
Reviewed-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/dsa/b53/b53_common.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 274f3679f33d..d8bc54cfcfbe 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -538,19 +538,18 @@ static void b53_disable_port(struct dsa_switch *ds, int port,
b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), reg);
}
-static void b53_enable_cpu_port(struct b53_device *dev)
+static void b53_enable_cpu_port(struct b53_device *dev, int port)
{
- unsigned int cpu_port = dev->cpu_port;
u8 port_ctrl;
/* BCM5325 CPU port is at 8 */
- if ((is5325(dev) || is5365(dev)) && cpu_port == B53_CPU_PORT_25)
- cpu_port = B53_CPU_PORT;
+ if ((is5325(dev) || is5365(dev)) && port == B53_CPU_PORT_25)
+ port = B53_CPU_PORT;
port_ctrl = PORT_CTRL_RX_BCST_EN |
PORT_CTRL_RX_MCST_EN |
PORT_CTRL_RX_UCST_EN;
- b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(cpu_port), port_ctrl);
+ b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), port_ctrl);
}
static void b53_enable_mib(struct b53_device *dev)
@@ -820,7 +819,7 @@ static int b53_setup(struct dsa_switch *ds)
if (BIT(port) & ds->enabled_port_mask)
b53_enable_port(ds, port, NULL);
else if (dsa_is_cpu_port(ds, port))
- b53_enable_cpu_port(dev);
+ b53_enable_cpu_port(dev, port);
else
b53_disable_port(ds, port, NULL);
}
--
2.9.3
^ permalink raw reply related
* [PATCH net-next v2 01/12] net: dsa: b53: Remove is_cpu_port()
From: Florian Fainelli @ 2017-09-19 2:19 UTC (permalink / raw)
To: netdev; +Cc: andrew, vivien.didelot, davem, Florian Fainelli
In-Reply-To: <20170919021947.8971-1-f.fainelli@gmail.com>
This is not used anywhere, so remove it.
Reviewed-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/dsa/b53/b53_priv.h | 5 -----
1 file changed, 5 deletions(-)
diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h
index 01bd8cbe9a3f..7528b22aeb03 100644
--- a/drivers/net/dsa/b53/b53_priv.h
+++ b/drivers/net/dsa/b53/b53_priv.h
@@ -186,11 +186,6 @@ static inline int is58xx(struct b53_device *dev)
#define B53_CPU_PORT_25 5
#define B53_CPU_PORT 8
-static inline int is_cpu_port(struct b53_device *dev, int port)
-{
- return dev->cpu_port;
-}
-
struct b53_device *b53_switch_alloc(struct device *base,
const struct b53_io_ops *ops,
void *priv);
--
2.9.3
^ permalink raw reply related
* [PATCH net-next v2 00/12] net: dsa: b53/bcm_sf2 cleanups
From: Florian Fainelli @ 2017-09-19 2:19 UTC (permalink / raw)
To: netdev; +Cc: andrew, vivien.didelot, davem, Florian Fainelli
Hi all,
This patch series is a first pass set of clean-ups to reduce the number of LOCs
between b53 and bcm_sf2 and sharing as many functions as possible.
There is a number of additional cleanups queued up locally that require more
thorough testing.
Thanks!
Changes in v2:
- added Reviewed-by tags from Vivien
- added a missing EXPORT_SYMBOL() in patch 8
- fixed a typo in patch 5
Florian Fainelli (12):
net: dsa: b53: Remove is_cpu_port()
net: dsa: b53: Make b53_enable_cpu_port() take a port argument
net: dsa: b53: Defer port enabling to calling port_enable
net: dsa: bcm_sf2: Defer port enabling to calling port_enable
net: dsa: b53: Use a macro to define I/O operations
net: dsa: b53: Move Broadcom header setup to b53
net: dsa: b53: Define EEE register page
net: dsa: b53: Move EEE functions to b53
net: dsa: b53: Wire-up EEE
net: dsa: b53: Export b53_imp_vlan_setup()
net: dsa: bcm_sf2: Use SF2_NUM_EGRESS_QUEUES for CFP
net: dsa: bcm_sf2: Utilize b53_{enable,disable}_port
drivers/net/dsa/b53/b53_common.c | 151 ++++++++++++++++++++++++++++++++----
drivers/net/dsa/b53/b53_priv.h | 145 ++++++++---------------------------
drivers/net/dsa/b53/b53_regs.h | 48 ++++++++++++
drivers/net/dsa/bcm_sf2.c | 161 +++------------------------------------
drivers/net/dsa/bcm_sf2.h | 2 -
drivers/net/dsa/bcm_sf2_cfp.c | 6 +-
drivers/net/dsa/bcm_sf2_regs.h | 11 ---
7 files changed, 228 insertions(+), 296 deletions(-)
--
2.9.3
^ permalink raw reply
* Re: [PATCH net] bpf: fix ri->map prog pointer on bpf_prog_realloc
From: Alexei Starovoitov @ 2017-09-19 1:43 UTC (permalink / raw)
To: Daniel Borkmann; +Cc: davem, john.fastabend, ast, netdev
In-Reply-To: <b797841607c3327007a787af3418cb0a60b868c0.1505783562.git.daniel@iogearbox.net>
On Tue, Sep 19, 2017 at 03:16:44AM +0200, Daniel Borkmann wrote:
> Commit 109980b894e9 ("bpf: don't select potentially stale
> ri->map from buggy xdp progs") passed the pointer to the prog
> itself to be loaded into r4 prior on bpf_redirect_map() helper
> call, so that we can store the owner into ri->map_owner out of
> the helper.
>
> Issue with that is that the actual address of the prog is still
> subject to change when subsequent rewrites occur, e.g. through
> patching other helper functions or constant blinding. Thus, we
> really need to take prog->aux as the address we're holding, and
> then during runtime fetch the actual pointer via aux->prog. This
> also works with prog clones as they share the same aux and fixup
> pointer to self after blinding finished.
>
> Fixes: 109980b894e9 ("bpf: don't select potentially stale ri->map from buggy xdp progs")
> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
> ---
> kernel/bpf/verifier.c | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 799b245..243c09f 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -4205,9 +4205,17 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
> }
>
> if (insn->imm == BPF_FUNC_redirect_map) {
> - u64 addr = (unsigned long)prog;
> + /* Note, we cannot use prog directly as imm as subsequent
> + * rewrites would still change the prog pointer. The only
> + * stable address we can use is aux, which also works with
> + * prog clones during blinding.
> + */
good catch. extra load at runtime sucks, but I don't see better solution.
> + u64 addr = (unsigned long)prog->aux;
> + const int r4 = BPF_REG_4;
> struct bpf_insn r4_ld[] = {
> - BPF_LD_IMM64(BPF_REG_4, addr),
> + BPF_LD_IMM64(r4, addr),
> + BPF_LDX_MEM(BPF_DW, r4, r4,
> + offsetof(struct bpf_prog_aux, prog)),
needs to be BPF_FIELD_SIZEOF(struct bpf_prog_aux, prog) to work on 32-bit
^ permalink raw reply
* Re: cross namespace interface notification for tun devices
From: Jason A. Donenfeld @ 2017-09-19 1:24 UTC (permalink / raw)
To: Netdev; +Cc: Mathias
In-Reply-To: <CAHmME9pD_kees+xrjTeWXgi26UdhbMVgvoddbCyueTZkbguvAg@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 612 bytes --]
On Mon, Sep 18, 2017 at 8:47 PM, Jason A. Donenfeld <Jason@zx2c4.com> wrote:
> The best I've come up with is, in a sleep loop, writing to the tun
> device's fd something with a NULL or invalid payload. If the interface
> is down, the kernel returns -EIO. If the interface is up, the kernel
> returns -EINVAL. This seems to be a reliable distinguisher, but is a
> pretty insane way of doing it. And sleep loops are somewhat different
> from events too.
Specifically, I'm referring to the horrific hack exemplified in the
attached .c file, in case anybody is curious about the details of what
I'd rather not use.
[-- Attachment #2: tuntest.c --]
[-- Type: text/x-csrc, Size: 1373 bytes --]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <linux/if.h>
#include <linux/if_tun.h>
int main(int argc, char *argv[])
{
/* If IFF_NO_PI is specified, this still sort of works but it
* bumps the device error counters, which we don't want, so
* it's best not to use this trick with IFF_NO_PI. */
struct ifreq ifr = { .ifr_flags = IFF_TUN };
int tun, sock, ret;
tun = open("/dev/net/tun", O_RDWR);
if (tun < 0) {
perror("[-] open(/dev/net/tun)");
return 1;
}
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
perror("[-] socket(AF_INET, SOCK_DGRAM)");
return 1;
}
ret = ioctl(tun, TUNSETIFF, &ifr);
if (ret < 0) {
perror("[-] ioctl(TUNSETIFF)");
return 1;
}
if (write(tun, NULL, 0) >= 0 || errno != EIO)
perror("[-] write(if:down, NULL, 0) did not return -EIO");
else
fprintf(stderr, "[+] write(if:down, NULL, 0) returned -EIO: test successful\n");
ifr.ifr_flags = IFF_UP;
ret = ioctl(sock, SIOCSIFFLAGS, &ifr);
if (ret < 0) {
perror("[-] ioctl(SIOCSIFFLAGS)");
return 1;
}
if (write(tun, NULL, 0) >= 0 || errno != EINVAL)
perror("[-] write(if:up, NULL, 0) did not return -EINVAL");
else
fprintf(stderr, "[+] write(if:up, NULL, 0) returned -EINVAL: test successful\n");
return 0;
}
^ permalink raw reply
* [PATCH net] bpf: fix ri->map prog pointer on bpf_prog_realloc
From: Daniel Borkmann @ 2017-09-19 1:16 UTC (permalink / raw)
To: davem; +Cc: john.fastabend, ast, netdev, Daniel Borkmann
Commit 109980b894e9 ("bpf: don't select potentially stale
ri->map from buggy xdp progs") passed the pointer to the prog
itself to be loaded into r4 prior on bpf_redirect_map() helper
call, so that we can store the owner into ri->map_owner out of
the helper.
Issue with that is that the actual address of the prog is still
subject to change when subsequent rewrites occur, e.g. through
patching other helper functions or constant blinding. Thus, we
really need to take prog->aux as the address we're holding, and
then during runtime fetch the actual pointer via aux->prog. This
also works with prog clones as they share the same aux and fixup
pointer to self after blinding finished.
Fixes: 109980b894e9 ("bpf: don't select potentially stale ri->map from buggy xdp progs")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
---
kernel/bpf/verifier.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 799b245..243c09f 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -4205,9 +4205,17 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
}
if (insn->imm == BPF_FUNC_redirect_map) {
- u64 addr = (unsigned long)prog;
+ /* Note, we cannot use prog directly as imm as subsequent
+ * rewrites would still change the prog pointer. The only
+ * stable address we can use is aux, which also works with
+ * prog clones during blinding.
+ */
+ u64 addr = (unsigned long)prog->aux;
+ const int r4 = BPF_REG_4;
struct bpf_insn r4_ld[] = {
- BPF_LD_IMM64(BPF_REG_4, addr),
+ BPF_LD_IMM64(r4, addr),
+ BPF_LDX_MEM(BPF_DW, r4, r4,
+ offsetof(struct bpf_prog_aux, prog)),
*insn,
};
cnt = ARRAY_SIZE(r4_ld);
--
1.9.3
^ permalink raw reply related
* RE: [PATCH V2] tipc: Use bsearch library function
From: Jon Maloy @ 2017-09-19 1:08 UTC (permalink / raw)
To: Joe Perches, Thomas Meyer
Cc: Ying Xue, netdev@vger.kernel.org,
tipc-discussion@lists.sourceforge.net,
linux-kernel@vger.kernel.org, davem@davemloft.net
In-Reply-To: <1505682926.16316.15.camel@perches.com>
> -----Original Message-----
> From: netdev-owner@vger.kernel.org [mailto:netdev-
> owner@vger.kernel.org] On Behalf Of Joe Perches
> Sent: Sunday, September 17, 2017 23:15
> To: Jon Maloy <jon.maloy@ericsson.com>; Thomas Meyer
> <thomas@m3y3r.de>
> Cc: Ying Xue <ying.xue@windriver.com>; netdev@vger.kernel.org; tipc-
> discussion@lists.sourceforge.net; linux-kernel@vger.kernel.org;
> davem@davemloft.net
> Subject: Re: [PATCH V2] tipc: Use bsearch library function
>
> On Sun, 2017-09-17 at 16:27 +0000, Jon Maloy wrote:
> > > -----Original Message-----
> > > From: Thomas Meyer [mailto:thomas@m3y3r.de]
> []
> > > What about the other binary search implementation in the same file?
> > > Should I try to convert it it will it get NAKed for performance reasons too?
> >
> > The searches for inserting and removing publications is less time
> > critical, so that would be ok with me.
> > If you have any more general interest in improving the code in this
> > file (which is needed) it would also be appreciated.
>
> Perhaps using an rbtree would be an improvement.
Not a bad idea. It would probably reduce the code amount, possibly at the expense of cache hit rate during the binary lookup.
It is worth looking into.
///jon
^ permalink raw reply
* [PATCH net 6/7] net: hns3: set default vlan id to PF
From: Salil Mehta @ 2017-09-19 1:06 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil.lnk, netdev,
linux-kernel, linux-rdma, linuxarm, Mingguang Qu
In-Reply-To: <20170919010628.175732-1-salil.mehta@huawei.com>
From: Lipeng <lipeng321@huawei.com>
When there is no vlan id in the packets, hardware will treat the vlan id
as 0 and look for the mac_vlan table. This patch set the default vlan id
of PF as 0. Without this config, it will fail when look for mac_vlan
table, and hardware will drop packets.
Signed-off-by: Mingguang Qu <qumingguang@huawei.com>
Signed-off-by: Lipeng <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 8e172afd4876..74008ef23169 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -3673,6 +3673,7 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev)
{
#define HCLGE_VLAN_TYPE_VF_TABLE 0
#define HCLGE_VLAN_TYPE_PORT_TABLE 1
+ struct hnae3_handle *handle;
int ret;
ret = hclge_set_vlan_filter_ctrl(hdev, HCLGE_VLAN_TYPE_VF_TABLE,
@@ -3682,8 +3683,11 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev)
ret = hclge_set_vlan_filter_ctrl(hdev, HCLGE_VLAN_TYPE_PORT_TABLE,
true);
+ if (ret)
+ return ret;
- return ret;
+ handle = &hdev->vport[0].nic;
+ return hclge_set_port_vlan_filter(handle, htons(ETH_P_8021Q), 0, false);
}
static int hclge_set_mtu(struct hnae3_handle *handle, int new_mtu)
--
2.11.0
^ permalink raw reply related
* [PATCH net 7/7] net: hns3: Fixes the premature exit of loop when matching clients
From: Salil Mehta @ 2017-09-19 1:06 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil.lnk, netdev,
linux-kernel, linux-rdma, linuxarm
In-Reply-To: <20170919010628.175732-1-salil.mehta@huawei.com>
From: Lipeng <lipeng321@huawei.com>
When register/unregister ae_dev, ae_dev should match all client
in the client_list. Enet and roce can co-exists together so we
should continue checking for enet and roce presence together.
So break should not be there.
Above caused problems in loading and unloading of modules.
Signed-off-by: Lipeng <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hnae3.c | 43 ++++++-----------------------
1 file changed, 9 insertions(+), 34 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.c b/drivers/net/ethernet/hisilicon/hns3/hnae3.c
index 59efbd605416..5bcb2238acb2 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.c
@@ -37,20 +37,15 @@ static bool hnae3_client_match(enum hnae3_client_type client_type,
}
static int hnae3_match_n_instantiate(struct hnae3_client *client,
- struct hnae3_ae_dev *ae_dev,
- bool is_reg, bool *matched)
+ struct hnae3_ae_dev *ae_dev, bool is_reg)
{
int ret;
- *matched = false;
-
/* check if this client matches the type of ae_dev */
if (!(hnae3_client_match(client->type, ae_dev->dev_type) &&
hnae_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))) {
return 0;
}
- /* there is a match of client and dev */
- *matched = true;
/* now, (un-)instantiate client by calling lower layer */
if (is_reg) {
@@ -69,7 +64,6 @@ int hnae3_register_client(struct hnae3_client *client)
{
struct hnae3_client *client_tmp;
struct hnae3_ae_dev *ae_dev;
- bool matched;
int ret = 0;
mutex_lock(&hnae3_common_lock);
@@ -86,7 +80,7 @@ int hnae3_register_client(struct hnae3_client *client)
/* if the client could not be initialized on current port, for
* any error reasons, move on to next available port
*/
- ret = hnae3_match_n_instantiate(client, ae_dev, true, &matched);
+ ret = hnae3_match_n_instantiate(client, ae_dev, true);
if (ret)
dev_err(&ae_dev->pdev->dev,
"match and instantiation failed for port\n");
@@ -102,12 +96,11 @@ EXPORT_SYMBOL(hnae3_register_client);
void hnae3_unregister_client(struct hnae3_client *client)
{
struct hnae3_ae_dev *ae_dev;
- bool matched;
mutex_lock(&hnae3_common_lock);
/* un-initialize the client on every matched port */
list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
- hnae3_match_n_instantiate(client, ae_dev, false, &matched);
+ hnae3_match_n_instantiate(client, ae_dev, false);
}
list_del(&client->node);
@@ -124,7 +117,6 @@ int hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
const struct pci_device_id *id;
struct hnae3_ae_dev *ae_dev;
struct hnae3_client *client;
- bool matched;
int ret = 0;
mutex_lock(&hnae3_common_lock);
@@ -151,13 +143,10 @@ int hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
* initialize the figure out client instance
*/
list_for_each_entry(client, &hnae3_client_list, node) {
- ret = hnae3_match_n_instantiate(client, ae_dev, true,
- &matched);
+ ret = hnae3_match_n_instantiate(client, ae_dev, true);
if (ret)
dev_err(&ae_dev->pdev->dev,
"match and instantiation failed\n");
- if (matched)
- break;
}
}
@@ -175,7 +164,6 @@ void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo)
const struct pci_device_id *id;
struct hnae3_ae_dev *ae_dev;
struct hnae3_client *client;
- bool matched;
mutex_lock(&hnae3_common_lock);
/* Check if there are matched ae_dev */
@@ -187,12 +175,8 @@ void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo)
/* check the client list for the match with this ae_dev type and
* un-initialize the figure out client instance
*/
- list_for_each_entry(client, &hnae3_client_list, node) {
- hnae3_match_n_instantiate(client, ae_dev, false,
- &matched);
- if (matched)
- break;
- }
+ list_for_each_entry(client, &hnae3_client_list, node)
+ hnae3_match_n_instantiate(client, ae_dev, false);
ae_algo->ops->uninit_ae_dev(ae_dev);
hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
@@ -212,7 +196,6 @@ int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
const struct pci_device_id *id;
struct hnae3_ae_algo *ae_algo;
struct hnae3_client *client;
- bool matched;
int ret = 0;
mutex_lock(&hnae3_common_lock);
@@ -246,13 +229,10 @@ int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
* initialize the figure out client instance
*/
list_for_each_entry(client, &hnae3_client_list, node) {
- ret = hnae3_match_n_instantiate(client, ae_dev, true,
- &matched);
+ ret = hnae3_match_n_instantiate(client, ae_dev, true);
if (ret)
dev_err(&ae_dev->pdev->dev,
"match and instantiation failed\n");
- if (matched)
- break;
}
out_err:
@@ -270,7 +250,6 @@ void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev)
const struct pci_device_id *id;
struct hnae3_ae_algo *ae_algo;
struct hnae3_client *client;
- bool matched;
mutex_lock(&hnae3_common_lock);
/* Check if there are matched ae_algo */
@@ -279,12 +258,8 @@ void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev)
if (!id)
continue;
- list_for_each_entry(client, &hnae3_client_list, node) {
- hnae3_match_n_instantiate(client, ae_dev, false,
- &matched);
- if (matched)
- break;
- }
+ list_for_each_entry(client, &hnae3_client_list, node)
+ hnae3_match_n_instantiate(client, ae_dev, false);
ae_algo->ops->uninit_ae_dev(ae_dev);
hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
--
2.11.0
^ permalink raw reply related
* [PATCH net 5/7] net: hns3: fixes the ether address copy with more appropriate API
From: Salil Mehta @ 2017-09-19 1:06 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil.lnk, netdev,
linux-kernel, linux-rdma, linuxarm
In-Reply-To: <20170919010628.175732-1-salil.mehta@huawei.com>
This patch replaces the ethernet address copy instance with more
appropriate ether_addr_copy() function.
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index eafd9c678162..8e172afd4876 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -1063,8 +1063,7 @@ static int hclge_configure(struct hclge_dev *hdev)
hdev->base_tqp_pid = 0;
hdev->rss_size_max = 1;
hdev->rx_buf_len = cfg.rx_buf_len;
- for (i = 0; i < ETH_ALEN; i++)
- hdev->hw.mac.mac_addr[i] = cfg.mac_addr[i];
+ ether_addr_copy(hdev->hw.mac.mac_addr, cfg.mac_addr);
hdev->hw.mac.media_type = cfg.media_type;
hdev->hw.mac.phy_addr = cfg.phy_addr;
hdev->num_desc = cfg.tqp_desc_num;
--
2.11.0
^ permalink raw reply related
* [PATCH net 4/7] net: hns3: fix a bug of set mac address
From: Salil Mehta @ 2017-09-19 1:06 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil.lnk, netdev,
linux-kernel, linux-rdma, linuxarm
In-Reply-To: <20170919010628.175732-1-salil.mehta@huawei.com>
From: Lipeng <lipeng321@huawei.com>
HNS3 driver get mac address from NCL_config file and set the mac address
to HW. If the mac address in NCL_config is invalid, driver will set a
random mac address, and use this address.
The current code will set random mac address to HW, but will not set the
valid mac address from NCL_config file to HW. This patch fix the bug.
Signed-off-by: Lipeng <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c
index 1c3e29447891..4d68d6ea5143 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c
@@ -2705,10 +2705,11 @@ static void hns3_init_mac_addr(struct net_device *netdev)
eth_hw_addr_random(netdev);
dev_warn(priv->dev, "using random MAC address %pM\n",
netdev->dev_addr);
- /* Also copy this new MAC address into hdev */
- if (h->ae_algo->ops->set_mac_addr)
- h->ae_algo->ops->set_mac_addr(h, netdev->dev_addr);
}
+
+ if (h->ae_algo->ops->set_mac_addr)
+ h->ae_algo->ops->set_mac_addr(h, netdev->dev_addr);
+
}
static void hns3_nic_set_priv_ops(struct net_device *netdev)
--
2.11.0
^ permalink raw reply related
* [PATCH net 3/7] net: hns3: Fix ring and vector map command
From: Salil Mehta @ 2017-09-19 1:06 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil.lnk, netdev,
linux-kernel, linux-rdma, linuxarm, Mingguang Qu
In-Reply-To: <20170919010628.175732-1-salil.mehta@huawei.com>
From: Lipeng <lipeng321@huawei.com>
This patch add INT_GL and VF id to vector configure when bind ring
with vector. INT_GL means Interrupt Gap Limiting. Vector id starts
from 0 in each VF, so the bind command must specify VF id.
Signed-off-by: Lipeng <lipeng321@huawei.com>
Signed-off-by: Mingguang Qu <qumingguang@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 8 ++++++--
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 8 ++++++++
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index 91ae0135ee50..c2b613b40509 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -238,7 +238,7 @@ struct hclge_tqp_map {
u8 rsv[18];
};
-#define HCLGE_VECTOR_ELEMENTS_PER_CMD 11
+#define HCLGE_VECTOR_ELEMENTS_PER_CMD 10
enum hclge_int_type {
HCLGE_INT_TX,
@@ -252,8 +252,12 @@ struct hclge_ctrl_vector_chain {
#define HCLGE_INT_TYPE_S 0
#define HCLGE_INT_TYPE_M 0x3
#define HCLGE_TQP_ID_S 2
-#define HCLGE_TQP_ID_M (0x3fff << HCLGE_TQP_ID_S)
+#define HCLGE_TQP_ID_M (0x7ff << HCLGE_TQP_ID_S)
+#define HCLGE_INT_GL_IDX_S 13
+#define HCLGE_INT_GL_IDX_M (0x3 << HCLGE_INT_GL_IDX_S)
__le16 tqp_type_and_id[HCLGE_VECTOR_ELEMENTS_PER_CMD];
+ u8 vfid;
+ u8 rsv;
};
#define HCLGE_TC_NUM 8
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index e324bc6e9f4f..eafd9c678162 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -2680,7 +2680,11 @@ int hclge_map_vport_ring_to_vector(struct hclge_vport *vport, int vector_id,
hnae_get_bit(node->flag, HNAE3_RING_TYPE_B));
hnae_set_field(req->tqp_type_and_id[i], HCLGE_TQP_ID_M,
HCLGE_TQP_ID_S, node->tqp_index);
+ hnae_set_field(req->tqp_type_and_id[i], HCLGE_INT_GL_IDX_M,
+ HCLGE_INT_GL_IDX_S,
+ hnae_get_bit(node->flag, HNAE3_RING_TYPE_B));
req->tqp_type_and_id[i] = cpu_to_le16(req->tqp_type_and_id[i]);
+ req->vfid = vport->vport_id;
if (++i >= HCLGE_VECTOR_ELEMENTS_PER_CMD) {
req->int_cause_num = HCLGE_VECTOR_ELEMENTS_PER_CMD;
@@ -2764,8 +2768,12 @@ static int hclge_unmap_ring_from_vector(
hnae_get_bit(node->flag, HNAE3_RING_TYPE_B));
hnae_set_field(req->tqp_type_and_id[i], HCLGE_TQP_ID_M,
HCLGE_TQP_ID_S, node->tqp_index);
+ hnae_set_field(req->tqp_type_and_id[i], HCLGE_INT_GL_IDX_M,
+ HCLGE_INT_GL_IDX_S,
+ hnae_get_bit(node->flag, HNAE3_RING_TYPE_B));
req->tqp_type_and_id[i] = cpu_to_le16(req->tqp_type_and_id[i]);
+ req->vfid = vport->vport_id;
if (++i >= HCLGE_VECTOR_ELEMENTS_PER_CMD) {
req->int_cause_num = HCLGE_VECTOR_ELEMENTS_PER_CMD;
--
2.11.0
^ permalink raw reply related
* [PATCH net 2/7] net: hns3: fix the command used to unmap ring from vector
From: Salil Mehta @ 2017-09-19 1:06 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil.lnk, netdev,
linux-kernel, linux-rdma, linuxarm
In-Reply-To: <20170919010628.175732-1-salil.mehta@huawei.com>
From: Lipeng <lipeng321@huawei.com>
When unmap ring from vector, it use wrong command, this will cause
error if the unmap action need multi command description. This patch
fix the error.
Signed-off-by: Lipeng <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index db4e07dac29a..e324bc6e9f4f 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -2779,7 +2779,7 @@ static int hclge_unmap_ring_from_vector(
}
i = 0;
hclge_cmd_setup_basic_desc(&desc,
- HCLGE_OPC_ADD_RING_TO_VECTOR,
+ HCLGE_OPC_DEL_RING_TO_VECTOR,
false);
req->int_vector_id = vector_id;
}
--
2.11.0
^ permalink raw reply related
* [PATCH net 1/7] net: hns3: get phy addr from NCL_config
From: Salil Mehta @ 2017-09-19 1:06 UTC (permalink / raw)
To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
Cc: salil.mehta-hv44wF8Li93QT0dZR+AlfA,
yisen.zhuang-hv44wF8Li93QT0dZR+AlfA,
lipeng321-hv44wF8Li93QT0dZR+AlfA,
mehta.salil.lnk-Re5JQEeQqe8AvxtiuMwx3w,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-rdma-u79uwXL29TY76Z2rM5mHXA,
linuxarm-hv44wF8Li93QT0dZR+AlfA
In-Reply-To: <20170919010628.175732-1-salil.mehta-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
From: Lipeng <lipeng321-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
NCL_config file defines phy address for every port. Driver should get
phy address from NCL_config file.If do not get the right phy address,
every port will use the default phy address 0, different port use the
same phy address will cause error.
Signed-off-by: Lipeng <lipeng321-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
Signed-off-by: Salil Mehta <salil.mehta-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
---
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index bb45365fb817..db4e07dac29a 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -1066,6 +1066,7 @@ static int hclge_configure(struct hclge_dev *hdev)
for (i = 0; i < ETH_ALEN; i++)
hdev->hw.mac.mac_addr[i] = cfg.mac_addr[i];
hdev->hw.mac.media_type = cfg.media_type;
+ hdev->hw.mac.phy_addr = cfg.phy_addr;
hdev->num_desc = cfg.tqp_desc_num;
hdev->tm_info.num_pg = 1;
hdev->tm_info.num_tc = cfg.tc_num;
--
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH net 0/7] Bug fixes for the HNS3 Ethernet Driver for Hip08 SoC
From: Salil Mehta @ 2017-09-19 1:06 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil.lnk, netdev,
linux-kernel, linux-rdma, linuxarm
This patch set presents some bug fixes for the HNS3 Ethernet driver, identified
during internal testing & stabilization efforts.
This patch series is meant for Linux 4.14 kernel.
Lipeng (6):
net: hns3: get phy addr from NCL_config
net: hns3: fix the command used to unmap ring from vector
net: hns3: Fix ring and vector map command
net: hns3: fix a bug of set mac address
net: hns3: set default vlan id to PF
net: hns3: Fixes the premature exit of loop when matching clients
Salil Mehta (1):
net: hns3: fixes the ether address copy with more appropriate API
drivers/net/ethernet/hisilicon/hns3/hnae3.c | 43 +++++-----------------
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 8 +++-
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 20 ++++++++--
.../net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c | 7 ++--
4 files changed, 35 insertions(+), 43 deletions(-)
--
2.11.0
^ permalink raw reply
* RE: [PATCH RFC 6/6] Modify tag_ksz.c to support other KSZ switch drivers
From: Tristram.Ha @ 2017-09-19 0:45 UTC (permalink / raw)
To: f.fainelli
Cc: muvarov, pavel, nathan.leigh.conrad, vivien.didelot, netdev,
linux-kernel, Woojung.Huh, andrew
In-Reply-To: <c812edb6-9a8d-e8de-a288-3c2030b72bbd@gmail.com>
> I am not really sure why this is such a concern for you so soon when
> your driver is not even included yet. You should really aim for baby
> steps here: get the basic driver(s) included, with a limited set of
> features, and gradually add more features to the driver. When
> fwd_offload_mark and RSTP become a real problem, we can most
> definitively find a way to fix those in DSA and depending drivers.
I was under the impression that there is a new push of this new switchdev
model and so the DSA model was overhauled to support that.
The KSZ9477 driver is already in the kernel, and its register access is actually
much different from the other older switches. There are not much common
code to be reused. I always know this tail tag handling is the sticking point.
I will submit a much simplified driver and wait for switch access in the future.
^ permalink raw reply
* ipv4 ID calculation
From: Harsha Chenji @ 2017-09-19 0:43 UTC (permalink / raw)
To: netdev
Hi all,
Where is the ID field of the IPv4 header created when the DF flag is
set? I am looking at ip_build_and_send_pkt. The code seems to have
changed in 4.4-rc1:
if (ip_dont_fragment(sk, &rt->dst)) {
iph->frag_off = htons(IP_DF);
iph->id = 0;
} else {
iph->frag_off = 0;
__ip_select_ident(net, iph, 1);
}
old code (executed irrespective of DF or not):
ip_select_ident(sock_net(sk), skb, sk);
The code in Stevens is basically iph->id = htons(ip_ident++) and now
it seems to be calculated based on a hash + lookup table.
So where is the id of 0 overwritten when DF is set? Didn't find any
info in the docs.
P.S. - is this the right mailing list for these kind of questions?
Thanks!
^ permalink raw reply
* [PATCH net-next 14/14] gtp: GSO support
From: Tom Herbert @ 2017-09-19 0:39 UTC (permalink / raw)
To: davem; +Cc: netdev, pablo, laforge, rohit, Tom Herbert
In-Reply-To: <20170919003904.5124-1-tom@quantonium.net>
Need to define a gtp_gso_segment since the GTP header includes a length
field that must be set per packet. Also, GPv0 header includes a sequence
number that is incremented per packet.
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
drivers/net/gtp.c | 176 +++++++++++++++++++++++++++++++++++++++----
include/uapi/linux/if_link.h | 1 -
2 files changed, 163 insertions(+), 14 deletions(-)
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 2f9d810cf19f..a2c4d9804a8f 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -120,6 +120,8 @@ static u32 gtp_h_initval;
static void pdp_context_delete(struct pdp_ctx *pctx);
+static int gtp_gso_type;
+
static inline u32 gtp0_hashfn(u64 tid)
{
u32 *tid32 = (u32 *) &tid;
@@ -430,6 +432,69 @@ static int gtp1u_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
return 1;
}
+static struct sk_buff *gtp_gso_segment(struct sk_buff *skb,
+ netdev_features_t features)
+{
+ struct sk_buff *segs = ERR_PTR(-EINVAL);
+ int tnl_hlen = skb->mac_len;
+ struct gtp0_header *gtp0;
+
+ if (unlikely(!pskb_may_pull(skb, tnl_hlen)))
+ return ERR_PTR(-EINVAL);
+
+ /* Make sure we have a mininal GTP header */
+ if (unlikely(tnl_hlen < min_t(size_t, sizeof(struct gtp0_header),
+ sizeof(struct gtp1_header))))
+ return ERR_PTR(-EINVAL);
+
+ /* Determine version */
+ gtp0 = (struct gtp0_header *)skb->data;
+ switch (gtp0->flags >> 5) {
+ case GTP_V0: {
+ u16 tx_seq;
+
+ if (unlikely(tnl_hlen != sizeof(struct gtp0_header)))
+ return ERR_PTR(-EINVAL);
+
+ tx_seq = ntohs(gtp0->seq);
+
+ /* segment inner packet. */
+ segs = skb_mac_gso_segment(skb, features);
+ if (!IS_ERR_OR_NULL(segs)) {
+ skb = segs;
+ do {
+ gtp0 = (struct gtp0_header *)
+ skb_mac_header(skb);
+ gtp0->length = ntohs(skb->len - tnl_hlen);
+ gtp0->seq = htons(tx_seq);
+ tx_seq++;
+ } while ((skb = skb->next));
+ }
+ break;
+ }
+ case GTP_V1: {
+ struct gtp1_header *gtp1;
+
+ if (unlikely(tnl_hlen != sizeof(struct gtp1_header)))
+ return ERR_PTR(-EINVAL);
+
+ /* segment inner packet. */
+ segs = skb_mac_gso_segment(skb, features);
+ if (!IS_ERR_OR_NULL(segs)) {
+ skb = segs;
+ do {
+ gtp1 = (struct gtp1_header *)
+ skb_mac_header(skb);
+ gtp1->length = ntohs(skb->len - tnl_hlen);
+ } while ((skb = skb->next));
+ }
+ break;
+ }
+ }
+
+ return segs;
+}
+
static struct sk_buff **gtp_gro_receive_finish(struct sock *sk,
struct sk_buff **head,
struct sk_buff *skb,
@@ -688,18 +753,25 @@ static inline void gtp0_push_header(struct sk_buff *skb, struct pdp_ctx *pctx)
{
int payload_len = skb->len;
struct gtp0_header *gtp0;
+ u32 tx_seq;
gtp0 = skb_push(skb, sizeof(*gtp0));
gtp0->flags = 0x1e; /* v0, GTP-non-prime. */
gtp0->type = GTP_TPDU;
gtp0->length = htons(payload_len);
- gtp0->seq = htons((atomic_inc_return(&pctx->tx_seq) - 1) %
- 0xffff);
gtp0->flow = htons(pctx->u.v0.flow);
gtp0->number = 0xff;
gtp0->spare[0] = gtp0->spare[1] = gtp0->spare[2] = 0xff;
gtp0->tid = cpu_to_be64(pctx->u.v0.tid);
+
+ /* If skb is GSO allocate sequence numbers for all the segments */
+ tx_seq = skb_shinfo(skb)->gso_segs ?
+ atomic_add_return(skb_shinfo(skb)->gso_segs,
+ &pctx->tx_seq) :
+ atomic_inc_return(&pctx->tx_seq);
+
+ gtp0->seq = (htons((u16)tx_seq) - 1) & 0xffff;
}
static inline void gtp1_push_header(struct sk_buff *skb, struct pdp_ctx *pctx)
@@ -737,6 +809,59 @@ static void gtp_push_header(struct sk_buff *skb, struct pdp_ctx *pctx)
}
}
+static size_t gtp_max_header_len(int version)
+
+{
+ switch (version) {
+ case GTP_V0:
+ return sizeof(struct gtp0_header);
+ case GTP_V1:
+ return sizeof(struct gtp1_header) + 4;
+ }
+
+ /* Should not happen */
+ return 0;
+}
+
+static int gtp_build_skb(struct sk_buff *skb, struct dst_entry *dst,
+ struct pdp_ctx *pctx, bool xnet, int ip_hdr_len,
+ bool udp_sum)
+{
+ int type = (udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL) |
+ gtp_gso_type;
+ int min_headroom;
+ u16 protocol;
+ int err;
+
+ skb_scrub_packet(skb, xnet);
+
+ min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len +
+ gtp_max_header_len(pctx->gtp_version) + ip_hdr_len;
+
+ err = skb_cow_head(skb, min_headroom);
+ if (unlikely(err))
+ goto free_dst;
+
+ err = iptunnel_handle_offloads(skb, type);
+ if (err)
+ goto free_dst;
+
+ protocol = ipver_to_eth(ip_hdr(skb));
+
+ gtp_push_header(skb, pctx);
+
+ /* GTP header is treated as inner MAC header */
+ skb_reset_inner_mac_header(skb);
+
+ skb_set_inner_protocol(skb, protocol);
+
+ return 0;
+
+free_dst:
+ dst_release(dst);
+ return err;
+}
+
static int gtp_xmit(struct sk_buff *skb, struct net_device *dev,
struct pdp_ctx *pctx)
{
@@ -746,13 +871,6 @@ static int gtp_xmit(struct sk_buff *skb, struct net_device *dev,
bool udp_csum;
int err = 0;
- /* Ensure there is sufficient headroom. */
- err = skb_cow_head(skb, dev->needed_headroom);
- if (unlikely(err))
- goto out_err;
-
- skb_reset_inner_headers(skb);
-
if (pctx->peer_af == AF_INET) {
__be32 saddr = inet_sk(sk)->inet_saddr;
struct rtable *rt;
@@ -768,9 +886,13 @@ static int gtp_xmit(struct sk_buff *skb, struct net_device *dev,
goto out_err;
}
- skb_dst_drop(skb);
+ err = gtp_build_skb(skb, &rt->dst, pctx, xnet,
+ sizeof(struct iphdr),
+ !(pctx->cfg_flags &
+ GTP_F_UDP_ZERO_CSUM_TX));
+ if (err)
+ goto out_err;
- gtp_push_header(skb, pctx);
udp_csum = !(pctx->cfg_flags & GTP_F_UDP_ZERO_CSUM_TX);
udp_tunnel_xmit_skb(rt, sk, skb, saddr,
pctx->peer_addr_ip4.s_addr,
@@ -797,9 +919,13 @@ static int gtp_xmit(struct sk_buff *skb, struct net_device *dev,
goto out_err;
}
- skb_dst_drop(skb);
+ err = gtp_build_skb(skb, dst, pctx, xnet,
+ sizeof(struct ipv6hdr),
+ !(pctx->cfg_flags &
+ GTP_F_UDP_ZERO_CSUM6_TX));
+ if (err)
+ goto out_err;
- gtp_push_header(skb, pctx);
udp_csum = !(pctx->cfg_flags & GTP_F_UDP_ZERO_CSUM6_TX);
udp_tunnel6_xmit_skb(dst, sk, skb, dev,
&saddr, &pctx->peer_addr_ip6,
@@ -898,6 +1024,12 @@ static const struct net_device_ops gtp_netdev_ops = {
.ndo_get_stats64 = ip_tunnel_get_stats64,
};
+#define GTP_FEATURES (NETIF_F_SG | \
+ NETIF_F_FRAGLIST | \
+ NETIF_F_HIGHDMA | \
+ NETIF_F_GSO_SOFTWARE | \
+ NETIF_F_HW_CSUM)
+
static void gtp_link_setup(struct net_device *dev)
{
struct gtp_dev *gtp = netdev_priv(dev);
@@ -912,7 +1044,13 @@ static void gtp_link_setup(struct net_device *dev)
dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
dev->priv_flags |= IFF_NO_QUEUE;
+
dev->features |= NETIF_F_LLTX;
+ dev->features |= GTP_FEATURES;
+
+ dev->hw_features |= GTP_FEATURES;
+ dev->hw_features |= NETIF_F_GSO_SOFTWARE;
+
netif_keep_dst(dev);
/* Assume largest header, ie. GTPv0. */
@@ -1903,6 +2041,11 @@ static struct pernet_operations gtp_net_ops = {
.size = sizeof(struct gtp_net),
};
+static const struct skb_gso_app gtp_gso_app = {
+ .check_flags = SKB_GSO_UDP_TUNNEL | SKB_GSO_UDP_TUNNEL_CSUM,
+ .gso_segment = gtp_gso_segment,
+};
+
static int __init gtp_init(void)
{
int err;
@@ -1921,6 +2064,10 @@ static int __init gtp_init(void)
if (err < 0)
goto unreg_genl_family;
+ gtp_gso_type = skb_gso_app_register(>p_gso_app);
+ if (!gtp_gso_type)
+ pr_warn("GTP unable to create UDP app gso type");
+
pr_info("GTP module loaded (pdp ctx size %zd bytes)\n",
sizeof(struct pdp_ctx));
return 0;
@@ -1937,6 +2084,9 @@ late_initcall(gtp_init);
static void __exit gtp_fini(void)
{
+ if (gtp_gso_type)
+ skb_gso_app_unregister(gtp_gso_type, >p_gso_app);
+
unregister_pernet_subsys(>p_net_ops);
genl_unregister_family(>p_genl_family);
rtnl_link_unregister(>p_link_ops);
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 14a32d745e24..7c15db44eab3 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -558,7 +558,6 @@ enum {
IFLA_GTP_UDP_CSUM,
IFLA_GTP_UDP_ZERO_CSUM6_TX,
IFLA_GTP_UDP_ZERO_CSUM6_RX,
-
__IFLA_GTP_MAX,
};
#define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1)
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 13/14] gtp: Support for GRO
From: Tom Herbert @ 2017-09-19 0:39 UTC (permalink / raw)
To: davem; +Cc: netdev, pablo, laforge, rohit, Tom Herbert
In-Reply-To: <20170919003904.5124-1-tom@quantonium.net>
Populate GRO receive and GRO complete functions for GTP-Uv0 and v1.
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
drivers/net/gtp.c | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 204 insertions(+)
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index b53946f8b10b..2f9d810cf19f 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -22,6 +22,7 @@
#include <linux/jhash.h>
#include <linux/if_tunnel.h>
#include <linux/net.h>
+#include <linux/netdevice.h>
#include <linux/file.h>
#include <linux/gtp.h>
@@ -429,6 +430,205 @@ static int gtp1u_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
return 1;
}
+static struct sk_buff **gtp_gro_receive_finish(struct sock *sk,
+ struct sk_buff **head,
+ struct sk_buff *skb,
+ void *hdr, size_t hdrlen)
+{
+ const struct packet_offload *ptype;
+ struct sk_buff **pp;
+ __be16 type;
+
+ type = ipver_to_eth((struct iphdr *)((void *)hdr + hdrlen));
+ if (!type)
+ goto out_err;
+
+ rcu_read_lock();
+
+ ptype = gro_find_receive_by_type(type);
+ if (!ptype)
+ goto out_unlock_err;
+
+ skb_gro_pull(skb, hdrlen);
+ skb_gro_postpull_rcsum(skb, hdr, hdrlen);
+ pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
+
+ rcu_read_unlock();
+
+ return pp;
+
+out_unlock_err:
+ rcu_read_unlock();
+out_err:
+ NAPI_GRO_CB(skb)->flush |= 1;
+ return NULL;
+}
+
+static struct sk_buff **gtp0_gro_receive(struct sock *sk,
+ struct sk_buff **head,
+ struct sk_buff *skb)
+{
+ struct gtp0_header *gtp0;
+ size_t len, hdrlen, off;
+ struct sk_buff *p;
+
+ off = skb_gro_offset(skb);
+ len = off + sizeof(*gtp0);
+ hdrlen = sizeof(*gtp0);
+
+ gtp0 = skb_gro_header_fast(skb, off);
+ if (skb_gro_header_hard(skb, len)) {
+ gtp0 = skb_gro_header_slow(skb, len, off);
+ if (unlikely(!gtp0))
+ goto out;
+ }
+
+ if ((gtp0->flags >> 5) != GTP_V0 || gtp0->type != GTP_TPDU)
+ goto out;
+
+ hdrlen += sizeof(*gtp0);
+
+ /* To get IP version */
+ len += sizeof(struct iphdr);
+
+ /* Now get header with GTP header an IPv4 header (for version) */
+ if (skb_gro_header_hard(skb, len)) {
+ gtp0 = skb_gro_header_slow(skb, len, off);
+ if (unlikely(!gtp0))
+ goto out;
+ }
+
+ for (p = *head; p; p = p->next) {
+ const struct gtp0_header *gtp0_t;
+
+ if (!NAPI_GRO_CB(p)->same_flow)
+ continue;
+
+ gtp0_t = (struct gtp0_header *)(p->data + off);
+
+ if (gtp0->flags != gtp0_t->flags ||
+ gtp0->type != gtp0_t->type ||
+ gtp0->flow != gtp0_t->flow ||
+ gtp0->tid != gtp0_t->tid) {
+ NAPI_GRO_CB(p)->same_flow = 0;
+ continue;
+ }
+ }
+
+ return gtp_gro_receive_finish(sk, head, skb, gtp0, hdrlen);
+
+out:
+ NAPI_GRO_CB(skb)->flush |= 1;
+
+ return NULL;
+}
+
+static struct sk_buff **gtp1u_gro_receive(struct sock *sk,
+ struct sk_buff **head,
+ struct sk_buff *skb)
+{
+ struct gtp1_header *gtp1;
+ size_t len, hdrlen, off;
+ struct sk_buff *p;
+
+ off = skb_gro_offset(skb);
+ len = off + sizeof(*gtp1);
+ hdrlen = sizeof(*gtp1);
+
+ gtp1 = skb_gro_header_fast(skb, off);
+ if (skb_gro_header_hard(skb, len)) {
+ gtp1 = skb_gro_header_slow(skb, len, off);
+ if (unlikely(!gtp1))
+ goto out;
+ }
+
+ if ((gtp1->flags >> 5) != GTP_V1 || gtp1->type != GTP_TPDU)
+ goto out;
+
+ if (gtp1->flags & GTP1_F_MASK) {
+ hdrlen += 4;
+ len += 4;
+ }
+
+ len += sizeof(struct iphdr);
+
+ /* Now get header with GTP header an IPv4 header (for version) */
+ if (skb_gro_header_hard(skb, len)) {
+ gtp1 = skb_gro_header_slow(skb, len, off);
+ if (unlikely(!gtp1))
+ goto out;
+ }
+
+ for (p = *head; p; p = p->next) {
+ const struct gtp1_header *gtp1_t;
+
+ if (!NAPI_GRO_CB(p)->same_flow)
+ continue;
+
+ gtp1_t = (struct gtp1_header *)(p->data + off);
+
+ if (gtp1->flags != gtp1_t->flags ||
+ gtp1->type != gtp1_t->type ||
+ gtp1->tid != gtp1_t->tid) {
+ NAPI_GRO_CB(p)->same_flow = 0;
+ continue;
+ }
+ }
+
+ return gtp_gro_receive_finish(sk, head, skb, gtp1, hdrlen);
+
+out:
+ NAPI_GRO_CB(skb)->flush = 1;
+
+ return NULL;
+}
+
+static int gtp_gro_complete_finish(struct sock *sk, struct sk_buff *skb,
+ int nhoff, size_t hdrlen)
+{
+ struct packet_offload *ptype;
+ int err = -EINVAL;
+ __be16 type;
+
+ type = ipver_to_eth((struct iphdr *)(skb->data + nhoff + hdrlen));
+ if (!type)
+ return err;
+
+ rcu_read_lock();
+ ptype = gro_find_complete_by_type(type);
+ if (ptype)
+ err = ptype->callbacks.gro_complete(skb, nhoff + hdrlen);
+
+ rcu_read_unlock();
+
+ skb_set_inner_mac_header(skb, nhoff + hdrlen);
+
+ return err;
+}
+
+static int gtp0_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
+{
+ struct gtp0_header *gtp0 = (struct gtp0_header *)(skb->data + nhoff);
+ size_t hdrlen = sizeof(struct gtp0_header);
+
+ gtp0->length = htons(skb->len - nhoff - hdrlen);
+
+ return gtp_gro_complete_finish(sk, skb, nhoff, hdrlen);
+}
+
+static int gtp1u_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
+{
+ struct gtp1_header *gtp1 = (struct gtp1_header *)(skb->data + nhoff);
+ size_t hdrlen = sizeof(struct gtp1_header);
+
+ if (gtp1->flags & GTP1_F_MASK)
+ hdrlen += 4;
+
+ gtp1->length = htons(skb->len - nhoff - hdrlen);
+
+ return gtp_gro_complete_finish(sk, skb, nhoff, hdrlen);
+}
+
static void gtp_encap_destroy(struct sock *sk)
{
struct gtp_dev *gtp;
@@ -946,9 +1146,13 @@ static int gtp_encap_enable_sock(struct socket *sock, int type,
switch (type) {
case UDP_ENCAP_GTP0:
tuncfg.encap_rcv = gtp0_udp_encap_recv;
+ tuncfg.gro_receive = gtp0_gro_receive;
+ tuncfg.gro_complete = gtp0_gro_complete;
break;
case UDP_ENCAP_GTP1U:
tuncfg.encap_rcv = gtp1u_udp_encap_recv;
+ tuncfg.gro_receive = gtp1u_gro_receive;
+ tuncfg.gro_complete = gtp1u_gro_complete;
break;
default:
pr_debug("Unknown encap type %u\n", type);
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 12/14] gtp: Configuration for zero UDP checksum
From: Tom Herbert @ 2017-09-19 0:39 UTC (permalink / raw)
To: davem; +Cc: netdev, pablo, laforge, rohit, Tom Herbert
In-Reply-To: <20170919003904.5124-1-tom@quantonium.net>
Add configuration to control use of zero checksums on transmit for both
IPv4 and IPv6, and control over accepting zero IPv6 checksums on
receive.
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
drivers/net/gtp.c | 35 +++++++++++++++++++++++++++++++++--
include/uapi/linux/if_link.h | 4 ++++
2 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 393f63cb2576..b53946f8b10b 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -75,6 +75,13 @@ struct pdp_ctx {
struct rcu_head rcu_head;
struct dst_cache dst_cache;
+
+ unsigned int cfg_flags;
+
+#define GTP_F_UDP_ZERO_CSUM_TX 0x1
+#define GTP_F_UDP_ZERO_CSUM6_TX 0x2
+#define GTP_F_UDP_ZERO_CSUM6_RX 0x4
+
};
/* One instance of the GTP device. */
@@ -536,6 +543,7 @@ static int gtp_xmit(struct sk_buff *skb, struct net_device *dev,
struct gtp_dev *gtp = netdev_priv(dev);
bool xnet = !net_eq(gtp->net, dev_net(gtp->dev));
struct sock *sk = pctx->sk;
+ bool udp_csum;
int err = 0;
/* Ensure there is sufficient headroom. */
@@ -563,11 +571,12 @@ static int gtp_xmit(struct sk_buff *skb, struct net_device *dev,
skb_dst_drop(skb);
gtp_push_header(skb, pctx);
+ udp_csum = !(pctx->cfg_flags & GTP_F_UDP_ZERO_CSUM_TX);
udp_tunnel_xmit_skb(rt, sk, skb, saddr,
pctx->peer_addr_ip4.s_addr,
0, ip4_dst_hoplimit(&rt->dst), 0,
pctx->gtp_port, pctx->gtp_port,
- xnet, false);
+ xnet, !udp_csum);
netdev_dbg(dev, "gtp -> IP src: %pI4 dst: %pI4\n",
&saddr, &pctx->peer_addr_ip4.s_addr);
@@ -591,11 +600,12 @@ static int gtp_xmit(struct sk_buff *skb, struct net_device *dev,
skb_dst_drop(skb);
gtp_push_header(skb, pctx);
+ udp_csum = !(pctx->cfg_flags & GTP_F_UDP_ZERO_CSUM6_TX);
udp_tunnel6_xmit_skb(dst, sk, skb, dev,
&saddr, &pctx->peer_addr_ip6,
0, ip6_dst_hoplimit(dst), 0,
pctx->gtp_port, pctx->gtp_port,
- true);
+ !udp_csum);
netdev_dbg(dev, "gtp -> IP src: %pI6 dst: %pI6\n",
&saddr, &pctx->peer_addr_ip6);
@@ -728,6 +738,7 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
{
unsigned int role = GTP_ROLE_GGSN;
bool have_fd, have_ports;
+ unsigned int flags = 0;
bool is_ipv6 = false;
struct gtp_dev *gtp;
struct gtp_net *gn;
@@ -747,6 +758,21 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
return -EINVAL;
}
+ if (data[IFLA_GTP_UDP_CSUM]) {
+ if (!nla_get_u8(data[IFLA_GTP_UDP_CSUM]))
+ flags |= GTP_F_UDP_ZERO_CSUM_TX;
+ }
+
+ if (data[IFLA_GTP_UDP_ZERO_CSUM6_TX]) {
+ if (nla_get_u8(data[IFLA_GTP_UDP_ZERO_CSUM6_TX]))
+ flags |= GTP_F_UDP_ZERO_CSUM6_TX;
+ }
+
+ if (data[IFLA_GTP_UDP_ZERO_CSUM6_RX]) {
+ if (nla_get_u8(data[IFLA_GTP_UDP_ZERO_CSUM6_RX]))
+ flags |= GTP_F_UDP_ZERO_CSUM6_RX;
+ }
+
if (data[IFLA_GTP_AF]) {
u16 af = nla_get_u16(data[IFLA_GTP_AF]);
@@ -819,6 +845,9 @@ static const struct nla_policy gtp_policy[IFLA_GTP_MAX + 1] = {
[IFLA_GTP_ROLE] = { .type = NLA_U32 },
[IFLA_GTP_PORT0] = { .type = NLA_U16 },
[IFLA_GTP_PORT1] = { .type = NLA_U16 },
+ [IFLA_GTP_UDP_CSUM] = { .type = NLA_U8 },
+ [IFLA_GTP_UDP_ZERO_CSUM6_TX] = { .type = NLA_U8 },
+ [IFLA_GTP_UDP_ZERO_CSUM6_RX] = { .type = NLA_U8 },
};
static int gtp_validate(struct nlattr *tb[], struct nlattr *data[],
@@ -990,6 +1019,8 @@ static struct socket *gtp_create_sock(struct net *net, bool ipv6,
if (ipv6) {
udp_conf.family = AF_INET6;
+ udp_conf.use_udp6_rx_checksums =
+ !(flags & GTP_F_UDP_ZERO_CSUM6_RX);
udp_conf.ipv6_v6only = 1;
} else {
udp_conf.family = AF_INET;
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 81c26864abeb..14a32d745e24 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -555,6 +555,10 @@ enum {
IFLA_GTP_AF,
IFLA_GTP_PORT0,
IFLA_GTP_PORT1,
+ IFLA_GTP_UDP_CSUM,
+ IFLA_GTP_UDP_ZERO_CSUM6_TX,
+ IFLA_GTP_UDP_ZERO_CSUM6_RX,
+
__IFLA_GTP_MAX,
};
#define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1)
--
2.11.0
^ 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