* [PATCH v4 net-next 17/21] net: usb: aqc111: Initialize ethtool_ops structure
From: Igor Russkikh @ 2018-11-26 9:33 UTC (permalink / raw)
To: linux-usb@vger.kernel.org, davem@davemloft.net,
netdev@vger.kernel.org
Cc: andrew@lunn.ch, Dmitry Bezrukov, Igor Russkikh
In-Reply-To: <cover.1543224254.git.igor.russkikh@aquantia.com>
From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Implement get_drvinfo, set/get_msglevel, get_link callbacks
Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
drivers/net/usb/aqc111.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 3b42843d7017..9fc036d5354b 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/netdevice.h>
+#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/usb.h>
#include <linux/crc32.h>
@@ -18,6 +19,8 @@
#include "aqc111.h"
+#define DRIVER_NAME "aqc111"
+
static int aqc111_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value,
u16 index, u16 size, void *data)
{
@@ -178,6 +181,23 @@ static int aqc111_write16_cmd_async(struct usbnet *dev, u8 cmd, u16 value,
sizeof(tmp), &tmp);
}
+static void aqc111_get_drvinfo(struct net_device *net,
+ struct ethtool_drvinfo *info)
+{
+ struct usbnet *dev = netdev_priv(net);
+ struct aqc111_data *aqc111_data = dev->driver_priv;
+
+ /* Inherit standard device info */
+ usbnet_get_drvinfo(net, info);
+ strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver));
+ snprintf(info->fw_version, sizeof(info->fw_version), "%u.%u.%u",
+ aqc111_data->fw_ver.major,
+ aqc111_data->fw_ver.minor,
+ aqc111_data->fw_ver.rev);
+ info->eedump_len = 0x00;
+ info->regdump_len = 0x00;
+}
+
static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed)
{
struct aqc111_data *aqc111_data = dev->driver_priv;
@@ -225,6 +245,13 @@ static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed)
aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, &aqc111_data->phy_cfg);
}
+static const struct ethtool_ops aqc111_ethtool_ops = {
+ .get_drvinfo = aqc111_get_drvinfo,
+ .get_msglevel = usbnet_get_msglevel,
+ .set_msglevel = usbnet_set_msglevel,
+ .get_link = ethtool_op_get_link,
+};
+
static int aqc111_change_mtu(struct net_device *net, int new_mtu)
{
struct usbnet *dev = netdev_priv(net);
@@ -533,6 +560,7 @@ static int aqc111_bind(struct usbnet *dev, struct usb_interface *intf)
dev->net->max_mtu = 16334;
dev->net->netdev_ops = &aqc111_netdev_ops;
+ dev->net->ethtool_ops = &aqc111_ethtool_ops;
if (usb_device_no_sg_constraint(dev->udev))
dev->can_dma_sg = 1;
--
2.17.1
^ permalink raw reply related
* [PATCH v4 net-next 18/21] net: usb: aqc111: Implement get/set_link_ksettings callbacks
From: Igor Russkikh @ 2018-11-26 9:33 UTC (permalink / raw)
To: linux-usb@vger.kernel.org, davem@davemloft.net,
netdev@vger.kernel.org
Cc: andrew@lunn.ch, Dmitry Bezrukov, Igor Russkikh
In-Reply-To: <cover.1543224254.git.igor.russkikh@aquantia.com>
From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
drivers/net/usb/aqc111.c | 124 +++++++++++++++++++++++++++++++++++++++
1 file changed, 124 insertions(+)
diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 9fc036d5354b..650cea33f1a3 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -16,6 +16,7 @@
#include <linux/if_vlan.h>
#include <linux/usb/cdc.h>
#include <linux/usb/usbnet.h>
+#include <linux/linkmode.h>
#include "aqc111.h"
@@ -198,6 +199,84 @@ static void aqc111_get_drvinfo(struct net_device *net,
info->regdump_len = 0x00;
}
+static void aqc111_speed_to_link_mode(u32 speed,
+ struct ethtool_link_ksettings *elk)
+{
+ switch (speed) {
+ case SPEED_5000:
+ ethtool_link_ksettings_add_link_mode(elk, advertising,
+ 5000baseT_Full);
+ break;
+ case SPEED_2500:
+ ethtool_link_ksettings_add_link_mode(elk, advertising,
+ 2500baseT_Full);
+ break;
+ case SPEED_1000:
+ ethtool_link_ksettings_add_link_mode(elk, advertising,
+ 1000baseT_Full);
+ break;
+ case SPEED_100:
+ ethtool_link_ksettings_add_link_mode(elk, advertising,
+ 100baseT_Full);
+ break;
+ }
+}
+
+static int aqc111_get_link_ksettings(struct net_device *net,
+ struct ethtool_link_ksettings *elk)
+{
+ struct usbnet *dev = netdev_priv(net);
+ struct aqc111_data *aqc111_data = dev->driver_priv;
+ enum usb_device_speed usb_speed = dev->udev->speed;
+ u32 speed = SPEED_UNKNOWN;
+
+ ethtool_link_ksettings_zero_link_mode(elk, supported);
+ ethtool_link_ksettings_add_link_mode(elk, supported,
+ 100baseT_Full);
+ ethtool_link_ksettings_add_link_mode(elk, supported,
+ 1000baseT_Full);
+ if (usb_speed == USB_SPEED_SUPER) {
+ ethtool_link_ksettings_add_link_mode(elk, supported,
+ 2500baseT_Full);
+ ethtool_link_ksettings_add_link_mode(elk, supported,
+ 5000baseT_Full);
+ }
+ ethtool_link_ksettings_add_link_mode(elk, supported, TP);
+ ethtool_link_ksettings_add_link_mode(elk, supported, Autoneg);
+
+ elk->base.port = PORT_TP;
+ elk->base.transceiver = XCVR_INTERNAL;
+
+ elk->base.mdio_support = 0x00; /*Not supported*/
+
+ if (aqc111_data->autoneg)
+ linkmode_copy(elk->link_modes.advertising,
+ elk->link_modes.supported);
+ else
+ aqc111_speed_to_link_mode(aqc111_data->advertised_speed, elk);
+
+ elk->base.autoneg = aqc111_data->autoneg;
+
+ switch (aqc111_data->link_speed) {
+ case AQ_INT_SPEED_5G:
+ speed = SPEED_5000;
+ break;
+ case AQ_INT_SPEED_2_5G:
+ speed = SPEED_2500;
+ break;
+ case AQ_INT_SPEED_1G:
+ speed = SPEED_1000;
+ break;
+ case AQ_INT_SPEED_100M:
+ speed = SPEED_100;
+ break;
+ }
+ elk->base.duplex = DUPLEX_FULL;
+ elk->base.speed = speed;
+
+ return 0;
+}
+
static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed)
{
struct aqc111_data *aqc111_data = dev->driver_priv;
@@ -245,11 +324,56 @@ static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed)
aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, &aqc111_data->phy_cfg);
}
+static int aqc111_set_link_ksettings(struct net_device *net,
+ const struct ethtool_link_ksettings *elk)
+{
+ struct usbnet *dev = netdev_priv(net);
+ struct aqc111_data *aqc111_data = dev->driver_priv;
+ enum usb_device_speed usb_speed = dev->udev->speed;
+ u8 autoneg = elk->base.autoneg;
+ u32 speed = elk->base.speed;
+
+ if (autoneg == AUTONEG_ENABLE) {
+ if (aqc111_data->autoneg != AUTONEG_ENABLE) {
+ aqc111_data->autoneg = AUTONEG_ENABLE;
+ aqc111_data->advertised_speed =
+ (usb_speed == USB_SPEED_SUPER) ?
+ SPEED_5000 : SPEED_1000;
+ aqc111_set_phy_speed(dev, aqc111_data->autoneg,
+ aqc111_data->advertised_speed);
+ }
+ } else {
+ if (speed != SPEED_100 &&
+ speed != SPEED_1000 &&
+ speed != SPEED_2500 &&
+ speed != SPEED_5000 &&
+ speed != SPEED_UNKNOWN)
+ return -EINVAL;
+
+ if (elk->base.duplex != DUPLEX_FULL)
+ return -EINVAL;
+
+ if (usb_speed != USB_SPEED_SUPER && speed > SPEED_1000)
+ return -EINVAL;
+
+ aqc111_data->autoneg = AUTONEG_DISABLE;
+ if (speed != SPEED_UNKNOWN)
+ aqc111_data->advertised_speed = speed;
+
+ aqc111_set_phy_speed(dev, aqc111_data->autoneg,
+ aqc111_data->advertised_speed);
+ }
+
+ return 0;
+}
+
static const struct ethtool_ops aqc111_ethtool_ops = {
.get_drvinfo = aqc111_get_drvinfo,
.get_msglevel = usbnet_get_msglevel,
.set_msglevel = usbnet_set_msglevel,
.get_link = ethtool_op_get_link,
+ .get_link_ksettings = aqc111_get_link_ksettings,
+ .set_link_ksettings = aqc111_set_link_ksettings
};
static int aqc111_change_mtu(struct net_device *net, int new_mtu)
--
2.17.1
^ permalink raw reply related
* [PATCH v4 net-next 19/21] net: usb: aqc111: Add support for wake on LAN by MAGIC packet
From: Igor Russkikh @ 2018-11-26 9:33 UTC (permalink / raw)
To: linux-usb@vger.kernel.org, davem@davemloft.net,
netdev@vger.kernel.org
Cc: andrew@lunn.ch, Dmitry Bezrukov, Igor Russkikh
In-Reply-To: <cover.1543224254.git.igor.russkikh@aquantia.com>
From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
drivers/net/usb/aqc111.c | 180 +++++++++++++++++++++++++++++++++++++++
drivers/net/usb/aqc111.h | 12 +++
2 files changed, 192 insertions(+)
diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 650cea33f1a3..7c859b9417f1 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -54,6 +54,17 @@ static int aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value,
return ret;
}
+static int aqc111_read16_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value,
+ u16 index, u16 *data)
+{
+ int ret = 0;
+
+ ret = aqc111_read_cmd_nopm(dev, cmd, value, index, sizeof(*data), data);
+ le16_to_cpus(data);
+
+ return ret;
+}
+
static int aqc111_read16_cmd(struct usbnet *dev, u8 cmd, u16 value,
u16 index, u16 *data)
{
@@ -199,6 +210,35 @@ static void aqc111_get_drvinfo(struct net_device *net,
info->regdump_len = 0x00;
}
+static void aqc111_get_wol(struct net_device *net,
+ struct ethtool_wolinfo *wolinfo)
+{
+ struct usbnet *dev = netdev_priv(net);
+ struct aqc111_data *aqc111_data = dev->driver_priv;
+
+ wolinfo->supported = WAKE_MAGIC;
+ wolinfo->wolopts = 0;
+
+ if (aqc111_data->wol_flags & AQ_WOL_FLAG_MP)
+ wolinfo->wolopts |= WAKE_MAGIC;
+}
+
+static int aqc111_set_wol(struct net_device *net,
+ struct ethtool_wolinfo *wolinfo)
+{
+ struct usbnet *dev = netdev_priv(net);
+ struct aqc111_data *aqc111_data = dev->driver_priv;
+
+ if (wolinfo->wolopts & ~WAKE_MAGIC)
+ return -EINVAL;
+
+ aqc111_data->wol_flags = 0;
+ if (wolinfo->wolopts & WAKE_MAGIC)
+ aqc111_data->wol_flags |= AQ_WOL_FLAG_MP;
+
+ return 0;
+}
+
static void aqc111_speed_to_link_mode(u32 speed,
struct ethtool_link_ksettings *elk)
{
@@ -369,6 +409,8 @@ static int aqc111_set_link_ksettings(struct net_device *net,
static const struct ethtool_ops aqc111_ethtool_ops = {
.get_drvinfo = aqc111_get_drvinfo,
+ .get_wol = aqc111_get_wol,
+ .set_wol = aqc111_set_wol,
.get_msglevel = usbnet_get_msglevel,
.set_msglevel = usbnet_set_msglevel,
.get_link = ethtool_op_get_link,
@@ -1207,6 +1249,142 @@ static const struct driver_info aqc111_info = {
.tx_fixup = aqc111_tx_fixup,
};
+static int aqc111_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+ struct aqc111_data *aqc111_data = dev->driver_priv;
+ u16 temp_rx_ctrl = 0x00;
+ u16 reg16;
+ u8 reg8;
+
+ usbnet_suspend(intf, message);
+
+ aqc111_read16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, ®16);
+ temp_rx_ctrl = reg16;
+ /* Stop RX operations*/
+ reg16 &= ~SFR_RX_CTL_START;
+ aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, ®16);
+ /* Force bz */
+ aqc111_read16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
+ 2, ®16);
+ reg16 |= SFR_PHYPWR_RSTCTL_BZ;
+ aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_PHYPWR_RSTCTL,
+ 2, ®16);
+
+ reg8 = SFR_BULK_OUT_EFF_EN;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BULK_OUT_CTRL,
+ 1, 1, ®8);
+
+ temp_rx_ctrl &= ~(SFR_RX_CTL_START | SFR_RX_CTL_RF_WAK |
+ SFR_RX_CTL_AP | SFR_RX_CTL_AM);
+ aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
+ 2, &temp_rx_ctrl);
+
+ reg8 = 0x00;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH,
+ 1, 1, ®8);
+
+ if (aqc111_data->wol_flags) {
+ struct aqc111_wol_cfg wol_cfg = { 0 };
+
+ aqc111_data->phy_cfg |= AQ_WOL;
+ ether_addr_copy(wol_cfg.hw_addr, dev->net->dev_addr);
+ wol_cfg.flags = aqc111_data->wol_flags;
+
+ temp_rx_ctrl |= (SFR_RX_CTL_AB | SFR_RX_CTL_START);
+ aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL,
+ 2, &temp_rx_ctrl);
+ reg8 = 0x00;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK,
+ 1, 1, ®8);
+ reg8 = SFR_BMRX_DMA_EN;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BMRX_DMA_CONTROL,
+ 1, 1, ®8);
+ reg8 = SFR_RX_PATH_READY;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH,
+ 1, 1, ®8);
+ reg8 = 0x07;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QCTRL,
+ 1, 1, ®8);
+ reg8 = 0x00;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+ SFR_RX_BULKIN_QTIMR_LOW, 1, 1, ®8);
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC,
+ SFR_RX_BULKIN_QTIMR_HIGH, 1, 1, ®8);
+ reg8 = 0xFF;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QSIZE,
+ 1, 1, ®8);
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_BULKIN_QIFG,
+ 1, 1, ®8);
+
+ aqc111_read16_cmd_nopm(dev, AQ_ACCESS_MAC,
+ SFR_MEDIUM_STATUS_MODE, 2, ®16);
+ reg16 |= SFR_MEDIUM_RECEIVE_EN;
+ aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC,
+ SFR_MEDIUM_STATUS_MODE, 2, ®16);
+
+ aqc111_write_cmd(dev, AQ_WOL_CFG, 0, 0,
+ WOL_CFG_SIZE, &wol_cfg);
+ aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0,
+ &aqc111_data->phy_cfg);
+ } else {
+ aqc111_data->phy_cfg |= AQ_LOW_POWER;
+ aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0,
+ &aqc111_data->phy_cfg);
+
+ /* Disable RX path */
+ aqc111_read16_cmd_nopm(dev, AQ_ACCESS_MAC,
+ SFR_MEDIUM_STATUS_MODE, 2, ®16);
+ reg16 &= ~SFR_MEDIUM_RECEIVE_EN;
+ aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC,
+ SFR_MEDIUM_STATUS_MODE, 2, ®16);
+ }
+
+ return 0;
+}
+
+static int aqc111_resume(struct usb_interface *intf)
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+ struct aqc111_data *aqc111_data = dev->driver_priv;
+ u16 reg16;
+ u8 reg8;
+
+ netif_carrier_off(dev->net);
+
+ /* Power up ethernet PHY */
+ aqc111_data->phy_cfg |= AQ_PHY_POWER_EN;
+ aqc111_data->phy_cfg &= ~AQ_LOW_POWER;
+ aqc111_data->phy_cfg &= ~AQ_WOL;
+
+ reg8 = 0xFF;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_BM_INT_MASK,
+ 1, 1, ®8);
+ /* Configure RX control register => start operation */
+ reg16 = aqc111_data->rxctl;
+ reg16 &= ~SFR_RX_CTL_START;
+ aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, ®16);
+
+ reg16 |= SFR_RX_CTL_START;
+ aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_RX_CTL, 2, ®16);
+
+ aqc111_set_phy_speed(dev, aqc111_data->autoneg,
+ aqc111_data->advertised_speed);
+
+ aqc111_read16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+ 2, ®16);
+ reg16 |= SFR_MEDIUM_RECEIVE_EN;
+ aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_MEDIUM_STATUS_MODE,
+ 2, ®16);
+ reg8 = SFR_RX_PATH_READY;
+ aqc111_write_cmd_nopm(dev, AQ_ACCESS_MAC, SFR_ETH_MAC_PATH,
+ 1, 1, ®8);
+ reg8 = 0x0;
+ aqc111_write_cmd(dev, AQ_ACCESS_MAC, SFR_BMRX_DMA_CONTROL, 1, 1, ®8);
+
+ return usbnet_resume(intf);
+}
+
#define AQC111_USB_ETH_DEV(vid, pid, table) \
USB_DEVICE_INTERFACE_CLASS((vid), (pid), USB_CLASS_VENDOR_SPEC), \
.driver_info = (unsigned long)&(table) \
@@ -1228,6 +1406,8 @@ static struct usb_driver aq_driver = {
.name = "aqc111",
.id_table = products,
.probe = usbnet_probe,
+ .suspend = aqc111_suspend,
+ .resume = aqc111_resume,
.disconnect = usbnet_disconnect,
};
diff --git a/drivers/net/usb/aqc111.h b/drivers/net/usb/aqc111.h
index 0ce23a741211..4d68b3a6067c 100644
--- a/drivers/net/usb/aqc111.h
+++ b/drivers/net/usb/aqc111.h
@@ -18,6 +18,7 @@
#define AQ_ACCESS_MAC 0x01
#define AQ_FLASH_PARAMETERS 0x20
#define AQ_PHY_POWER 0x31
+#define AQ_WOL_CFG 0x60
#define AQ_PHY_OPS 0x61
#define AQ_USB_PHY_SET_TIMEOUT 10000
@@ -145,8 +146,18 @@
#define AQ_DSH_RETRIES_SHIFT 0x18
#define AQ_DSH_RETRIES_MASK 0xF000000
+#define AQ_WOL_FLAG_MP 0x2
+
/******************************************************************************/
+struct aqc111_wol_cfg {
+ u8 hw_addr[6];
+ u8 flags;
+ u8 rsvd[283];
+} __packed;
+
+#define WOL_CFG_SIZE sizeof(struct aqc111_wol_cfg)
+
struct aqc111_data {
u16 rxctl;
u8 rx_checksum;
@@ -160,6 +171,7 @@ struct aqc111_data {
u8 rev;
} fw_ver;
u32 phy_cfg;
+ u8 wol_flags;
};
#define AQ_LS_MASK 0x8000
--
2.17.1
^ permalink raw reply related
* [PATCH v4 net-next 20/21] net: usb: aqc111: Add ASIX's HW ids
From: Igor Russkikh @ 2018-11-26 9:33 UTC (permalink / raw)
To: linux-usb@vger.kernel.org, davem@davemloft.net,
netdev@vger.kernel.org
Cc: andrew@lunn.ch, Dmitry Bezrukov, Igor Russkikh
In-Reply-To: <cover.1543224254.git.igor.russkikh@aquantia.com>
From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
It enables driver for ASIX products which are also based on
aqc111/112U chips.
Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
drivers/net/usb/aqc111.c | 40 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index 7c859b9417f1..f69d566bd523 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -1249,6 +1249,44 @@ static const struct driver_info aqc111_info = {
.tx_fixup = aqc111_tx_fixup,
};
+#define ASIX111_DESC \
+"ASIX USB 3.1 Gen1 to 5G Multi-Gigabit Ethernet Adapter"
+
+static const struct driver_info asix111_info = {
+ .description = ASIX111_DESC,
+ .bind = aqc111_bind,
+ .unbind = aqc111_unbind,
+ .status = aqc111_status,
+ .link_reset = aqc111_link_reset,
+ .reset = aqc111_reset,
+ .stop = aqc111_stop,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX |
+ FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET,
+ .rx_fixup = aqc111_rx_fixup,
+ .tx_fixup = aqc111_tx_fixup,
+};
+
+#undef ASIX111_DESC
+
+#define ASIX112_DESC \
+"ASIX USB 3.1 Gen1 to 2.5G Multi-Gigabit Ethernet Adapter"
+
+static const struct driver_info asix112_info = {
+ .description = ASIX112_DESC,
+ .bind = aqc111_bind,
+ .unbind = aqc111_unbind,
+ .status = aqc111_status,
+ .link_reset = aqc111_link_reset,
+ .reset = aqc111_reset,
+ .stop = aqc111_stop,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX |
+ FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET,
+ .rx_fixup = aqc111_rx_fixup,
+ .tx_fixup = aqc111_tx_fixup,
+};
+
+#undef ASIX112_DESC
+
static int aqc111_suspend(struct usb_interface *intf, pm_message_t message)
{
struct usbnet *dev = usb_get_intfdata(intf);
@@ -1398,6 +1436,8 @@ static int aqc111_resume(struct usb_interface *intf)
static const struct usb_device_id products[] = {
{AQC111_USB_ETH_DEV(0x2eca, 0xc101, aqc111_info)},
+ {AQC111_USB_ETH_DEV(0x0b95, 0x2790, asix111_info)},
+ {AQC111_USB_ETH_DEV(0x0b95, 0x2791, asix112_info)},
{ },/* END */
};
MODULE_DEVICE_TABLE(usb, products);
--
2.17.1
^ permalink raw reply related
* [PATCH v4 net-next 21/21] net: usb: aqc111: Extend cdc_ether blacklist
From: Igor Russkikh @ 2018-11-26 9:33 UTC (permalink / raw)
To: linux-usb@vger.kernel.org, davem@davemloft.net,
netdev@vger.kernel.org
Cc: andrew@lunn.ch, Dmitry Bezrukov, Igor Russkikh
In-Reply-To: <cover.1543224254.git.igor.russkikh@aquantia.com>
From: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Added Aquantia and ASIX device IDs to prevent loading cdc_ether for
these devices. Our firmware reports CDC configuration simultaneously
with vendor specific.
Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
---
drivers/net/usb/cdc_ether.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 5c42cf81a08b..b3b3c05903a1 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -562,6 +562,8 @@ static const struct driver_info wwan_info = {
#define MICROSOFT_VENDOR_ID 0x045e
#define UBLOX_VENDOR_ID 0x1546
#define TPLINK_VENDOR_ID 0x2357
+#define AQUANTIA_VENDOR_ID 0x2eca
+#define ASIX_VENDOR_ID 0x0b95
static const struct usb_device_id products[] = {
/* BLACKLIST !!
@@ -821,6 +823,30 @@ static const struct usb_device_id products[] = {
.driver_info = 0,
},
+/* Aquantia AQtion USB to 5GbE Controller (based on AQC111U) */
+{
+ USB_DEVICE_AND_INTERFACE_INFO(AQUANTIA_VENDOR_ID, 0xc101,
+ USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
+ USB_CDC_PROTO_NONE),
+ .driver_info = 0,
+},
+
+/* ASIX USB 3.1 Gen1 to 5G Multi-Gigabit Ethernet Adapter(based on AQC111U) */
+{
+ USB_DEVICE_AND_INTERFACE_INFO(ASIX_VENDOR_ID, 0x2790, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_ETHERNET,
+ USB_CDC_PROTO_NONE),
+ .driver_info = 0,
+},
+
+/* ASIX USB 3.1 Gen1 to 2.5G Multi-Gigabit Ethernet Adapter(based on AQC112U) */
+{
+ USB_DEVICE_AND_INTERFACE_INFO(ASIX_VENDOR_ID, 0x2791, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_ETHERNET,
+ USB_CDC_PROTO_NONE),
+ .driver_info = 0,
+},
+
/* WHITELIST!!!
*
* CDC Ether uses two interfaces, not necessarily consecutive.
--
2.17.1
^ permalink raw reply related
* [PATCH] net: tcp: add correct check for tcp_retransmit_skb()
From: Sharath Chandra Vurukala @ 2018-11-26 9:35 UTC (permalink / raw)
To: netdev; +Cc: kapandey, chinagar
when the tcp_retranmission_timer expires and tcp_retranmsit_skb is
called if the retranmsission fails due to local congestion,
backoff should not incremented.
tcp_retransmit_skb() returns non-zero negative value in some cases of
failure but the caller tcp_retransmission_timer() has a check for
failure which checks if the return value is greater than zero.
The check is corrected to check for non-zero value.
Change-Id: I494fed73b2e385216402c91e9558d5c2884add5b
Signed-off-by: Sharath Chandra Vurukala <sharathv@codeaurora.org>
---
net/ipv4/tcp_timer.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 4be66e4..a70b4a9 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -536,7 +536,7 @@ void tcp_retransmit_timer(struct sock *sk)
tcp_enter_loss(sk);
- if (tcp_retransmit_skb(sk, tcp_write_queue_head(sk), 1) > 0) {
+ if (tcp_retransmit_skb(sk, tcp_write_queue_head(sk), 1) != 0) {
/* Retransmission failed because of local congestion,
* do not backoff.
*/
--
1.9.1
^ permalink raw reply related
* KASAN: stack-out-of-bounds Read in refcount_sub_and_test_checked
From: syzbot @ 2018-11-26 20:39 UTC (permalink / raw)
To: davem, kuznet, linux-kernel, netdev, syzkaller-bugs, yoshfuji
Hello,
syzbot found the following crash on:
HEAD commit: 358be656406d selftests/net: add txring_overwrite
git tree: net-next
console output: https://syzkaller.appspot.com/x/log.txt?x=113f8ed5400000
kernel config: https://syzkaller.appspot.com/x/.config?x=c36a72af2123e78a
dashboard link: https://syzkaller.appspot.com/bug?extid=d3ed975648421c381ca4
compiler: gcc (GCC) 8.0.1 20180413 (experimental)
Unfortunately, I don't have any reproducer for this crash yet.
IMPORTANT: if you fix the bug, please add the following tag to the commit:
Reported-by: syzbot+d3ed975648421c381ca4@syzkaller.appspotmail.com
==================================================================
BUG: KASAN: stack-out-of-bounds in atomic_read
include/asm-generic/atomic-instrumented.h:21 [inline]
BUG: KASAN: stack-out-of-bounds in refcount_sub_and_test_checked+0x9d/0x310
lib/refcount.c:179
Read of size 4 at addr ffff8881da9c0bf0 by task udevd/15453
CPU: 1 PID: 15453 Comm: udevd Not tainted 4.20.0-rc3+ #313
PANIC: double fault, error_code: 0x0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Call Trace:
__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x244/0x39d lib/dump_stack.c:113
CPU: 0 PID: 18956 Comm: syz-executor1 Not tainted 4.20.0-rc3+ #313
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
RIP: 0010:__udp4_lib_lookup+0x25/0x870 net/ipv4/udp.c:466
Code: ff 0f 1f 40 00 55 48 89 e5 41 57 41 56 41 55 49 bd 00 00 00 00 00 fc
ff df 41 54 53 44 89 c3 48 81 ec 00 01 00 00 48 8b 45 20 <48> 89 bd 28 ff
ff ff 66 c1 c3 08 4c 8b 65 18 89 b5 1c ff ff ff 89
print_address_description.cold.7+0x9/0x1ff mm/kasan/report.c:256
RSP: 0018:ffff8881d9a8af98 EFLAGS: 00010282
kasan_report_error mm/kasan/report.c:354 [inline]
kasan_report.cold.8+0x242/0x309 mm/kasan/report.c:412
RAX: 0000000000000000 RBX: 000000000000e5be RCX: 00000000111414ac
RDX: 000000000000224e RSI: 00000000aa1414ac RDI: ffff88818b3fc340
check_memory_region_inline mm/kasan/kasan.c:260 [inline]
check_memory_region+0x13e/0x1b0 mm/kasan/kasan.c:267
RBP: ffff8881d9a8b0c0 R08: 000000000000e5be R09: 0000000000000001
kasan_check_read+0x11/0x20 mm/kasan/kasan.c:272
R10: 0000000000000000 R11: ffff8881dae2db3b R12: ffff8881d7835800
atomic_read include/asm-generic/atomic-instrumented.h:21 [inline]
refcount_sub_and_test_checked+0x9d/0x310 lib/refcount.c:179
R13: dffffc0000000000 R14: ffff8881d78357ec R15: 0000000000000003
FS: 00007f18ebe99700(0000) GS:ffff8881dae00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ffff8881d9a8af88 CR3: 000000014f1a9000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
refcount_dec_and_test_checked+0x1a/0x20 lib/refcount.c:212
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
kref_put include/linux/kref.h:69 [inline]
aa_put_label security/apparmor/include/label.h:447 [inline]
aa_free_file_ctx security/apparmor/include/file.h:75 [inline]
apparmor_file_free_security+0x115/0x1a0 security/apparmor/lsm.c:450
Call Trace:
---
This bug is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
syzbot will keep track of this bug report. See:
https://goo.gl/tpsmEJ#bug-status-tracking for how to communicate with
syzbot.
^ permalink raw reply
* Re: [PATCH net-next v3 5/5] netns: enable to dump full nsid translation table
From: kbuild test robot @ 2018-11-26 10:06 UTC (permalink / raw)
To: Nicolas Dichtel; +Cc: kbuild-all, dsahern, netdev, davem, Nicolas Dichtel
In-Reply-To: <20181122222215.23554-6-nicolas.dichtel@6wind.com>
[-- Attachment #1: Type: text/plain, Size: 4062 bytes --]
Hi Nicolas,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on net-next/master]
url: https://github.com/0day-ci/linux/commits/Nicolas-Dichtel/netns-remove-net-arg-from-rtnl_net_fill/20181126-035032
config: x86_64-allmodconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All warnings (new ones prefixed by >>):
include/linux/slab.h:332:43: warning: dubious: x & !y
include/linux/slab.h:332:43: warning: dubious: x & !y
>> net/core/net_namespace.c:963:23: warning: context imbalance in 'rtnl_net_dumpid' - different lock contexts for basic block
vim +/rtnl_net_dumpid +963 net/core/net_namespace.c
5589651eb Nicolas Dichtel 2018-11-22 929
a143c40c3 Nicolas Dichtel 2015-04-07 930 static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
a143c40c3 Nicolas Dichtel 2015-04-07 931 {
a143c40c3 Nicolas Dichtel 2015-04-07 932 struct rtnl_net_dump_cb net_cb = {
5589651eb Nicolas Dichtel 2018-11-22 933 .tgt_net = sock_net(skb->sk),
a143c40c3 Nicolas Dichtel 2015-04-07 934 .skb = skb,
70955fc94 Nicolas Dichtel 2018-11-22 935 .fillargs = {
70955fc94 Nicolas Dichtel 2018-11-22 936 .portid = NETLINK_CB(cb->skb).portid,
70955fc94 Nicolas Dichtel 2018-11-22 937 .seq = cb->nlh->nlmsg_seq,
70955fc94 Nicolas Dichtel 2018-11-22 938 .flags = NLM_F_MULTI,
70955fc94 Nicolas Dichtel 2018-11-22 939 .cmd = RTM_NEWNSID,
70955fc94 Nicolas Dichtel 2018-11-22 940 },
a143c40c3 Nicolas Dichtel 2015-04-07 941 .idx = 0,
a143c40c3 Nicolas Dichtel 2015-04-07 942 .s_idx = cb->args[0],
a143c40c3 Nicolas Dichtel 2015-04-07 943 };
5589651eb Nicolas Dichtel 2018-11-22 944 int err = 0;
a143c40c3 Nicolas Dichtel 2015-04-07 945
5589651eb Nicolas Dichtel 2018-11-22 946 if (cb->strict_check) {
5589651eb Nicolas Dichtel 2018-11-22 947 err = rtnl_valid_dump_net_req(cb->nlh, skb->sk, &net_cb, cb);
5589651eb Nicolas Dichtel 2018-11-22 948 if (err < 0)
5589651eb Nicolas Dichtel 2018-11-22 949 goto end;
f80f14c36 David Ahern 2018-10-07 950 }
f80f14c36 David Ahern 2018-10-07 951
5589651eb Nicolas Dichtel 2018-11-22 952 spin_lock_bh(&net_cb.tgt_net->nsid_lock);
8a46e1ccc Nicolas Dichtel 2018-11-22 953 if (net_cb.fillargs.add_ref &&
8a46e1ccc Nicolas Dichtel 2018-11-22 954 !net_eq(net_cb.ref_net, net_cb.tgt_net) &&
8a46e1ccc Nicolas Dichtel 2018-11-22 955 !spin_trylock_bh(&net_cb.ref_net->nsid_lock)) {
8a46e1ccc Nicolas Dichtel 2018-11-22 956 err = -EAGAIN;
8a46e1ccc Nicolas Dichtel 2018-11-22 957 goto end;
8a46e1ccc Nicolas Dichtel 2018-11-22 958 }
5589651eb Nicolas Dichtel 2018-11-22 959 idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb);
8a46e1ccc Nicolas Dichtel 2018-11-22 960 if (net_cb.fillargs.add_ref &&
8a46e1ccc Nicolas Dichtel 2018-11-22 961 !net_eq(net_cb.ref_net, net_cb.tgt_net))
8a46e1ccc Nicolas Dichtel 2018-11-22 962 spin_unlock_bh(&net_cb.ref_net->nsid_lock);
5589651eb Nicolas Dichtel 2018-11-22 @963 spin_unlock_bh(&net_cb.tgt_net->nsid_lock);
a143c40c3 Nicolas Dichtel 2015-04-07 964
a143c40c3 Nicolas Dichtel 2015-04-07 965 cb->args[0] = net_cb.idx;
5589651eb Nicolas Dichtel 2018-11-22 966 end:
8a46e1ccc Nicolas Dichtel 2018-11-22 967 if (net_cb.fillargs.add_ref)
5589651eb Nicolas Dichtel 2018-11-22 968 put_net(net_cb.tgt_net);
5589651eb Nicolas Dichtel 2018-11-22 969 return err < 0 ? err : skb->len;
a143c40c3 Nicolas Dichtel 2015-04-07 970 }
a143c40c3 Nicolas Dichtel 2015-04-07 971
:::::: The code at line 963 was first introduced by commit
:::::: 5589651eb5e06b32107a1d8830af4be67aa58b85 netns: add support of NETNSA_TARGET_NSID
:::::: TO: Nicolas Dichtel <nicolas.dichtel@6wind.com>
:::::: CC: 0day robot <lkp@intel.com>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 66610 bytes --]
^ permalink raw reply
* Re: [PATCH] net: tcp: add correct check for tcp_retransmit_skb()
From: Joey Pabalinas @ 2018-11-26 10:16 UTC (permalink / raw)
To: Sharath Chandra Vurukala; +Cc: netdev, kapandey, chinagar, Joey Pabalinas
In-Reply-To: <20181126093234.GA18963@svurukal-linux.qualcomm.com>
[-- Attachment #1: Type: text/plain, Size: 842 bytes --]
On Mon, Nov 26, 2018 at 03:05:50PM +0530, Sharath Chandra Vurukala wrote:
> when the tcp_retranmission_timer expires and tcp_retranmsit_skb is
> called if the retranmsission fails due to local congestion,
> backoff should not incremented.
>
> tcp_retransmit_skb() returns non-zero negative value in some cases of
> failure but the caller tcp_retransmission_timer() has a check for
> failure which checks if the return value is greater than zero.
> The check is corrected to check for non-zero value.
>
> Change-Id: I494fed73b2e385216402c91e9558d5c2884add5b
> Signed-off-by: Sharath Chandra Vurukala <sharathv@codeaurora.org>
You are right, tcp_retransmit_skb() calls `int err = __tcp_retransmit_skb()`
which returns non-zero on error.
Reviewed-by: Joey Pabalinas <joeypabalinas@gmail.com>
--
Cheers,
Joey Pabalinas
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* [PATCH net-next v3 4/4] qed: Add support for MBI upgrade over MFW.
From: Sudarsana Reddy Kalluru @ 2018-11-26 10:27 UTC (permalink / raw)
To: davem; +Cc: netdev, Ariel.Elior, Michal.Kalderon
In-Reply-To: <20181126102700.3360-1-sudarsana.kalluru@cavium.com>
The patch adds driver support for MBI image update through MFW.
Signed-off-by: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
Signed-off-by: Ariel Elior <Ariel.Elior@cavium.com>
Signed-off-by: Michal Kalderon <Michal.Kalderon@cavium.com>
---
drivers/net/ethernet/qlogic/qed/qed_hsi.h | 6 ++++
drivers/net/ethernet/qlogic/qed/qed_main.c | 13 +++++++--
drivers/net/ethernet/qlogic/qed/qed_mcp.c | 45 +++++++++++++++---------------
drivers/net/ethernet/qlogic/qed/qed_mcp.h | 10 -------
4 files changed, 40 insertions(+), 34 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
index 5c221eb..7e120b5 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
@@ -12655,6 +12655,7 @@ struct public_drv_mb {
#define DRV_MB_PARAM_DCBX_NOTIFY_MASK 0x000000FF
#define DRV_MB_PARAM_DCBX_NOTIFY_SHIFT 3
+#define DRV_MB_PARAM_NVM_PUT_FILE_BEGIN_MBI 0x3
#define DRV_MB_PARAM_NVM_LEN_OFFSET 24
#define DRV_MB_PARAM_CFG_VF_MSIX_VF_ID_SHIFT 0
@@ -12814,6 +12815,11 @@ struct public_drv_mb {
union drv_union_data union_data;
};
+#define FW_MB_PARAM_NVM_PUT_FILE_REQ_OFFSET_MASK 0x00ffffff
+#define FW_MB_PARAM_NVM_PUT_FILE_REQ_OFFSET_SHIFT 0
+#define FW_MB_PARAM_NVM_PUT_FILE_REQ_SIZE_MASK 0xff000000
+#define FW_MB_PARAM_NVM_PUT_FILE_REQ_SIZE_SHIFT 24
+
enum MFW_DRV_MSG_TYPE {
MFW_DRV_MSG_LINK_CHANGE,
MFW_DRV_MSG_FLR_FW_ACK_FAILED,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index fff7f04..4b3e682 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -1939,21 +1939,30 @@ static int qed_nvm_flash_image_access(struct qed_dev *cdev, const u8 **data,
* 0B | 0x3 [command index] |
* 4B | b'0: check_response? | b'1-31 reserved |
* 8B | File-type | reserved |
+ * 12B | Image length in bytes |
* \----------------------------------------------------------------------/
* Start a new file of the provided type
*/
static int qed_nvm_flash_image_file_start(struct qed_dev *cdev,
const u8 **data, bool *check_resp)
{
+ u32 file_type, file_size = 0;
int rc;
*data += 4;
*check_resp = !!(**data & BIT(0));
*data += 4;
+ file_type = **data;
DP_VERBOSE(cdev, NETIF_MSG_DRV,
- "About to start a new file of type %02x\n", **data);
- rc = qed_mcp_nvm_put_file_begin(cdev, **data);
+ "About to start a new file of type %02x\n", file_type);
+ if (file_type == DRV_MB_PARAM_NVM_PUT_FILE_BEGIN_MBI) {
+ *data += 4;
+ file_size = *((u32 *)(*data));
+ }
+
+ rc = qed_mcp_nvm_write(cdev, QED_PUT_FILE_BEGIN, file_type,
+ (u8 *)(&file_size), 4);
*data += 4;
return rc;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index 34ed757..e7f18e3 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -2745,24 +2745,6 @@ int qed_mcp_nvm_resp(struct qed_dev *cdev, u8 *p_buf)
return 0;
}
-int qed_mcp_nvm_put_file_begin(struct qed_dev *cdev, u32 addr)
-{
- struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
- struct qed_ptt *p_ptt;
- u32 resp, param;
- int rc;
-
- p_ptt = qed_ptt_acquire(p_hwfn);
- if (!p_ptt)
- return -EBUSY;
- rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_NVM_PUT_FILE_BEGIN, addr,
- &resp, ¶m);
- cdev->mcp_nvm_resp = resp;
- qed_ptt_release(p_hwfn, p_ptt);
-
- return rc;
-}
-
int qed_mcp_nvm_write(struct qed_dev *cdev,
u32 cmd, u32 addr, u8 *p_buf, u32 len)
{
@@ -2776,6 +2758,9 @@ int qed_mcp_nvm_write(struct qed_dev *cdev,
return -EBUSY;
switch (cmd) {
+ case QED_PUT_FILE_BEGIN:
+ nvm_cmd = DRV_MSG_CODE_NVM_PUT_FILE_BEGIN;
+ break;
case QED_PUT_FILE_DATA:
nvm_cmd = DRV_MSG_CODE_NVM_PUT_FILE_DATA;
break;
@@ -2788,10 +2773,14 @@ int qed_mcp_nvm_write(struct qed_dev *cdev,
goto out;
}
+ buf_size = min_t(u32, (len - buf_idx), MCP_DRV_NVM_BUF_LEN);
while (buf_idx < len) {
- buf_size = min_t(u32, (len - buf_idx), MCP_DRV_NVM_BUF_LEN);
- nvm_offset = ((buf_size << DRV_MB_PARAM_NVM_LEN_OFFSET) |
- addr) + buf_idx;
+ if (cmd == QED_PUT_FILE_BEGIN)
+ nvm_offset = addr;
+ else
+ nvm_offset = ((buf_size <<
+ DRV_MB_PARAM_NVM_LEN_OFFSET) | addr) +
+ buf_idx;
rc = qed_mcp_nvm_wr_cmd(p_hwfn, p_ptt, nvm_cmd, nvm_offset,
&resp, ¶m, buf_size,
(u32 *)&p_buf[buf_idx]);
@@ -2816,7 +2805,19 @@ int qed_mcp_nvm_write(struct qed_dev *cdev,
if (buf_idx % 0x1000 > (buf_idx + buf_size) % 0x1000)
usleep_range(1000, 2000);
- buf_idx += buf_size;
+ /* For MBI upgrade, MFW response includes the next buffer offset
+ * to be delivered to MFW.
+ */
+ if (param && cmd == QED_PUT_FILE_DATA) {
+ buf_idx = QED_MFW_GET_FIELD(param,
+ FW_MB_PARAM_NVM_PUT_FILE_REQ_OFFSET);
+ buf_size = QED_MFW_GET_FIELD(param,
+ FW_MB_PARAM_NVM_PUT_FILE_REQ_SIZE);
+ } else {
+ buf_idx += buf_size;
+ buf_size = min_t(u32, (len - buf_idx),
+ MCP_DRV_NVM_BUF_LEN);
+ }
}
cdev->mcp_nvm_resp = resp;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
index 1adfe52..eddf677 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
@@ -543,16 +543,6 @@ int qed_mcp_nvm_write(struct qed_dev *cdev,
u32 cmd, u32 addr, u8 *p_buf, u32 len);
/**
- * @brief Put file begin
- *
- * @param cdev
- * @param addr - nvm offset
- *
- * @return int - 0 - operation was successful.
- */
-int qed_mcp_nvm_put_file_begin(struct qed_dev *cdev, u32 addr);
-
-/**
* @brief Check latest response
*
* @param cdev
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next v3 2/4] qede: Simplify the usage of qede-flags.
From: Sudarsana Reddy Kalluru @ 2018-11-26 10:26 UTC (permalink / raw)
To: davem; +Cc: netdev, Ariel.Elior, Michal.Kalderon
In-Reply-To: <20181126102700.3360-1-sudarsana.kalluru@cavium.com>
The values represented by qede->flags is being used in mixed ways:
1. As 'value' at some places e.g., QEDE_FLAGS_IS_VF usage
2. As bit-mask(value) at some places e.g., QEDE_FLAGS_PTP_TX_IN_PRORGESS
usage.
This implementation pose problems in future when we want to add more flag
values e.g., overlap of the values, overflow of 64-bit storage.
Updated the implementation to go with approach (2) for qede->flags.
Signed-off-by: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
Signed-off-by: Ariel Elior <Ariel.Elior@cavium.com>
Signed-off-by: Michal Kalderon <Michal.Kalderon@cavium.com>
---
drivers/net/ethernet/qlogic/qede/qede.h | 11 +++++++----
drivers/net/ethernet/qlogic/qede/qede_main.c | 2 +-
drivers/net/ethernet/qlogic/qede/qede_ptp.c | 6 +++---
3 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h
index de98a97..f8ced12 100644
--- a/drivers/net/ethernet/qlogic/qede/qede.h
+++ b/drivers/net/ethernet/qlogic/qede/qede.h
@@ -168,6 +168,12 @@ struct qede_rdma_dev {
#define QEDE_RFS_MAX_FLTR 256
+enum qede_flags_bit {
+ QEDE_FLAGS_IS_VF = 0,
+ QEDE_FLAGS_PTP_TX_IN_PRORGESS,
+ QEDE_FLAGS_TX_TIMESTAMPING_EN
+};
+
struct qede_dev {
struct qed_dev *cdev;
struct net_device *ndev;
@@ -177,10 +183,7 @@ struct qede_dev {
u8 dp_level;
unsigned long flags;
-#define QEDE_FLAG_IS_VF BIT(0)
-#define IS_VF(edev) (!!((edev)->flags & QEDE_FLAG_IS_VF))
-#define QEDE_TX_TIMESTAMPING_EN BIT(1)
-#define QEDE_FLAGS_PTP_TX_IN_PRORGESS BIT(2)
+#define IS_VF(edev) (test_bit(QEDE_FLAGS_IS_VF, &(edev)->flags))
const struct qed_eth_ops *ops;
struct qede_ptp *ptp;
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 46d0f2e..0f1c480 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -1086,7 +1086,7 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level,
}
if (is_vf)
- edev->flags |= QEDE_FLAG_IS_VF;
+ set_bit(QEDE_FLAGS_IS_VF, &edev->flags);
qede_init_ndev(edev);
diff --git a/drivers/net/ethernet/qlogic/qede/qede_ptp.c b/drivers/net/ethernet/qlogic/qede/qede_ptp.c
index 013ff56..5f3f42a 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_ptp.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_ptp.c
@@ -223,12 +223,12 @@ static int qede_ptp_cfg_filters(struct qede_dev *edev)
switch (ptp->tx_type) {
case HWTSTAMP_TX_ON:
- edev->flags |= QEDE_TX_TIMESTAMPING_EN;
+ set_bit(QEDE_FLAGS_TX_TIMESTAMPING_EN, &edev->flags);
tx_type = QED_PTP_HWTSTAMP_TX_ON;
break;
case HWTSTAMP_TX_OFF:
- edev->flags &= ~QEDE_TX_TIMESTAMPING_EN;
+ clear_bit(QEDE_FLAGS_TX_TIMESTAMPING_EN, &edev->flags);
tx_type = QED_PTP_HWTSTAMP_TX_OFF;
break;
@@ -518,7 +518,7 @@ void qede_ptp_tx_ts(struct qede_dev *edev, struct sk_buff *skb)
if (test_and_set_bit_lock(QEDE_FLAGS_PTP_TX_IN_PRORGESS, &edev->flags))
return;
- if (unlikely(!(edev->flags & QEDE_TX_TIMESTAMPING_EN))) {
+ if (unlikely(!test_bit(QEDE_FLAGS_TX_TIMESTAMPING_EN, &edev->flags))) {
DP_NOTICE(edev,
"Tx timestamping was not enabled, this packet will not be timestamped\n");
} else if (unlikely(ptp->tx_skb)) {
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next v3 3/4] qede: Update link status only when interface is ready.
From: Sudarsana Reddy Kalluru @ 2018-11-26 10:26 UTC (permalink / raw)
To: davem; +Cc: netdev, Ariel.Elior, Michal.Kalderon
In-Reply-To: <20181126102700.3360-1-sudarsana.kalluru@cavium.com>
In the case of internal reload (e.g., mtu change), there could be a race
between link-up notification from mfw and the driver unload processing. In
such case kernel assumes the link is up and starts using the queues which
leads to the server crash.
Send link notification to the kernel only when driver has already requested
MFW for the link.
Signed-off-by: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
Signed-off-by: Ariel Elior <Ariel.Elior@cavium.com>
Signed-off-by: Michal Kalderon <Michal.Kalderon@cavium.com>
---
drivers/net/ethernet/qlogic/qede/qede.h | 1 +
drivers/net/ethernet/qlogic/qede/qede_main.c | 8 ++++++--
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h
index f8ced12..8c0fe59 100644
--- a/drivers/net/ethernet/qlogic/qede/qede.h
+++ b/drivers/net/ethernet/qlogic/qede/qede.h
@@ -170,6 +170,7 @@ struct qede_rdma_dev {
enum qede_flags_bit {
QEDE_FLAGS_IS_VF = 0,
+ QEDE_FLAGS_LINK_REQUESTED,
QEDE_FLAGS_PTP_TX_IN_PRORGESS,
QEDE_FLAGS_TX_TIMESTAMPING_EN
};
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 0f1c480..efbb4f3 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -2057,6 +2057,8 @@ static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode,
if (!is_locked)
__qede_lock(edev);
+ clear_bit(QEDE_FLAGS_LINK_REQUESTED, &edev->flags);
+
edev->state = QEDE_STATE_CLOSED;
qede_rdma_dev_event_close(edev);
@@ -2163,6 +2165,8 @@ static int qede_load(struct qede_dev *edev, enum qede_load_mode mode,
/* Program un-configured VLANs */
qede_configure_vlan_filters(edev);
+ set_bit(QEDE_FLAGS_LINK_REQUESTED, &edev->flags);
+
/* Ask for link-up using current configuration */
memset(&link_params, 0, sizeof(link_params));
link_params.link_up = true;
@@ -2258,8 +2262,8 @@ static void qede_link_update(void *dev, struct qed_link_output *link)
{
struct qede_dev *edev = dev;
- if (!netif_running(edev->ndev)) {
- DP_VERBOSE(edev, NETIF_MSG_LINK, "Interface is not running\n");
+ if (!test_bit(QEDE_FLAGS_LINK_REQUESTED, &edev->flags)) {
+ DP_VERBOSE(edev, NETIF_MSG_LINK, "Interface is not ready\n");
return;
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next v3 1/4] qed: Display port_id in the UFP debug messages.
From: Sudarsana Reddy Kalluru @ 2018-11-26 10:26 UTC (permalink / raw)
To: davem; +Cc: netdev, Ariel.Elior, Michal.Kalderon
In-Reply-To: <20181126102700.3360-1-sudarsana.kalluru@cavium.com>
MFW sends UFP notifications mostly during the device init phase and PFs
might not be assigned with a name by this time. Hence capturing port-id in
the debug messages would help in finding which PF the ufp notification was
sent to.
Also, fixed a minor scemantic issue in a debug print.
Signed-off-by: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
Signed-off-by: Ariel Elior <Ariel.Elior@cavium.com>
Signed-off-by: Michal Kalderon <Michal.Kalderon@cavium.com>
---
drivers/net/ethernet/qlogic/qed/qed_mcp.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index a96364d..34ed757 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -1619,7 +1619,7 @@ static void qed_mcp_update_stag(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
qed_sp_pf_update_stag(p_hwfn);
}
- DP_VERBOSE(p_hwfn, QED_MSG_SP, "ovlan = %d hw_mode = 0x%x\n",
+ DP_VERBOSE(p_hwfn, QED_MSG_SP, "ovlan = %d hw_mode = 0x%x\n",
p_hwfn->mcp_info->func_info.ovlan, p_hwfn->hw_info.hw_mode);
/* Acknowledge the MFW */
@@ -1641,7 +1641,9 @@ void qed_mcp_read_ufp_config(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
val = (port_cfg & OEM_CFG_CHANNEL_TYPE_MASK) >>
OEM_CFG_CHANNEL_TYPE_OFFSET;
if (val != OEM_CFG_CHANNEL_TYPE_STAGGED)
- DP_NOTICE(p_hwfn, "Incorrect UFP Channel type %d\n", val);
+ DP_NOTICE(p_hwfn,
+ "Incorrect UFP Channel type %d port_id 0x%02x\n",
+ val, MFW_PORT(p_hwfn));
val = (port_cfg & OEM_CFG_SCHED_TYPE_MASK) >> OEM_CFG_SCHED_TYPE_OFFSET;
if (val == OEM_CFG_SCHED_TYPE_ETS) {
@@ -1650,7 +1652,9 @@ void qed_mcp_read_ufp_config(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
p_hwfn->ufp_info.mode = QED_UFP_MODE_VNIC_BW;
} else {
p_hwfn->ufp_info.mode = QED_UFP_MODE_UNKNOWN;
- DP_NOTICE(p_hwfn, "Unknown UFP scheduling mode %d\n", val);
+ DP_NOTICE(p_hwfn,
+ "Unknown UFP scheduling mode %d port_id 0x%02x\n",
+ val, MFW_PORT(p_hwfn));
}
qed_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info, MCP_PF_ID(p_hwfn));
@@ -1665,13 +1669,15 @@ void qed_mcp_read_ufp_config(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
p_hwfn->ufp_info.pri_type = QED_UFP_PRI_OS;
} else {
p_hwfn->ufp_info.pri_type = QED_UFP_PRI_UNKNOWN;
- DP_NOTICE(p_hwfn, "Unknown Host priority control %d\n", val);
+ DP_NOTICE(p_hwfn,
+ "Unknown Host priority control %d port_id 0x%02x\n",
+ val, MFW_PORT(p_hwfn));
}
DP_NOTICE(p_hwfn,
- "UFP shmem config: mode = %d tc = %d pri_type = %d\n",
- p_hwfn->ufp_info.mode,
- p_hwfn->ufp_info.tc, p_hwfn->ufp_info.pri_type);
+ "UFP shmem config: mode = %d tc = %d pri_type = %d port_id 0x%02x\n",
+ p_hwfn->ufp_info.mode, p_hwfn->ufp_info.tc,
+ p_hwfn->ufp_info.pri_type, MFW_PORT(p_hwfn));
}
static int
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH net-next] net/ncsi: Add NCSI Mellanox OEM command
From: Vijay Khemka @ 2018-11-26 21:23 UTC (permalink / raw)
To: David Miller
Cc: sam@mendozajonas.com, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, openbmc@lists.ozlabs.org,
Justin.Lee1@Dell.com, joel@jms.id.au,
linux-aspeed@lists.ozlabs.org
In-Reply-To: <20181121.165244.777667590099933299.davem@davemloft.net>
Thanks David,
I will fix this and upload next version.
Regards
-Vijay
On 11/21/18, 4:55 PM, "David Miller" <davem@davemloft.net> wrote:
From: Vijay Khemka <vijaykhemka@fb.com>
Date: Tue, 20 Nov 2018 12:35:16 -0800
> +static int ncsi_oem_gma_handler_mlx(struct ncsi_cmd_arg *nca)
> +{
> + unsigned char data[NCSI_OEM_MLX_CMD_GMA_LEN];
> + int ret = 0;
> +
> + nca->payload = NCSI_OEM_MLX_CMD_GMA_LEN;
> +
> + memset(data, 0, NCSI_OEM_MLX_CMD_GMA_LEN);
> + *(unsigned int *)data = ntohl(NCSI_OEM_MFR_MLX_ID);
'data' is not necessarily aligned on an unsigned int boundary.
But second of all you want to use a fixed size type like "u32" or
similar here, not "unsigned int".
Altogether, something like:
union {
u8 data_u8[NCSI_OEM_MLX_CMD_GMA_LEN];
u32 data_u32[[NCSI_OEM_MLX_CMD_GMA_LEN / sizeof(u32)];
} u;
memset(&u, 0, sizeof(u));
u.data_u32[0] = ntohl(NCSI_OEM_MFR_MLX_ID);
u.data_u8[5] = NCSI_OEM_MLX_CMD_GMA;
u.data_u8[6] = NCSI_OEM_MLX_CMD_GMA_PARAM;
If the rest of the ncsi driver has crud like this, it all needs
to be fixed up similarly.
^ permalink raw reply
* [PATCH net-next v3 0/4] qed* enhancements series
From: Sudarsana Reddy Kalluru @ 2018-11-26 10:26 UTC (permalink / raw)
To: davem; +Cc: netdev, Ariel.Elior, Michal.Kalderon, Sudarsana Reddy Kalluru
From: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
The patch series add few enhancements to qed/qede drivers.
Changes from previous versions:
-------------------------------
v3: Revert v2 changes as the other paths (i.e. ptp) access the same data in
atomic context.
v2: Use __set_bit()/__clear_bit() where data access doesn't need to be
atomic.
Please consider applying it to "net-next".
Sudarsana Reddy Kalluru (4):
qed: Display port_id in the UFP debug messages.
qede: Simplify the usage of qede-flags.
qede: Update link status only when interface is ready.
qed: Add support for MBI upgrade over MFW.
drivers/net/ethernet/qlogic/qed/qed_hsi.h | 6 +++
drivers/net/ethernet/qlogic/qed/qed_main.c | 13 +++++-
drivers/net/ethernet/qlogic/qed/qed_mcp.c | 65 +++++++++++++++-------------
drivers/net/ethernet/qlogic/qed/qed_mcp.h | 10 -----
drivers/net/ethernet/qlogic/qede/qede.h | 12 +++--
drivers/net/ethernet/qlogic/qede/qede_main.c | 10 +++--
drivers/net/ethernet/qlogic/qede/qede_ptp.c | 6 +--
7 files changed, 71 insertions(+), 51 deletions(-)
--
1.8.3.1
^ permalink raw reply
* [PATCH] netfilter: ipset: do not call ipset_nest_end after nla_nest_cancel
From: Pan Bian @ 2018-11-26 10:42 UTC (permalink / raw)
To: Pablo Neira Ayuso, Jozsef Kadlecsik, Florian Westphal,
David S. Miller
Cc: Stefano Brivio, netfilter-devel, coreteam, netdev, linux-kernel,
Pan Bian
In the error handling block, nla_nest_cancel(skb, atd) is called to
cancel the nest operation. But then, ipset_nest_end(skb, atd) is
unexpected called to end the nest operation. This patch calls the
ipset_nest_end only on the branch that nla_nest_cancel is
not called.
Fixes: 45040978c89("netfilter: ipset: Fix set:list type crash when
flush/dump set in parallel")
Signed-off-by: Pan Bian <bianpan2016@163.com>
---
net/netfilter/ipset/ip_set_list_set.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
index 4eef55d..8da228d 100644
--- a/net/netfilter/ipset/ip_set_list_set.c
+++ b/net/netfilter/ipset/ip_set_list_set.c
@@ -531,8 +531,8 @@ list_set_list(const struct ip_set *set,
ret = -EMSGSIZE;
} else {
cb->args[IPSET_CB_ARG0] = i;
+ ipset_nest_end(skb, atd);
}
- ipset_nest_end(skb, atd);
out:
rcu_read_unlock();
return ret;
--
2.7.4
^ permalink raw reply related
* Re: [v5, PATCH 2/2] dt-binding: mediatek-dwmac: add binding document for MediaTek MT2712 DWMAC
From: Rob Herring @ 2018-11-26 21:46 UTC (permalink / raw)
To: biao huang
Cc: Andrew Lunn, davem, honghui.zhang, yt.shen, liguo.zhang,
mark.rutland, nelson.chang, matthias.bgg, netdev, devicetree,
linux-kernel, linux-arm-kernel, linux-mediatek, joabreu
In-Reply-To: <1542936676.24219.66.camel@mhfsdcap03>
On Fri, Nov 23, 2018 at 09:31:16AM +0800, biao huang wrote:
> Dear Andrew,
>
> Thanks for you remind.
>
> Sincerely, I respect any comment from any reviewer. If I didn't reply
> for any comment, really sorry for that.
>
> As to this "tx-delay" issue, the following reply in v3 maybe ignored.
> https://lkml.org/lkml/2018/11/19/158
>
> "the delay time in mediatek dwmac design is not so accurate,
> the current mt2712 and the following ICs will not use the
> same delay design, but will use stages to indicate different
> delay time.
> so maybe "mediatek.tx-delay" represent the delay stage is a
> good choice"
>
> And to make it clearer here.
>
> In mt2712, there are two delay macro circuit: named fine-tune and
> coarse-tune.
> a. fine-tune, 170+/-50ps per stage, total 32 stages
> b. coarse-tune, 0.55+/-0.2ns per stage, total 32 stages
> If we only consider mt2712, delay in fine-tune select a integer
> multiple of 170ps, delay in coarse-tune select a integer multiple of
> 550ps, for stage 0~31, the delay in fine-tune will not have the same
> value with that in coarse-tune.
> OK, It seems the property "fine-tune" can be eliminated .
>
> But the following ic will not have the same accuracy as mt2712,
> and maybe will not have two delay macro circuit to be selected.
New IC will have new compatible string then. If it is different, then
likely these properties would have to change or have different meaning
unless you use time.
> 1. assume two delay macro circuit in the following ic,
> fine-tune, 100ps per stage, coarse-tune, 0.55ns per stage,
> if we want delay 2.2ns, fine-tune will get a 22, and coarse-tune get a
> 4. We can't distinguish which delay macro we are choosing.
Why wouldn't you just choose fine-tune for anything less than the max
range (3200ps in this example) and course for greater than 3100ps.
> 2. assume only one delay macro circuit is used, a similar case as 1
> will also increase the complexity of driver.
> Then, we need define more flag property to know which delay macro we
> are handling.
>
> The common things for all delay macro circuit in MediaTek mac design is
> the stages, not the accuracy. so if we maintain stage info in "mediatek,
> tx-delay", we only need care which stage we should choose.
> And for each IC, we will recommend a best stage as a candidate.
What if you had a 3rd delay circuit?
> Above is my personal opinion, may be my understanding is wrong,
> welcome for further discussion.
>
> Thanks a lot.
^ permalink raw reply
* Re: [PATCH bpf-next 1/3] bpf: helper to pop data from messages
From: Quentin Monnet @ 2018-11-26 11:16 UTC (permalink / raw)
To: John Fastabend; +Cc: Daniel Borkmann, ast, netdev
In-Reply-To: <d5a37ecc-2fc2-441f-5548-6447c9883021@iogearbox.net>
2018-11-26 02:05 UTC+0100 ~ Daniel Borkmann <daniel@iogearbox.net>
> On 11/23/2018 02:38 AM, John Fastabend wrote:
>> This adds a BPF SK_MSG program helper so that we can pop data from a
>> msg. We use this to pop metadata from a previous push data call.
>>
>> Signed-off-by: John Fastabend <john.fastabend@gmail.com>
>> ---
>> include/uapi/linux/bpf.h | 13 +++-
>> net/core/filter.c | 169 +++++++++++++++++++++++++++++++++++++++++++++++
>> net/ipv4/tcp_bpf.c | 14 +++-
>> 3 files changed, 192 insertions(+), 4 deletions(-)
>>
>> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
>> index c1554aa..64681f8 100644
>> --- a/include/uapi/linux/bpf.h
>> +++ b/include/uapi/linux/bpf.h
>> @@ -2268,6 +2268,16 @@ union bpf_attr {
>> *
>> * Return
>> * 0 on success, or a negative error in case of failure.
>> + *
>> + * int bpf_msg_pop_data(struct sk_msg_buff *msg, u32 start, u32 pop, u64 flags)
>> + * Description
>> + * Will remove 'pop' bytes from a msg starting at byte 'start'.
>> + * This result in ENOMEM errors under certain situations where
>> + * a allocation and copy are required due to a full ring buffer.
>> + * However, the helper will try to avoid doing the allocation
>> + * if possible. Other errors can occur if input parameters are
>> + * invalid either do to start byte not being valid part of msg
>> + * payload and/or pop value being to large.
>> */
Hi John,
If you respin could you please update the helper documentation to use
RST syntax for argument and constant names (*pop* instead of 'pop',
*msg*, *start*, *flags*, **ENOMEM**), and document the return value from
the helper?
Thanks a lot,
Quentin
^ permalink raw reply
* [PATCH net] sctp: check and update stream->out_curr when allocating stream_out
From: Xin Long @ 2018-11-26 11:22 UTC (permalink / raw)
To: network dev, linux-sctp; +Cc: davem, Marcelo Ricardo Leitner, Neil Horman
Now when using stream reconfig to add out streams, stream->out
will get re-allocated, and all old streams' information will
be copied to the new ones and the old ones will be freed.
So without stream->out_curr updated, next time when trying to
send from stream->out_curr stream, a panic would be caused.
This patch is to define sctp_stream_out_copy used to update the
stream->out_curr pointer to the new stream when copying the old
streams' information.
While at it, rename fa_copy to sctp_stream_in_copy.
Fixes: 5bbbbe32a431 ("sctp: introduce stream scheduler foundations")
Reported-by: Ying Xu <yinxu@redhat.com>
Reported-by: syzbot+e33a3a138267ca119c7d@syzkaller.appspotmail.com
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
net/sctp/stream.c | 46 ++++++++++++++++++++++++++++++++--------------
1 file changed, 32 insertions(+), 14 deletions(-)
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index 3892e76..0687eeb 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -61,18 +61,6 @@ static void fa_free(struct flex_array *fa)
flex_array_free(fa);
}
-static void fa_copy(struct flex_array *fa, struct flex_array *from,
- size_t index, size_t count)
-{
- void *elem;
-
- while (count--) {
- elem = flex_array_get(from, index);
- flex_array_put(fa, index, elem, 0);
- index++;
- }
-}
-
static void fa_zero(struct flex_array *fa, size_t index, size_t count)
{
void *elem;
@@ -135,6 +123,36 @@ static void sctp_stream_outq_migrate(struct sctp_stream *stream,
kfree(SCTP_SO(stream, i)->ext);
}
+static void sctp_stream_in_copy(struct flex_array *fa,
+ struct sctp_stream *stream, __u16 count)
+{
+ size_t index = 0;
+ void *elem;
+
+ count = min(count, stream->incnt);
+ while (count--) {
+ elem = flex_array_get(stream->in, index);
+ flex_array_put(fa, index, elem, 0);
+ index++;
+ }
+}
+
+static void sctp_stream_out_copy(struct flex_array *fa,
+ struct sctp_stream *stream, __u16 count)
+{
+ size_t index = 0;
+ void *elem;
+
+ count = min(count, stream->outcnt);
+ while (count--) {
+ elem = flex_array_get(stream->out, index);
+ flex_array_put(fa, index, elem, 0);
+ if (stream->out_curr == elem)
+ stream->out_curr = flex_array_get(fa, index);
+ index++;
+ }
+}
+
static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt,
gfp_t gfp)
{
@@ -146,7 +164,7 @@ static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt,
return -ENOMEM;
if (stream->out) {
- fa_copy(out, stream->out, 0, min(outcnt, stream->outcnt));
+ sctp_stream_out_copy(out, stream, outcnt);
fa_free(stream->out);
}
@@ -169,7 +187,7 @@ static int sctp_stream_alloc_in(struct sctp_stream *stream, __u16 incnt,
return -ENOMEM;
if (stream->in) {
- fa_copy(in, stream->in, 0, min(incnt, stream->incnt));
+ sctp_stream_in_copy(in, stream, incnt);
fa_free(stream->in);
}
--
2.1.0
^ permalink raw reply related
* RE: [PATCH net-next 1/8] dpaa2-eth: Add basic XDP support
From: Camelia Alexandra Groza @ 2018-11-26 11:36 UTC (permalink / raw)
To: Ioana Ciocoi Radulescu; +Cc: netdev@vger.kernel.org, davem@davemloft.net
> -----Original Message-----
> From: netdev-owner@vger.kernel.org <netdev-owner@vger.kernel.org>
> On Behalf Of Ioana Ciocoi Radulescu
> Sent: Friday, November 23, 2018 18:57
> To: netdev@vger.kernel.org; davem@davemloft.net
> Subject: [PATCH net-next 1/8] dpaa2-eth: Add basic XDP support
>
> +static int dpaa2_eth_change_mtu(struct net_device *dev, int new_mtu)
> +{
> + struct dpaa2_eth_priv *priv = netdev_priv(dev);
> + int err;
> +
> + if (!priv->xdp_prog)
> + goto out;
> +
> + if (!xdp_mtu_valid(priv, new_mtu))
> + return -EINVAL;
An error message would be helpful to let the user know which MTU values are acceptable in XDP context.
^ permalink raw reply
* [RFC PATCH 0/3] sk_buff: add skb extension infrastructure
From: Florian Westphal @ 2018-11-26 11:38 UTC (permalink / raw)
To: netdev
The (out-of-tree) Multipath-TCP implementation needs a significant amount
of extra space in the skb control buffer.
Increasing skb->cb[] size in mainline is a non-starter for memory and
and performance reasons (f.e. increase in cb size also moves several
frequently-accessed fields to other cache lines).
One approach that might work for MPTCP is to extend skb_shared_info instead
of sk_buff. However, this comes with other drawbacks, e.g. it either
needs special skb allocation to make sure there is enough space for such
'extended shinfo' at the end of data buffer (which makes this only useable
for tx path) or increased size of skb_shared_info.
This adds an extension infrastructure for sk_buff instead:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb.
3. adding extension to an skb will COW the extension
buffer if needed.
This is also how xfrm and bridge_nf extra data (skb->sp, skb->nf_bridge)
are handled.
In the future, protocols that need to store more than 48 bytes in skb->cb[]
could add a 'SKB_EXT_EXTRA_CB' or similar to allocate extra space.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
have been enabled for this skb.
2. extension pointer, located at the end of the sk_buff.
If active_extensions byte is 0, pointer value is undefined.
Last patch converts nf_bridge to use the extension infrastructure:
The 'nf_bridge' pointer is removed, i.e. sk_buff size remains the same.
Extra code added to skb clone and free paths (to deal with
refcount/free of extension area) replace the existing code that
deals with skb->nf_bridge.
Conversion of skb->sp (ipsec/xfrm secpath) to an skb extension could be
done as a followup, but I'm reluctant to work on this before there is
agreement that this is the right direction.
Comments welcome.
include/linux/netfilter_bridge.h | 33 +++++---
include/linux/skbuff.h | 142 +++++++++++++++++++++++++++++------
include/net/netfilter/br_netfilter.h | 14 ---
net/Kconfig | 4
net/bridge/br_netfilter_hooks.c | 39 +++------
net/bridge/br_netfilter_ipv6.c | 4
net/core/skbuff.c | 134 ++++++++++++++++++++++++++++++++-
net/ipv4/ip_output.c | 1
net/ipv4/netfilter/nf_reject_ipv4.c | 6 -
net/ipv6/ip6_output.c | 1
net/ipv6/netfilter/nf_reject_ipv6.c | 10 +-
net/netfilter/nf_log_common.c | 20 ++--
net/netfilter/nf_queue.c | 50 ++++++++----
net/netfilter/nfnetlink_queue.c | 23 ++---
net/netfilter/xt_physdev.c | 2
15 files changed, 368 insertions(+), 115 deletions(-)
^ permalink raw reply
* [RFC PATCH 1/3] netfilter: avoid using skb->nf_bridge directly
From: Florian Westphal @ 2018-11-26 11:38 UTC (permalink / raw)
To: netdev; +Cc: Florian Westphal
In-Reply-To: <20181126113857.29270-1-fw@strlen.de>
plan is to remove this pointer from sk_buff, so use the existing helpers
in more places to reduce noise later on.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/linux/netfilter_bridge.h | 33 +++++++++++++-----
include/net/netfilter/br_netfilter.h | 6 ----
net/bridge/br_netfilter_hooks.c | 19 ++++++++---
net/ipv4/netfilter/nf_reject_ipv4.c | 6 ++--
net/ipv6/netfilter/nf_reject_ipv6.c | 10 ++++--
net/netfilter/nf_log_common.c | 20 +++++------
net/netfilter/nf_queue.c | 50 ++++++++++++++++++----------
net/netfilter/nfnetlink_queue.c | 23 ++++++-------
net/netfilter/xt_physdev.c | 2 +-
9 files changed, 103 insertions(+), 66 deletions(-)
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
index fa0686500970..0a65a422587c 100644
--- a/include/linux/netfilter_bridge.h
+++ b/include/linux/netfilter_bridge.h
@@ -17,43 +17,58 @@ static inline void br_drop_fake_rtable(struct sk_buff *skb)
skb_dst_drop(skb);
}
+static inline struct nf_bridge_info *
+nf_bridge_info_get(const struct sk_buff *skb)
+{
+ return skb->nf_bridge;
+}
+
+static inline bool nf_bridge_info_exists(const struct sk_buff *skb)
+{
+ return skb->nf_bridge != NULL;
+}
+
static inline int nf_bridge_get_physinif(const struct sk_buff *skb)
{
- struct nf_bridge_info *nf_bridge;
+ const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
- if (skb->nf_bridge == NULL)
+ if (!nf_bridge)
return 0;
- nf_bridge = skb->nf_bridge;
return nf_bridge->physindev ? nf_bridge->physindev->ifindex : 0;
}
static inline int nf_bridge_get_physoutif(const struct sk_buff *skb)
{
- struct nf_bridge_info *nf_bridge;
+ const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
- if (skb->nf_bridge == NULL)
+ if (!nf_bridge)
return 0;
- nf_bridge = skb->nf_bridge;
return nf_bridge->physoutdev ? nf_bridge->physoutdev->ifindex : 0;
}
static inline struct net_device *
nf_bridge_get_physindev(const struct sk_buff *skb)
{
- return skb->nf_bridge ? skb->nf_bridge->physindev : NULL;
+ const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
+
+ return nf_bridge ? nf_bridge->physindev : NULL;
}
static inline struct net_device *
nf_bridge_get_physoutdev(const struct sk_buff *skb)
{
- return skb->nf_bridge ? skb->nf_bridge->physoutdev : NULL;
+ const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
+
+ return nf_bridge ? nf_bridge->physoutdev : NULL;
}
static inline bool nf_bridge_in_prerouting(const struct sk_buff *skb)
{
- return skb->nf_bridge && skb->nf_bridge->in_prerouting;
+ const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
+
+ return nf_bridge && nf_bridge->in_prerouting;
}
#else
#define br_drop_fake_rtable(skb) do { } while (0)
diff --git a/include/net/netfilter/br_netfilter.h b/include/net/netfilter/br_netfilter.h
index 74af19c3a8f7..6efc0153987b 100644
--- a/include/net/netfilter/br_netfilter.h
+++ b/include/net/netfilter/br_netfilter.h
@@ -22,12 +22,6 @@ int br_nf_hook_thresh(unsigned int hook, struct net *net, struct sock *sk,
int (*okfn)(struct net *, struct sock *,
struct sk_buff *));
-static inline struct nf_bridge_info *
-nf_bridge_info_get(const struct sk_buff *skb)
-{
- return skb->nf_bridge;
-}
-
unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb);
static inline void nf_bridge_push_encap_header(struct sk_buff *skb)
diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
index c9383c470a83..c58cf68b45c5 100644
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -247,7 +247,9 @@ static int br_validate_ipv4(struct net *net, struct sk_buff *skb)
void nf_bridge_update_protocol(struct sk_buff *skb)
{
- switch (skb->nf_bridge->orig_proto) {
+ const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
+
+ switch (nf_bridge->orig_proto) {
case BRNF_PROTO_8021Q:
skb->protocol = htons(ETH_P_8021Q);
break;
@@ -569,7 +571,8 @@ static unsigned int br_nf_forward_ip(void *priv,
struct net_device *parent;
u_int8_t pf;
- if (!skb->nf_bridge)
+ nf_bridge = nf_bridge_info_get(skb);
+ if (!nf_bridge)
return NF_ACCEPT;
/* Need exclusive nf_bridge_info since we might have multiple
@@ -701,7 +704,9 @@ br_nf_ip_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
static unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb)
{
- if (skb->nf_bridge->orig_proto == BRNF_PROTO_PPPOE)
+ const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
+
+ if (nf_bridge->orig_proto == BRNF_PROTO_PPPOE)
return PPPOE_SES_HLEN;
return 0;
}
@@ -839,7 +844,9 @@ static unsigned int ip_sabotage_in(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
- if (skb->nf_bridge && !skb->nf_bridge->in_prerouting &&
+ struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
+
+ if (nf_bridge && !nf_bridge->in_prerouting &&
!netif_is_l3_master(skb->dev)) {
state->okfn(state->net, state->sk, skb);
return NF_STOLEN;
@@ -877,7 +884,9 @@ static void br_nf_pre_routing_finish_bridge_slow(struct sk_buff *skb)
static int br_nf_dev_xmit(struct sk_buff *skb)
{
- if (skb->nf_bridge && skb->nf_bridge->bridged_dnat) {
+ const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
+
+ if (nf_bridge && nf_bridge->bridged_dnat) {
br_nf_pre_routing_finish_bridge_slow(skb);
return 1;
}
diff --git a/net/ipv4/netfilter/nf_reject_ipv4.c b/net/ipv4/netfilter/nf_reject_ipv4.c
index 5cd06ba3535d..aa8304c618b8 100644
--- a/net/ipv4/netfilter/nf_reject_ipv4.c
+++ b/net/ipv4/netfilter/nf_reject_ipv4.c
@@ -102,6 +102,7 @@ EXPORT_SYMBOL_GPL(nf_reject_ip_tcphdr_put);
/* Send RST reply */
void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook)
{
+ struct net_device *br_indev __maybe_unused;
struct sk_buff *nskb;
struct iphdr *niph;
const struct tcphdr *oth;
@@ -147,10 +148,11 @@ void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook)
* build the eth header using the original destination's MAC as the
* source, and send the RST packet directly.
*/
- if (oldskb->nf_bridge) {
+ br_indev = nf_bridge_get_physindev(oldskb);
+ if (br_indev) {
struct ethhdr *oeth = eth_hdr(oldskb);
- nskb->dev = nf_bridge_get_physindev(oldskb);
+ nskb->dev = br_indev;
niph->tot_len = htons(nskb->len);
ip_send_check(niph);
if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c
index 24858402e374..b9c8a763c863 100644
--- a/net/ipv6/netfilter/nf_reject_ipv6.c
+++ b/net/ipv6/netfilter/nf_reject_ipv6.c
@@ -131,6 +131,7 @@ EXPORT_SYMBOL_GPL(nf_reject_ip6_tcphdr_put);
void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
{
+ struct net_device *br_indev __maybe_unused;
struct sk_buff *nskb;
struct tcphdr _otcph;
const struct tcphdr *otcph;
@@ -197,15 +198,18 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
* build the eth header using the original destination's MAC as the
* source, and send the RST packet directly.
*/
- if (oldskb->nf_bridge) {
+ br_indev = nf_bridge_get_physindev(oldskb);
+ if (br_indev) {
struct ethhdr *oeth = eth_hdr(oldskb);
- nskb->dev = nf_bridge_get_physindev(oldskb);
+ nskb->dev = br_indev;
nskb->protocol = htons(ETH_P_IPV6);
ip6h->payload_len = htons(sizeof(struct tcphdr));
if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
- oeth->h_source, oeth->h_dest, nskb->len) < 0)
+ oeth->h_source, oeth->h_dest, nskb->len) < 0) {
+ kfree_skb(nskb);
return;
+ }
dev_queue_xmit(nskb);
} else
#endif
diff --git a/net/netfilter/nf_log_common.c b/net/netfilter/nf_log_common.c
index a8c5c846aec1..3a0d6880b7c9 100644
--- a/net/netfilter/nf_log_common.c
+++ b/net/netfilter/nf_log_common.c
@@ -156,22 +156,20 @@ nf_log_dump_packet_common(struct nf_log_buf *m, u_int8_t pf,
const struct net_device *out,
const struct nf_loginfo *loginfo, const char *prefix)
{
+ const struct net_device *physoutdev __maybe_unused;
+ const struct net_device *physindev __maybe_unused;
+
nf_log_buf_add(m, KERN_SOH "%c%sIN=%s OUT=%s ",
'0' + loginfo->u.log.level, prefix,
in ? in->name : "",
out ? out->name : "");
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
- if (skb->nf_bridge) {
- const struct net_device *physindev;
- const struct net_device *physoutdev;
-
- physindev = nf_bridge_get_physindev(skb);
- if (physindev && in != physindev)
- nf_log_buf_add(m, "PHYSIN=%s ", physindev->name);
- physoutdev = nf_bridge_get_physoutdev(skb);
- if (physoutdev && out != physoutdev)
- nf_log_buf_add(m, "PHYSOUT=%s ", physoutdev->name);
- }
+ physindev = nf_bridge_get_physindev(skb);
+ if (physindev && in != physindev)
+ nf_log_buf_add(m, "PHYSIN=%s ", physindev->name);
+ physoutdev = nf_bridge_get_physoutdev(skb);
+ if (physoutdev && out != physoutdev)
+ nf_log_buf_add(m, "PHYSOUT=%s ", physoutdev->name);
#endif
}
EXPORT_SYMBOL_GPL(nf_log_dump_packet_common);
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index d67a96a25a68..a36a77bae1d6 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -46,6 +46,24 @@ void nf_unregister_queue_handler(struct net *net)
}
EXPORT_SYMBOL(nf_unregister_queue_handler);
+static void nf_queue_entry_release_br_nf_refs(struct sk_buff *skb)
+{
+#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+ struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
+
+ if (nf_bridge) {
+ struct net_device *physdev;
+
+ physdev = nf_bridge_get_physindev(skb);
+ if (physdev)
+ dev_put(physdev);
+ physdev = nf_bridge_get_physoutdev(skb);
+ if (physdev)
+ dev_put(physdev);
+ }
+#endif
+}
+
void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
{
struct nf_hook_state *state = &entry->state;
@@ -57,20 +75,28 @@ void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
dev_put(state->out);
if (state->sk)
sock_put(state->sk);
+
+ nf_queue_entry_release_br_nf_refs(entry->skb);
+}
+EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs);
+
+static void nf_queue_entry_get_br_nf_refs(struct sk_buff *skb)
+{
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
- if (entry->skb->nf_bridge) {
+ struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
+
+ if (nf_bridge) {
struct net_device *physdev;
- physdev = nf_bridge_get_physindev(entry->skb);
+ physdev = nf_bridge_get_physindev(skb);
if (physdev)
- dev_put(physdev);
- physdev = nf_bridge_get_physoutdev(entry->skb);
+ dev_hold(physdev);
+ physdev = nf_bridge_get_physoutdev(skb);
if (physdev)
- dev_put(physdev);
+ dev_hold(physdev);
}
#endif
}
-EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs);
/* Bump dev refs so they don't vanish while packet is out */
void nf_queue_entry_get_refs(struct nf_queue_entry *entry)
@@ -83,18 +109,8 @@ void nf_queue_entry_get_refs(struct nf_queue_entry *entry)
dev_hold(state->out);
if (state->sk)
sock_hold(state->sk);
-#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
- if (entry->skb->nf_bridge) {
- struct net_device *physdev;
- physdev = nf_bridge_get_physindev(entry->skb);
- if (physdev)
- dev_hold(physdev);
- physdev = nf_bridge_get_physoutdev(entry->skb);
- if (physdev)
- dev_hold(physdev);
- }
-#endif
+ nf_queue_entry_get_br_nf_refs(entry->skb);
}
EXPORT_SYMBOL_GPL(nf_queue_entry_get_refs);
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 1ce30efe6854..0dcc3592d053 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -727,13 +727,13 @@ nf_queue_entry_dup(struct nf_queue_entry *e)
*/
static void nf_bridge_adjust_skb_data(struct sk_buff *skb)
{
- if (skb->nf_bridge)
+ if (nf_bridge_info_get(skb))
__skb_push(skb, skb->network_header - skb->mac_header);
}
static void nf_bridge_adjust_segmented_data(struct sk_buff *skb)
{
- if (skb->nf_bridge)
+ if (nf_bridge_info_get(skb))
__skb_pull(skb, skb->network_header - skb->mac_header);
}
#else
@@ -904,23 +904,22 @@ nfqnl_set_mode(struct nfqnl_instance *queue,
static int
dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
{
+#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+ int physinif, physoutif;
+
+ physinif = nf_bridge_get_physinif(entry->skb);
+ physoutif = nf_bridge_get_physoutif(entry->skb);
+
+ if (physinif == ifindex || physoutif == ifindex)
+ return 1;
+#endif
if (entry->state.in)
if (entry->state.in->ifindex == ifindex)
return 1;
if (entry->state.out)
if (entry->state.out->ifindex == ifindex)
return 1;
-#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
- if (entry->skb->nf_bridge) {
- int physinif, physoutif;
- physinif = nf_bridge_get_physinif(entry->skb);
- physoutif = nf_bridge_get_physoutif(entry->skb);
-
- if (physinif == ifindex || physoutif == ifindex)
- return 1;
- }
-#endif
return 0;
}
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index 9d6d67b953ac..4034d70bff39 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -33,7 +33,7 @@ physdev_mt(const struct sk_buff *skb, struct xt_action_param *par)
/* Not a bridged IP packet or no info available yet:
* LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if
* the destination device will be a bridge. */
- if (!skb->nf_bridge) {
+ if (!nf_bridge_info_exists(skb)) {
/* Return MATCH if the invert flags of the used options are on */
if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
!(info->invert & XT_PHYSDEV_OP_BRIDGED))
--
2.18.1
^ permalink raw reply related
* [RFC PATCH 2/3] sk_buff: add skb extension infrastructure
From: Florian Westphal @ 2018-11-26 11:38 UTC (permalink / raw)
To: netdev; +Cc: Florian Westphal
In-Reply-To: <20181126113857.29270-1-fw@strlen.de>
adds an extension infrastructure for sk_buff:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb.
This is also how xfrm and bridge netfilter skb-associated data
(skb->sp and skb->nf_bridge) are handled.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
have been allocated for the skb.
2. extension pointer, located at the end of the sk_buff.
If active_extensions is 0, its content is undefined.
The 'nf_bridge' pointer is removed, i.e. sk_buff size remains the same,
in a followup patch.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but replaces the existing code that
deals with skb->nf_bridge.
This patch only adds the basic infrastructure, the nf_bridge conversion
is done in the next patch.
Conversion of skb->sp (ipsec/xfrm secpath) to an skb extension is planned
as a followup.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/linux/skbuff.h | 124 +++++++++++++++++++++++++++++++++++++-
net/Kconfig | 3 +
net/core/skbuff.c | 131 +++++++++++++++++++++++++++++++++++++++++
net/ipv4/ip_output.c | 1 +
net/ipv6/ip6_output.c | 1 +
5 files changed, 259 insertions(+), 1 deletion(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 73902acf2b71..832904d71a85 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -245,6 +245,7 @@ struct iov_iter;
struct napi_struct;
struct bpf_prog;
union bpf_attr;
+struct skb_ext;
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
struct nf_conntrack {
@@ -633,6 +634,7 @@ typedef unsigned char *sk_buff_data_t;
* @queue_mapping: Queue mapping for multiqueue devices
* @xmit_more: More SKBs are pending for this queue
* @pfmemalloc: skbuff was allocated from PFMEMALLOC reserves
+ * @active_extensions: active extensions (skb_ext_id types)
* @ndisc_nodetype: router type (from link layer)
* @ooo_okay: allow the mapping of a socket to a queue to be changed
* @l4_hash: indicate hash is a canonical 4-tuple hash over transport
@@ -662,6 +664,7 @@ typedef unsigned char *sk_buff_data_t;
* @data: Data head pointer
* @truesize: Buffer size
* @users: User count - see {datagram,tcp}.c
+ * @extensions: allocated extensions, valid if active_extensions is nonzero
*/
struct sk_buff {
@@ -744,7 +747,9 @@ struct sk_buff {
head_frag:1,
xmit_more:1,
pfmemalloc:1;
-
+#ifdef CONFIG_SKB_EXTENSIONS
+ __u8 active_extensions;
+#endif
/* fields enclosed in headers_start/headers_end are copied
* using a single memcpy() in __copy_skb_header()
*/
@@ -866,6 +871,11 @@ struct sk_buff {
*data;
unsigned int truesize;
refcount_t users;
+
+#ifdef CONFIG_SKB_EXTENSIONS
+ /* only useable after checking ->active_extensions != 0 */
+ struct skb_ext *extensions;
+#endif
};
#ifdef __KERNEL__
@@ -3889,6 +3899,118 @@ static inline void nf_conntrack_get(struct nf_conntrack *nfct)
atomic_inc(&nfct->use);
}
#endif
+
+#ifdef CONFIG_SKB_EXTENSIONS
+enum skb_ext_id {
+#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+ SKB_EXT_BRIDGE_NF,
+#endif
+ SKB_EXT_NUM, /* must be last */
+};
+
+/* each extension aligned to this value */
+#define SKB_EXT_ALIGN 8
+/* offsets/len: left-shift needed to translate offset to bytes */
+#define SKB_EXT_ALIGN_SHIFT 3
+
+/**
+ * struct skb_ext - sk_buff extensions
+ * @refcount: 1 on allocation, deallocated on 0
+ * @offset: offset to add to @data to obtain extension address
+ * @len: size currently allocated, stored in SKB_EXT_ALIGN_SHIFT units
+ * @data: start of extension data, variable sized
+ *
+ * Note: offsets and len are stored in chunks of 8 bytes, this allows
+ * to use 'u8' types while allowing up to 2kb worth of extension data.
+ */
+struct skb_ext {
+ refcount_t refcnt;
+ u8 offset[SKB_EXT_NUM]; /* chunks of 8 bytes */
+ u8 len; /* same, i.e. size == len << 3 */
+ char data[0] __aligned(SKB_EXT_ALIGN);
+};
+
+void *skb_ext_add(struct sk_buff *skb, enum skb_ext_id id);
+void __skb_ext_del(struct sk_buff *skb, enum skb_ext_id id);
+void __skb_ext_free(struct skb_ext *ext);
+
+static inline void __skb_ext_put(struct skb_ext *ext)
+{
+ if (ext && refcount_dec_and_test(&ext->refcnt))
+ __skb_ext_free(ext);
+}
+
+static inline void skb_ext_put(struct sk_buff *skb)
+{
+ if (skb->active_extensions)
+ __skb_ext_put(skb->extensions);
+}
+
+static inline void skb_ext_get(struct sk_buff *skb)
+{
+ if (skb->active_extensions) {
+ struct skb_ext *ext = skb->extensions;
+
+ if (ext)
+ refcount_inc(&ext->refcnt);
+ }
+}
+
+static inline void __skb_ext_copy(struct sk_buff *dst,
+ const struct sk_buff *src)
+{
+ dst->active_extensions = src->active_extensions;
+
+ if (src->active_extensions) {
+ struct skb_ext *ext = src->extensions;
+
+ if (ext)
+ refcount_inc(&ext->refcnt);
+ dst->extensions = ext;
+ }
+}
+
+static inline void skb_ext_copy(struct sk_buff *dst, const struct sk_buff *src)
+{
+ skb_ext_put(dst);
+ __skb_ext_copy(dst, src);
+}
+
+static inline bool __skb_ext_exist(const struct skb_ext *ext, enum skb_ext_id i)
+{
+ return !!ext->offset[i];
+}
+
+static inline bool skb_ext_exist(const struct sk_buff *skb, enum skb_ext_id id)
+{
+ return skb->active_extensions & (1 << id);
+}
+
+static inline void skb_ext_del(struct sk_buff *skb, enum skb_ext_id id)
+{
+ if (skb_ext_exist(skb, id))
+ __skb_ext_del(skb, id);
+}
+
+static inline void *skb_ext_find(const struct sk_buff *skb, enum skb_ext_id id)
+{
+ if (skb_ext_exist(skb, id)) {
+ struct skb_ext *ext = skb->extensions;
+
+ if (ext && __skb_ext_exist(ext, id))
+ return (void *)ext + (ext->offset[id] << 3);
+ }
+
+ return NULL;
+}
+#else
+static inline void skb_ext_put(struct sk_buff *skb) {}
+static inline void skb_ext_get(struct sk_buff *skb) {}
+static inline void skb_ext_del(struct sk_buff *skb, int unused) {}
+static inline void __skb_ext_copy(struct sk_buff *d, const struct sk_buff *s) {}
+static inline void skb_ext_copy(struct sk_buff *dst, const struct sk_buff *s) {}
+#endif /* CONFIG_SKB_EXTENSIONS */
+
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
{
diff --git a/net/Kconfig b/net/Kconfig
index f235edb593ba..93b291292860 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -51,6 +51,9 @@ config NET_INGRESS
config NET_EGRESS
bool
+config SKB_EXTENSIONS
+ bool
+
menu "Networking options"
source "net/packet/Kconfig"
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 02cd7ae3d0fb..e29016030633 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -617,6 +617,7 @@ void skb_release_head_state(struct sk_buff *skb)
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
nf_bridge_put(skb->nf_bridge);
#endif
+ skb_ext_put(skb);
}
/* Free everything but the sk_buff shell. */
@@ -796,6 +797,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
new->dev = old->dev;
memcpy(new->cb, old->cb, sizeof(old->cb));
skb_dst_copy(new, old);
+ __skb_ext_copy(new, old);
#ifdef CONFIG_XFRM
new->sp = secpath_get(old->sp);
#endif
@@ -5531,3 +5533,132 @@ void skb_condense(struct sk_buff *skb)
*/
skb->truesize = SKB_TRUESIZE(skb_end_offset(skb));
}
+
+#ifdef CONFIG_SKB_EXTENSIONS
+static const u8 skb_ext_type_len[] = {
+#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+ [SKB_EXT_BRIDGE_NF] = sizeof(struct nf_bridge_info),
+#endif
+};
+
+static void *skb_ext_get_ptr(struct skb_ext *ext, enum skb_ext_id id)
+{
+ return (void *)ext + (ext->offset[id] << SKB_EXT_ALIGN_SHIFT);
+}
+
+static struct skb_ext *skb_ext_cow(unsigned int len,
+ struct skb_ext *old)
+{
+ struct skb_ext *new = kmalloc(len, GFP_ATOMIC);
+
+ if (!new)
+ return NULL;
+
+ if (!old) {
+ memset(new->offset, 0, sizeof(new->offset));
+ refcount_set(&new->refcnt, 1);
+ return new;
+ }
+
+ memcpy(new, old, old->len << SKB_EXT_ALIGN_SHIFT);
+ refcount_set(&new->refcnt, 1);
+ __skb_ext_put(old);
+ return new;
+}
+
+static __always_inline unsigned int skb_ext_total_length(void)
+{
+ return 0 +
+#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+ skb_ext_type_len[SKB_EXT_BRIDGE_NF] +
+#endif
+ 0;
+}
+
+/**
+ * skb_ext_add - allocate space for given extension, COW if needed
+ * @skb: buffer
+ * @id: extension to allocate space for
+ *
+ * Allocates enough space for the given extension.
+ * If the extension is already present, a pointer to that extension
+ * is returned.
+ *
+ * If the skb was cloned, COW applies and the returned memory can be
+ * modified without changing the extension space of clones buffers.
+ *
+ * Returns pointer to the extenion or NULL on allocation failure.
+ */
+void *skb_ext_add(struct sk_buff *skb, enum skb_ext_id id)
+{
+ unsigned int newlen, newoff, oldlen;
+ struct skb_ext *new, *old = NULL;
+ bool cow_needed = true;
+
+ BUILD_BUG_ON(SKB_EXT_NUM >= 8);
+ BUILD_BUG_ON(skb_ext_total_length() > (255 << 3));
+
+ if (skb->active_extensions) {
+ old = skb->extensions;
+
+ cow_needed = refcount_read(&old->refcnt) > 1;
+
+ if (__skb_ext_exist(old, id)) {
+ if (!cow_needed) {
+ new = old;
+ goto set_active;
+ }
+
+ /* extension was allocated previously and it
+ * might be used by a cloned skb. COW needed.
+ */
+ new = skb_ext_cow(old->len << SKB_EXT_ALIGN_SHIFT, old);
+ if (!new)
+ return NULL;
+
+ skb->extensions = new;
+ goto set_active;
+ }
+ oldlen = old->len << SKB_EXT_ALIGN_SHIFT;
+ } else {
+ oldlen = sizeof(*new);
+ }
+
+ newoff = ALIGN(oldlen, SKB_EXT_ALIGN);
+ newlen = newoff + skb_ext_type_len[id];
+
+ if (cow_needed)
+ new = skb_ext_cow(newlen, old);
+ else
+ new = krealloc(old, newlen, GFP_ATOMIC);
+ if (!new)
+ return NULL;
+
+ new->offset[id] = newoff >> SKB_EXT_ALIGN_SHIFT;
+ new->len = newlen >> SKB_EXT_ALIGN_SHIFT;
+ skb->extensions = new;
+set_active:
+ skb->active_extensions |= 1 << id;
+ return skb_ext_get_ptr(new, id);
+}
+EXPORT_SYMBOL(skb_ext_add);
+
+void __skb_ext_del(struct sk_buff *skb, enum skb_ext_id id)
+{
+ struct skb_ext *ext;
+
+ skb->active_extensions &= ~(1 << id);
+ if (skb->active_extensions == 0) {
+ ext = skb->extensions;
+ skb->extensions = NULL;
+ __skb_ext_put(ext);
+ }
+}
+EXPORT_SYMBOL(__skb_ext_del);
+
+void __skb_ext_free(struct skb_ext *ext)
+{
+ kfree(ext);
+}
+EXPORT_SYMBOL(__skb_ext_free);
+#endif /* CONFIG_SKB_EXTENSIONS */
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index c09219e7f230..a12e12f983d5 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -533,6 +533,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
to->tc_index = from->tc_index;
#endif
nf_copy(to, from);
+ skb_ext_copy(to, from);
#if IS_ENABLED(CONFIG_IP_VS)
to->ipvs_property = from->ipvs_property;
#endif
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 89e0d5118afe..7eeb0f24be87 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -574,6 +574,7 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
to->tc_index = from->tc_index;
#endif
nf_copy(to, from);
+ skb_ext_copy(to, from);
skb_copy_secmark(to, from);
}
--
2.18.1
^ permalink raw reply related
* [RFC PATCH 3/3] net: convert bridge_nf to use skb extension infrastructure
From: Florian Westphal @ 2018-11-26 11:38 UTC (permalink / raw)
To: netdev; +Cc: Florian Westphal
In-Reply-To: <20181126113857.29270-1-fw@strlen.de>
This converts the bridge netfilter (calling iptables hooks from bridge)
facility to use the extension infrastructure instead.
The bridge_nf specific hooks in skb clone and free paths are removed, they
have been replaced by the skb_ext hooks that do the same as the bridge nf
allocations hooks did.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/linux/netfilter_bridge.h | 4 ++--
include/linux/skbuff.h | 28 ++--------------------------
include/net/netfilter/br_netfilter.h | 8 ++++----
net/Kconfig | 1 +
net/bridge/br_netfilter_hooks.c | 20 ++------------------
net/bridge/br_netfilter_ipv6.c | 4 ++--
net/core/skbuff.c | 3 ---
7 files changed, 13 insertions(+), 55 deletions(-)
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
index 0a65a422587c..5f2614d02e03 100644
--- a/include/linux/netfilter_bridge.h
+++ b/include/linux/netfilter_bridge.h
@@ -20,12 +20,12 @@ static inline void br_drop_fake_rtable(struct sk_buff *skb)
static inline struct nf_bridge_info *
nf_bridge_info_get(const struct sk_buff *skb)
{
- return skb->nf_bridge;
+ return skb_ext_find(skb, SKB_EXT_BRIDGE_NF);
}
static inline bool nf_bridge_info_exists(const struct sk_buff *skb)
{
- return skb->nf_bridge != NULL;
+ return skb_ext_exist(skb, SKB_EXT_BRIDGE_NF);
}
static inline int nf_bridge_get_physinif(const struct sk_buff *skb)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 832904d71a85..c33654da09c3 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -255,7 +255,6 @@ struct nf_conntrack {
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
struct nf_bridge_info {
- refcount_t use;
enum {
BRNF_PROTO_UNCHANGED,
BRNF_PROTO_8021Q,
@@ -717,9 +716,6 @@ struct sk_buff {
#endif
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
unsigned long _nfct;
-#endif
-#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
- struct nf_bridge_info *nf_bridge;
#endif
unsigned int len,
data_len;
@@ -4011,18 +4007,6 @@ static inline void __skb_ext_copy(struct sk_buff *d, const struct sk_buff *s) {}
static inline void skb_ext_copy(struct sk_buff *dst, const struct sk_buff *s) {}
#endif /* CONFIG_SKB_EXTENSIONS */
-#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
-static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
-{
- if (nf_bridge && refcount_dec_and_test(&nf_bridge->use))
- kfree(nf_bridge);
-}
-static inline void nf_bridge_get(struct nf_bridge_info *nf_bridge)
-{
- if (nf_bridge)
- refcount_inc(&nf_bridge->use);
-}
-#endif /* CONFIG_BRIDGE_NETFILTER */
static inline void nf_reset(struct sk_buff *skb)
{
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
@@ -4030,8 +4014,7 @@ static inline void nf_reset(struct sk_buff *skb)
skb->_nfct = 0;
#endif
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
- nf_bridge_put(skb->nf_bridge);
- skb->nf_bridge = NULL;
+ skb_ext_del(skb, SKB_EXT_BRIDGE_NF);
#endif
}
@@ -4049,7 +4032,7 @@ static inline void ipvs_reset(struct sk_buff *skb)
#endif
}
-/* Note: This doesn't put any conntrack and bridge info in dst. */
+/* Note: This doesn't put any conntrack info in dst. */
static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src,
bool copy)
{
@@ -4057,10 +4040,6 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src,
dst->_nfct = src->_nfct;
nf_conntrack_get(skb_nfct(src));
#endif
-#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
- dst->nf_bridge = src->nf_bridge;
- nf_bridge_get(src->nf_bridge);
-#endif
#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || defined(CONFIG_NF_TABLES)
if (copy)
dst->nf_trace = src->nf_trace;
@@ -4071,9 +4050,6 @@ static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src)
{
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_conntrack_put(skb_nfct(dst));
-#endif
-#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
- nf_bridge_put(dst->nf_bridge);
#endif
__nf_copy(dst, src, true);
}
diff --git a/include/net/netfilter/br_netfilter.h b/include/net/netfilter/br_netfilter.h
index 6efc0153987b..4cd56808ac4e 100644
--- a/include/net/netfilter/br_netfilter.h
+++ b/include/net/netfilter/br_netfilter.h
@@ -6,12 +6,12 @@
static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb)
{
- skb->nf_bridge = kzalloc(sizeof(struct nf_bridge_info), GFP_ATOMIC);
+ struct nf_bridge_info *b = skb_ext_add(skb, SKB_EXT_BRIDGE_NF);
- if (likely(skb->nf_bridge))
- refcount_set(&(skb->nf_bridge->use), 1);
+ if (b)
+ memset(b, 0, sizeof(*b));
- return skb->nf_bridge;
+ return b;
}
void nf_bridge_update_protocol(struct sk_buff *skb);
diff --git a/net/Kconfig b/net/Kconfig
index 93b291292860..5cb9de1aaf88 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -187,6 +187,7 @@ config BRIDGE_NETFILTER
depends on NETFILTER && INET
depends on NETFILTER_ADVANCED
select NETFILTER_FAMILY_BRIDGE
+ select SKB_EXTENSIONS
default m
---help---
Enabling this option will let arptables resp. iptables see bridged
diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
index c58cf68b45c5..d21a23698410 100644
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -132,10 +132,7 @@ static DEFINE_PER_CPU(struct brnf_frag_data, brnf_frag_data_storage);
static void nf_bridge_info_free(struct sk_buff *skb)
{
- if (skb->nf_bridge) {
- nf_bridge_put(skb->nf_bridge);
- skb->nf_bridge = NULL;
- }
+ skb_ext_del(skb, SKB_EXT_BRIDGE_NF);
}
static inline struct net_device *bridge_parent(const struct net_device *dev)
@@ -148,19 +145,7 @@ static inline struct net_device *bridge_parent(const struct net_device *dev)
static inline struct nf_bridge_info *nf_bridge_unshare(struct sk_buff *skb)
{
- struct nf_bridge_info *nf_bridge = skb->nf_bridge;
-
- if (refcount_read(&nf_bridge->use) > 1) {
- struct nf_bridge_info *tmp = nf_bridge_alloc(skb);
-
- if (tmp) {
- memcpy(tmp, nf_bridge, sizeof(struct nf_bridge_info));
- refcount_set(&tmp->use, 1);
- }
- nf_bridge_put(nf_bridge);
- nf_bridge = tmp;
- }
- return nf_bridge;
+ return skb_ext_add(skb, SKB_EXT_BRIDGE_NF);
}
unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb)
@@ -508,7 +493,6 @@ static unsigned int br_nf_pre_routing(void *priv,
if (br_validate_ipv4(state->net, skb))
return NF_DROP;
- nf_bridge_put(skb->nf_bridge);
if (!nf_bridge_alloc(skb))
return NF_DROP;
if (!setup_pre_routing(skb))
diff --git a/net/bridge/br_netfilter_ipv6.c b/net/bridge/br_netfilter_ipv6.c
index 96c072e71ea2..94039f588f1d 100644
--- a/net/bridge/br_netfilter_ipv6.c
+++ b/net/bridge/br_netfilter_ipv6.c
@@ -224,8 +224,8 @@ unsigned int br_nf_pre_routing_ipv6(void *priv,
if (br_validate_ipv6(state->net, skb))
return NF_DROP;
- nf_bridge_put(skb->nf_bridge);
- if (!nf_bridge_alloc(skb))
+ nf_bridge = nf_bridge_alloc(skb);
+ if (!nf_bridge)
return NF_DROP;
if (!setup_pre_routing(skb))
return NF_DROP;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index e29016030633..614499d9898c 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -613,9 +613,6 @@ void skb_release_head_state(struct sk_buff *skb)
}
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
nf_conntrack_put(skb_nfct(skb));
-#endif
-#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
- nf_bridge_put(skb->nf_bridge);
#endif
skb_ext_put(skb);
}
--
2.18.1
^ permalink raw reply related
* Re: Very Urgent !!!
From: Ruth Yoda @ 2018-11-26 11:46 UTC (permalink / raw)
Date::
Monday, November 26th, 2018.
WITH DUE RESPECT :
Let me start by introduce myself; I am Mrs.Ruth Yoda, Bill and
Exchange manager (Bank of Africa) Ouagadougou, Burkina Faso. I write
you this letter based on the latest development at our bank which i
will like to bring to your personal edification, $12,250Million
transfer claims. This is a legitimate transaction and i agree to offer
you 40% of this money as my foreign partner after confirmation of the
fund in your bank account, if you are interested, please get back to
me for more clarification.
Yours faithful,
Mrs.Ruth Yoda
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox