1
0
mirror of https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2026-01-11 17:10:13 +00:00

Including fixes from netfilter and CAN.

Current release - regressions:
 
   - netfilter: nf_conncount: fix leaked ct in error paths
 
   - sched: act_mirred: fix loop detection
 
   - sctp: fix potential deadlock in sctp_clone_sock()
 
   - can: fix build dependency
 
   - eth: mlx5e: do not update BQL of old txqs during channel reconfiguration
 
 Previous releases - regressions:
 
   - sched: ets: always remove class from active list before deleting it
 
   - inet: frags: flush pending skbs in fqdir_pre_exit()
 
   - netfilter:  nf_nat: remove bogus direction check
 
   - mptcp:
     - schedule rtx timer only after pushing data
     - avoid deadlock on fallback while reinjecting
 
   - can: gs_usb: fix error handling
 
   - eth: mlx5e:
     - avoid unregistering PSP twice
     - fix double unregister of HCA_PORTS component
 
   - eth: bnxt_en: fix XDP_TX path
 
   - eth: mlxsw: fix use-after-free when updating multicast route stats
 
 Previous releases - always broken:
 
   - ethtool: avoid overflowing userspace buffer on stats query
 
   - openvswitch: fix middle attribute validation in push_nsh() action
 
   - eth: mlx5: fw_tracer, validate format string parameters
 
   - eth: mlxsw: spectrum_router: fix neighbour use-after-free
 
   - eth: ipvlan: ignore PACKET_LOOPBACK in handle_mode_l2()
 
 Misc:
 
   - Jozsef Kadlecsik retires from maintaining netfilter
 
   - tools: ynl: fix build on systems with old kernel headers
 
 Signed-off-by: Paolo Abeni <pabeni@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCgAwFiEEg1AjqC77wbdLX2LbKSR5jcyPE6QFAmlEPS0SHHBhYmVuaUBy
 ZWRoYXQuY29tAAoJECkkeY3MjxOkHLEP/3TnVI9qLivOGsZ48bn5UUcIaIlX0wiw
 i5gwpUhbtW3zcLSphO0Nh/CmProme6dFhaMOOkk48bKAdIxRpOMbCC20bfYDLyd0
 ZJTUQqheKpuI23vOnhfs2TTOkcqz6cM7txUq681taQ8Nfo8Dbf0fgOO2HT5ljRD+
 JXlxrdvicZDtve68sSdnsAj5M15EPQGKTPMyPkymBmCKnCMQK9SQKaeTEtaW6NIO
 yM0KqDSNoulDc/6LYMhx8DTtyE7yTiTxwe2NixjdyYljXsk0KiRDirCzxnZuSgh8
 oh+cFLdFDq4mwdYEKjgC5c3ifQyLEpZvwzlY5MKoobsVnT5SbigeSK53l5rEkO3V
 sM84lITHfqTJvlid0AF/ixEc6iWwV7nGRBHh2FXNbfoIKt45eF77jPi9YFsq6Z95
 vlCzYIbY0f2L1y3mPvZbzGQbh2Z12b5kyK8QA1j7SK+zNzxgXbf4+ZtYxHg7O3Ne
 gecmIpTKXMWodaZyfsRQPjR/F6UIlMqsgl9Ci9bfUw+XwL8x+7bJxQAQz+yVjLla
 ng14BItiYKBavcPZBjYlhGKqD1fzGhVZqQecrCkF0VTbMusRd9RcwytU1NG4QGDx
 V5aL28ht85KtMednEWOBkrg+PeXnNyZHzLAf2Xtx3UkaGgiDC8G4IxUv3orlOLD1
 sFPfZnSiGCof
 =6pla
 -----END PGP SIGNATURE-----

Merge tag 'net-6.19-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net

Pull networking fixes from Paolo Abeni:
 "Including fixes from netfilter and CAN.

  Current release - regressions:

   - netfilter: nf_conncount: fix leaked ct in error paths

   - sched: act_mirred: fix loop detection

   - sctp: fix potential deadlock in sctp_clone_sock()

   - can: fix build dependency

   - eth: mlx5e: do not update BQL of old txqs during channel
     reconfiguration

  Previous releases - regressions:

   - sched: ets: always remove class from active list before deleting it

   - inet: frags: flush pending skbs in fqdir_pre_exit()

   - netfilter: nf_nat: remove bogus direction check

   - mptcp:
      - schedule rtx timer only after pushing data
      - avoid deadlock on fallback while reinjecting

   - can: gs_usb: fix error handling

   - eth:
      - mlx5e:
         - avoid unregistering PSP twice
         - fix double unregister of HCA_PORTS component
      - bnxt_en: fix XDP_TX path
      - mlxsw: fix use-after-free when updating multicast route stats

  Previous releases - always broken:

   - ethtool: avoid overflowing userspace buffer on stats query

   - openvswitch: fix middle attribute validation in push_nsh() action

   - eth:
      - mlx5: fw_tracer, validate format string parameters
      - mlxsw: spectrum_router: fix neighbour use-after-free
      - ipvlan: ignore PACKET_LOOPBACK in handle_mode_l2()

  Misc:

   - Jozsef Kadlecsik retires from maintaining netfilter

   - tools: ynl: fix build on systems with old kernel headers"

* tag 'net-6.19-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (83 commits)
  net: hns3: add VLAN id validation before using
  net: hns3: using the num_tqps to check whether tqp_index is out of range when vf get ring info from mbx
  net: hns3: using the num_tqps in the vf driver to apply for resources
  net: enetc: do not transmit redirected XDP frames when the link is down
  selftests/tc-testing: Test case exercising potential mirred redirect deadlock
  net/sched: act_mirred: fix loop detection
  sctp: Clear inet_opt in sctp_v6_copy_ip_options().
  sctp: Fetch inet6_sk() after setting ->pinet6 in sctp_clone_sock().
  net/handshake: duplicate handshake cancellations leak socket
  net/mlx5e: Don't include PSP in the hard MTU calculations
  net/mlx5e: Do not update BQL of old txqs during channel reconfiguration
  net/mlx5e: Trigger neighbor resolution for unresolved destinations
  net/mlx5e: Use ip6_dst_lookup instead of ipv6_dst_lookup_flow for MAC init
  net/mlx5: Serialize firmware reset with devlink
  net/mlx5: fw_tracer, Handle escaped percent properly
  net/mlx5: fw_tracer, Validate format string parameters
  net/mlx5: Drain firmware reset in shutdown callback
  net/mlx5: fw reset, clear reset requested on drain_fw_reset
  net: dsa: mxl-gsw1xx: manually clear RANEG bit
  net: dsa: mxl-gsw1xx: fix .shutdown driver operation
  ...
This commit is contained in:
Linus Torvalds 2025-12-19 07:55:35 +12:00
commit 7b8e9264f5
88 changed files with 769 additions and 269 deletions

View File

@ -1987,6 +1987,7 @@ D: netfilter: TCP window tracking code
D: netfilter: raw table D: netfilter: raw table
D: netfilter: iprange match D: netfilter: iprange match
D: netfilter: new logging interfaces D: netfilter: new logging interfaces
D: netfilter: ipset
D: netfilter: various other hacks D: netfilter: various other hacks
S: Tata S: Tata
S: Hungary S: Hungary

View File

@ -18028,7 +18028,6 @@ F: drivers/net/ethernet/neterion/
NETFILTER NETFILTER
M: Pablo Neira Ayuso <pablo@netfilter.org> M: Pablo Neira Ayuso <pablo@netfilter.org>
M: Jozsef Kadlecsik <kadlec@netfilter.org>
M: Florian Westphal <fw@strlen.de> M: Florian Westphal <fw@strlen.de>
R: Phil Sutter <phil@nwl.cc> R: Phil Sutter <phil@nwl.cc>
L: netfilter-devel@vger.kernel.org L: netfilter-devel@vger.kernel.org

View File

@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
menuconfig CAN_DEV menuconfig CAN_DEV
tristate "CAN Device Drivers" bool "CAN Device Drivers"
default y default y
depends on CAN depends on CAN
help help
@ -17,10 +17,7 @@ menuconfig CAN_DEV
virtual ones. If you own such devices or plan to use the virtual CAN virtual ones. If you own such devices or plan to use the virtual CAN
interfaces to develop applications, say Y here. interfaces to develop applications, say Y here.
To compile as a module, choose M here: the module will be called if CAN_DEV && CAN
can-dev.
if CAN_DEV
config CAN_VCAN config CAN_VCAN
tristate "Virtual Local CAN Interface (vcan)" tristate "Virtual Local CAN Interface (vcan)"

View File

@ -7,7 +7,7 @@ obj-$(CONFIG_CAN_VCAN) += vcan.o
obj-$(CONFIG_CAN_VXCAN) += vxcan.o obj-$(CONFIG_CAN_VXCAN) += vxcan.o
obj-$(CONFIG_CAN_SLCAN) += slcan/ obj-$(CONFIG_CAN_SLCAN) += slcan/
obj-y += dev/ obj-$(CONFIG_CAN_DEV) += dev/
obj-y += esd/ obj-y += esd/
obj-y += rcar/ obj-y += rcar/
obj-y += rockchip/ obj-y += rockchip/

View File

@ -1,9 +1,8 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_CAN_DEV) += can-dev.o obj-$(CONFIG_CAN) += can-dev.o
can-dev-y += skb.o
can-dev-$(CONFIG_CAN_DEV) += skb.o
can-dev-$(CONFIG_CAN_CALC_BITTIMING) += calc_bittiming.o can-dev-$(CONFIG_CAN_CALC_BITTIMING) += calc_bittiming.o
can-dev-$(CONFIG_CAN_NETLINK) += bittiming.o can-dev-$(CONFIG_CAN_NETLINK) += bittiming.o
can-dev-$(CONFIG_CAN_NETLINK) += dev.o can-dev-$(CONFIG_CAN_NETLINK) += dev.o

View File

@ -1074,7 +1074,7 @@ out_usb_free_urb:
usb_free_urb(urb); usb_free_urb(urb);
out_usb_kill_anchored_urbs: out_usb_kill_anchored_urbs:
if (!parent->active_channels) { if (!parent->active_channels) {
usb_kill_anchored_urbs(&dev->tx_submitted); usb_kill_anchored_urbs(&parent->rx_submitted);
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
gs_usb_timestamp_stop(parent); gs_usb_timestamp_stop(parent);

View File

@ -444,9 +444,6 @@ static void gswip_remove(struct platform_device *pdev)
if (!priv) if (!priv)
return; return;
/* disable the switch */
gswip_disable_switch(priv);
dsa_unregister_switch(priv->ds); dsa_unregister_switch(priv->ds);
for (i = 0; i < priv->num_gphy_fw; i++) for (i = 0; i < priv->num_gphy_fw; i++)

View File

@ -294,8 +294,6 @@ struct gswip_priv {
u16 version; u16 version;
}; };
void gswip_disable_switch(struct gswip_priv *priv);
int gswip_probe_common(struct gswip_priv *priv, u32 version); int gswip_probe_common(struct gswip_priv *priv, u32 version);
#endif /* __LANTIQ_GSWIP_H */ #endif /* __LANTIQ_GSWIP_H */

View File

@ -752,6 +752,13 @@ static int gswip_setup(struct dsa_switch *ds)
return 0; return 0;
} }
static void gswip_teardown(struct dsa_switch *ds)
{
struct gswip_priv *priv = ds->priv;
regmap_clear_bits(priv->mdio, GSWIP_MDIO_GLOB, GSWIP_MDIO_GLOB_ENABLE);
}
static enum dsa_tag_protocol gswip_get_tag_protocol(struct dsa_switch *ds, static enum dsa_tag_protocol gswip_get_tag_protocol(struct dsa_switch *ds,
int port, int port,
enum dsa_tag_protocol mp) enum dsa_tag_protocol mp)
@ -1629,6 +1636,7 @@ static const struct phylink_mac_ops gswip_phylink_mac_ops = {
static const struct dsa_switch_ops gswip_switch_ops = { static const struct dsa_switch_ops gswip_switch_ops = {
.get_tag_protocol = gswip_get_tag_protocol, .get_tag_protocol = gswip_get_tag_protocol,
.setup = gswip_setup, .setup = gswip_setup,
.teardown = gswip_teardown,
.port_setup = gswip_port_setup, .port_setup = gswip_port_setup,
.port_enable = gswip_port_enable, .port_enable = gswip_port_enable,
.port_disable = gswip_port_disable, .port_disable = gswip_port_disable,
@ -1656,12 +1664,6 @@ static const struct dsa_switch_ops gswip_switch_ops = {
.port_hsr_leave = dsa_port_simple_hsr_leave, .port_hsr_leave = dsa_port_simple_hsr_leave,
}; };
void gswip_disable_switch(struct gswip_priv *priv)
{
regmap_clear_bits(priv->mdio, GSWIP_MDIO_GLOB, GSWIP_MDIO_GLOB_ENABLE);
}
EXPORT_SYMBOL_GPL(gswip_disable_switch);
static int gswip_validate_cpu_port(struct dsa_switch *ds) static int gswip_validate_cpu_port(struct dsa_switch *ds)
{ {
struct gswip_priv *priv = ds->priv; struct gswip_priv *priv = ds->priv;
@ -1718,15 +1720,14 @@ int gswip_probe_common(struct gswip_priv *priv, u32 version)
err = gswip_validate_cpu_port(priv->ds); err = gswip_validate_cpu_port(priv->ds);
if (err) if (err)
goto disable_switch; goto unregister_switch;
dev_info(priv->dev, "probed GSWIP version %lx mod %lx\n", dev_info(priv->dev, "probed GSWIP version %lx mod %lx\n",
GSWIP_VERSION_REV(version), GSWIP_VERSION_MOD(version)); GSWIP_VERSION_REV(version), GSWIP_VERSION_MOD(version));
return 0; return 0;
disable_switch: unregister_switch:
gswip_disable_switch(priv);
dsa_unregister_switch(priv->ds); dsa_unregister_switch(priv->ds);
return err; return err;

View File

@ -11,10 +11,12 @@
#include <linux/bits.h> #include <linux/bits.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/jiffies.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_mdio.h> #include <linux/of_mdio.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/workqueue.h>
#include <net/dsa.h> #include <net/dsa.h>
#include "lantiq_gswip.h" #include "lantiq_gswip.h"
@ -29,6 +31,7 @@ struct gsw1xx_priv {
struct regmap *clk; struct regmap *clk;
struct regmap *shell; struct regmap *shell;
struct phylink_pcs pcs; struct phylink_pcs pcs;
struct delayed_work clear_raneg;
phy_interface_t tbi_interface; phy_interface_t tbi_interface;
struct gswip_priv gswip; struct gswip_priv gswip;
}; };
@ -145,7 +148,9 @@ static void gsw1xx_pcs_disable(struct phylink_pcs *pcs)
{ {
struct gsw1xx_priv *priv = pcs_to_gsw1xx(pcs); struct gsw1xx_priv *priv = pcs_to_gsw1xx(pcs);
/* Assert SGMII shell reset */ cancel_delayed_work_sync(&priv->clear_raneg);
/* Assert SGMII shell reset (will also clear RANEG bit) */
regmap_set_bits(priv->shell, GSW1XX_SHELL_RST_REQ, regmap_set_bits(priv->shell, GSW1XX_SHELL_RST_REQ,
GSW1XX_RST_REQ_SGMII_SHELL); GSW1XX_RST_REQ_SGMII_SHELL);
@ -255,10 +260,16 @@ static int gsw1xx_pcs_reset(struct gsw1xx_priv *priv)
FIELD_PREP(GSW1XX_SGMII_PHY_RX0_CFG2_FILT_CNT, FIELD_PREP(GSW1XX_SGMII_PHY_RX0_CFG2_FILT_CNT,
GSW1XX_SGMII_PHY_RX0_CFG2_FILT_CNT_DEF); GSW1XX_SGMII_PHY_RX0_CFG2_FILT_CNT_DEF);
/* TODO: Take care of inverted RX pair once generic property is /* RX lane seems to be inverted internally, so bit
* GSW1XX_SGMII_PHY_RX0_CFG2_INVERT needs to be set for normal
* (ie. non-inverted) operation.
*
* TODO: Take care of inverted RX pair once generic property is
* available * available
*/ */
val |= GSW1XX_SGMII_PHY_RX0_CFG2_INVERT;
ret = regmap_write(priv->sgmii, GSW1XX_SGMII_PHY_RX0_CFG2, val); ret = regmap_write(priv->sgmii, GSW1XX_SGMII_PHY_RX0_CFG2, val);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -422,12 +433,29 @@ static int gsw1xx_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
return 0; return 0;
} }
static void gsw1xx_pcs_clear_raneg(struct work_struct *work)
{
struct gsw1xx_priv *priv =
container_of(work, struct gsw1xx_priv, clear_raneg.work);
regmap_clear_bits(priv->sgmii, GSW1XX_SGMII_TBI_ANEGCTL,
GSW1XX_SGMII_TBI_ANEGCTL_RANEG);
}
static void gsw1xx_pcs_an_restart(struct phylink_pcs *pcs) static void gsw1xx_pcs_an_restart(struct phylink_pcs *pcs)
{ {
struct gsw1xx_priv *priv = pcs_to_gsw1xx(pcs); struct gsw1xx_priv *priv = pcs_to_gsw1xx(pcs);
cancel_delayed_work_sync(&priv->clear_raneg);
regmap_set_bits(priv->sgmii, GSW1XX_SGMII_TBI_ANEGCTL, regmap_set_bits(priv->sgmii, GSW1XX_SGMII_TBI_ANEGCTL,
GSW1XX_SGMII_TBI_ANEGCTL_RANEG); GSW1XX_SGMII_TBI_ANEGCTL_RANEG);
/* despite being documented as self-clearing, the RANEG bit
* sometimes remains set, preventing auto-negotiation from happening.
* MaxLinear advises to manually clear the bit after 10ms.
*/
schedule_delayed_work(&priv->clear_raneg, msecs_to_jiffies(10));
} }
static void gsw1xx_pcs_link_up(struct phylink_pcs *pcs, static void gsw1xx_pcs_link_up(struct phylink_pcs *pcs,
@ -630,6 +658,8 @@ static int gsw1xx_probe(struct mdio_device *mdiodev)
if (ret) if (ret)
return ret; return ret;
INIT_DELAYED_WORK(&priv->clear_raneg, gsw1xx_pcs_clear_raneg);
ret = gswip_probe_common(&priv->gswip, version); ret = gswip_probe_common(&priv->gswip, version);
if (ret) if (ret)
return ret; return ret;
@ -642,25 +672,31 @@ static int gsw1xx_probe(struct mdio_device *mdiodev)
static void gsw1xx_remove(struct mdio_device *mdiodev) static void gsw1xx_remove(struct mdio_device *mdiodev)
{ {
struct gswip_priv *priv = dev_get_drvdata(&mdiodev->dev); struct gswip_priv *priv = dev_get_drvdata(&mdiodev->dev);
struct gsw1xx_priv *gsw1xx_priv;
if (!priv) if (!priv)
return; return;
gswip_disable_switch(priv);
dsa_unregister_switch(priv->ds); dsa_unregister_switch(priv->ds);
gsw1xx_priv = container_of(priv, struct gsw1xx_priv, gswip);
cancel_delayed_work_sync(&gsw1xx_priv->clear_raneg);
} }
static void gsw1xx_shutdown(struct mdio_device *mdiodev) static void gsw1xx_shutdown(struct mdio_device *mdiodev)
{ {
struct gswip_priv *priv = dev_get_drvdata(&mdiodev->dev); struct gswip_priv *priv = dev_get_drvdata(&mdiodev->dev);
struct gsw1xx_priv *gsw1xx_priv;
if (!priv) if (!priv)
return; return;
dsa_switch_shutdown(priv->ds);
dev_set_drvdata(&mdiodev->dev, NULL); dev_set_drvdata(&mdiodev->dev, NULL);
gswip_disable_switch(priv); gsw1xx_priv = container_of(priv, struct gsw1xx_priv, gswip);
cancel_delayed_work_sync(&gsw1xx_priv->clear_raneg);
} }
static const struct gswip_hw_info gsw12x_data = { static const struct gswip_hw_info gsw12x_data = {

View File

@ -1790,6 +1790,9 @@ static int b44_nway_reset(struct net_device *dev)
u32 bmcr; u32 bmcr;
int r; int r;
if (bp->flags & B44_FLAG_EXTERNAL_PHY)
return phy_ethtool_nway_reset(dev);
spin_lock_irq(&bp->lock); spin_lock_irq(&bp->lock);
b44_readphy(bp, MII_BMCR, &bmcr); b44_readphy(bp, MII_BMCR, &bmcr);
b44_readphy(bp, MII_BMCR, &bmcr); b44_readphy(bp, MII_BMCR, &bmcr);

View File

@ -268,13 +268,11 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
case XDP_TX: case XDP_TX:
rx_buf = &rxr->rx_buf_ring[cons]; rx_buf = &rxr->rx_buf_ring[cons];
mapping = rx_buf->mapping - bp->rx_dma_offset; mapping = rx_buf->mapping - bp->rx_dma_offset;
*event &= BNXT_TX_CMP_EVENT;
if (unlikely(xdp_buff_has_frags(xdp))) { if (unlikely(xdp_buff_has_frags(xdp))) {
struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp); struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp);
tx_needed += sinfo->nr_frags; tx_needed += sinfo->nr_frags;
*event = BNXT_AGG_EVENT;
} }
if (tx_avail < tx_needed) { if (tx_avail < tx_needed) {
@ -287,6 +285,7 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
dma_sync_single_for_device(&pdev->dev, mapping + offset, *len, dma_sync_single_for_device(&pdev->dev, mapping + offset, *len,
bp->rx_dir); bp->rx_dir);
*event &= ~BNXT_RX_EVENT;
*event |= BNXT_TX_EVENT; *event |= BNXT_TX_EVENT;
__bnxt_xmit_xdp(bp, txr, mapping + offset, *len, __bnxt_xmit_xdp(bp, txr, mapping + offset, *len,
NEXT_RX(rxr->rx_prod), xdp); NEXT_RX(rxr->rx_prod), xdp);

View File

@ -1787,7 +1787,8 @@ int enetc_xdp_xmit(struct net_device *ndev, int num_frames,
int xdp_tx_bd_cnt, i, k; int xdp_tx_bd_cnt, i, k;
int xdp_tx_frm_cnt = 0; int xdp_tx_frm_cnt = 0;
if (unlikely(test_bit(ENETC_TX_DOWN, &priv->flags))) if (unlikely(test_bit(ENETC_TX_DOWN, &priv->flags) ||
!netif_carrier_ok(ndev)))
return -ENETDOWN; return -ENETDOWN;
enetc_lock_mdio(); enetc_lock_mdio();

View File

@ -3933,6 +3933,11 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep,
txq->bd.cur = bdp; txq->bd.cur = bdp;
/* Trigger transmission start */ /* Trigger transmission start */
if (!(fep->quirks & FEC_QUIRK_ERR007885) ||
!readl(txq->bd.reg_desc_active) ||
!readl(txq->bd.reg_desc_active) ||
!readl(txq->bd.reg_desc_active) ||
!readl(txq->bd.reg_desc_active))
writel(0, txq->bd.reg_desc_active); writel(0, txq->bd.reg_desc_active);
return 0; return 0;

View File

@ -647,12 +647,9 @@ static int gve_setup_device_resources(struct gve_priv *priv)
err = gve_alloc_counter_array(priv); err = gve_alloc_counter_array(priv);
if (err) if (err)
goto abort_with_rss_config_cache; goto abort_with_rss_config_cache;
err = gve_init_clock(priv);
if (err)
goto abort_with_counter;
err = gve_alloc_notify_blocks(priv); err = gve_alloc_notify_blocks(priv);
if (err) if (err)
goto abort_with_clock; goto abort_with_counter;
err = gve_alloc_stats_report(priv); err = gve_alloc_stats_report(priv);
if (err) if (err)
goto abort_with_ntfy_blocks; goto abort_with_ntfy_blocks;
@ -683,10 +680,16 @@ static int gve_setup_device_resources(struct gve_priv *priv)
} }
} }
err = gve_init_clock(priv);
if (err) {
dev_err(&priv->pdev->dev, "Failed to init clock");
goto abort_with_ptype_lut;
}
err = gve_init_rss_config(priv, priv->rx_cfg.num_queues); err = gve_init_rss_config(priv, priv->rx_cfg.num_queues);
if (err) { if (err) {
dev_err(&priv->pdev->dev, "Failed to init RSS config"); dev_err(&priv->pdev->dev, "Failed to init RSS config");
goto abort_with_ptype_lut; goto abort_with_clock;
} }
err = gve_adminq_report_stats(priv, priv->stats_report_len, err = gve_adminq_report_stats(priv, priv->stats_report_len,
@ -698,6 +701,8 @@ static int gve_setup_device_resources(struct gve_priv *priv)
gve_set_device_resources_ok(priv); gve_set_device_resources_ok(priv);
return 0; return 0;
abort_with_clock:
gve_teardown_clock(priv);
abort_with_ptype_lut: abort_with_ptype_lut:
kvfree(priv->ptype_lut_dqo); kvfree(priv->ptype_lut_dqo);
priv->ptype_lut_dqo = NULL; priv->ptype_lut_dqo = NULL;
@ -705,8 +710,6 @@ abort_with_stats_report:
gve_free_stats_report(priv); gve_free_stats_report(priv);
abort_with_ntfy_blocks: abort_with_ntfy_blocks:
gve_free_notify_blocks(priv); gve_free_notify_blocks(priv);
abort_with_clock:
gve_teardown_clock(priv);
abort_with_counter: abort_with_counter:
gve_free_counter_array(priv); gve_free_counter_array(priv);
abort_with_rss_config_cache: abort_with_rss_config_cache:

View File

@ -10555,6 +10555,9 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
bool writen_to_tbl = false; bool writen_to_tbl = false;
int ret = 0; int ret = 0;
if (vlan_id >= VLAN_N_VID)
return -EINVAL;
/* When device is resetting or reset failed, firmware is unable to /* When device is resetting or reset failed, firmware is unable to
* handle mailbox. Just record the vlan id, and remove it after * handle mailbox. Just record the vlan id, and remove it after
* reset finished. * reset finished.

View File

@ -193,10 +193,10 @@ static int hclge_get_ring_chain_from_mbx(
return -EINVAL; return -EINVAL;
for (i = 0; i < ring_num; i++) { for (i = 0; i < ring_num; i++) {
if (req->msg.param[i].tqp_index >= vport->nic.kinfo.rss_size) { if (req->msg.param[i].tqp_index >= vport->nic.kinfo.num_tqps) {
dev_err(&hdev->pdev->dev, "tqp index(%u) is out of range(0-%u)\n", dev_err(&hdev->pdev->dev, "tqp index(%u) is out of range(0-%u)\n",
req->msg.param[i].tqp_index, req->msg.param[i].tqp_index,
vport->nic.kinfo.rss_size - 1U); vport->nic.kinfo.num_tqps - 1U);
return -EINVAL; return -EINVAL;
} }
} }

View File

@ -368,12 +368,12 @@ static int hclgevf_knic_setup(struct hclgevf_dev *hdev)
new_tqps = kinfo->rss_size * num_tc; new_tqps = kinfo->rss_size * num_tc;
kinfo->num_tqps = min(new_tqps, hdev->num_tqps); kinfo->num_tqps = min(new_tqps, hdev->num_tqps);
kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, kinfo->num_tqps, kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, hdev->num_tqps,
sizeof(struct hnae3_queue *), GFP_KERNEL); sizeof(struct hnae3_queue *), GFP_KERNEL);
if (!kinfo->tqp) if (!kinfo->tqp)
return -ENOMEM; return -ENOMEM;
for (i = 0; i < kinfo->num_tqps; i++) { for (i = 0; i < hdev->num_tqps; i++) {
hdev->htqp[i].q.handle = &hdev->nic; hdev->htqp[i].q.handle = &hdev->nic;
hdev->htqp[i].q.tqp_index = i; hdev->htqp[i].q.tqp_index = i;
kinfo->tqp[i] = &hdev->htqp[i].q; kinfo->tqp[i] = &hdev->htqp[i].q;

View File

@ -197,6 +197,11 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change,
struct pci_dev *pdev = dev->pdev; struct pci_dev *pdev = dev->pdev;
int ret = 0; int ret = 0;
if (mlx5_fw_reset_in_progress(dev)) {
NL_SET_ERR_MSG_MOD(extack, "Can't reload during firmware reset");
return -EBUSY;
}
if (mlx5_dev_is_lightweight(dev)) { if (mlx5_dev_is_lightweight(dev)) {
if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT) if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT)
return -EOPNOTSUPP; return -EOPNOTSUPP;

View File

@ -33,6 +33,7 @@
#include "lib/eq.h" #include "lib/eq.h"
#include "fw_tracer.h" #include "fw_tracer.h"
#include "fw_tracer_tracepoint.h" #include "fw_tracer_tracepoint.h"
#include <linux/ctype.h>
static int mlx5_query_mtrc_caps(struct mlx5_fw_tracer *tracer) static int mlx5_query_mtrc_caps(struct mlx5_fw_tracer *tracer)
{ {
@ -358,6 +359,47 @@ static const char *VAL_PARM = "%llx";
static const char *REPLACE_64_VAL_PARM = "%x%x"; static const char *REPLACE_64_VAL_PARM = "%x%x";
static const char *PARAM_CHAR = "%"; static const char *PARAM_CHAR = "%";
static bool mlx5_is_valid_spec(const char *str)
{
/* Parse format specifiers to find the actual type.
* Structure: %[flags][width][.precision][length]type
* Skip flags, width, precision & length.
*/
while (isdigit(*str) || *str == '#' || *str == '.' || *str == 'l')
str++;
/* Check if it's a valid integer/hex specifier or %%:
* Valid formats: %x, %d, %i, %u, etc.
*/
if (*str != 'x' && *str != 'X' && *str != 'd' && *str != 'i' &&
*str != 'u' && *str != 'c' && *str != '%')
return false;
return true;
}
static bool mlx5_tracer_validate_params(const char *str)
{
const char *substr = str;
if (!str)
return false;
substr = strstr(substr, PARAM_CHAR);
while (substr) {
if (!mlx5_is_valid_spec(substr + 1))
return false;
if (*(substr + 1) == '%')
substr = strstr(substr + 2, PARAM_CHAR);
else
substr = strstr(substr + 1, PARAM_CHAR);
}
return true;
}
static int mlx5_tracer_message_hash(u32 message_id) static int mlx5_tracer_message_hash(u32 message_id)
{ {
return jhash_1word(message_id, 0) & (MESSAGE_HASH_SIZE - 1); return jhash_1word(message_id, 0) & (MESSAGE_HASH_SIZE - 1);
@ -419,6 +461,10 @@ static int mlx5_tracer_get_num_of_params(char *str)
char *substr, *pstr = str; char *substr, *pstr = str;
int num_of_params = 0; int num_of_params = 0;
/* Validate that all parameters are valid before processing */
if (!mlx5_tracer_validate_params(str))
return -EINVAL;
/* replace %llx with %x%x */ /* replace %llx with %x%x */
substr = strstr(pstr, VAL_PARM); substr = strstr(pstr, VAL_PARM);
while (substr) { while (substr) {
@ -427,11 +473,15 @@ static int mlx5_tracer_get_num_of_params(char *str)
substr = strstr(pstr, VAL_PARM); substr = strstr(pstr, VAL_PARM);
} }
/* count all the % characters */ /* count all the % characters, but skip %% (escaped percent) */
substr = strstr(str, PARAM_CHAR); substr = strstr(str, PARAM_CHAR);
while (substr) { while (substr) {
if (*(substr + 1) != '%') {
num_of_params += 1; num_of_params += 1;
str = substr + 1; str = substr + 1;
} else {
str = substr + 2;
}
substr = strstr(str, PARAM_CHAR); substr = strstr(str, PARAM_CHAR);
} }
@ -570,6 +620,9 @@ void mlx5_tracer_print_trace(struct tracer_string_format *str_frmt,
{ {
char tmp[512]; char tmp[512];
if (str_frmt->invalid_string)
snprintf(tmp, sizeof(tmp), "BAD_FORMAT: %s", str_frmt->string);
else
snprintf(tmp, sizeof(tmp), str_frmt->string, snprintf(tmp, sizeof(tmp), str_frmt->string,
str_frmt->params[0], str_frmt->params[0],
str_frmt->params[1], str_frmt->params[1],
@ -609,6 +662,13 @@ static int mlx5_tracer_handle_raw_string(struct mlx5_fw_tracer *tracer,
return 0; return 0;
} }
static void mlx5_tracer_handle_bad_format_string(struct mlx5_fw_tracer *tracer,
struct tracer_string_format *cur_string)
{
cur_string->invalid_string = true;
list_add_tail(&cur_string->list, &tracer->ready_strings_list);
}
static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer, static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer,
struct tracer_event *tracer_event) struct tracer_event *tracer_event)
{ {
@ -619,12 +679,18 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer,
if (!cur_string) if (!cur_string)
return mlx5_tracer_handle_raw_string(tracer, tracer_event); return mlx5_tracer_handle_raw_string(tracer, tracer_event);
cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string);
cur_string->last_param_num = 0;
cur_string->event_id = tracer_event->event_id; cur_string->event_id = tracer_event->event_id;
cur_string->tmsn = tracer_event->string_event.tmsn; cur_string->tmsn = tracer_event->string_event.tmsn;
cur_string->timestamp = tracer_event->string_event.timestamp; cur_string->timestamp = tracer_event->string_event.timestamp;
cur_string->lost = tracer_event->lost_event; cur_string->lost = tracer_event->lost_event;
cur_string->last_param_num = 0;
cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string);
if (cur_string->num_of_params < 0) {
pr_debug("%s Invalid format string parameters\n",
__func__);
mlx5_tracer_handle_bad_format_string(tracer, cur_string);
return 0;
}
if (cur_string->num_of_params == 0) /* trace with no params */ if (cur_string->num_of_params == 0) /* trace with no params */
list_add_tail(&cur_string->list, &tracer->ready_strings_list); list_add_tail(&cur_string->list, &tracer->ready_strings_list);
} else { } else {
@ -634,6 +700,11 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer,
__func__, tracer_event->string_event.tmsn); __func__, tracer_event->string_event.tmsn);
return mlx5_tracer_handle_raw_string(tracer, tracer_event); return mlx5_tracer_handle_raw_string(tracer, tracer_event);
} }
if (cur_string->num_of_params < 0) {
pr_debug("%s string parameter of invalid string, dumping\n",
__func__);
return 0;
}
cur_string->last_param_num += 1; cur_string->last_param_num += 1;
if (cur_string->last_param_num > TRACER_MAX_PARAMS) { if (cur_string->last_param_num > TRACER_MAX_PARAMS) {
pr_debug("%s Number of params exceeds the max (%d)\n", pr_debug("%s Number of params exceeds the max (%d)\n",

View File

@ -125,6 +125,7 @@ struct tracer_string_format {
struct list_head list; struct list_head list;
u32 timestamp; u32 timestamp;
bool lost; bool lost;
bool invalid_string;
}; };
enum mlx5_fw_tracer_ownership_state { enum mlx5_fw_tracer_ownership_state {

View File

@ -69,7 +69,7 @@ struct page_pool;
#define MLX5E_METADATA_ETHER_TYPE (0x8CE4) #define MLX5E_METADATA_ETHER_TYPE (0x8CE4)
#define MLX5E_METADATA_ETHER_LEN 8 #define MLX5E_METADATA_ETHER_LEN 8
#define MLX5E_ETH_HARD_MTU (ETH_HLEN + PSP_ENCAP_HLEN + PSP_TRL_SIZE + VLAN_HLEN + ETH_FCS_LEN) #define MLX5E_ETH_HARD_MTU (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN)
#define MLX5E_HW2SW_MTU(params, hwmtu) ((hwmtu) - ((params)->hard_mtu)) #define MLX5E_HW2SW_MTU(params, hwmtu) ((hwmtu) - ((params)->hard_mtu))
#define MLX5E_SW2HW_MTU(params, swmtu) ((swmtu) + ((params)->hard_mtu)) #define MLX5E_SW2HW_MTU(params, swmtu) ((swmtu) + ((params)->hard_mtu))

View File

@ -342,9 +342,8 @@ static void mlx5e_ipsec_init_macs(struct mlx5e_ipsec_sa_entry *sa_entry,
rt_dst_entry = &rt->dst; rt_dst_entry = &rt->dst;
break; break;
case AF_INET6: case AF_INET6:
rt_dst_entry = ipv6_stub->ipv6_dst_lookup_flow( if (!IS_ENABLED(CONFIG_IPV6) ||
dev_net(netdev), NULL, &fl6, NULL); ip6_dst_lookup(dev_net(netdev), NULL, &rt_dst_entry, &fl6))
if (IS_ERR(rt_dst_entry))
goto neigh; goto neigh;
break; break;
default: default:
@ -359,6 +358,9 @@ static void mlx5e_ipsec_init_macs(struct mlx5e_ipsec_sa_entry *sa_entry,
neigh_ha_snapshot(addr, n, netdev); neigh_ha_snapshot(addr, n, netdev);
ether_addr_copy(dst, addr); ether_addr_copy(dst, addr);
if (attrs->dir == XFRM_DEV_OFFLOAD_OUT &&
is_zero_ether_addr(addr))
neigh_event_send(n, NULL);
dst_release(rt_dst_entry); dst_release(rt_dst_entry);
neigh_release(n); neigh_release(n);
return; return;

View File

@ -6825,7 +6825,6 @@ static void _mlx5e_remove(struct auxiliary_device *adev)
* is already unregistered before changing to NIC profile. * is already unregistered before changing to NIC profile.
*/ */
if (priv->netdev->reg_state == NETREG_REGISTERED) { if (priv->netdev->reg_state == NETREG_REGISTERED) {
mlx5e_psp_unregister(priv);
unregister_netdev(priv->netdev); unregister_netdev(priv->netdev);
_mlx5e_suspend(adev, false); _mlx5e_suspend(adev, false);
} else { } else {

View File

@ -939,6 +939,10 @@ void mlx5e_free_txqsq_descs(struct mlx5e_txqsq *sq)
sq->dma_fifo_cc = dma_fifo_cc; sq->dma_fifo_cc = dma_fifo_cc;
sq->cc = sqcc; sq->cc = sqcc;
/* Do not update BQL for TXQs that got replaced by new active ones, as
* netdev_tx_reset_queue() is called for them in mlx5e_activate_txqsq().
*/
if (sq == sq->priv->txq2sq[sq->txq_ix])
netdev_tx_completed_queue(sq->txq, npkts, nbytes); netdev_tx_completed_queue(sq->txq, npkts, nbytes);
} }

View File

@ -52,6 +52,7 @@
#include "devlink.h" #include "devlink.h"
#include "lag/lag.h" #include "lag/lag.h"
#include "en/tc/post_meter.h" #include "en/tc/post_meter.h"
#include "fw_reset.h"
/* There are two match-all miss flows, one for unicast dst mac and /* There are two match-all miss flows, one for unicast dst mac and
* one for multicast. * one for multicast.
@ -3991,6 +3992,11 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
if (IS_ERR(esw)) if (IS_ERR(esw))
return PTR_ERR(esw); return PTR_ERR(esw);
if (mlx5_fw_reset_in_progress(esw->dev)) {
NL_SET_ERR_MSG_MOD(extack, "Can't change eswitch mode during firmware reset");
return -EBUSY;
}
if (esw_mode_from_devlink(mode, &mlx5_mode)) if (esw_mode_from_devlink(mode, &mlx5_mode))
return -EINVAL; return -EINVAL;

View File

@ -15,6 +15,7 @@ enum {
MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS, MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS,
MLX5_FW_RESET_FLAGS_RELOAD_REQUIRED, MLX5_FW_RESET_FLAGS_RELOAD_REQUIRED,
MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, MLX5_FW_RESET_FLAGS_UNLOAD_EVENT,
MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS,
}; };
struct mlx5_fw_reset { struct mlx5_fw_reset {
@ -128,6 +129,16 @@ int mlx5_fw_reset_query(struct mlx5_core_dev *dev, u8 *reset_level, u8 *reset_ty
return mlx5_reg_mfrl_query(dev, reset_level, reset_type, NULL, NULL); return mlx5_reg_mfrl_query(dev, reset_level, reset_type, NULL, NULL);
} }
bool mlx5_fw_reset_in_progress(struct mlx5_core_dev *dev)
{
struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
if (!fw_reset)
return false;
return test_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags);
}
static int mlx5_fw_reset_get_reset_method(struct mlx5_core_dev *dev, static int mlx5_fw_reset_get_reset_method(struct mlx5_core_dev *dev,
u8 *reset_method) u8 *reset_method)
{ {
@ -243,6 +254,8 @@ static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev)
BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE)); BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE));
devl_unlock(devlink); devl_unlock(devlink);
} }
clear_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags);
} }
static void mlx5_stop_sync_reset_poll(struct mlx5_core_dev *dev) static void mlx5_stop_sync_reset_poll(struct mlx5_core_dev *dev)
@ -462,27 +475,48 @@ static void mlx5_sync_reset_request_event(struct work_struct *work)
struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset, struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset,
reset_request_work); reset_request_work);
struct mlx5_core_dev *dev = fw_reset->dev; struct mlx5_core_dev *dev = fw_reset->dev;
bool nack_request = false;
struct devlink *devlink;
int err; int err;
err = mlx5_fw_reset_get_reset_method(dev, &fw_reset->reset_method); err = mlx5_fw_reset_get_reset_method(dev, &fw_reset->reset_method);
if (err) if (err) {
nack_request = true;
mlx5_core_warn(dev, "Failed reading MFRL, err %d\n", err); mlx5_core_warn(dev, "Failed reading MFRL, err %d\n", err);
} else if (!mlx5_is_reset_now_capable(dev, fw_reset->reset_method) ||
test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST,
&fw_reset->reset_flags)) {
nack_request = true;
}
if (err || test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, &fw_reset->reset_flags) || devlink = priv_to_devlink(dev);
!mlx5_is_reset_now_capable(dev, fw_reset->reset_method)) { /* For external resets, try to acquire devl_lock. Skip if devlink reset is
* pending (lock already held)
*/
if (nack_request ||
(!test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP,
&fw_reset->reset_flags) &&
!devl_trylock(devlink))) {
err = mlx5_fw_reset_set_reset_sync_nack(dev); err = mlx5_fw_reset_set_reset_sync_nack(dev);
mlx5_core_warn(dev, "PCI Sync FW Update Reset Nack %s", mlx5_core_warn(dev, "PCI Sync FW Update Reset Nack %s",
err ? "Failed" : "Sent"); err ? "Failed" : "Sent");
return; return;
} }
if (mlx5_sync_reset_set_reset_requested(dev)) if (mlx5_sync_reset_set_reset_requested(dev))
return; goto unlock;
set_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags);
err = mlx5_fw_reset_set_reset_sync_ack(dev); err = mlx5_fw_reset_set_reset_sync_ack(dev);
if (err) if (err)
mlx5_core_warn(dev, "PCI Sync FW Update Reset Ack Failed. Error code: %d\n", err); mlx5_core_warn(dev, "PCI Sync FW Update Reset Ack Failed. Error code: %d\n", err);
else else
mlx5_core_warn(dev, "PCI Sync FW Update Reset Ack. Device reset is expected.\n"); mlx5_core_warn(dev, "PCI Sync FW Update Reset Ack. Device reset is expected.\n");
unlock:
if (!test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags))
devl_unlock(devlink);
} }
static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev, u16 dev_id) static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev, u16 dev_id)
@ -722,6 +756,8 @@ static void mlx5_sync_reset_abort_event(struct work_struct *work)
if (mlx5_sync_reset_clear_reset_requested(dev, true)) if (mlx5_sync_reset_clear_reset_requested(dev, true))
return; return;
clear_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags);
mlx5_core_warn(dev, "PCI Sync FW Update Reset Aborted.\n"); mlx5_core_warn(dev, "PCI Sync FW Update Reset Aborted.\n");
} }
@ -758,6 +794,7 @@ static void mlx5_sync_reset_timeout_work(struct work_struct *work)
if (mlx5_sync_reset_clear_reset_requested(dev, true)) if (mlx5_sync_reset_clear_reset_requested(dev, true))
return; return;
clear_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags);
mlx5_core_warn(dev, "PCI Sync FW Update Reset Timeout.\n"); mlx5_core_warn(dev, "PCI Sync FW Update Reset Timeout.\n");
} }
@ -844,7 +881,8 @@ void mlx5_drain_fw_reset(struct mlx5_core_dev *dev)
cancel_work_sync(&fw_reset->reset_reload_work); cancel_work_sync(&fw_reset->reset_reload_work);
cancel_work_sync(&fw_reset->reset_now_work); cancel_work_sync(&fw_reset->reset_now_work);
cancel_work_sync(&fw_reset->reset_abort_work); cancel_work_sync(&fw_reset->reset_abort_work);
cancel_delayed_work(&fw_reset->reset_timeout_work); if (test_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags))
mlx5_sync_reset_clear_reset_requested(dev, true);
} }
static const struct devlink_param mlx5_fw_reset_devlink_params[] = { static const struct devlink_param mlx5_fw_reset_devlink_params[] = {

View File

@ -10,6 +10,7 @@ int mlx5_fw_reset_query(struct mlx5_core_dev *dev, u8 *reset_level, u8 *reset_ty
int mlx5_fw_reset_set_reset_sync(struct mlx5_core_dev *dev, u8 reset_type_sel, int mlx5_fw_reset_set_reset_sync(struct mlx5_core_dev *dev, u8 reset_type_sel,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev); int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev);
bool mlx5_fw_reset_in_progress(struct mlx5_core_dev *dev);
int mlx5_fw_reset_wait_reset_done(struct mlx5_core_dev *dev); int mlx5_fw_reset_wait_reset_done(struct mlx5_core_dev *dev);
void mlx5_sync_reset_unload_flow(struct mlx5_core_dev *dev, bool locked); void mlx5_sync_reset_unload_flow(struct mlx5_core_dev *dev, bool locked);

View File

@ -1413,6 +1413,7 @@ static int __mlx5_lag_dev_add_mdev(struct mlx5_core_dev *dev)
static void mlx5_lag_unregister_hca_devcom_comp(struct mlx5_core_dev *dev) static void mlx5_lag_unregister_hca_devcom_comp(struct mlx5_core_dev *dev)
{ {
mlx5_devcom_unregister_component(dev->priv.hca_devcom_comp); mlx5_devcom_unregister_component(dev->priv.hca_devcom_comp);
dev->priv.hca_devcom_comp = NULL;
} }
static int mlx5_lag_register_hca_devcom_comp(struct mlx5_core_dev *dev) static int mlx5_lag_register_hca_devcom_comp(struct mlx5_core_dev *dev)

View File

@ -67,12 +67,19 @@ err_metadata:
static int enable_mpesw(struct mlx5_lag *ldev) static int enable_mpesw(struct mlx5_lag *ldev)
{ {
int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
struct mlx5_core_dev *dev0; struct mlx5_core_dev *dev0;
int err; int err;
int idx;
int i; int i;
if (idx < 0 || ldev->mode != MLX5_LAG_MODE_NONE) if (ldev->mode == MLX5_LAG_MODE_MPESW)
return 0;
if (ldev->mode != MLX5_LAG_MODE_NONE)
return -EINVAL;
idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
if (idx < 0)
return -EINVAL; return -EINVAL;
dev0 = ldev->pf[idx].dev; dev0 = ldev->pf[idx].dev;

View File

@ -2231,6 +2231,7 @@ static void shutdown(struct pci_dev *pdev)
mlx5_core_info(dev, "Shutdown was called\n"); mlx5_core_info(dev, "Shutdown was called\n");
set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state); set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state);
mlx5_drain_fw_reset(dev);
mlx5_drain_health_wq(dev); mlx5_drain_health_wq(dev);
err = mlx5_try_fast_unload(dev); err = mlx5_try_fast_unload(dev);
if (err) if (err)

View File

@ -440,7 +440,9 @@ int mlxsw_sp_mr_route_add(struct mlxsw_sp_mr_table *mr_table,
rhashtable_remove_fast(&mr_table->route_ht, rhashtable_remove_fast(&mr_table->route_ht,
&mr_orig_route->ht_node, &mr_orig_route->ht_node,
mlxsw_sp_mr_route_ht_params); mlxsw_sp_mr_route_ht_params);
mutex_lock(&mr_table->route_list_lock);
list_del(&mr_orig_route->node); list_del(&mr_orig_route->node);
mutex_unlock(&mr_table->route_list_lock);
mlxsw_sp_mr_route_destroy(mr_table, mr_orig_route); mlxsw_sp_mr_route_destroy(mr_table, mr_orig_route);
} }

View File

@ -2265,6 +2265,7 @@ mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n,
if (!neigh_entry) if (!neigh_entry)
return NULL; return NULL;
neigh_hold(n);
neigh_entry->key.n = n; neigh_entry->key.n = n;
neigh_entry->rif = rif; neigh_entry->rif = rif;
INIT_LIST_HEAD(&neigh_entry->nexthop_list); INIT_LIST_HEAD(&neigh_entry->nexthop_list);
@ -2274,6 +2275,7 @@ mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n,
static void mlxsw_sp_neigh_entry_free(struct mlxsw_sp_neigh_entry *neigh_entry) static void mlxsw_sp_neigh_entry_free(struct mlxsw_sp_neigh_entry *neigh_entry)
{ {
neigh_release(neigh_entry->key.n);
kfree(neigh_entry); kfree(neigh_entry);
} }
@ -2858,6 +2860,11 @@ static int mlxsw_sp_router_schedule_work(struct net *net,
if (!net_work) if (!net_work)
return NOTIFY_BAD; return NOTIFY_BAD;
/* Take a reference to ensure the neighbour won't be destructed until
* we drop the reference in the work item.
*/
neigh_clone(n);
INIT_WORK(&net_work->work, cb); INIT_WORK(&net_work->work, cb);
net_work->mlxsw_sp = router->mlxsw_sp; net_work->mlxsw_sp = router->mlxsw_sp;
net_work->n = n; net_work->n = n;
@ -2881,11 +2888,6 @@ static int mlxsw_sp_router_schedule_neigh_work(struct mlxsw_sp_router *router,
struct net *net; struct net *net;
net = neigh_parms_net(n->parms); net = neigh_parms_net(n->parms);
/* Take a reference to ensure the neighbour won't be destructed until we
* drop the reference in delayed work.
*/
neigh_clone(n);
return mlxsw_sp_router_schedule_work(net, router, n, return mlxsw_sp_router_schedule_work(net, router, n,
mlxsw_sp_router_neigh_event_work); mlxsw_sp_router_neigh_event_work);
} }
@ -4320,6 +4322,8 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp,
if (err) if (err)
goto err_neigh_entry_insert; goto err_neigh_entry_insert;
neigh_release(old_n);
read_lock_bh(&n->lock); read_lock_bh(&n->lock);
nud_state = n->nud_state; nud_state = n->nud_state;
dead = n->dead; dead = n->dead;
@ -4328,14 +4332,10 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp,
list_for_each_entry(nh, &neigh_entry->nexthop_list, list_for_each_entry(nh, &neigh_entry->nexthop_list,
neigh_list_node) { neigh_list_node) {
neigh_release(old_n);
neigh_clone(n);
__mlxsw_sp_nexthop_neigh_update(nh, !entry_connected); __mlxsw_sp_nexthop_neigh_update(nh, !entry_connected);
mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp); mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp);
} }
neigh_release(n);
return 0; return 0;
err_neigh_entry_insert: err_neigh_entry_insert:
@ -4428,6 +4428,11 @@ static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp,
} }
} }
/* Release the reference taken by neigh_lookup() / neigh_create() since
* neigh_entry already holds one.
*/
neigh_release(n);
/* If that is the first nexthop connected to that neigh, add to /* If that is the first nexthop connected to that neigh, add to
* nexthop_neighs_list * nexthop_neighs_list
*/ */
@ -4454,11 +4459,9 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_nexthop *nh) struct mlxsw_sp_nexthop *nh)
{ {
struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry; struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry;
struct neighbour *n;
if (!neigh_entry) if (!neigh_entry)
return; return;
n = neigh_entry->key.n;
__mlxsw_sp_nexthop_neigh_update(nh, true); __mlxsw_sp_nexthop_neigh_update(nh, true);
list_del(&nh->neigh_list_node); list_del(&nh->neigh_list_node);
@ -4472,8 +4475,6 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp,
if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list)) if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list))
mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry); mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry);
neigh_release(n);
} }
static bool mlxsw_sp_ipip_netdev_ul_up(struct net_device *ol_dev) static bool mlxsw_sp_ipip_netdev_ul_up(struct net_device *ol_dev)

View File

@ -2655,9 +2655,6 @@ static void rtl_wol_enable_rx(struct rtl8169_private *tp)
static void rtl_prepare_power_down(struct rtl8169_private *tp) static void rtl_prepare_power_down(struct rtl8169_private *tp)
{ {
if (tp->dash_enabled)
return;
if (tp->mac_version == RTL_GIGA_MAC_VER_32 || if (tp->mac_version == RTL_GIGA_MAC_VER_32 ||
tp->mac_version == RTL_GIGA_MAC_VER_33) tp->mac_version == RTL_GIGA_MAC_VER_33)
rtl_ephy_write(tp, 0x19, 0xff64); rtl_ephy_write(tp, 0x19, 0xff64);
@ -4812,7 +4809,7 @@ static void rtl8169_down(struct rtl8169_private *tp)
rtl_disable_exit_l1(tp); rtl_disable_exit_l1(tp);
rtl_prepare_power_down(tp); rtl_prepare_power_down(tp);
if (tp->dash_type != RTL_DASH_NONE) if (tp->dash_type != RTL_DASH_NONE && !tp->saved_wolopts)
rtl8168_driver_stop(tp); rtl8168_driver_stop(tp);
} }

View File

@ -209,6 +209,7 @@ config TI_ICSSG_PRUETH_SR1
depends on PRU_REMOTEPROC depends on PRU_REMOTEPROC
depends on NET_SWITCHDEV depends on NET_SWITCHDEV
depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER
depends on PTP_1588_CLOCK_OPTIONAL
help help
Support dual Gigabit Ethernet ports over the ICSSG PRU Subsystem. Support dual Gigabit Ethernet ports over the ICSSG PRU Subsystem.
This subsystem is available on the AM65 SR1.0 platform. This subsystem is available on the AM65 SR1.0 platform.
@ -234,7 +235,7 @@ config TI_PRUETH
depends on PRU_REMOTEPROC depends on PRU_REMOTEPROC
depends on NET_SWITCHDEV depends on NET_SWITCHDEV
select TI_ICSS_IEP select TI_ICSS_IEP
imply PTP_1588_CLOCK depends on PTP_1588_CLOCK_OPTIONAL
help help
Some TI SoCs has Programmable Realtime Unit (PRU) cores which can Some TI SoCs has Programmable Realtime Unit (PRU) cores which can
support Single or Dual Ethernet ports with the help of firmware code support Single or Dual Ethernet ports with the help of firmware code

View File

@ -737,6 +737,9 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb,
struct ethhdr *eth = eth_hdr(skb); struct ethhdr *eth = eth_hdr(skb);
rx_handler_result_t ret = RX_HANDLER_PASS; rx_handler_result_t ret = RX_HANDLER_PASS;
if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
return RX_HANDLER_PASS;
if (is_multicast_ether_addr(eth->h_dest)) { if (is_multicast_ether_addr(eth->h_dest)) {
if (ipvlan_external_frame(skb, port)) { if (ipvlan_external_frame(skb, port)) {
struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);

View File

@ -698,7 +698,7 @@ static int mv88q2xxx_hwmon_write(struct device *dev,
switch (attr) { switch (attr) {
case hwmon_temp_max: case hwmon_temp_max:
clamp_val(val, -75000, 180000); val = clamp(val, -75000, 180000);
val = (val / 1000) + 75; val = (val / 1000) + 75;
val = FIELD_PREP(MDIO_MMD_PCS_MV_TEMP_SENSOR3_INT_THRESH_MASK, val = FIELD_PREP(MDIO_MMD_PCS_MV_TEMP_SENSOR3_INT_THRESH_MASK,
val); val);

View File

@ -691,10 +691,6 @@ static int rtl8211f_config_aldps(struct phy_device *phydev)
static int rtl8211f_config_phy_eee(struct phy_device *phydev) static int rtl8211f_config_phy_eee(struct phy_device *phydev)
{ {
/* RTL8211FVD has no PHYCR2 register */
if (phydev->drv->phy_id == RTL_8211FVD_PHYID)
return 0;
/* Disable PHY-mode EEE so LPI is passed to the MAC */ /* Disable PHY-mode EEE so LPI is passed to the MAC */
return phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2, return phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2,
RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0); RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0);

View File

@ -497,6 +497,8 @@ static const struct sfp_quirk sfp_quirks[] = {
SFP_QUIRK("ALCATELLUCENT", "3FE46541AA", sfp_quirk_2500basex, SFP_QUIRK("ALCATELLUCENT", "3FE46541AA", sfp_quirk_2500basex,
sfp_fixup_nokia), sfp_fixup_nokia),
SFP_QUIRK_F("BIDB", "X-ONU-SFPP", sfp_fixup_potron),
// FLYPRO SFP-10GT-CS-30M uses Rollball protocol to talk to the PHY. // FLYPRO SFP-10GT-CS-30M uses Rollball protocol to talk to the PHY.
SFP_QUIRK_F("FLYPRO", "SFP-10GT-CS-30M", sfp_fixup_rollball), SFP_QUIRK_F("FLYPRO", "SFP-10GT-CS-30M", sfp_fixup_rollball),

View File

@ -406,7 +406,7 @@ static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy)
if (rc || (transferred != sizeof(cmd))) { if (rc || (transferred != sizeof(cmd))) {
nfc_err(&phy->udev->dev, nfc_err(&phy->udev->dev,
"Reader power on cmd error %d\n", rc); "Reader power on cmd error %d\n", rc);
return rc; return rc ?: -EINVAL;
} }
rc = usb_submit_urb(phy->in_urb, GFP_KERNEL); rc = usb_submit_urb(phy->in_urb, GFP_KERNEL);

View File

@ -123,26 +123,14 @@ void inet_frags_fini(struct inet_frags *);
int fqdir_init(struct fqdir **fqdirp, struct inet_frags *f, struct net *net); int fqdir_init(struct fqdir **fqdirp, struct inet_frags *f, struct net *net);
static inline void fqdir_pre_exit(struct fqdir *fqdir) void fqdir_pre_exit(struct fqdir *fqdir);
{
/* Prevent creation of new frags.
* Pairs with READ_ONCE() in inet_frag_find().
*/
WRITE_ONCE(fqdir->high_thresh, 0);
/* Pairs with READ_ONCE() in inet_frag_kill(), ip_expire()
* and ip6frag_expire_frag_queue().
*/
WRITE_ONCE(fqdir->dead, true);
}
void fqdir_exit(struct fqdir *fqdir); void fqdir_exit(struct fqdir *fqdir);
void inet_frag_kill(struct inet_frag_queue *q, int *refs); void inet_frag_kill(struct inet_frag_queue *q, int *refs);
void inet_frag_destroy(struct inet_frag_queue *q); void inet_frag_destroy(struct inet_frag_queue *q);
struct inet_frag_queue *inet_frag_find(struct fqdir *fqdir, void *key); struct inet_frag_queue *inet_frag_find(struct fqdir *fqdir, void *key);
/* Free all skbs in the queue; return the sum of their truesizes. */ void inet_frag_queue_flush(struct inet_frag_queue *q,
unsigned int inet_frag_rbtree_purge(struct rb_root *root,
enum skb_drop_reason reason); enum skb_drop_reason reason);
static inline void inet_frag_putn(struct inet_frag_queue *q, int refs) static inline void inet_frag_putn(struct inet_frag_queue *q, int refs)

View File

@ -69,9 +69,6 @@ ip6frag_expire_frag_queue(struct net *net, struct frag_queue *fq)
int refs = 1; int refs = 1;
rcu_read_lock(); rcu_read_lock();
/* Paired with the WRITE_ONCE() in fqdir_pre_exit(). */
if (READ_ONCE(fq->q.fqdir->dead))
goto out_rcu_unlock;
spin_lock(&fq->q.lock); spin_lock(&fq->q.lock);
if (fq->q.flags & INET_FRAG_COMPLETE) if (fq->q.flags & INET_FRAG_COMPLETE)
@ -80,6 +77,12 @@ ip6frag_expire_frag_queue(struct net *net, struct frag_queue *fq)
fq->q.flags |= INET_FRAG_DROP; fq->q.flags |= INET_FRAG_DROP;
inet_frag_kill(&fq->q, &refs); inet_frag_kill(&fq->q, &refs);
/* Paired with the WRITE_ONCE() in fqdir_pre_exit(). */
if (READ_ONCE(fq->q.fqdir->dead)) {
inet_frag_queue_flush(&fq->q, 0);
goto out;
}
dev = dev_get_by_index_rcu(net, fq->iif); dev = dev_get_by_index_rcu(net, fq->iif);
if (!dev) if (!dev)
goto out; goto out;

View File

@ -1091,6 +1091,29 @@ struct nft_rule_blob {
__attribute__((aligned(__alignof__(struct nft_rule_dp)))); __attribute__((aligned(__alignof__(struct nft_rule_dp))));
}; };
enum nft_chain_types {
NFT_CHAIN_T_DEFAULT = 0,
NFT_CHAIN_T_ROUTE,
NFT_CHAIN_T_NAT,
NFT_CHAIN_T_MAX
};
/**
* struct nft_chain_validate_state - validation state
*
* If a chain is encountered again during table validation it is
* possible to avoid revalidation provided the calling context is
* compatible. This structure stores relevant calling context of
* previous validations.
*
* @hook_mask: the hook numbers and locations the chain is linked to
* @depth: the deepest call chain level the chain is linked to
*/
struct nft_chain_validate_state {
u8 hook_mask[NFT_CHAIN_T_MAX];
u8 depth;
};
/** /**
* struct nft_chain - nf_tables chain * struct nft_chain - nf_tables chain
* *
@ -1109,6 +1132,7 @@ struct nft_rule_blob {
* @udlen: user data length * @udlen: user data length
* @udata: user data in the chain * @udata: user data in the chain
* @blob_next: rule blob pointer to the next in the chain * @blob_next: rule blob pointer to the next in the chain
* @vstate: validation state
*/ */
struct nft_chain { struct nft_chain {
struct nft_rule_blob __rcu *blob_gen_0; struct nft_rule_blob __rcu *blob_gen_0;
@ -1128,9 +1152,10 @@ struct nft_chain {
/* Only used during control plane commit phase: */ /* Only used during control plane commit phase: */
struct nft_rule_blob *blob_next; struct nft_rule_blob *blob_next;
struct nft_chain_validate_state vstate;
}; };
int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain); int nft_chain_validate(const struct nft_ctx *ctx, struct nft_chain *chain);
int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set, int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
const struct nft_set_iter *iter, const struct nft_set_iter *iter,
struct nft_elem_priv *elem_priv); struct nft_elem_priv *elem_priv);
@ -1138,13 +1163,6 @@ int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set);
int nf_tables_bind_chain(const struct nft_ctx *ctx, struct nft_chain *chain); int nf_tables_bind_chain(const struct nft_ctx *ctx, struct nft_chain *chain);
void nf_tables_unbind_chain(const struct nft_ctx *ctx, struct nft_chain *chain); void nf_tables_unbind_chain(const struct nft_ctx *ctx, struct nft_chain *chain);
enum nft_chain_types {
NFT_CHAIN_T_DEFAULT = 0,
NFT_CHAIN_T_ROUTE,
NFT_CHAIN_T_NAT,
NFT_CHAIN_T_MAX
};
/** /**
* struct nft_chain_type - nf_tables chain type info * struct nft_chain_type - nf_tables chain type info
* *

View File

@ -2,6 +2,7 @@
/* Do not edit directly, auto-generated from: */ /* Do not edit directly, auto-generated from: */
/* Documentation/netlink/specs/em.yaml */ /* Documentation/netlink/specs/em.yaml */
/* YNL-GEN uapi header */ /* YNL-GEN uapi header */
/* To regenerate run: tools/net/ynl/ynl-regen.sh */
#ifndef _UAPI_LINUX_ENERGY_MODEL_H #ifndef _UAPI_LINUX_ENERGY_MODEL_H
#define _UAPI_LINUX_ENERGY_MODEL_H #define _UAPI_LINUX_ENERGY_MODEL_H

View File

@ -40,6 +40,7 @@
#define MPTCP_PM_ADDR_FLAG_FULLMESH _BITUL(3) #define MPTCP_PM_ADDR_FLAG_FULLMESH _BITUL(3)
#define MPTCP_PM_ADDR_FLAG_IMPLICIT _BITUL(4) #define MPTCP_PM_ADDR_FLAG_IMPLICIT _BITUL(4)
#define MPTCP_PM_ADDR_FLAG_LAMINAR _BITUL(5) #define MPTCP_PM_ADDR_FLAG_LAMINAR _BITUL(5)
#define MPTCP_PM_ADDR_FLAGS_MASK GENMASK(5, 0)
struct mptcp_info { struct mptcp_info {
__u8 mptcpi_subflows; __u8 mptcpi_subflows;

View File

@ -2,6 +2,7 @@
/* Do not edit directly, auto-generated from: */ /* Do not edit directly, auto-generated from: */
/* Documentation/netlink/specs/em.yaml */ /* Documentation/netlink/specs/em.yaml */
/* YNL-GEN kernel source */ /* YNL-GEN kernel source */
/* To regenerate run: tools/net/ynl/ynl-regen.sh */
#include <net/netlink.h> #include <net/netlink.h>
#include <net/genetlink.h> #include <net/genetlink.h>

View File

@ -2,6 +2,7 @@
/* Do not edit directly, auto-generated from: */ /* Do not edit directly, auto-generated from: */
/* Documentation/netlink/specs/em.yaml */ /* Documentation/netlink/specs/em.yaml */
/* YNL-GEN kernel header */ /* YNL-GEN kernel header */
/* To regenerate run: tools/net/ynl/ynl-regen.sh */
#ifndef _LINUX_EM_GEN_H #ifndef _LINUX_EM_GEN_H
#define _LINUX_EM_GEN_H #define _LINUX_EM_GEN_H

View File

@ -92,8 +92,15 @@ static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt)
len = le16_to_cpu(tmp); len = le16_to_cpu(tmp);
/* Subtract for FCS on length if FCS is not used. */ /* Subtract for FCS on length if FCS is not used. */
if (!this->dofcs) if (!this->dofcs) {
if (len < 2) {
++cffrml_rcv_error;
pr_err("Invalid frame length (%d)\n", len);
cfpkt_destroy(pkt);
return -EPROTO;
}
len -= 2; len -= 2;
}
if (cfpkt_setlen(pkt, len) < 0) { if (cfpkt_setlen(pkt, len) < 0) {
++cffrml_rcv_error; ++cffrml_rcv_error;

View File

@ -5,7 +5,6 @@
menuconfig CAN menuconfig CAN
tristate "CAN bus subsystem support" tristate "CAN bus subsystem support"
select CAN_DEV
help help
Controller Area Network (CAN) is a slow (up to 1Mbit/s) serial Controller Area Network (CAN) is a slow (up to 1Mbit/s) serial
communications protocol. Development of the CAN bus started in communications protocol. Development of the CAN bus started in

View File

@ -482,6 +482,12 @@ static int j1939_sk_bind(struct socket *sock, struct sockaddr_unsized *uaddr, in
goto out_release_sock; goto out_release_sock;
} }
if (ndev->reg_state != NETREG_REGISTERED) {
dev_put(ndev);
ret = -ENODEV;
goto out_release_sock;
}
can_ml = can_get_ml_priv(ndev); can_ml = can_get_ml_priv(ndev);
if (!can_ml) { if (!can_ml) {
dev_put(ndev); dev_put(ndev);

View File

@ -1567,6 +1567,8 @@ int j1939_session_activate(struct j1939_session *session)
if (active) { if (active) {
j1939_session_put(active); j1939_session_put(active);
ret = -EAGAIN; ret = -EAGAIN;
} else if (priv->ndev->reg_state != NETREG_REGISTERED) {
ret = -ENODEV;
} else { } else {
WARN_ON_ONCE(session->state != J1939_SESSION_NEW); WARN_ON_ONCE(session->state != J1939_SESSION_NEW);
list_add_tail(&session->active_session_list_entry, list_add_tail(&session->active_session_list_entry,

View File

@ -2383,6 +2383,9 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr)
return -ENOMEM; return -ENOMEM;
WARN_ON_ONCE(!ret); WARN_ON_ONCE(!ret);
if (gstrings.len && gstrings.len != ret)
gstrings.len = 0;
else
gstrings.len = ret; gstrings.len = ret;
if (gstrings.len) { if (gstrings.len) {
@ -2509,10 +2512,13 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
if (copy_from_user(&stats, useraddr, sizeof(stats))) if (copy_from_user(&stats, useraddr, sizeof(stats)))
return -EFAULT; return -EFAULT;
if (stats.n_stats && stats.n_stats != n_stats)
stats.n_stats = 0;
else
stats.n_stats = n_stats; stats.n_stats = n_stats;
if (n_stats) { if (stats.n_stats) {
data = vzalloc(array_size(n_stats, sizeof(u64))); data = vzalloc(array_size(stats.n_stats, sizeof(u64)));
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
ops->get_ethtool_stats(dev, &stats, data); ops->get_ethtool_stats(dev, &stats, data);
@ -2524,7 +2530,9 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
if (copy_to_user(useraddr, &stats, sizeof(stats))) if (copy_to_user(useraddr, &stats, sizeof(stats)))
goto out; goto out;
useraddr += sizeof(stats); useraddr += sizeof(stats);
if (n_stats && copy_to_user(useraddr, data, array_size(n_stats, sizeof(u64)))) if (stats.n_stats &&
copy_to_user(useraddr, data,
array_size(stats.n_stats, sizeof(u64))))
goto out; goto out;
ret = 0; ret = 0;
@ -2560,6 +2568,10 @@ static int ethtool_get_phy_stats_phydev(struct phy_device *phydev,
return -EOPNOTSUPP; return -EOPNOTSUPP;
n_stats = phy_ops->get_sset_count(phydev); n_stats = phy_ops->get_sset_count(phydev);
if (stats->n_stats && stats->n_stats != n_stats) {
stats->n_stats = 0;
return 0;
}
ret = ethtool_vzalloc_stats_array(n_stats, data); ret = ethtool_vzalloc_stats_array(n_stats, data);
if (ret) if (ret)
@ -2580,6 +2592,10 @@ static int ethtool_get_phy_stats_ethtool(struct net_device *dev,
return -EOPNOTSUPP; return -EOPNOTSUPP;
n_stats = ops->get_sset_count(dev, ETH_SS_PHY_STATS); n_stats = ops->get_sset_count(dev, ETH_SS_PHY_STATS);
if (stats->n_stats && stats->n_stats != n_stats) {
stats->n_stats = 0;
return 0;
}
ret = ethtool_vzalloc_stats_array(n_stats, data); ret = ethtool_vzalloc_stats_array(n_stats, data);
if (ret) if (ret)
@ -2616,7 +2632,9 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr)
} }
useraddr += sizeof(stats); useraddr += sizeof(stats);
if (copy_to_user(useraddr, data, array_size(stats.n_stats, sizeof(u64)))) if (stats.n_stats &&
copy_to_user(useraddr, data,
array_size(stats.n_stats, sizeof(u64))))
ret = -EFAULT; ret = -EFAULT;
out: out:

View File

@ -276,6 +276,8 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
out_unlock: out_unlock:
spin_unlock(&hn->hn_lock); spin_unlock(&hn->hn_lock);
out_err: out_err:
/* Restore original destructor so socket teardown still runs on failure */
req->hr_sk->sk_destruct = req->hr_odestruct;
trace_handshake_submit_err(net, req, req->hr_sk, ret); trace_handshake_submit_err(net, req, req->hr_sk, ret);
handshake_req_destroy(req); handshake_req_destroy(req);
return ret; return ret;
@ -324,7 +326,11 @@ bool handshake_req_cancel(struct sock *sk)
hn = handshake_pernet(net); hn = handshake_pernet(net);
if (hn && remove_pending(hn, req)) { if (hn && remove_pending(hn, req)) {
/* Request hadn't been accepted */ /* Request hadn't been accepted - mark cancelled */
if (test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED, &req->hr_flags)) {
trace_handshake_cancel_busy(net, req, sk);
return false;
}
goto out_true; goto out_true;
} }
if (test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED, &req->hr_flags)) { if (test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED, &req->hr_flags)) {

View File

@ -205,6 +205,8 @@ struct sk_buff *prp_get_untagged_frame(struct hsr_frame_info *frame,
__pskb_copy(frame->skb_prp, __pskb_copy(frame->skb_prp,
skb_headroom(frame->skb_prp), skb_headroom(frame->skb_prp),
GFP_ATOMIC); GFP_ATOMIC);
if (!frame->skb_std)
return NULL;
} else { } else {
/* Unexpected */ /* Unexpected */
WARN_ONCE(1, "%s:%d: Unexpected frame received (port_src %s)\n", WARN_ONCE(1, "%s:%d: Unexpected frame received (port_src %s)\n",

View File

@ -218,6 +218,41 @@ static int __init inet_frag_wq_init(void)
pure_initcall(inet_frag_wq_init); pure_initcall(inet_frag_wq_init);
void fqdir_pre_exit(struct fqdir *fqdir)
{
struct inet_frag_queue *fq;
struct rhashtable_iter hti;
/* Prevent creation of new frags.
* Pairs with READ_ONCE() in inet_frag_find().
*/
WRITE_ONCE(fqdir->high_thresh, 0);
/* Pairs with READ_ONCE() in inet_frag_kill(), ip_expire()
* and ip6frag_expire_frag_queue().
*/
WRITE_ONCE(fqdir->dead, true);
rhashtable_walk_enter(&fqdir->rhashtable, &hti);
rhashtable_walk_start(&hti);
while ((fq = rhashtable_walk_next(&hti))) {
if (IS_ERR(fq)) {
if (PTR_ERR(fq) != -EAGAIN)
break;
continue;
}
spin_lock_bh(&fq->lock);
if (!(fq->flags & INET_FRAG_COMPLETE))
inet_frag_queue_flush(fq, 0);
spin_unlock_bh(&fq->lock);
}
rhashtable_walk_stop(&hti);
rhashtable_walk_exit(&hti);
}
EXPORT_SYMBOL(fqdir_pre_exit);
void fqdir_exit(struct fqdir *fqdir) void fqdir_exit(struct fqdir *fqdir)
{ {
INIT_WORK(&fqdir->destroy_work, fqdir_work_fn); INIT_WORK(&fqdir->destroy_work, fqdir_work_fn);
@ -263,8 +298,8 @@ static void inet_frag_destroy_rcu(struct rcu_head *head)
kmem_cache_free(f->frags_cachep, q); kmem_cache_free(f->frags_cachep, q);
} }
unsigned int inet_frag_rbtree_purge(struct rb_root *root, static unsigned int
enum skb_drop_reason reason) inet_frag_rbtree_purge(struct rb_root *root, enum skb_drop_reason reason)
{ {
struct rb_node *p = rb_first(root); struct rb_node *p = rb_first(root);
unsigned int sum = 0; unsigned int sum = 0;
@ -284,7 +319,17 @@ unsigned int inet_frag_rbtree_purge(struct rb_root *root,
} }
return sum; return sum;
} }
EXPORT_SYMBOL(inet_frag_rbtree_purge);
void inet_frag_queue_flush(struct inet_frag_queue *q,
enum skb_drop_reason reason)
{
unsigned int sum;
reason = reason ?: SKB_DROP_REASON_FRAG_REASM_TIMEOUT;
sum = inet_frag_rbtree_purge(&q->rb_fragments, reason);
sub_frag_mem_limit(q->fqdir, sum);
}
EXPORT_SYMBOL(inet_frag_queue_flush);
void inet_frag_destroy(struct inet_frag_queue *q) void inet_frag_destroy(struct inet_frag_queue *q)
{ {
@ -327,7 +372,9 @@ static struct inet_frag_queue *inet_frag_alloc(struct fqdir *fqdir,
timer_setup(&q->timer, f->frag_expire, 0); timer_setup(&q->timer, f->frag_expire, 0);
spin_lock_init(&q->lock); spin_lock_init(&q->lock);
/* One reference for the timer, one for the hash table. */ /* One reference for the timer, one for the hash table.
* We never take any extra references, only decrement this field.
*/
refcount_set(&q->refcnt, 2); refcount_set(&q->refcnt, 2);
return q; return q;

View File

@ -134,11 +134,6 @@ static void ip_expire(struct timer_list *t)
net = qp->q.fqdir->net; net = qp->q.fqdir->net;
rcu_read_lock(); rcu_read_lock();
/* Paired with WRITE_ONCE() in fqdir_pre_exit(). */
if (READ_ONCE(qp->q.fqdir->dead))
goto out_rcu_unlock;
spin_lock(&qp->q.lock); spin_lock(&qp->q.lock);
if (qp->q.flags & INET_FRAG_COMPLETE) if (qp->q.flags & INET_FRAG_COMPLETE)
@ -146,6 +141,13 @@ static void ip_expire(struct timer_list *t)
qp->q.flags |= INET_FRAG_DROP; qp->q.flags |= INET_FRAG_DROP;
inet_frag_kill(&qp->q, &refs); inet_frag_kill(&qp->q, &refs);
/* Paired with WRITE_ONCE() in fqdir_pre_exit(). */
if (READ_ONCE(qp->q.fqdir->dead)) {
inet_frag_queue_flush(&qp->q, 0);
goto out;
}
__IP_INC_STATS(net, IPSTATS_MIB_REASMFAILS); __IP_INC_STATS(net, IPSTATS_MIB_REASMFAILS);
__IP_INC_STATS(net, IPSTATS_MIB_REASMTIMEOUT); __IP_INC_STATS(net, IPSTATS_MIB_REASMTIMEOUT);
@ -240,16 +242,10 @@ static int ip_frag_too_far(struct ipq *qp)
static int ip_frag_reinit(struct ipq *qp) static int ip_frag_reinit(struct ipq *qp)
{ {
unsigned int sum_truesize = 0; if (!mod_timer_pending(&qp->q.timer, jiffies + qp->q.fqdir->timeout))
if (!mod_timer(&qp->q.timer, jiffies + qp->q.fqdir->timeout)) {
refcount_inc(&qp->q.refcnt);
return -ETIMEDOUT; return -ETIMEDOUT;
}
sum_truesize = inet_frag_rbtree_purge(&qp->q.rb_fragments, inet_frag_queue_flush(&qp->q, SKB_DROP_REASON_FRAG_TOO_FAR);
SKB_DROP_REASON_FRAG_TOO_FAR);
sub_frag_mem_limit(qp->q.fqdir, sum_truesize);
qp->q.flags = 0; qp->q.flags = 0;
qp->q.len = 0; qp->q.len = 0;

View File

@ -4,7 +4,7 @@ config MPTCP
depends on INET depends on INET
select SKB_EXTENSIONS select SKB_EXTENSIONS
select CRYPTO_LIB_SHA256 select CRYPTO_LIB_SHA256
select CRYPTO select CRYPTO_LIB_UTILS
help help
Multipath TCP (MPTCP) connections send and receive data over multiple Multipath TCP (MPTCP) connections send and receive data over multiple
subflows in order to utilize multiple network paths. Each subflow subflows in order to utilize multiple network paths. Each subflow

View File

@ -119,7 +119,8 @@ int mptcp_pm_parse_entry(struct nlattr *attr, struct genl_info *info,
} }
if (tb[MPTCP_PM_ADDR_ATTR_FLAGS]) if (tb[MPTCP_PM_ADDR_ATTR_FLAGS])
entry->flags = nla_get_u32(tb[MPTCP_PM_ADDR_ATTR_FLAGS]); entry->flags = nla_get_u32(tb[MPTCP_PM_ADDR_ATTR_FLAGS]) &
MPTCP_PM_ADDR_FLAGS_MASK;
if (tb[MPTCP_PM_ADDR_ATTR_PORT]) if (tb[MPTCP_PM_ADDR_ATTR_PORT])
entry->addr.port = htons(nla_get_u16(tb[MPTCP_PM_ADDR_ATTR_PORT])); entry->addr.port = htons(nla_get_u16(tb[MPTCP_PM_ADDR_ATTR_PORT]));

View File

@ -1623,7 +1623,7 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
struct mptcp_sendmsg_info info = { struct mptcp_sendmsg_info info = {
.flags = flags, .flags = flags,
}; };
bool do_check_data_fin = false; bool copied = false;
int push_count = 1; int push_count = 1;
while (mptcp_send_head(sk) && (push_count > 0)) { while (mptcp_send_head(sk) && (push_count > 0)) {
@ -1665,7 +1665,7 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
push_count--; push_count--;
continue; continue;
} }
do_check_data_fin = true; copied = true;
} }
} }
} }
@ -1674,11 +1674,14 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
if (ssk) if (ssk)
mptcp_push_release(ssk, &info); mptcp_push_release(ssk, &info);
/* ensure the rtx timer is running */ /* Avoid scheduling the rtx timer if no data has been pushed; the timer
* will be updated on positive acks by __mptcp_cleanup_una().
*/
if (copied) {
if (!mptcp_rtx_timer_pending(sk)) if (!mptcp_rtx_timer_pending(sk))
mptcp_reset_rtx_timer(sk); mptcp_reset_rtx_timer(sk);
if (do_check_data_fin)
mptcp_check_send_data_fin(sk); mptcp_check_send_data_fin(sk);
}
} }
static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk, bool first) static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk, bool first)
@ -2766,10 +2769,13 @@ static void __mptcp_retrans(struct sock *sk)
/* /*
* make the whole retrans decision, xmit, disallow * make the whole retrans decision, xmit, disallow
* fallback atomic * fallback atomic, note that we can't retrans even
* when an infinite fallback is in progress, i.e. new
* subflows are disallowed.
*/ */
spin_lock_bh(&msk->fallback_lock); spin_lock_bh(&msk->fallback_lock);
if (__mptcp_check_fallback(msk)) { if (__mptcp_check_fallback(msk) ||
!msk->allow_subflows) {
spin_unlock_bh(&msk->fallback_lock); spin_unlock_bh(&msk->fallback_lock);
release_sock(ssk); release_sock(ssk);
goto clear_scheduled; goto clear_scheduled;

View File

@ -408,6 +408,9 @@ err_put:
return -1; return -1;
err_unreach: err_unreach:
if (!skb->dev)
skb->dev = skb_dst(skb)->dev;
dst_link_failure(skb); dst_link_failure(skb);
return -1; return -1;
} }

View File

@ -172,14 +172,14 @@ static int __nf_conncount_add(struct net *net,
struct nf_conn *found_ct; struct nf_conn *found_ct;
unsigned int collect = 0; unsigned int collect = 0;
bool refcounted = false; bool refcounted = false;
int err = 0;
if (!get_ct_or_tuple_from_skb(net, skb, l3num, &ct, &tuple, &zone, &refcounted)) if (!get_ct_or_tuple_from_skb(net, skb, l3num, &ct, &tuple, &zone, &refcounted))
return -ENOENT; return -ENOENT;
if (ct && nf_ct_is_confirmed(ct)) { if (ct && nf_ct_is_confirmed(ct)) {
if (refcounted) err = -EEXIST;
nf_ct_put(ct); goto out_put;
return -EEXIST;
} }
if ((u32)jiffies == list->last_gc) if ((u32)jiffies == list->last_gc)
@ -231,12 +231,16 @@ static int __nf_conncount_add(struct net *net,
} }
add_new_node: add_new_node:
if (WARN_ON_ONCE(list->count > INT_MAX)) if (WARN_ON_ONCE(list->count > INT_MAX)) {
return -EOVERFLOW; err = -EOVERFLOW;
goto out_put;
}
conn = kmem_cache_alloc(conncount_conn_cachep, GFP_ATOMIC); conn = kmem_cache_alloc(conncount_conn_cachep, GFP_ATOMIC);
if (conn == NULL) if (conn == NULL) {
return -ENOMEM; err = -ENOMEM;
goto out_put;
}
conn->tuple = tuple; conn->tuple = tuple;
conn->zone = *zone; conn->zone = *zone;
@ -249,7 +253,7 @@ add_new_node:
out_put: out_put:
if (refcounted) if (refcounted)
nf_ct_put(ct); nf_ct_put(ct);
return 0; return err;
} }
int nf_conncount_add_skb(struct net *net, int nf_conncount_add_skb(struct net *net,
@ -456,11 +460,10 @@ restart:
rb_link_node_rcu(&rbconn->node, parent, rbnode); rb_link_node_rcu(&rbconn->node, parent, rbnode);
rb_insert_color(&rbconn->node, root); rb_insert_color(&rbconn->node, root);
if (refcounted)
nf_ct_put(ct);
} }
out_unlock: out_unlock:
if (refcounted)
nf_ct_put(ct);
spin_unlock_bh(&nf_conncount_locks[hash]); spin_unlock_bh(&nf_conncount_locks[hash]);
return count; return count;
} }

View File

@ -2487,6 +2487,7 @@ void nf_conntrack_cleanup_net(struct net *net)
void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list) void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list)
{ {
struct nf_ct_iter_data iter_data = {}; struct nf_ct_iter_data iter_data = {};
unsigned long start = jiffies;
struct net *net; struct net *net;
int busy; int busy;
@ -2507,6 +2508,8 @@ i_see_dead_people:
busy = 1; busy = 1;
} }
if (busy) { if (busy) {
DEBUG_NET_WARN_ONCE(time_after(jiffies, start + 60 * HZ),
"conntrack cleanup blocked for 60s");
schedule(); schedule();
goto i_see_dead_people; goto i_see_dead_people;
} }

View File

@ -250,6 +250,9 @@ static void nft_dev_forward_path(const struct nft_pktinfo *pkt,
if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0) if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0)
nft_dev_path_info(&stack, &info, ha, &ft->data); nft_dev_path_info(&stack, &info, ha, &ft->data);
if (info.outdev)
route->tuple[dir].out.ifindex = info.outdev->ifindex;
if (!info.indev || !nft_flowtable_find_dev(info.indev, ft)) if (!info.indev || !nft_flowtable_find_dev(info.indev, ft))
return; return;
@ -269,7 +272,6 @@ static void nft_dev_forward_path(const struct nft_pktinfo *pkt,
route->tuple[!dir].in.num_encaps = info.num_encaps; route->tuple[!dir].in.num_encaps = info.num_encaps;
route->tuple[!dir].in.ingress_vlans = info.ingress_vlans; route->tuple[!dir].in.ingress_vlans = info.ingress_vlans;
route->tuple[dir].out.ifindex = info.outdev->ifindex;
if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) { if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) {
memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN); memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN);

View File

@ -294,25 +294,13 @@ nf_nat_used_tuple_new(const struct nf_conntrack_tuple *tuple,
ct = nf_ct_tuplehash_to_ctrack(thash); ct = nf_ct_tuplehash_to_ctrack(thash);
/* NB: IP_CT_DIR_ORIGINAL should be impossible because
* nf_nat_used_tuple() handles origin collisions.
*
* Handle remote chance other CPU confirmed its ct right after.
*/
if (thash->tuple.dst.dir != IP_CT_DIR_REPLY)
goto out;
/* clashing connection subject to NAT? Retry with new tuple. */ /* clashing connection subject to NAT? Retry with new tuple. */
if (READ_ONCE(ct->status) & uses_nat) if (READ_ONCE(ct->status) & uses_nat)
goto out; goto out;
if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
&ignored_ct->tuplehash[IP_CT_DIR_REPLY].tuple) && &ignored_ct->tuplehash[IP_CT_DIR_REPLY].tuple))
nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple,
&ignored_ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple)) {
taken = false; taken = false;
goto out;
}
out: out:
nf_ct_put(ct); nf_ct_put(ct);
return taken; return taken;

View File

@ -123,6 +123,29 @@ static void nft_validate_state_update(struct nft_table *table, u8 new_validate_s
table->validate_state = new_validate_state; table->validate_state = new_validate_state;
} }
static bool nft_chain_vstate_valid(const struct nft_ctx *ctx,
const struct nft_chain *chain)
{
const struct nft_base_chain *base_chain;
enum nft_chain_types type;
u8 hooknum;
if (WARN_ON_ONCE(!nft_is_base_chain(ctx->chain)))
return false;
base_chain = nft_base_chain(ctx->chain);
hooknum = base_chain->ops.hooknum;
type = base_chain->type->type;
/* chain is already validated for this call depth */
if (chain->vstate.depth >= ctx->level &&
chain->vstate.hook_mask[type] & BIT(hooknum))
return true;
return false;
}
static void nf_tables_trans_destroy_work(struct work_struct *w); static void nf_tables_trans_destroy_work(struct work_struct *w);
static void nft_trans_gc_work(struct work_struct *work); static void nft_trans_gc_work(struct work_struct *work);
@ -4079,6 +4102,29 @@ static void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *r
nf_tables_rule_destroy(ctx, rule); nf_tables_rule_destroy(ctx, rule);
} }
static void nft_chain_vstate_update(const struct nft_ctx *ctx, struct nft_chain *chain)
{
const struct nft_base_chain *base_chain;
enum nft_chain_types type;
u8 hooknum;
/* ctx->chain must hold the calling base chain. */
if (WARN_ON_ONCE(!nft_is_base_chain(ctx->chain))) {
memset(&chain->vstate, 0, sizeof(chain->vstate));
return;
}
base_chain = nft_base_chain(ctx->chain);
hooknum = base_chain->ops.hooknum;
type = base_chain->type->type;
BUILD_BUG_ON(BIT(NF_INET_NUMHOOKS) > U8_MAX);
chain->vstate.hook_mask[type] |= BIT(hooknum);
if (chain->vstate.depth < ctx->level)
chain->vstate.depth = ctx->level;
}
/** nft_chain_validate - loop detection and hook validation /** nft_chain_validate - loop detection and hook validation
* *
* @ctx: context containing call depth and base chain * @ctx: context containing call depth and base chain
@ -4088,15 +4134,25 @@ static void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *r
* and set lookups until either the jump limit is hit or all reachable * and set lookups until either the jump limit is hit or all reachable
* chains have been validated. * chains have been validated.
*/ */
int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain) int nft_chain_validate(const struct nft_ctx *ctx, struct nft_chain *chain)
{ {
struct nft_expr *expr, *last; struct nft_expr *expr, *last;
struct nft_rule *rule; struct nft_rule *rule;
int err; int err;
BUILD_BUG_ON(NFT_JUMP_STACK_SIZE > 255);
if (ctx->level == NFT_JUMP_STACK_SIZE) if (ctx->level == NFT_JUMP_STACK_SIZE)
return -EMLINK; return -EMLINK;
if (ctx->level > 0) {
/* jumps to base chains are not allowed. */
if (nft_is_base_chain(chain))
return -ELOOP;
if (nft_chain_vstate_valid(ctx, chain))
return 0;
}
list_for_each_entry(rule, &chain->rules, list) { list_for_each_entry(rule, &chain->rules, list) {
if (fatal_signal_pending(current)) if (fatal_signal_pending(current))
return -EINTR; return -EINTR;
@ -4115,8 +4171,11 @@ int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain)
if (err < 0) if (err < 0)
return err; return err;
} }
cond_resched();
} }
nft_chain_vstate_update(ctx, chain);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(nft_chain_validate); EXPORT_SYMBOL_GPL(nft_chain_validate);
@ -4128,7 +4187,7 @@ static int nft_table_validate(struct net *net, const struct nft_table *table)
.net = net, .net = net,
.family = table->family, .family = table->family,
}; };
int err; int err = 0;
list_for_each_entry(chain, &table->chains, list) { list_for_each_entry(chain, &table->chains, list) {
if (!nft_is_base_chain(chain)) if (!nft_is_base_chain(chain))
@ -4137,12 +4196,14 @@ static int nft_table_validate(struct net *net, const struct nft_table *table)
ctx.chain = chain; ctx.chain = chain;
err = nft_chain_validate(&ctx, chain); err = nft_chain_validate(&ctx, chain);
if (err < 0) if (err < 0)
return err; goto err;
cond_resched();
} }
return 0; err:
list_for_each_entry(chain, &table->chains, list)
memset(&chain->vstate, 0, sizeof(chain->vstate));
return err;
} }
int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set, int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
@ -11676,21 +11737,10 @@ static int nft_validate_register_store(const struct nft_ctx *ctx,
enum nft_data_types type, enum nft_data_types type,
unsigned int len) unsigned int len)
{ {
int err;
switch (reg) { switch (reg) {
case NFT_REG_VERDICT: case NFT_REG_VERDICT:
if (type != NFT_DATA_VERDICT) if (type != NFT_DATA_VERDICT)
return -EINVAL; return -EINVAL;
if (data != NULL &&
(data->verdict.code == NFT_GOTO ||
data->verdict.code == NFT_JUMP)) {
err = nft_chain_validate(ctx, data->verdict.chain);
if (err < 0)
return err;
}
break; break;
default: default:
if (type != NFT_DATA_VALUE) if (type != NFT_DATA_VALUE)

View File

@ -43,8 +43,10 @@ void nr_output(struct sock *sk, struct sk_buff *skb)
frontlen = skb_headroom(skb); frontlen = skb_headroom(skb);
while (skb->len > 0) { while (skb->len > 0) {
if ((skbn = sock_alloc_send_skb(sk, frontlen + NR_MAX_PACKET_SIZE, 0, &err)) == NULL) if ((skbn = sock_alloc_send_skb(sk, frontlen + NR_MAX_PACKET_SIZE, 0, &err)) == NULL) {
kfree_skb(skb);
return; return;
}
skb_reserve(skbn, frontlen); skb_reserve(skbn, frontlen);

View File

@ -2802,13 +2802,20 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
return err; return err;
} }
static bool validate_push_nsh(const struct nlattr *attr, bool log) static bool validate_push_nsh(const struct nlattr *a, bool log)
{ {
struct nlattr *nsh_key = nla_data(a);
struct sw_flow_match match; struct sw_flow_match match;
struct sw_flow_key key; struct sw_flow_key key;
/* There must be one and only one NSH header. */
if (!nla_ok(nsh_key, nla_len(a)) ||
nla_total_size(nla_len(nsh_key)) != nla_len(a) ||
nla_type(nsh_key) != OVS_KEY_ATTR_NSH)
return false;
ovs_match_init(&match, &key, true, NULL); ovs_match_init(&match, &key, true, NULL);
return !nsh_key_put_from_nlattr(attr, &match, false, true, log); return !nsh_key_put_from_nlattr(nsh_key, &match, false, true, log);
} }
/* Return false if there are any non-masked bits set. /* Return false if there are any non-masked bits set.
@ -3389,7 +3396,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
return -EINVAL; return -EINVAL;
} }
mac_proto = MAC_PROTO_NONE; mac_proto = MAC_PROTO_NONE;
if (!validate_push_nsh(nla_data(a), log)) if (!validate_push_nsh(a, log))
return -EINVAL; return -EINVAL;
break; break;

View File

@ -281,6 +281,15 @@ static int tcf_mirred_to_dev(struct sk_buff *skb, struct tcf_mirred *m,
want_ingress = tcf_mirred_act_wants_ingress(m_eaction); want_ingress = tcf_mirred_act_wants_ingress(m_eaction);
if (dev == skb->dev && want_ingress == at_ingress) {
pr_notice_once("tc mirred: Loop (%s:%s --> %s:%s)\n",
netdev_name(skb->dev),
at_ingress ? "ingress" : "egress",
netdev_name(dev),
want_ingress ? "ingress" : "egress");
goto err_cant_do;
}
/* All mirred/redirected skbs should clear previous ct info */ /* All mirred/redirected skbs should clear previous ct info */
nf_reset_ct(skb_to_send); nf_reset_ct(skb_to_send);
if (want_ingress && !at_ingress) /* drop dst for egress -> ingress */ if (want_ingress && !at_ingress) /* drop dst for egress -> ingress */

View File

@ -652,7 +652,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt,
sch_tree_lock(sch); sch_tree_lock(sch);
for (i = nbands; i < oldbands; i++) { for (i = nbands; i < oldbands; i++) {
if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) if (cl_is_active(&q->classes[i]))
list_del_init(&q->classes[i].alist); list_del_init(&q->classes[i].alist);
qdisc_purge_queue(q->classes[i].qdisc); qdisc_purge_queue(q->classes[i].qdisc);
} }
@ -664,6 +664,10 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt,
q->classes[i].deficit = quanta[i]; q->classes[i].deficit = quanta[i];
} }
} }
for (i = q->nstrict; i < nstrict; i++) {
if (cl_is_active(&q->classes[i]))
list_del_init(&q->classes[i].alist);
}
WRITE_ONCE(q->nstrict, nstrict); WRITE_ONCE(q->nstrict, nstrict);
memcpy(q->prio2band, priomap, sizeof(priomap)); memcpy(q->prio2band, priomap, sizeof(priomap));

View File

@ -492,6 +492,8 @@ static void sctp_v6_copy_ip_options(struct sock *sk, struct sock *newsk)
struct ipv6_pinfo *newnp, *np = inet6_sk(sk); struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
struct ipv6_txoptions *opt; struct ipv6_txoptions *opt;
inet_sk(newsk)->inet_opt = NULL;
newnp = inet6_sk(newsk); newnp = inet6_sk(newsk);
rcu_read_lock(); rcu_read_lock();

View File

@ -4863,8 +4863,6 @@ static struct sock *sctp_clone_sock(struct sock *sk,
newsp->pf->to_sk_daddr(&asoc->peer.primary_addr, newsk); newsp->pf->to_sk_daddr(&asoc->peer.primary_addr, newsk);
newinet->inet_dport = htons(asoc->peer.port); newinet->inet_dport = htons(asoc->peer.port);
newsp->pf->copy_ip_options(sk, newsk);
atomic_set(&newinet->inet_id, get_random_u16()); atomic_set(&newinet->inet_id, get_random_u16());
inet_set_bit(MC_LOOP, newsk); inet_set_bit(MC_LOOP, newsk);
@ -4874,17 +4872,20 @@ static struct sock *sctp_clone_sock(struct sock *sk,
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
if (sk->sk_family == AF_INET6) { if (sk->sk_family == AF_INET6) {
struct ipv6_pinfo *newnp = inet6_sk(newsk); struct ipv6_pinfo *newnp;
newinet->pinet6 = &((struct sctp6_sock *)newsk)->inet6; newinet->pinet6 = &((struct sctp6_sock *)newsk)->inet6;
newinet->ipv6_fl_list = NULL; newinet->ipv6_fl_list = NULL;
newnp = inet6_sk(newsk);
memcpy(newnp, inet6_sk(sk), sizeof(struct ipv6_pinfo)); memcpy(newnp, inet6_sk(sk), sizeof(struct ipv6_pinfo));
newnp->ipv6_mc_list = NULL; newnp->ipv6_mc_list = NULL;
newnp->ipv6_ac_list = NULL; newnp->ipv6_ac_list = NULL;
} }
#endif #endif
newsp->pf->copy_ip_options(sk, newsk);
newsp->do_auto_asconf = 0; newsp->do_auto_asconf = 0;
skb_queue_head_init(&newsp->pd_lobby); skb_queue_head_init(&newsp->pd_lobby);

View File

@ -199,7 +199,7 @@ static void unix_free_vertices(struct scm_fp_list *fpl)
} }
} }
static DEFINE_SPINLOCK(unix_gc_lock); static __cacheline_aligned_in_smp DEFINE_SPINLOCK(unix_gc_lock);
void unix_add_edges(struct scm_fp_list *fpl, struct unix_sock *receiver) void unix_add_edges(struct scm_fp_list *fpl, struct unix_sock *receiver)
{ {

View File

@ -13,6 +13,7 @@ UAPI_PATH:=../../../../include/uapi/
# need the explicit -D matching what's in /usr, to avoid multiple definitions. # need the explicit -D matching what's in /usr, to avoid multiple definitions.
get_hdr_inc=-D$(1) -include $(UAPI_PATH)/linux/$(2) get_hdr_inc=-D$(1) -include $(UAPI_PATH)/linux/$(2)
get_hdr_inc2=-D$(1) -D$(2) -include $(UAPI_PATH)/linux/$(3)
CFLAGS_devlink:=$(call get_hdr_inc,_LINUX_DEVLINK_H_,devlink.h) CFLAGS_devlink:=$(call get_hdr_inc,_LINUX_DEVLINK_H_,devlink.h)
CFLAGS_dpll:=$(call get_hdr_inc,_LINUX_DPLL_H,dpll.h) CFLAGS_dpll:=$(call get_hdr_inc,_LINUX_DPLL_H,dpll.h)
@ -48,3 +49,4 @@ CFLAGS_tc:= $(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) \
$(call get_hdr_inc,_TC_SKBEDIT_H,tc_act/tc_skbedit.h) \ $(call get_hdr_inc,_TC_SKBEDIT_H,tc_act/tc_skbedit.h) \
$(call get_hdr_inc,_TC_TUNNEL_KEY_H,tc_act/tc_tunnel_key.h) $(call get_hdr_inc,_TC_TUNNEL_KEY_H,tc_act/tc_tunnel_key.h)
CFLAGS_tcp_metrics:=$(call get_hdr_inc,_LINUX_TCP_METRICS_H,tcp_metrics.h) CFLAGS_tcp_metrics:=$(call get_hdr_inc,_LINUX_TCP_METRICS_H,tcp_metrics.h)
CFLAGS_wireguard:=$(call get_hdr_inc2,_LINUX_WIREGUARD_H,_WG_UAPI_WIREGUARD_H,wireguard.h)

View File

@ -1,4 +1,9 @@
CFLAGS += $(KHDR_INCLUDES) -Wall -Wflex-array-member-not-at-end top_srcdir := ../../../../..
include $(top_srcdir)/scripts/Makefile.compiler
cc-option = $(call __cc-option, $(CC),,$(1),$(2))
CFLAGS += $(KHDR_INCLUDES) -Wall $(call cc-option,-Wflex-array-member-not-at-end)
TEST_GEN_PROGS := \ TEST_GEN_PROGS := \
diag_uid \ diag_uid \

View File

@ -29,6 +29,7 @@ CONFIG_NET_ACT_VLAN=m
CONFIG_NET_CLS_BASIC=m CONFIG_NET_CLS_BASIC=m
CONFIG_NET_CLS_FLOWER=m CONFIG_NET_CLS_FLOWER=m
CONFIG_NET_CLS_MATCHALL=m CONFIG_NET_CLS_MATCHALL=m
CONFIG_NET_CLS_U32=m
CONFIG_NET_EMATCH=y CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_META=m CONFIG_NET_EMATCH_META=m
CONFIG_NETFILTER=y CONFIG_NETFILTER=y

View File

@ -138,12 +138,17 @@ install_capture()
defer tc qdisc del dev "$dev" clsact defer tc qdisc del dev "$dev" clsact
tc filter add dev "$dev" ingress proto ip pref 104 \ tc filter add dev "$dev" ingress proto ip pref 104 \
flower skip_hw ip_proto udp dst_port "$VXPORT" \ u32 match ip protocol 0x11 0xff \
match u16 "$VXPORT" 0xffff at 0x16 \
match u16 0x0800 0xffff at 0x30 \
action pass action pass
defer tc filter del dev "$dev" ingress proto ip pref 104 defer tc filter del dev "$dev" ingress proto ip pref 104
tc filter add dev "$dev" ingress proto ipv6 pref 106 \ tc filter add dev "$dev" ingress proto ipv6 pref 106 \
flower skip_hw ip_proto udp dst_port "$VXPORT" \ u32 match ip6 protocol 0x11 0xff \
match u16 "$VXPORT" 0xffff at 0x2a \
match u16 0x86dd 0xffff at 0x44 \
match u8 0x11 0xff at 0x4c \
action pass action pass
defer tc filter del dev "$dev" ingress proto ipv6 pref 106 defer tc filter del dev "$dev" ingress proto ipv6 pref 106
} }
@ -248,13 +253,6 @@ vx_create()
} }
export -f vx_create export -f vx_create
vx_wait()
{
# Wait for all the ARP, IGMP etc. noise to settle down so that the
# tunnel is clear for measurements.
sleep 10
}
vx10_create() vx10_create()
{ {
vx_create vx10 10 id 1000 "$@" vx_create vx10 10 id 1000 "$@"
@ -267,18 +265,6 @@ vx20_create()
} }
export -f vx20_create export -f vx20_create
vx10_create_wait()
{
vx10_create "$@"
vx_wait
}
vx20_create_wait()
{
vx20_create "$@"
vx_wait
}
ns_init_common() ns_init_common()
{ {
local ns=$1; shift local ns=$1; shift
@ -554,7 +540,7 @@ ipv4_nomcroute()
# Install a misleading (S,G) rule to attempt to trick the system into # Install a misleading (S,G) rule to attempt to trick the system into
# pushing the packets elsewhere. # pushing the packets elsewhere.
adf_install_broken_sg adf_install_broken_sg
vx10_create_wait local 192.0.2.100 group "$GROUP4" dev "$swp2" vx10_create local 192.0.2.100 group "$GROUP4" dev "$swp2"
do_test 4 10 0 "IPv4 nomcroute" do_test 4 10 0 "IPv4 nomcroute"
} }
@ -562,7 +548,7 @@ ipv6_nomcroute()
{ {
# Like for IPv4, install a misleading (S,G). # Like for IPv4, install a misleading (S,G).
adf_install_broken_sg adf_install_broken_sg
vx20_create_wait local 2001:db8:4::1 group "$GROUP6" dev "$swp2" vx20_create local 2001:db8:4::1 group "$GROUP6" dev "$swp2"
do_test 6 10 0 "IPv6 nomcroute" do_test 6 10 0 "IPv6 nomcroute"
} }
@ -581,35 +567,35 @@ ipv6_nomcroute_rx()
ipv4_mcroute() ipv4_mcroute()
{ {
adf_install_sg adf_install_sg
vx10_create_wait local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute vx10_create local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute
do_test 4 10 10 "IPv4 mcroute" do_test 4 10 10 "IPv4 mcroute"
} }
ipv6_mcroute() ipv6_mcroute()
{ {
adf_install_sg adf_install_sg
vx20_create_wait local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute vx20_create local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
do_test 6 10 10 "IPv6 mcroute" do_test 6 10 10 "IPv6 mcroute"
} }
ipv4_mcroute_rx() ipv4_mcroute_rx()
{ {
adf_install_sg adf_install_sg
vx10_create_wait local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute vx10_create local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute
ipv4_do_test_rx 0 "IPv4 mcroute ping" ipv4_do_test_rx 0 "IPv4 mcroute ping"
} }
ipv6_mcroute_rx() ipv6_mcroute_rx()
{ {
adf_install_sg adf_install_sg
vx20_create_wait local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute vx20_create local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
ipv6_do_test_rx 0 "IPv6 mcroute ping" ipv6_do_test_rx 0 "IPv6 mcroute ping"
} }
ipv4_mcroute_changelink() ipv4_mcroute_changelink()
{ {
adf_install_sg adf_install_sg
vx10_create_wait local 192.0.2.100 group "$GROUP4" dev "$IPMR" vx10_create local 192.0.2.100 group "$GROUP4" dev "$IPMR"
ip link set dev vx10 type vxlan mcroute ip link set dev vx10 type vxlan mcroute
sleep 1 sleep 1
do_test 4 10 10 "IPv4 mcroute changelink" do_test 4 10 10 "IPv4 mcroute changelink"
@ -618,7 +604,7 @@ ipv4_mcroute_changelink()
ipv6_mcroute_changelink() ipv6_mcroute_changelink()
{ {
adf_install_sg adf_install_sg
vx20_create_wait local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute vx20_create local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
ip link set dev vx20 type vxlan mcroute ip link set dev vx20 type vxlan mcroute
sleep 1 sleep 1
do_test 6 10 10 "IPv6 mcroute changelink" do_test 6 10 10 "IPv6 mcroute changelink"
@ -627,47 +613,47 @@ ipv6_mcroute_changelink()
ipv4_mcroute_starg() ipv4_mcroute_starg()
{ {
adf_install_starg adf_install_starg
vx10_create_wait local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute vx10_create local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute
do_test 4 10 10 "IPv4 mcroute (*,G)" do_test 4 10 10 "IPv4 mcroute (*,G)"
} }
ipv6_mcroute_starg() ipv6_mcroute_starg()
{ {
adf_install_starg adf_install_starg
vx20_create_wait local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute vx20_create local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
do_test 6 10 10 "IPv6 mcroute (*,G)" do_test 6 10 10 "IPv6 mcroute (*,G)"
} }
ipv4_mcroute_starg_rx() ipv4_mcroute_starg_rx()
{ {
adf_install_starg adf_install_starg
vx10_create_wait local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute vx10_create local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute
ipv4_do_test_rx 0 "IPv4 mcroute (*,G) ping" ipv4_do_test_rx 0 "IPv4 mcroute (*,G) ping"
} }
ipv6_mcroute_starg_rx() ipv6_mcroute_starg_rx()
{ {
adf_install_starg adf_install_starg
vx20_create_wait local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute vx20_create local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
ipv6_do_test_rx 0 "IPv6 mcroute (*,G) ping" ipv6_do_test_rx 0 "IPv6 mcroute (*,G) ping"
} }
ipv4_mcroute_noroute() ipv4_mcroute_noroute()
{ {
vx10_create_wait local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute vx10_create local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute
do_test 4 0 0 "IPv4 mcroute, no route" do_test 4 0 0 "IPv4 mcroute, no route"
} }
ipv6_mcroute_noroute() ipv6_mcroute_noroute()
{ {
vx20_create_wait local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute vx20_create local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
do_test 6 0 0 "IPv6 mcroute, no route" do_test 6 0 0 "IPv6 mcroute, no route"
} }
ipv4_mcroute_fdb() ipv4_mcroute_fdb()
{ {
adf_install_sg adf_install_sg
vx10_create_wait local 192.0.2.100 dev "$IPMR" mcroute vx10_create local 192.0.2.100 dev "$IPMR" mcroute
bridge fdb add dev vx10 \ bridge fdb add dev vx10 \
00:00:00:00:00:00 self static dst "$GROUP4" via "$IPMR" 00:00:00:00:00:00 self static dst "$GROUP4" via "$IPMR"
do_test 4 10 10 "IPv4 mcroute FDB" do_test 4 10 10 "IPv4 mcroute FDB"
@ -676,7 +662,7 @@ ipv4_mcroute_fdb()
ipv6_mcroute_fdb() ipv6_mcroute_fdb()
{ {
adf_install_sg adf_install_sg
vx20_create_wait local 2001:db8:4::1 dev "$IPMR" mcroute vx20_create local 2001:db8:4::1 dev "$IPMR" mcroute
bridge -6 fdb add dev vx20 \ bridge -6 fdb add dev vx20 \
00:00:00:00:00:00 self static dst "$GROUP6" via "$IPMR" 00:00:00:00:00:00 self static dst "$GROUP6" via "$IPMR"
do_test 6 10 10 "IPv6 mcroute FDB" do_test 6 10 10 "IPv6 mcroute FDB"
@ -686,7 +672,7 @@ ipv6_mcroute_fdb()
ipv4_mcroute_fdb_oif0() ipv4_mcroute_fdb_oif0()
{ {
adf_install_sg adf_install_sg
vx10_create_wait local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute vx10_create local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute
bridge fdb del dev vx10 00:00:00:00:00:00 bridge fdb del dev vx10 00:00:00:00:00:00
bridge fdb add dev vx10 00:00:00:00:00:00 self static dst "$GROUP4" bridge fdb add dev vx10 00:00:00:00:00:00 self static dst "$GROUP4"
do_test 4 10 10 "IPv4 mcroute oif=0" do_test 4 10 10 "IPv4 mcroute oif=0"
@ -703,7 +689,7 @@ ipv6_mcroute_fdb_oif0()
defer ip -6 route del table local multicast "$GROUP6/128" dev "$IPMR" defer ip -6 route del table local multicast "$GROUP6/128" dev "$IPMR"
adf_install_sg adf_install_sg
vx20_create_wait local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute vx20_create local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
bridge -6 fdb del dev vx20 00:00:00:00:00:00 bridge -6 fdb del dev vx20 00:00:00:00:00:00
bridge -6 fdb add dev vx20 00:00:00:00:00:00 self static dst "$GROUP6" bridge -6 fdb add dev vx20 00:00:00:00:00:00 self static dst "$GROUP6"
do_test 6 10 10 "IPv6 mcroute oif=0" do_test 6 10 10 "IPv6 mcroute oif=0"
@ -716,7 +702,7 @@ ipv4_mcroute_fdb_oif0_sep()
adf_install_sg_sep adf_install_sg_sep
adf_ip_addr_add lo 192.0.2.120/28 adf_ip_addr_add lo 192.0.2.120/28
vx10_create_wait local 192.0.2.120 group "$GROUP4" dev "$IPMR" mcroute vx10_create local 192.0.2.120 group "$GROUP4" dev "$IPMR" mcroute
bridge fdb del dev vx10 00:00:00:00:00:00 bridge fdb del dev vx10 00:00:00:00:00:00
bridge fdb add dev vx10 00:00:00:00:00:00 self static dst "$GROUP4" bridge fdb add dev vx10 00:00:00:00:00:00 self static dst "$GROUP4"
do_test 4 10 10 "IPv4 mcroute TX!=RX oif=0" do_test 4 10 10 "IPv4 mcroute TX!=RX oif=0"
@ -727,7 +713,7 @@ ipv4_mcroute_fdb_oif0_sep_rx()
adf_install_sg_sep_rx lo adf_install_sg_sep_rx lo
adf_ip_addr_add lo 192.0.2.120/28 adf_ip_addr_add lo 192.0.2.120/28
vx10_create_wait local 192.0.2.120 group "$GROUP4" dev "$IPMR" mcroute vx10_create local 192.0.2.120 group "$GROUP4" dev "$IPMR" mcroute
bridge fdb del dev vx10 00:00:00:00:00:00 bridge fdb del dev vx10 00:00:00:00:00:00
bridge fdb add dev vx10 00:00:00:00:00:00 self static dst "$GROUP4" bridge fdb add dev vx10 00:00:00:00:00:00 self static dst "$GROUP4"
ipv4_do_test_rx 0 "IPv4 mcroute TX!=RX oif=0 ping" ipv4_do_test_rx 0 "IPv4 mcroute TX!=RX oif=0 ping"
@ -738,7 +724,7 @@ ipv4_mcroute_fdb_sep_rx()
adf_install_sg_sep_rx lo adf_install_sg_sep_rx lo
adf_ip_addr_add lo 192.0.2.120/28 adf_ip_addr_add lo 192.0.2.120/28
vx10_create_wait local 192.0.2.120 group "$GROUP4" dev "$IPMR" mcroute vx10_create local 192.0.2.120 group "$GROUP4" dev "$IPMR" mcroute
bridge fdb del dev vx10 00:00:00:00:00:00 bridge fdb del dev vx10 00:00:00:00:00:00
bridge fdb add \ bridge fdb add \
dev vx10 00:00:00:00:00:00 self static dst "$GROUP4" via lo dev vx10 00:00:00:00:00:00 self static dst "$GROUP4" via lo
@ -750,7 +736,7 @@ ipv6_mcroute_fdb_sep_rx()
adf_install_sg_sep_rx "X$IPMR" adf_install_sg_sep_rx "X$IPMR"
adf_ip_addr_add "X$IPMR" 2001:db8:5::1/64 adf_ip_addr_add "X$IPMR" 2001:db8:5::1/64
vx20_create_wait local 2001:db8:5::1 group "$GROUP6" dev "$IPMR" mcroute vx20_create local 2001:db8:5::1 group "$GROUP6" dev "$IPMR" mcroute
bridge -6 fdb del dev vx20 00:00:00:00:00:00 bridge -6 fdb del dev vx20 00:00:00:00:00:00
bridge -6 fdb add dev vx20 00:00:00:00:00:00 \ bridge -6 fdb add dev vx20 00:00:00:00:00:00 \
self static dst "$GROUP6" via "X$IPMR" self static dst "$GROUP6" via "X$IPMR"

View File

@ -280,7 +280,8 @@ tc_rule_stats_get()
local selector=${1:-.packets}; shift local selector=${1:-.packets}; shift
tc -j -s filter show dev $dev $dir pref $pref \ tc -j -s filter show dev $dev $dir pref $pref \
| jq ".[1].options.actions[].stats$selector" | jq ".[] | select(.options.actions) |
.options.actions[].stats$selector"
} }
tc_rule_handle_stats_get() tc_rule_handle_stats_get()

View File

@ -24,7 +24,8 @@ static inline void ksft_ready(void)
fd = STDOUT_FILENO; fd = STDOUT_FILENO;
} }
write(fd, msg, sizeof(msg)); if (write(fd, msg, sizeof(msg)) < 0)
perror("write()");
if (fd != STDOUT_FILENO) if (fd != STDOUT_FILENO)
close(fd); close(fd);
} }
@ -48,7 +49,8 @@ static inline void ksft_wait(void)
fd = STDIN_FILENO; fd = STDIN_FILENO;
} }
read(fd, &byte, sizeof(byte)); if (read(fd, &byte, sizeof(byte)) < 0)
perror("read()");
if (fd != STDIN_FILENO) if (fd != STDIN_FILENO)
close(fd); close(fd);
} }

View File

@ -192,6 +192,10 @@ check "show_endpoints" \
flush_endpoint flush_endpoint
check "show_endpoints" "" "flush addrs" check "show_endpoints" "" "flush addrs"
add_endpoint 10.0.1.1 flags unknown
check "show_endpoints" "$(format_endpoints "1,10.0.1.1")" "ignore unknown flags"
flush_endpoint
set_limits 9 1 2>/dev/null set_limits 9 1 2>/dev/null
check "get_limits" "${default_limits}" "rcv addrs above hard limit" check "get_limits" "${default_limits}" "rcv addrs above hard limit"

View File

@ -24,6 +24,8 @@
#define IPPROTO_MPTCP 262 #define IPPROTO_MPTCP 262
#endif #endif
#define MPTCP_PM_ADDR_FLAG_UNKNOWN _BITUL(7)
static void syntax(char *argv[]) static void syntax(char *argv[])
{ {
fprintf(stderr, "%s add|ann|rem|csf|dsf|get|set|del|flush|dump|events|listen|accept [<args>]\n", argv[0]); fprintf(stderr, "%s add|ann|rem|csf|dsf|get|set|del|flush|dump|events|listen|accept [<args>]\n", argv[0]);
@ -836,6 +838,8 @@ int add_addr(int fd, int pm_family, int argc, char *argv[])
flags |= MPTCP_PM_ADDR_FLAG_BACKUP; flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
else if (!strcmp(tok, "fullmesh")) else if (!strcmp(tok, "fullmesh"))
flags |= MPTCP_PM_ADDR_FLAG_FULLMESH; flags |= MPTCP_PM_ADDR_FLAG_FULLMESH;
else if (!strcmp(tok, "unknown"))
flags |= MPTCP_PM_ADDR_FLAG_UNKNOWN;
else else
error(1, errno, error(1, errno,
"unknown flag %s", argv[arg]); "unknown flag %s", argv[arg]);
@ -1048,6 +1052,13 @@ static void print_addr(struct rtattr *attrs, int len)
printf(","); printf(",");
} }
if (flags & MPTCP_PM_ADDR_FLAG_UNKNOWN) {
printf("unknown");
flags &= ~MPTCP_PM_ADDR_FLAG_UNKNOWN;
if (flags)
printf(",");
}
/* bump unknown flags, if any */ /* bump unknown flags, if any */
if (flags) if (flags)
printf("0x%x", flags); printf("0x%x", flags);

View File

@ -116,7 +116,7 @@ run_one_clash_test()
# not a failure: clash resolution logic did not trigger. # not a failure: clash resolution logic did not trigger.
# With right timing, xmit completed sequentially and # With right timing, xmit completed sequentially and
# no parallel insertion occurs. # no parallel insertion occurs.
return $ksft_skip return $ksft_xfail
} }
run_clash_test() run_clash_test()
@ -133,12 +133,12 @@ run_clash_test()
if [ $rv -eq 0 ];then if [ $rv -eq 0 ];then
echo "PASS: clash resolution test for $daddr:$dport on attempt $i" echo "PASS: clash resolution test for $daddr:$dport on attempt $i"
return 0 return 0
elif [ $rv -eq $ksft_skip ]; then elif [ $rv -eq $ksft_xfail ]; then
softerr=1 softerr=1
fi fi
done done
[ $softerr -eq 1 ] && echo "SKIP: clash resolution for $daddr:$dport did not trigger" [ $softerr -eq 1 ] && echo "XFAIL: clash resolution for $daddr:$dport did not trigger"
} }
ip link add veth0 netns "$nsclient1" type veth peer name veth0 netns "$nsrouter" ip link add veth0 netns "$nsclient1" type veth peer name veth0 netns "$nsrouter"
@ -167,8 +167,7 @@ load_simple_ruleset "$nsclient2"
run_clash_test "$nsclient2" "$nsclient2" 127.0.0.1 9001 run_clash_test "$nsclient2" "$nsclient2" 127.0.0.1 9001
if [ $clash_resolution_active -eq 0 ];then if [ $clash_resolution_active -eq 0 ];then
[ "$ret" -eq 0 ] && ret=$ksft_skip [ "$ret" -eq 0 ] && ret=$ksft_xfail
echo "SKIP: Clash resolution did not trigger"
fi fi
exit $ret exit $ret

View File

@ -33,9 +33,14 @@ static void die(const char *e)
exit(111); exit(111);
} }
static void die_port(uint16_t got, uint16_t want) static void die_port(const struct sockaddr_in *sin, uint16_t want)
{ {
fprintf(stderr, "Port number changed, wanted %d got %d\n", want, ntohs(got)); uint16_t got = ntohs(sin->sin_port);
char str[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str));
fprintf(stderr, "Port number changed, wanted %d got %d from %s\n", want, got, str);
exit(1); exit(1);
} }
@ -100,7 +105,7 @@ int main(int argc, char *argv[])
die("child recvfrom"); die("child recvfrom");
if (peer.sin_port != htons(PORT)) if (peer.sin_port != htons(PORT))
die_port(peer.sin_port, PORT); die_port(&peer, PORT);
} else { } else {
if (sendto(s2, buf, LEN, 0, (struct sockaddr *)&sa1, sizeof(sa1)) != LEN) if (sendto(s2, buf, LEN, 0, (struct sockaddr *)&sa1, sizeof(sa1)) != LEN)
continue; continue;
@ -109,7 +114,7 @@ int main(int argc, char *argv[])
die("parent recvfrom"); die("parent recvfrom");
if (peer.sin_port != htons((PORT + 1))) if (peer.sin_port != htons((PORT + 1)))
die_port(peer.sin_port, PORT + 1); die_port(&peer, PORT + 1);
} }
} }

View File

@ -45,6 +45,8 @@ if ip netns exec "$ns0" ./conntrack_reverse_clash; then
echo "PASS: No SNAT performed for null bindings" echo "PASS: No SNAT performed for null bindings"
else else
echo "ERROR: SNAT performed without any matching snat rule" echo "ERROR: SNAT performed without any matching snat rule"
ip netns exec "$ns0" conntrack -L
ip netns exec "$ns0" conntrack -S
exit 1 exit 1
fi fi

View File

@ -26,7 +26,7 @@
+0.01 > R 643160523:643160523(0) win 0 +0.01 > R 643160523:643160523(0) win 0
+0.01 `conntrack -f $NFCT_IP_VERSION -L -p tcp --dport 8080 2>/dev/null | grep UNREPLIED | grep -q SYN_SENT` +0.1 `conntrack -f $NFCT_IP_VERSION -L -p tcp --dport 8080 2>/dev/null | grep UNREPLIED | grep -q SYN_SENT`
// Must go through. // Must go through.
+0.01 > S 0:0(0) win 65535 <mss 1460,sackOK,TS val 1 ecr 0,nop,wscale 8> +0.01 > S 0:0(0) win 65535 <mss 1460,sackOK,TS val 1 ecr 0,nop,wscale 8>

View File

@ -81,7 +81,8 @@ static void run_server(void)
if (getsockopt(connfd, SOL_SOCKET, SO_INCOMING_NAPI_ID, &opt, &len) < 0) if (getsockopt(connfd, SOL_SOCKET, SO_INCOMING_NAPI_ID, &opt, &len) < 0)
error(1, errno, "getsockopt(SO_INCOMING_NAPI_ID)"); error(1, errno, "getsockopt(SO_INCOMING_NAPI_ID)");
read(connfd, buf, 64); if (read(connfd, buf, 64) < 0)
perror("read()");
fprintf(outfile, "%d\n", opt); fprintf(outfile, "%d\n", opt);
fclose(outfile); fclose(outfile);

View File

@ -2786,10 +2786,10 @@ TEST_F(tls_err, epoll_partial_rec)
TEST_F(tls_err, poll_partial_rec_async) TEST_F(tls_err, poll_partial_rec_async)
{ {
struct pollfd pfd = { }; struct pollfd pfd = { };
char token = '\0';
ssize_t rec_len; ssize_t rec_len;
char rec[256]; char rec[256];
char buf[128]; char buf[128];
char token;
int p[2]; int p[2];
int ret; int ret;

View File

@ -1052,5 +1052,51 @@
"$TC qdisc del dev $DEV1 ingress_block 21 clsact", "$TC qdisc del dev $DEV1 ingress_block 21 clsact",
"$TC actions flush action mirred" "$TC actions flush action mirred"
] ]
},
{
"id": "7eba",
"name": "Redirect multiport: dummy egress -> dummy egress (Loop)",
"category": [
"filter",
"mirred"
],
"plugins": {
"requires": [
"nsPlugin"
]
},
"setup": [
"$IP link set dev $DUMMY up || true",
"$IP addr add 10.10.10.10/24 dev $DUMMY || true",
"$TC qdisc add dev $DUMMY handle 1: root drr",
"$TC filter add dev $DUMMY parent 1: protocol ip prio 10 matchall action mirred egress redirect dev $DUMMY index 1"
],
"cmdUnderTest": "ping -c1 -W0.01 -I $DUMMY 10.10.10.1",
"expExitCode": "1",
"verifyCmd": "$TC -j -s actions get action mirred index 1",
"matchJSON": [
{
"total acts": 0
},
{
"actions": [
{
"order": 1,
"kind": "mirred",
"mirred_action": "redirect",
"direction": "egress",
"index": 1,
"stats": {
"packets": 1,
"overlimits": 1
},
"not_in_hw": true
}
]
}
],
"teardown": [
"$TC qdisc del dev $DUMMY root"
]
} }
] ]

View File

@ -1033,5 +1033,83 @@
"teardown": [ "teardown": [
"$TC qdisc del dev $DUMMY handle 1: root" "$TC qdisc del dev $DUMMY handle 1: root"
] ]
},
{
"id": "6e4f",
"name": "Try to delete ets drr class' qdisc while still keeping it in the active list",
"category": [
"qdisc",
"ets",
"tbf"
],
"plugins": {
"requires": [
"nsPlugin",
"scapyPlugin"
]
},
"setup": [
"$IP link set dev $DUMMY up || true",
"$IP addr add 10.10.11.10/24 dev $DUMMY || true",
"$TC qdisc add dev $DUMMY root handle 1: ets bands 2 strict 1",
"$TC qdisc add dev $DUMMY parent 1:2 handle 20: tbf rate 8bit burst 100b latency 1s",
"$TC filter add dev $DUMMY parent 1: basic classid 1:2",
"ping -c2 -W0.01 -s 56 -I $DUMMY 10.10.11.11 || true",
"$TC qdisc change dev $DUMMY root handle 1: ets bands 2 strict 2",
"$TC qdisc change dev $DUMMY root handle 1: ets bands 1 strict 1"
],
"cmdUnderTest": "ping -c1 -W0.01 -s 56 -I $DUMMY 10.10.11.11",
"expExitCode": "1",
"verifyCmd": "$TC -s -j qdisc ls dev $DUMMY root",
"matchJSON": [
{
"kind": "ets",
"handle": "1:",
"bytes": 196,
"packets": 2
}
],
"teardown": [
"$TC qdisc del dev $DUMMY root handle 1:"
]
},
{
"id": "0b8f",
"name": "Try to add ets class to the active list twice",
"category": [
"qdisc",
"ets",
"tbf"
],
"plugins": {
"requires": [
"nsPlugin",
"scapyPlugin"
]
},
"setup": [
"$IP link set dev $DUMMY up || true",
"$IP addr add 10.10.11.10/24 dev $DUMMY || true",
"$TC qdisc add dev $DUMMY root handle 1: ets bands 2 strict 1",
"$TC qdisc add dev $DUMMY parent 1:2 handle 20: tbf rate 8bit burst 100b latency 1s",
"$TC filter add dev $DUMMY parent 1: basic classid 1:2",
"ping -c2 -W0.01 -s 56 -I $DUMMY 10.10.11.11 || true",
"$TC qdisc change dev $DUMMY root handle 1: ets bands 2 strict 2",
"$TC qdisc change dev $DUMMY root handle 1: ets bands 2 strict 1"
],
"cmdUnderTest": "ping -c1 -W0.01 -s 56 -I $DUMMY 10.10.11.11",
"expExitCode": "1",
"verifyCmd": "$TC -s -j qdisc ls dev $DUMMY root",
"matchJSON": [
{
"kind": "ets",
"handle": "1:",
"bytes": 98,
"packets": 1
}
],
"teardown": [
"$TC qdisc del dev $DUMMY root handle 1:"
]
} }
] ]