Including fixes from CAN, netfilter and wireless.

We have an IPv6 routing regression with the relevant fix still
 a WiP. This v2 includes a last-minute revert to avoid more
 problems.
 
 Current release - new code bugs:
 
   - wifi: nl80211: completely disable per-link stats for now
 
 Previous releases - regressions:
 
   - dev_ioctl: take ops lock in hwtstamp lower paths
 
   - netfilter:
     - fix spurious set lookup failures
     - fix lockdep splat due to missing annotation
 
   - genetlink: fix genl_bind() invoking bind() after -EPERM
 
   - phy: transfer phy_config_inband() locking responsibility to phylink
 
   - can: xilinx_can: fix use-after-free of transmitted SKB
 
   - hsr: fix lock warnings
 
   - eth: igb: fix NULL pointer dereference in ethtool loopback test
 
   - eth: i40e: fix Jumbo Frame support after iPXE boot
 
   - eth: macsec: sync features on RTM_NEWLINK
 
 Previous releases - always broken:
 
   - tunnels: reset the GSO metadata before reusing the skb
 
   - mptcp: make sync_socket_options propagate SOCK_KEEPOPEN
 
   - can: j1939: implement NETDEV_UNREGISTER notification hanidler
 
   - wifi: ath12k: fix WMI TLV header misalignment
 
 Signed-off-by: Paolo Abeni <pabeni@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEEg1AjqC77wbdLX2LbKSR5jcyPE6QFAmjC4tYSHHBhYmVuaUBy
 ZWRoYXQuY29tAAoJECkkeY3MjxOkNwcQAIh8d10PYJ6iJvyxqBKVNT2CTr4wVk27
 lT9rB9t4Jdq4EhuDdRmolVPrkXEt4FiGnqPOsYIK+tPN5j6fgPaksA/lCKr3HMhT
 N7qfhCzUFUJQqZEA3pBy5RnRIzNupdTP3rcXFG8QPnGfzdcOZ2m1Tu/36rjt6lmE
 lB+9pLQBjI15r67v08ZzEGHfTX4FqlnlCu/jbcYhXNF6erv3jZRboneytJ3fxbMW
 kRdmi9wctMprKmWVFmaA0OPkwigMBO8xILnYOCcFhQcGKLugc58YGsjzBJbp/yUA
 Qmxb3Gl9pFe97u/URoLPXUE+2hF1X7ydT9hMXrle/gcXVnmU6rN+4xQuEzVPBOK7
 J3qh8IH5joMLaQS4VKSD/Wh0RrtDHJdduLDcjtL8qRkFyS30FqY0USd8prMkIE7I
 /s9Wdi96nC3WEZQtZKg0mRrSeTtbRR0/KO5gEb6MHaAE8ffKJa7MsMZlrh9VoJvM
 PC4PJnOr0Qy5MNAA1MxBWK6Dcsnor4cBkvE35uMoCkUoxOeTnKuruo0kyZYqmrIh
 VOnKrb3+w/I4lDXgQ4kIcpyQfrqMky8R6EGvQvjm2c2OLWZBCmBRU1c0Fjw789O4
 jMdzjs7H9ild2KwBZK4e7KfdoUnlxIza2Yh4pFLUf2R3NqBZ2vQTkpoCF4AK+wzU
 636F5GITLcVe
 =XjZM
 -----END PGP SIGNATURE-----

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

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

  We have an IPv6 routing regression with the relevant fix still a WiP.
  This includes a last-minute revert to avoid more problems.

  Current release - new code bugs:

   - wifi: nl80211: completely disable per-link stats for now

  Previous releases - regressions:

   - dev_ioctl: take ops lock in hwtstamp lower paths

   - netfilter:
       - fix spurious set lookup failures
       - fix lockdep splat due to missing annotation

   - genetlink: fix genl_bind() invoking bind() after -EPERM

   - phy: transfer phy_config_inband() locking responsibility to phylink

   - can: xilinx_can: fix use-after-free of transmitted SKB

   - hsr: fix lock warnings

   - eth:
       - igb: fix NULL pointer dereference in ethtool loopback test
       - i40e: fix Jumbo Frame support after iPXE boot
       - macsec: sync features on RTM_NEWLINK

  Previous releases - always broken:

   - tunnels: reset the GSO metadata before reusing the skb

   - mptcp: make sync_socket_options propagate SOCK_KEEPOPEN

   - can: j1939: implement NETDEV_UNREGISTER notification hanidler

   - wifi: ath12k: fix WMI TLV header misalignment"

* tag 'net-6.17-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (47 commits)
  Revert "net: usb: asix: ax88772: drop phylink use in PM to avoid MDIO runtime PM wakeups"
  hsr: hold rcu and dev lock for hsr_get_port_ndev
  hsr: use hsr_for_each_port_rtnl in hsr_port_get_hsr
  hsr: use rtnl lock when iterating over ports
  wifi: nl80211: completely disable per-link stats for now
  net: usb: asix: ax88772: drop phylink use in PM to avoid MDIO runtime PM wakeups
  net: ethtool: fix wrong type used in struct kernel_ethtool_ts_info
  MAINTAINERS: add Phil as netfilter reviewer
  netfilter: nf_tables: restart set lookup on base_seq change
  netfilter: nf_tables: make nft_set_do_lookup available unconditionally
  netfilter: nf_tables: place base_seq in struct net
  netfilter: nft_set_rbtree: continue traversal if element is inactive
  netfilter: nft_set_pipapo: don't check genbit from packetpath lookups
  netfilter: nft_set_bitmap: fix lockdep splat due to missing annotation
  can: rcar_can: rcar_can_resume(): fix s2ram with PSCI
  can: xilinx_can: xcan_write_frame(): fix use-after-free of transmitted SKB
  can: j1939: j1939_local_ecu_get(): undo increment when j1939_local_ecu_get() fails
  can: j1939: j1939_sk_bind(): call j1939_priv_put() immediately when j1939_local_ecu_get() failed
  can: j1939: implement NETDEV_UNREGISTER notification handler
  selftests: can: enable CONFIG_CAN_VCAN as a module
  ...
This commit is contained in:
Linus Torvalds 2025-09-11 08:54:42 -07:00
commit db87bd2ad1
58 changed files with 542 additions and 227 deletions

View file

@ -256,7 +256,7 @@ attribute-sets:
type: u32
-
name: if-idx
type: u32
type: s32
-
name: reset-reason
type: u32

View file

@ -742,7 +742,7 @@ The broadcast manager sends responses to user space in the same form:
struct timeval ival1, ival2; /* count and subsequent interval */
canid_t can_id; /* unique can_id for task */
__u32 nframes; /* number of can_frames following */
struct can_frame frames[0];
struct can_frame frames[];
};
The aligned payload 'frames' uses the same basic CAN frame structure defined

View file

@ -60,10 +60,10 @@ address announcements. Typically, it is the client side that initiates subflows,
and the server side that announces additional addresses via the ``ADD_ADDR`` and
``REMOVE_ADDR`` options.
Path managers are controlled by the ``net.mptcp.pm_type`` sysctl knob -- see
mptcp-sysctl.rst. There are two types: the in-kernel one (type ``0``) where the
same rules are applied for all the connections (see: ``ip mptcp``) ; and the
userspace one (type ``1``), controlled by a userspace daemon (i.e. `mptcpd
Path managers are controlled by the ``net.mptcp.path_manager`` sysctl knob --
see mptcp-sysctl.rst. There are two types: the in-kernel one (``kernel``) where
the same rules are applied for all the connections (see: ``ip mptcp``) ; and the
userspace one (``userspace``), controlled by a userspace daemon (i.e. `mptcpd
<https://mptcpd.mptcp.dev/>`_) where different rules can be applied for each
connection. The path managers can be controlled via a Netlink API; see
netlink_spec/mptcp_pm.rst.

View file

@ -17479,6 +17479,7 @@ NETFILTER
M: Pablo Neira Ayuso <pablo@netfilter.org>
M: Jozsef Kadlecsik <kadlec@netfilter.org>
M: Florian Westphal <fw@strlen.de>
R: Phil Sutter <phil@nwl.cc>
L: netfilter-devel@vger.kernel.org
L: coreteam@netfilter.org
S: Maintained

View file

@ -861,7 +861,6 @@ static int rcar_can_resume(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct rcar_can_priv *priv = netdev_priv(ndev);
u16 ctlr;
int err;
if (!netif_running(ndev))
@ -873,12 +872,7 @@ static int rcar_can_resume(struct device *dev)
return err;
}
ctlr = readw(&priv->regs->ctlr);
ctlr &= ~RCAR_CAN_CTLR_SLPM;
writew(ctlr, &priv->regs->ctlr);
ctlr &= ~RCAR_CAN_CTLR_CANM;
writew(ctlr, &priv->regs->ctlr);
priv->can.state = CAN_STATE_ERROR_ACTIVE;
rcar_can_start(ndev);
netif_device_attach(ndev);
netif_start_queue(ndev);

View file

@ -690,14 +690,6 @@ static void xcan_write_frame(struct net_device *ndev, struct sk_buff *skb,
dlc |= XCAN_DLCR_EDL_MASK;
}
if (!(priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES) &&
(priv->devtype.flags & XCAN_FLAG_TXFEMP))
can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max, 0);
else
can_put_echo_skb(skb, ndev, 0, 0);
priv->tx_head++;
priv->write_reg(priv, XCAN_FRAME_ID_OFFSET(frame_offset), id);
/* If the CAN frame is RTR frame this write triggers transmission
* (not on CAN FD)
@ -730,6 +722,14 @@ static void xcan_write_frame(struct net_device *ndev, struct sk_buff *skb,
data[1]);
}
}
if (!(priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES) &&
(priv->devtype.flags & XCAN_FLAG_TXFEMP))
can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max, 0);
else
can_put_echo_skb(skb, ndev, 0, 0);
priv->tx_head++;
}
/**

View file

@ -1273,9 +1273,15 @@ static int b53_setup(struct dsa_switch *ds)
*/
ds->untag_vlan_aware_bridge_pvid = true;
/* Ageing time is set in seconds */
ds->ageing_time_min = 1 * 1000;
ds->ageing_time_max = AGE_TIME_MAX * 1000;
if (dev->chip_id == BCM53101_DEVICE_ID) {
/* BCM53101 uses 0.5 second increments */
ds->ageing_time_min = 1 * 500;
ds->ageing_time_max = AGE_TIME_MAX * 500;
} else {
/* Everything else uses 1 second increments */
ds->ageing_time_min = 1 * 1000;
ds->ageing_time_max = AGE_TIME_MAX * 1000;
}
ret = b53_reset_switch(dev);
if (ret) {
@ -2559,7 +2565,10 @@ int b53_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
else
reg = B53_AGING_TIME_CONTROL;
atc = DIV_ROUND_CLOSEST(msecs, 1000);
if (dev->chip_id == BCM53101_DEVICE_ID)
atc = DIV_ROUND_CLOSEST(msecs, 500);
else
atc = DIV_ROUND_CLOSEST(msecs, 1000);
if (!is5325(dev) && !is5365(dev))
atc |= AGE_CHANGE;

View file

@ -2363,7 +2363,8 @@ static void fec_enet_phy_reset_after_clk_enable(struct net_device *ndev)
*/
phy_dev = of_phy_find_device(fep->phy_node);
phy_reset_after_clk_enable(phy_dev);
put_device(&phy_dev->mdio.dev);
if (phy_dev)
put_device(&phy_dev->mdio.dev);
}
}

View file

@ -1561,6 +1561,7 @@ I40E_CHECK_CMD_LENGTH(i40e_aq_set_phy_config);
struct i40e_aq_set_mac_config {
__le16 max_frame_size;
u8 params;
#define I40E_AQ_SET_MAC_CONFIG_CRC_EN BIT(2)
u8 tx_timer_priority; /* bitmap */
__le16 tx_timer_value;
__le16 fc_refresh_threshold;

View file

@ -1189,6 +1189,40 @@ int i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures,
return status;
}
/**
* i40e_aq_set_mac_config - Configure MAC settings
* @hw: pointer to the hw struct
* @max_frame_size: Maximum Frame Size to be supported by the port
* @cmd_details: pointer to command details structure or NULL
*
* Set MAC configuration (0x0603). Note that max_frame_size must be greater
* than zero.
*
* Return: 0 on success, or a negative error code on failure.
*/
int i40e_aq_set_mac_config(struct i40e_hw *hw, u16 max_frame_size,
struct i40e_asq_cmd_details *cmd_details)
{
struct i40e_aq_set_mac_config *cmd;
struct libie_aq_desc desc;
cmd = libie_aq_raw(&desc);
if (max_frame_size == 0)
return -EINVAL;
i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_mac_config);
cmd->max_frame_size = cpu_to_le16(max_frame_size);
cmd->params = I40E_AQ_SET_MAC_CONFIG_CRC_EN;
#define I40E_AQ_SET_MAC_CONFIG_FC_DEFAULT_THRESHOLD 0x7FFF
cmd->fc_refresh_threshold =
cpu_to_le16(I40E_AQ_SET_MAC_CONFIG_FC_DEFAULT_THRESHOLD);
return i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
}
/**
* i40e_aq_clear_pxe_mode
* @hw: pointer to the hw struct

View file

@ -4156,7 +4156,7 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename)
irq_num = pf->msix_entries[base + vector].vector;
irq_set_affinity_notifier(irq_num, NULL);
irq_update_affinity_hint(irq_num, NULL);
free_irq(irq_num, &vsi->q_vectors[vector]);
free_irq(irq_num, vsi->q_vectors[vector]);
}
return err;
}
@ -16045,13 +16045,17 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev_dbg(&pf->pdev->dev, "get supported phy types ret = %pe last_status = %s\n",
ERR_PTR(err), libie_aq_str(pf->hw.aq.asq_last_status));
/* make sure the MFS hasn't been set lower than the default */
#define MAX_FRAME_SIZE_DEFAULT 0x2600
val = FIELD_GET(I40E_PRTGL_SAH_MFS_MASK,
rd32(&pf->hw, I40E_PRTGL_SAH));
if (val < MAX_FRAME_SIZE_DEFAULT)
dev_warn(&pdev->dev, "MFS for port %x (%d) has been set below the default (%d)\n",
pf->hw.port, val, MAX_FRAME_SIZE_DEFAULT);
err = i40e_aq_set_mac_config(hw, MAX_FRAME_SIZE_DEFAULT, NULL);
if (err)
dev_warn(&pdev->dev, "set mac config ret = %pe last_status = %s\n",
ERR_PTR(err), libie_aq_str(pf->hw.aq.asq_last_status));
/* Make sure the MFS is set to the expected value */
val = rd32(hw, I40E_PRTGL_SAH);
FIELD_MODIFY(I40E_PRTGL_SAH_MFS_MASK, &val, MAX_FRAME_SIZE_DEFAULT);
wr32(hw, I40E_PRTGL_SAH, val);
/* Add a filter to drop all Flow control frames from any VSI from being
* transmitted. By doing so we stop a malicious VF from sending out

View file

@ -98,6 +98,8 @@ int i40e_aq_set_mac_loopback(struct i40e_hw *hw,
struct i40e_asq_cmd_details *cmd_details);
int i40e_aq_set_phy_int_mask(struct i40e_hw *hw, u16 mask,
struct i40e_asq_cmd_details *cmd_details);
int i40e_aq_set_mac_config(struct i40e_hw *hw, u16 max_frame_size,
struct i40e_asq_cmd_details *cmd_details);
int i40e_aq_clear_pxe_mode(struct i40e_hw *hw,
struct i40e_asq_cmd_details *cmd_details);
int i40e_aq_set_link_restart_an(struct i40e_hw *hw,

View file

@ -2081,11 +2081,8 @@ static void igb_diag_test(struct net_device *netdev,
} else {
dev_info(&adapter->pdev->dev, "online testing starting\n");
/* PHY is powered down when interface is down */
if (if_running && igb_link_test(adapter, &data[TEST_LINK]))
if (igb_link_test(adapter, &data[TEST_LINK]))
eth_test->flags |= ETH_TEST_FL_FAILED;
else
data[TEST_LINK] = 0;
/* Online tests aren't run; pass by default */
data[TEST_REG] = 0;

View file

@ -4453,8 +4453,7 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring)
if (xdp_rxq_info_is_reg(&rx_ring->xdp_rxq))
xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
res = xdp_rxq_info_reg(&rx_ring->xdp_rxq, rx_ring->netdev,
rx_ring->queue_index,
rx_ring->q_vector->napi.napi_id);
rx_ring->queue_index, 0);
if (res < 0) {
dev_err(dev, "Failed to register xdp_rxq index %u\n",
rx_ring->queue_index);

View file

@ -654,7 +654,7 @@ static void icssg_prueth_hsr_fdb_add_del(struct prueth_emac *emac,
static int icssg_prueth_hsr_add_mcast(struct net_device *ndev, const u8 *addr)
{
struct net_device *real_dev;
struct net_device *real_dev, *port_dev;
struct prueth_emac *emac;
u8 vlan_id, i;
@ -663,11 +663,15 @@ static int icssg_prueth_hsr_add_mcast(struct net_device *ndev, const u8 *addr)
if (is_hsr_master(real_dev)) {
for (i = HSR_PT_SLAVE_A; i < HSR_PT_INTERLINK; i++) {
emac = netdev_priv(hsr_get_port_ndev(real_dev, i));
if (!emac)
port_dev = hsr_get_port_ndev(real_dev, i);
emac = netdev_priv(port_dev);
if (!emac) {
dev_put(port_dev);
return -EINVAL;
}
icssg_prueth_hsr_fdb_add_del(emac, addr, vlan_id,
true);
dev_put(port_dev);
}
} else {
emac = netdev_priv(real_dev);
@ -679,7 +683,7 @@ static int icssg_prueth_hsr_add_mcast(struct net_device *ndev, const u8 *addr)
static int icssg_prueth_hsr_del_mcast(struct net_device *ndev, const u8 *addr)
{
struct net_device *real_dev;
struct net_device *real_dev, *port_dev;
struct prueth_emac *emac;
u8 vlan_id, i;
@ -688,11 +692,15 @@ static int icssg_prueth_hsr_del_mcast(struct net_device *ndev, const u8 *addr)
if (is_hsr_master(real_dev)) {
for (i = HSR_PT_SLAVE_A; i < HSR_PT_INTERLINK; i++) {
emac = netdev_priv(hsr_get_port_ndev(real_dev, i));
if (!emac)
port_dev = hsr_get_port_ndev(real_dev, i);
emac = netdev_priv(port_dev);
if (!emac) {
dev_put(port_dev);
return -EINVAL;
}
icssg_prueth_hsr_fdb_add_del(emac, addr, vlan_id,
false);
dev_put(port_dev);
}
} else {
emac = netdev_priv(real_dev);

View file

@ -2078,10 +2078,6 @@ static void wx_setup_mrqc(struct wx *wx)
{
u32 rss_field = 0;
/* VT, and RSS do not coexist at the same time */
if (test_bit(WX_FLAG_VMDQ_ENABLED, wx->flags))
return;
/* Disable indicating checksum in descriptor, enables RSS hash */
wr32m(wx, WX_PSR_CTL, WX_PSR_CTL_PCSD, WX_PSR_CTL_PCSD);

View file

@ -4286,6 +4286,7 @@ static int macsec_newlink(struct net_device *dev,
if (err < 0)
goto del_dev;
netdev_update_features(dev);
netif_stacked_transfer_operstate(real_dev, dev);
linkwatch_fire_event(dev);

View file

@ -361,7 +361,7 @@ config NXP_TJA11XX_PHY
tristate "NXP TJA11xx PHYs support"
depends on HWMON
help
Currently supports the NXP TJA1100 and TJA1101 PHY.
Currently supports the NXP TJA1100, TJA1101 and TJA1102 PHYs.
config NCN26000_PHY
tristate "Onsemi 10BASE-T1S Ethernet PHY"

View file

@ -1065,23 +1065,19 @@ EXPORT_SYMBOL_GPL(phy_inband_caps);
*/
int phy_config_inband(struct phy_device *phydev, unsigned int modes)
{
int err;
lockdep_assert_held(&phydev->lock);
if (!!(modes & LINK_INBAND_DISABLE) +
!!(modes & LINK_INBAND_ENABLE) +
!!(modes & LINK_INBAND_BYPASS) != 1)
return -EINVAL;
mutex_lock(&phydev->lock);
if (!phydev->drv)
err = -EIO;
return -EIO;
else if (!phydev->drv->config_inband)
err = -EOPNOTSUPP;
else
err = phydev->drv->config_inband(phydev, modes);
mutex_unlock(&phydev->lock);
return -EOPNOTSUPP;
return err;
return phydev->drv->config_inband(phydev, modes);
}
EXPORT_SYMBOL(phy_config_inband);

View file

@ -287,8 +287,7 @@ static bool phy_uses_state_machine(struct phy_device *phydev)
if (phydev->phy_link_change == phy_link_change)
return phydev->attached_dev && phydev->adjust_link;
/* phydev->phy_link_change is implicitly phylink_phy_change() */
return true;
return !!phydev->phy_link_change;
}
static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
@ -1864,6 +1863,8 @@ void phy_detach(struct phy_device *phydev)
phydev->attached_dev = NULL;
phy_link_topo_del_phy(dev, phydev);
}
phydev->phy_link_change = NULL;
phydev->phylink = NULL;
if (!phydev->is_on_sfp_module)

View file

@ -67,6 +67,8 @@ struct phylink {
struct timer_list link_poll;
struct mutex state_mutex;
/* Serialize updates to pl->phydev with phylink_resolve() */
struct mutex phydev_mutex;
struct phylink_link_state phy_state;
unsigned int phy_ib_mode;
struct work_struct resolve;
@ -1432,6 +1434,7 @@ static void phylink_get_fixed_state(struct phylink *pl,
static void phylink_mac_initial_config(struct phylink *pl, bool force_restart)
{
struct phylink_link_state link_state;
struct phy_device *phy = pl->phydev;
switch (pl->req_link_an_mode) {
case MLO_AN_PHY:
@ -1455,7 +1458,11 @@ static void phylink_mac_initial_config(struct phylink *pl, bool force_restart)
link_state.link = false;
phylink_apply_manual_flow(pl, &link_state);
if (phy)
mutex_lock(&phy->lock);
phylink_major_config(pl, force_restart, &link_state);
if (phy)
mutex_unlock(&phy->lock);
}
static const char *phylink_pause_to_str(int pause)
@ -1591,8 +1598,13 @@ static void phylink_resolve(struct work_struct *w)
struct phylink_link_state link_state;
bool mac_config = false;
bool retrigger = false;
struct phy_device *phy;
bool cur_link_state;
mutex_lock(&pl->phydev_mutex);
phy = pl->phydev;
if (phy)
mutex_lock(&phy->lock);
mutex_lock(&pl->state_mutex);
cur_link_state = phylink_link_is_up(pl);
@ -1626,11 +1638,11 @@ static void phylink_resolve(struct work_struct *w)
/* If we have a phy, the "up" state is the union of both the
* PHY and the MAC
*/
if (pl->phydev)
if (phy)
link_state.link &= pl->phy_state.link;
/* Only update if the PHY link is up */
if (pl->phydev && pl->phy_state.link) {
if (phy && pl->phy_state.link) {
/* If the interface has changed, force a link down
* event if the link isn't already down, and re-resolve.
*/
@ -1694,6 +1706,9 @@ static void phylink_resolve(struct work_struct *w)
queue_work(system_power_efficient_wq, &pl->resolve);
}
mutex_unlock(&pl->state_mutex);
if (phy)
mutex_unlock(&phy->lock);
mutex_unlock(&pl->phydev_mutex);
}
static void phylink_run_resolve(struct phylink *pl)
@ -1829,6 +1844,7 @@ struct phylink *phylink_create(struct phylink_config *config,
if (!pl)
return ERR_PTR(-ENOMEM);
mutex_init(&pl->phydev_mutex);
mutex_init(&pl->state_mutex);
INIT_WORK(&pl->resolve, phylink_resolve);
@ -2089,6 +2105,7 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,
dev_name(&phy->mdio.dev), phy->drv->name, irq_str);
kfree(irq_str);
mutex_lock(&pl->phydev_mutex);
mutex_lock(&phy->lock);
mutex_lock(&pl->state_mutex);
pl->phydev = phy;
@ -2134,6 +2151,7 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,
mutex_unlock(&pl->state_mutex);
mutex_unlock(&phy->lock);
mutex_unlock(&pl->phydev_mutex);
phylink_dbg(pl,
"phy: %s setting supported %*pb advertising %*pb\n",
@ -2312,6 +2330,7 @@ void phylink_disconnect_phy(struct phylink *pl)
ASSERT_RTNL();
mutex_lock(&pl->phydev_mutex);
phy = pl->phydev;
if (phy) {
mutex_lock(&phy->lock);
@ -2321,8 +2340,11 @@ void phylink_disconnect_phy(struct phylink *pl)
pl->mac_tx_clk_stop = false;
mutex_unlock(&pl->state_mutex);
mutex_unlock(&phy->lock);
flush_work(&pl->resolve);
}
mutex_unlock(&pl->phydev_mutex);
if (phy) {
flush_work(&pl->resolve);
phy_disconnect(phy);
}
}

View file

@ -4078,12 +4078,68 @@ static int ath12k_mac_fils_discovery(struct ath12k_link_vif *arvif,
return ret;
}
static void ath12k_mac_vif_setup_ps(struct ath12k_link_vif *arvif)
{
struct ath12k *ar = arvif->ar;
struct ieee80211_vif *vif = arvif->ahvif->vif;
struct ieee80211_conf *conf = &ath12k_ar_to_hw(ar)->conf;
enum wmi_sta_powersave_param param;
struct ieee80211_bss_conf *info;
enum wmi_sta_ps_mode psmode;
int ret;
int timeout;
bool enable_ps;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (vif->type != NL80211_IFTYPE_STATION)
return;
enable_ps = arvif->ahvif->ps;
if (enable_ps) {
psmode = WMI_STA_PS_MODE_ENABLED;
param = WMI_STA_PS_PARAM_INACTIVITY_TIME;
timeout = conf->dynamic_ps_timeout;
if (timeout == 0) {
info = ath12k_mac_get_link_bss_conf(arvif);
if (!info) {
ath12k_warn(ar->ab, "unable to access bss link conf in setup ps for vif %pM link %u\n",
vif->addr, arvif->link_id);
return;
}
/* firmware doesn't like 0 */
timeout = ieee80211_tu_to_usec(info->beacon_int) / 1000;
}
ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param,
timeout);
if (ret) {
ath12k_warn(ar->ab, "failed to set inactivity time for vdev %d: %i\n",
arvif->vdev_id, ret);
return;
}
} else {
psmode = WMI_STA_PS_MODE_DISABLED;
}
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %d psmode %s\n",
arvif->vdev_id, psmode ? "enable" : "disable");
ret = ath12k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id, psmode);
if (ret)
ath12k_warn(ar->ab, "failed to set sta power save mode %d for vdev %d: %d\n",
psmode, arvif->vdev_id, ret);
}
static void ath12k_mac_op_vif_cfg_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u64 changed)
{
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
unsigned long links = ahvif->links_map;
struct ieee80211_vif_cfg *vif_cfg;
struct ieee80211_bss_conf *info;
struct ath12k_link_vif *arvif;
struct ieee80211_sta *sta;
@ -4147,61 +4203,24 @@ static void ath12k_mac_op_vif_cfg_changed(struct ieee80211_hw *hw,
}
}
}
}
static void ath12k_mac_vif_setup_ps(struct ath12k_link_vif *arvif)
{
struct ath12k *ar = arvif->ar;
struct ieee80211_vif *vif = arvif->ahvif->vif;
struct ieee80211_conf *conf = &ath12k_ar_to_hw(ar)->conf;
enum wmi_sta_powersave_param param;
struct ieee80211_bss_conf *info;
enum wmi_sta_ps_mode psmode;
int ret;
int timeout;
bool enable_ps;
if (changed & BSS_CHANGED_PS) {
links = ahvif->links_map;
vif_cfg = &vif->cfg;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
if (!arvif || !arvif->ar)
continue;
if (vif->type != NL80211_IFTYPE_STATION)
return;
ar = arvif->ar;
enable_ps = arvif->ahvif->ps;
if (enable_ps) {
psmode = WMI_STA_PS_MODE_ENABLED;
param = WMI_STA_PS_PARAM_INACTIVITY_TIME;
timeout = conf->dynamic_ps_timeout;
if (timeout == 0) {
info = ath12k_mac_get_link_bss_conf(arvif);
if (!info) {
ath12k_warn(ar->ab, "unable to access bss link conf in setup ps for vif %pM link %u\n",
vif->addr, arvif->link_id);
return;
if (ar->ab->hw_params->supports_sta_ps) {
ahvif->ps = vif_cfg->ps;
ath12k_mac_vif_setup_ps(arvif);
}
/* firmware doesn't like 0 */
timeout = ieee80211_tu_to_usec(info->beacon_int) / 1000;
}
ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param,
timeout);
if (ret) {
ath12k_warn(ar->ab, "failed to set inactivity time for vdev %d: %i\n",
arvif->vdev_id, ret);
return;
}
} else {
psmode = WMI_STA_PS_MODE_DISABLED;
}
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %d psmode %s\n",
arvif->vdev_id, psmode ? "enable" : "disable");
ret = ath12k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id, psmode);
if (ret)
ath12k_warn(ar->ab, "failed to set sta power save mode %d for vdev %d: %d\n",
psmode, arvif->vdev_id, ret);
}
static bool ath12k_mac_supports_tpc(struct ath12k *ar, struct ath12k_vif *ahvif,
@ -4223,7 +4242,6 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar,
{
struct ath12k_vif *ahvif = arvif->ahvif;
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
struct ieee80211_vif_cfg *vif_cfg = &vif->cfg;
struct cfg80211_chan_def def;
u32 param_id, param_value;
enum nl80211_band band;
@ -4510,12 +4528,6 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar,
}
ath12k_mac_fils_discovery(arvif, info);
if (changed & BSS_CHANGED_PS &&
ar->ab->hw_params->supports_sta_ps) {
ahvif->ps = vif_cfg->ps;
ath12k_mac_vif_setup_ps(arvif);
}
}
static struct ath12k_vif_cache *ath12k_ahvif_get_link_cache(struct ath12k_vif *ahvif,

View file

@ -843,7 +843,7 @@ int ath12k_wmi_mgmt_send(struct ath12k_link_vif *arvif, u32 buf_id,
cmd->tx_params_valid = 0;
frame_tlv = (struct wmi_tlv *)(skb->data + sizeof(*cmd));
frame_tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, buf_len);
frame_tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, buf_len_aligned);
memcpy(frame_tlv->value, frame->data, buf_len);

View file

@ -124,13 +124,13 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x0082, 0x1304, iwl6005_mac_cfg)},/* low 5GHz active */
{IWL_PCI_DEVICE(0x0082, 0x1305, iwl6005_mac_cfg)},/* high 5GHz active */
/* 6x30 Series */
{IWL_PCI_DEVICE(0x008A, 0x5305, iwl1000_mac_cfg)},
{IWL_PCI_DEVICE(0x008A, 0x5307, iwl1000_mac_cfg)},
{IWL_PCI_DEVICE(0x008A, 0x5325, iwl1000_mac_cfg)},
{IWL_PCI_DEVICE(0x008A, 0x5327, iwl1000_mac_cfg)},
{IWL_PCI_DEVICE(0x008B, 0x5315, iwl1000_mac_cfg)},
{IWL_PCI_DEVICE(0x008B, 0x5317, iwl1000_mac_cfg)},
/* 1030/6x30 Series */
{IWL_PCI_DEVICE(0x008A, 0x5305, iwl6030_mac_cfg)},
{IWL_PCI_DEVICE(0x008A, 0x5307, iwl6030_mac_cfg)},
{IWL_PCI_DEVICE(0x008A, 0x5325, iwl6030_mac_cfg)},
{IWL_PCI_DEVICE(0x008A, 0x5327, iwl6030_mac_cfg)},
{IWL_PCI_DEVICE(0x008B, 0x5315, iwl6030_mac_cfg)},
{IWL_PCI_DEVICE(0x008B, 0x5317, iwl6030_mac_cfg)},
{IWL_PCI_DEVICE(0x0090, 0x5211, iwl6030_mac_cfg)},
{IWL_PCI_DEVICE(0x0090, 0x5215, iwl6030_mac_cfg)},
{IWL_PCI_DEVICE(0x0090, 0x5216, iwl6030_mac_cfg)},
@ -181,12 +181,12 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x08AE, 0x1027, iwl1000_mac_cfg)},
/* 130 Series WiFi */
{IWL_PCI_DEVICE(0x0896, 0x5005, iwl1000_mac_cfg)},
{IWL_PCI_DEVICE(0x0896, 0x5007, iwl1000_mac_cfg)},
{IWL_PCI_DEVICE(0x0897, 0x5015, iwl1000_mac_cfg)},
{IWL_PCI_DEVICE(0x0897, 0x5017, iwl1000_mac_cfg)},
{IWL_PCI_DEVICE(0x0896, 0x5025, iwl1000_mac_cfg)},
{IWL_PCI_DEVICE(0x0896, 0x5027, iwl1000_mac_cfg)},
{IWL_PCI_DEVICE(0x0896, 0x5005, iwl6030_mac_cfg)},
{IWL_PCI_DEVICE(0x0896, 0x5007, iwl6030_mac_cfg)},
{IWL_PCI_DEVICE(0x0897, 0x5015, iwl6030_mac_cfg)},
{IWL_PCI_DEVICE(0x0897, 0x5017, iwl6030_mac_cfg)},
{IWL_PCI_DEVICE(0x0896, 0x5025, iwl6030_mac_cfg)},
{IWL_PCI_DEVICE(0x0896, 0x5027, iwl6030_mac_cfg)},
/* 2x00 Series */
{IWL_PCI_DEVICE(0x0890, 0x4022, iwl2000_mac_cfg)},

View file

@ -277,7 +277,9 @@ static void virt_wifi_connect_complete(struct work_struct *work)
priv->is_connected = true;
/* Schedules an event that acquires the rtnl lock. */
cfg80211_connect_result(priv->upperdev, requested_bss, NULL, 0, NULL, 0,
cfg80211_connect_result(priv->upperdev,
priv->is_connected ? fake_router_bssid : NULL,
NULL, 0, NULL, 0,
status, GFP_KERNEL);
netif_carrier_on(priv->upperdev);
}

View file

@ -856,8 +856,8 @@ struct kernel_ethtool_ts_info {
enum hwtstamp_provider_qualifier phc_qualifier;
enum hwtstamp_source phc_source;
int phc_phyindex;
enum hwtstamp_tx_types tx_types;
enum hwtstamp_rx_filters rx_filters;
u32 tx_types;
u32 rx_filters;
};
/**

View file

@ -1912,7 +1912,6 @@ struct nftables_pernet {
struct mutex commit_mutex;
u64 table_handle;
u64 tstamp;
unsigned int base_seq;
unsigned int gc_seq;
u8 validate_state;
struct work_struct destroy_work;

View file

@ -109,17 +109,11 @@ nft_hash_lookup_fast(const struct net *net, const struct nft_set *set,
const struct nft_set_ext *
nft_hash_lookup(const struct net *net, const struct nft_set *set,
const u32 *key);
#endif
const struct nft_set_ext *
nft_set_do_lookup(const struct net *net, const struct nft_set *set,
const u32 *key);
#else
static inline const struct nft_set_ext *
nft_set_do_lookup(const struct net *net, const struct nft_set *set,
const u32 *key)
{
return set->ops->lookup(net, set, key);
}
#endif
/* called from nft_pipapo_avx2.c */
const struct nft_set_ext *

View file

@ -3,6 +3,7 @@
#define _NETNS_NFTABLES_H_
struct netns_nftables {
unsigned int base_seq;
u8 gencursor;
};

View file

@ -324,6 +324,13 @@ int br_boolopt_multi_toggle(struct net_bridge *br,
int err = 0;
int opt_id;
opt_id = find_next_bit(&bitmap, BITS_PER_LONG, BR_BOOLOPT_MAX);
if (opt_id != BITS_PER_LONG) {
NL_SET_ERR_MSG_FMT_MOD(extack, "Unknown boolean option %d",
opt_id);
return -EINVAL;
}
for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) {
bool on = !!(bm->optval & BIT(opt_id));

View file

@ -290,8 +290,11 @@ int j1939_local_ecu_get(struct j1939_priv *priv, name_t name, u8 sa)
if (!ecu)
ecu = j1939_ecu_create_locked(priv, name);
err = PTR_ERR_OR_ZERO(ecu);
if (err)
if (err) {
if (j1939_address_is_unicast(sa))
priv->ents[sa].nusers--;
goto done;
}
ecu->nusers++;
/* TODO: do we care if ecu->addr != sa? */

View file

@ -212,6 +212,7 @@ void j1939_priv_get(struct j1939_priv *priv);
/* notify/alert all j1939 sockets bound to ifindex */
void j1939_sk_netdev_event_netdown(struct j1939_priv *priv);
void j1939_sk_netdev_event_unregister(struct j1939_priv *priv);
int j1939_cancel_active_session(struct j1939_priv *priv, struct sock *sk);
void j1939_tp_init(struct j1939_priv *priv);

View file

@ -377,6 +377,9 @@ static int j1939_netdev_notify(struct notifier_block *nb,
j1939_sk_netdev_event_netdown(priv);
j1939_ecu_unmap_all(priv);
break;
case NETDEV_UNREGISTER:
j1939_sk_netdev_event_unregister(priv);
break;
}
j1939_priv_put(priv);

View file

@ -521,6 +521,9 @@ static int j1939_sk_bind(struct socket *sock, struct sockaddr *uaddr, int len)
ret = j1939_local_ecu_get(priv, jsk->addr.src_name, jsk->addr.sa);
if (ret) {
j1939_netdev_stop(priv);
jsk->priv = NULL;
synchronize_rcu();
j1939_priv_put(priv);
goto out_release_sock;
}
@ -1300,6 +1303,55 @@ void j1939_sk_netdev_event_netdown(struct j1939_priv *priv)
read_unlock_bh(&priv->j1939_socks_lock);
}
void j1939_sk_netdev_event_unregister(struct j1939_priv *priv)
{
struct sock *sk;
struct j1939_sock *jsk;
bool wait_rcu = false;
rescan: /* The caller is holding a ref on this "priv" via j1939_priv_get_by_ndev(). */
read_lock_bh(&priv->j1939_socks_lock);
list_for_each_entry(jsk, &priv->j1939_socks, list) {
/* Skip if j1939_jsk_add() is not called on this socket. */
if (!(jsk->state & J1939_SOCK_BOUND))
continue;
sk = &jsk->sk;
sock_hold(sk);
read_unlock_bh(&priv->j1939_socks_lock);
/* Check if j1939_jsk_del() is not yet called on this socket after holding
* socket's lock, for both j1939_sk_bind() and j1939_sk_release() call
* j1939_jsk_del() with socket's lock held.
*/
lock_sock(sk);
if (jsk->state & J1939_SOCK_BOUND) {
/* Neither j1939_sk_bind() nor j1939_sk_release() called j1939_jsk_del().
* Make this socket no longer bound, by pretending as if j1939_sk_bind()
* dropped old references but did not get new references.
*/
j1939_jsk_del(priv, jsk);
j1939_local_ecu_put(priv, jsk->addr.src_name, jsk->addr.sa);
j1939_netdev_stop(priv);
/* Call j1939_priv_put() now and prevent j1939_sk_sock_destruct() from
* calling the corresponding j1939_priv_put().
*
* j1939_sk_sock_destruct() is supposed to call j1939_priv_put() after
* an RCU grace period. But since the caller is holding a ref on this
* "priv", we can defer synchronize_rcu() until immediately before
* the caller calls j1939_priv_put().
*/
j1939_priv_put(priv);
jsk->priv = NULL;
wait_rcu = true;
}
release_sock(sk);
sock_put(sk);
goto rescan;
}
read_unlock_bh(&priv->j1939_socks_lock);
if (wait_rcu)
synchronize_rcu();
}
static int j1939_sk_no_ioctlcmd(struct socket *sock, unsigned int cmd,
unsigned long arg)
{

View file

@ -464,8 +464,15 @@ int generic_hwtstamp_get_lower(struct net_device *dev,
if (!netif_device_present(dev))
return -ENODEV;
if (ops->ndo_hwtstamp_get)
return dev_get_hwtstamp_phylib(dev, kernel_cfg);
if (ops->ndo_hwtstamp_get) {
int err;
netdev_lock_ops(dev);
err = dev_get_hwtstamp_phylib(dev, kernel_cfg);
netdev_unlock_ops(dev);
return err;
}
/* Legacy path: unconverted lower driver */
return generic_hwtstamp_ioctl_lower(dev, SIOCGHWTSTAMP, kernel_cfg);
@ -481,8 +488,15 @@ int generic_hwtstamp_set_lower(struct net_device *dev,
if (!netif_device_present(dev))
return -ENODEV;
if (ops->ndo_hwtstamp_set)
return dev_set_hwtstamp_phylib(dev, kernel_cfg, extack);
if (ops->ndo_hwtstamp_set) {
int err;
netdev_lock_ops(dev);
err = dev_set_hwtstamp_phylib(dev, kernel_cfg, extack);
netdev_unlock_ops(dev);
return err;
}
/* Legacy path: unconverted lower driver */
return generic_hwtstamp_ioctl_lower(dev, SIOCSHWTSTAMP, kernel_cfg);

View file

@ -49,7 +49,7 @@ static bool hsr_check_carrier(struct hsr_port *master)
ASSERT_RTNL();
hsr_for_each_port(master->hsr, port) {
hsr_for_each_port_rtnl(master->hsr, port) {
if (port->type != HSR_PT_MASTER && is_slave_up(port->dev)) {
netif_carrier_on(master->dev);
return true;
@ -105,7 +105,7 @@ int hsr_get_max_mtu(struct hsr_priv *hsr)
struct hsr_port *port;
mtu_max = ETH_DATA_LEN;
hsr_for_each_port(hsr, port)
hsr_for_each_port_rtnl(hsr, port)
if (port->type != HSR_PT_MASTER)
mtu_max = min(port->dev->mtu, mtu_max);
@ -139,7 +139,7 @@ static int hsr_dev_open(struct net_device *dev)
hsr = netdev_priv(dev);
hsr_for_each_port(hsr, port) {
hsr_for_each_port_rtnl(hsr, port) {
if (port->type == HSR_PT_MASTER)
continue;
switch (port->type) {
@ -172,7 +172,7 @@ static int hsr_dev_close(struct net_device *dev)
struct hsr_priv *hsr;
hsr = netdev_priv(dev);
hsr_for_each_port(hsr, port) {
hsr_for_each_port_rtnl(hsr, port) {
if (port->type == HSR_PT_MASTER)
continue;
switch (port->type) {
@ -205,7 +205,7 @@ static netdev_features_t hsr_features_recompute(struct hsr_priv *hsr,
* may become enabled.
*/
features &= ~NETIF_F_ONE_FOR_ALL;
hsr_for_each_port(hsr, port)
hsr_for_each_port_rtnl(hsr, port)
features = netdev_increment_features(features,
port->dev->features,
mask);
@ -226,6 +226,7 @@ static netdev_tx_t hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)
struct hsr_priv *hsr = netdev_priv(dev);
struct hsr_port *master;
rcu_read_lock();
master = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
if (master) {
skb->dev = master->dev;
@ -238,6 +239,8 @@ static netdev_tx_t hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)
dev_core_stats_tx_dropped_inc(dev);
dev_kfree_skb_any(skb);
}
rcu_read_unlock();
return NETDEV_TX_OK;
}
@ -484,7 +487,7 @@ static void hsr_set_rx_mode(struct net_device *dev)
hsr = netdev_priv(dev);
hsr_for_each_port(hsr, port) {
hsr_for_each_port_rtnl(hsr, port) {
if (port->type == HSR_PT_MASTER)
continue;
switch (port->type) {
@ -506,7 +509,7 @@ static void hsr_change_rx_flags(struct net_device *dev, int change)
hsr = netdev_priv(dev);
hsr_for_each_port(hsr, port) {
hsr_for_each_port_rtnl(hsr, port) {
if (port->type == HSR_PT_MASTER)
continue;
switch (port->type) {
@ -534,7 +537,7 @@ static int hsr_ndo_vlan_rx_add_vid(struct net_device *dev,
hsr = netdev_priv(dev);
hsr_for_each_port(hsr, port) {
hsr_for_each_port_rtnl(hsr, port) {
if (port->type == HSR_PT_MASTER ||
port->type == HSR_PT_INTERLINK)
continue;
@ -580,7 +583,7 @@ static int hsr_ndo_vlan_rx_kill_vid(struct net_device *dev,
hsr = netdev_priv(dev);
hsr_for_each_port(hsr, port) {
hsr_for_each_port_rtnl(hsr, port) {
switch (port->type) {
case HSR_PT_SLAVE_A:
case HSR_PT_SLAVE_B:
@ -672,9 +675,14 @@ struct net_device *hsr_get_port_ndev(struct net_device *ndev,
struct hsr_priv *hsr = netdev_priv(ndev);
struct hsr_port *port;
rcu_read_lock();
hsr_for_each_port(hsr, port)
if (port->type == pt)
if (port->type == pt) {
dev_hold(port->dev);
rcu_read_unlock();
return port->dev;
}
rcu_read_unlock();
return NULL;
}
EXPORT_SYMBOL(hsr_get_port_ndev);

View file

@ -22,7 +22,7 @@ static bool hsr_slave_empty(struct hsr_priv *hsr)
{
struct hsr_port *port;
hsr_for_each_port(hsr, port)
hsr_for_each_port_rtnl(hsr, port)
if (port->type != HSR_PT_MASTER)
return false;
return true;
@ -134,7 +134,7 @@ struct hsr_port *hsr_port_get_hsr(struct hsr_priv *hsr, enum hsr_port_type pt)
{
struct hsr_port *port;
hsr_for_each_port(hsr, port)
hsr_for_each_port_rtnl(hsr, port)
if (port->type == pt)
return port;
return NULL;

View file

@ -224,6 +224,9 @@ struct hsr_priv {
#define hsr_for_each_port(hsr, port) \
list_for_each_entry_rcu((port), &(hsr)->ports, port_list)
#define hsr_for_each_port_rtnl(hsr, port) \
list_for_each_entry_rcu((port), &(hsr)->ports, port_list, lockdep_rtnl_is_held())
struct hsr_port *hsr_port_get_hsr(struct hsr_priv *hsr, enum hsr_port_type pt);
/* Caller must ensure skb is a valid HSR frame */

View file

@ -206,6 +206,9 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
if (!pskb_may_pull(skb, ETH_HLEN + sizeof(struct iphdr)))
return -EINVAL;
if (skb_is_gso(skb))
skb_gso_reset(skb);
skb_copy_bits(skb, skb_mac_offset(skb), &eh, ETH_HLEN);
pskb_pull(skb, ETH_HLEN);
skb_reset_network_header(skb);
@ -300,6 +303,9 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
if (!pskb_may_pull(skb, ETH_HLEN + sizeof(struct ipv6hdr)))
return -EINVAL;
if (skb_is_gso(skb))
skb_gso_reset(skb);
skb_copy_bits(skb, skb_mac_offset(skb), &eh, ETH_HLEN);
pskb_pull(skb, ETH_HLEN);
skb_reset_network_header(skb);

View file

@ -1532,13 +1532,12 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)
{
static const unsigned int tx_rx_locks = SOCK_RCVBUF_LOCK | SOCK_SNDBUF_LOCK;
struct sock *sk = (struct sock *)msk;
bool keep_open;
if (ssk->sk_prot->keepalive) {
if (sock_flag(sk, SOCK_KEEPOPEN))
ssk->sk_prot->keepalive(ssk, 1);
else
ssk->sk_prot->keepalive(ssk, 0);
}
keep_open = sock_flag(sk, SOCK_KEEPOPEN);
if (ssk->sk_prot->keepalive)
ssk->sk_prot->keepalive(ssk, keep_open);
sock_valbool_flag(ssk, SOCK_KEEPOPEN, keep_open);
ssk->sk_priority = sk->sk_priority;
ssk->sk_bound_dev_if = sk->sk_bound_dev_if;

View file

@ -1131,11 +1131,14 @@ nf_tables_chain_type_lookup(struct net *net, const struct nlattr *nla,
return ERR_PTR(-ENOENT);
}
static __be16 nft_base_seq(const struct net *net)
static unsigned int nft_base_seq(const struct net *net)
{
struct nftables_pernet *nft_net = nft_pernet(net);
return READ_ONCE(net->nft.base_seq);
}
return htons(nft_net->base_seq & 0xffff);
static __be16 nft_base_seq_be16(const struct net *net)
{
return htons(nft_base_seq(net) & 0xffff);
}
static const struct nla_policy nft_table_policy[NFTA_TABLE_MAX + 1] = {
@ -1155,7 +1158,7 @@ static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net,
nlh = nfnl_msg_put(skb, portid, seq,
nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event),
flags, family, NFNETLINK_V0, nft_base_seq(net));
flags, family, NFNETLINK_V0, nft_base_seq_be16(net));
if (!nlh)
goto nla_put_failure;
@ -1248,7 +1251,7 @@ static int nf_tables_dump_tables(struct sk_buff *skb,
rcu_read_lock();
nft_net = nft_pernet(net);
cb->seq = READ_ONCE(nft_net->base_seq);
cb->seq = nft_base_seq(net);
list_for_each_entry_rcu(table, &nft_net->tables, list) {
if (family != NFPROTO_UNSPEC && family != table->family)
@ -2030,7 +2033,7 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net,
nlh = nfnl_msg_put(skb, portid, seq,
nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event),
flags, family, NFNETLINK_V0, nft_base_seq(net));
flags, family, NFNETLINK_V0, nft_base_seq_be16(net));
if (!nlh)
goto nla_put_failure;
@ -2133,7 +2136,7 @@ static int nf_tables_dump_chains(struct sk_buff *skb,
rcu_read_lock();
nft_net = nft_pernet(net);
cb->seq = READ_ONCE(nft_net->base_seq);
cb->seq = nft_base_seq(net);
list_for_each_entry_rcu(table, &nft_net->tables, list) {
if (family != NFPROTO_UNSPEC && family != table->family)
@ -3671,7 +3674,7 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net,
u16 type = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event);
nlh = nfnl_msg_put(skb, portid, seq, type, flags, family, NFNETLINK_V0,
nft_base_seq(net));
nft_base_seq_be16(net));
if (!nlh)
goto nla_put_failure;
@ -3839,7 +3842,7 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
rcu_read_lock();
nft_net = nft_pernet(net);
cb->seq = READ_ONCE(nft_net->base_seq);
cb->seq = nft_base_seq(net);
list_for_each_entry_rcu(table, &nft_net->tables, list) {
if (family != NFPROTO_UNSPEC && family != table->family)
@ -4050,7 +4053,7 @@ static int nf_tables_getrule_reset(struct sk_buff *skb,
buf = kasprintf(GFP_ATOMIC, "%.*s:%u",
nla_len(nla[NFTA_RULE_TABLE]),
(char *)nla_data(nla[NFTA_RULE_TABLE]),
nft_net->base_seq);
nft_base_seq(net));
audit_log_nfcfg(buf, info->nfmsg->nfgen_family, 1,
AUDIT_NFT_OP_RULE_RESET, GFP_ATOMIC);
kfree(buf);
@ -4887,7 +4890,7 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
nlh = nfnl_msg_put(skb, portid, seq,
nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event),
flags, ctx->family, NFNETLINK_V0,
nft_base_seq(ctx->net));
nft_base_seq_be16(ctx->net));
if (!nlh)
goto nla_put_failure;
@ -5032,7 +5035,7 @@ static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb)
rcu_read_lock();
nft_net = nft_pernet(net);
cb->seq = READ_ONCE(nft_net->base_seq);
cb->seq = nft_base_seq(net);
list_for_each_entry_rcu(table, &nft_net->tables, list) {
if (ctx->family != NFPROTO_UNSPEC &&
@ -6209,7 +6212,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
rcu_read_lock();
nft_net = nft_pernet(net);
cb->seq = READ_ONCE(nft_net->base_seq);
cb->seq = nft_base_seq(net);
list_for_each_entry_rcu(table, &nft_net->tables, list) {
if (dump_ctx->ctx.family != NFPROTO_UNSPEC &&
@ -6238,7 +6241,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
seq = cb->nlh->nlmsg_seq;
nlh = nfnl_msg_put(skb, portid, seq, event, NLM_F_MULTI,
table->family, NFNETLINK_V0, nft_base_seq(net));
table->family, NFNETLINK_V0, nft_base_seq_be16(net));
if (!nlh)
goto nla_put_failure;
@ -6331,7 +6334,7 @@ static int nf_tables_fill_setelem_info(struct sk_buff *skb,
event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event);
nlh = nfnl_msg_put(skb, portid, seq, event, flags, ctx->family,
NFNETLINK_V0, nft_base_seq(ctx->net));
NFNETLINK_V0, nft_base_seq_be16(ctx->net));
if (!nlh)
goto nla_put_failure;
@ -6630,7 +6633,7 @@ static int nf_tables_getsetelem_reset(struct sk_buff *skb,
}
nelems++;
}
audit_log_nft_set_reset(dump_ctx.ctx.table, nft_net->base_seq, nelems);
audit_log_nft_set_reset(dump_ctx.ctx.table, nft_base_seq(info->net), nelems);
out_unlock:
rcu_read_unlock();
@ -8381,7 +8384,7 @@ static int nf_tables_fill_obj_info(struct sk_buff *skb, struct net *net,
nlh = nfnl_msg_put(skb, portid, seq,
nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event),
flags, family, NFNETLINK_V0, nft_base_seq(net));
flags, family, NFNETLINK_V0, nft_base_seq_be16(net));
if (!nlh)
goto nla_put_failure;
@ -8446,7 +8449,7 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
rcu_read_lock();
nft_net = nft_pernet(net);
cb->seq = READ_ONCE(nft_net->base_seq);
cb->seq = nft_base_seq(net);
list_for_each_entry_rcu(table, &nft_net->tables, list) {
if (family != NFPROTO_UNSPEC && family != table->family)
@ -8480,7 +8483,7 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
idx++;
}
if (ctx->reset && entries)
audit_log_obj_reset(table, nft_net->base_seq, entries);
audit_log_obj_reset(table, nft_base_seq(net), entries);
if (rc < 0)
break;
}
@ -8649,7 +8652,7 @@ static int nf_tables_getobj_reset(struct sk_buff *skb,
buf = kasprintf(GFP_ATOMIC, "%.*s:%u",
nla_len(nla[NFTA_OBJ_TABLE]),
(char *)nla_data(nla[NFTA_OBJ_TABLE]),
nft_net->base_seq);
nft_base_seq(net));
audit_log_nfcfg(buf, info->nfmsg->nfgen_family, 1,
AUDIT_NFT_OP_OBJ_RESET, GFP_ATOMIC);
kfree(buf);
@ -8754,9 +8757,8 @@ void nft_obj_notify(struct net *net, const struct nft_table *table,
struct nft_object *obj, u32 portid, u32 seq, int event,
u16 flags, int family, int report, gfp_t gfp)
{
struct nftables_pernet *nft_net = nft_pernet(net);
char *buf = kasprintf(gfp, "%s:%u",
table->name, nft_net->base_seq);
table->name, nft_base_seq(net));
audit_log_nfcfg(buf,
family,
@ -9442,7 +9444,7 @@ static int nf_tables_fill_flowtable_info(struct sk_buff *skb, struct net *net,
nlh = nfnl_msg_put(skb, portid, seq,
nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event),
flags, family, NFNETLINK_V0, nft_base_seq(net));
flags, family, NFNETLINK_V0, nft_base_seq_be16(net));
if (!nlh)
goto nla_put_failure;
@ -9511,7 +9513,7 @@ static int nf_tables_dump_flowtable(struct sk_buff *skb,
rcu_read_lock();
nft_net = nft_pernet(net);
cb->seq = READ_ONCE(nft_net->base_seq);
cb->seq = nft_base_seq(net);
list_for_each_entry_rcu(table, &nft_net->tables, list) {
if (family != NFPROTO_UNSPEC && family != table->family)
@ -9696,17 +9698,16 @@ static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable)
static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net,
u32 portid, u32 seq)
{
struct nftables_pernet *nft_net = nft_pernet(net);
struct nlmsghdr *nlh;
char buf[TASK_COMM_LEN];
int event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, NFT_MSG_NEWGEN);
nlh = nfnl_msg_put(skb, portid, seq, event, 0, AF_UNSPEC,
NFNETLINK_V0, nft_base_seq(net));
NFNETLINK_V0, nft_base_seq_be16(net));
if (!nlh)
goto nla_put_failure;
if (nla_put_be32(skb, NFTA_GEN_ID, htonl(nft_net->base_seq)) ||
if (nla_put_be32(skb, NFTA_GEN_ID, htonl(nft_base_seq(net))) ||
nla_put_be32(skb, NFTA_GEN_PROC_PID, htonl(task_pid_nr(current))) ||
nla_put_string(skb, NFTA_GEN_PROC_NAME, get_task_comm(buf, current)))
goto nla_put_failure;
@ -10968,11 +10969,12 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
* Bump generation counter, invalidate any dump in progress.
* Cannot fail after this point.
*/
base_seq = READ_ONCE(nft_net->base_seq);
base_seq = nft_base_seq(net);
while (++base_seq == 0)
;
WRITE_ONCE(nft_net->base_seq, base_seq);
/* pairs with smp_load_acquire in nft_lookup_eval */
smp_store_release(&net->nft.base_seq, base_seq);
gc_seq = nft_gc_seq_begin(nft_net);
@ -11181,7 +11183,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
nft_commit_notify(net, NETLINK_CB(skb).portid);
nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN);
nf_tables_commit_audit_log(&adl, nft_net->base_seq);
nf_tables_commit_audit_log(&adl, nft_base_seq(net));
nft_gc_seq_end(nft_net, gc_seq);
nft_net->validate_state = NFT_VALIDATE_SKIP;
@ -11506,7 +11508,7 @@ static bool nf_tables_valid_genid(struct net *net, u32 genid)
mutex_lock(&nft_net->commit_mutex);
nft_net->tstamp = get_jiffies_64();
genid_ok = genid == 0 || nft_net->base_seq == genid;
genid_ok = genid == 0 || nft_base_seq(net) == genid;
if (!genid_ok)
mutex_unlock(&nft_net->commit_mutex);
@ -12143,7 +12145,7 @@ static int __net_init nf_tables_init_net(struct net *net)
INIT_LIST_HEAD(&nft_net->module_list);
INIT_LIST_HEAD(&nft_net->notify_list);
mutex_init(&nft_net->commit_mutex);
nft_net->base_seq = 1;
net->nft.base_seq = 1;
nft_net->gc_seq = 0;
nft_net->validate_state = NFT_VALIDATE_SKIP;
INIT_WORK(&nft_net->destroy_work, nf_tables_trans_destroy_work);

View file

@ -24,11 +24,11 @@ struct nft_lookup {
struct nft_set_binding binding;
};
#ifdef CONFIG_MITIGATION_RETPOLINE
const struct nft_set_ext *
nft_set_do_lookup(const struct net *net, const struct nft_set *set,
const u32 *key)
static const struct nft_set_ext *
__nft_set_do_lookup(const struct net *net, const struct nft_set *set,
const u32 *key)
{
#ifdef CONFIG_MITIGATION_RETPOLINE
if (set->ops == &nft_set_hash_fast_type.ops)
return nft_hash_lookup_fast(net, set, key);
if (set->ops == &nft_set_hash_type.ops)
@ -51,10 +51,46 @@ nft_set_do_lookup(const struct net *net, const struct nft_set *set,
return nft_rbtree_lookup(net, set, key);
WARN_ON_ONCE(1);
#endif
return set->ops->lookup(net, set, key);
}
static unsigned int nft_base_seq(const struct net *net)
{
/* pairs with smp_store_release() in nf_tables_commit() */
return smp_load_acquire(&net->nft.base_seq);
}
static bool nft_lookup_should_retry(const struct net *net, unsigned int seq)
{
return unlikely(seq != nft_base_seq(net));
}
const struct nft_set_ext *
nft_set_do_lookup(const struct net *net, const struct nft_set *set,
const u32 *key)
{
const struct nft_set_ext *ext;
unsigned int base_seq;
do {
base_seq = nft_base_seq(net);
ext = __nft_set_do_lookup(net, set, key);
if (ext)
break;
/* No match? There is a small chance that lookup was
* performed in the old generation, but nf_tables_commit()
* already unlinked a (matching) element.
*
* We need to repeat the lookup to make sure that we didn't
* miss a matching element in the new generation.
*/
} while (nft_lookup_should_retry(net, base_seq));
return ext;
}
EXPORT_SYMBOL_GPL(nft_set_do_lookup);
#endif
void nft_lookup_eval(const struct nft_expr *expr,
struct nft_regs *regs,

View file

@ -226,7 +226,8 @@ static void nft_bitmap_walk(const struct nft_ctx *ctx,
const struct nft_bitmap *priv = nft_set_priv(set);
struct nft_bitmap_elem *be;
list_for_each_entry_rcu(be, &priv->list, head) {
list_for_each_entry_rcu(be, &priv->list, head,
lockdep_is_held(&nft_pernet(ctx->net)->commit_mutex)) {
if (iter->count < iter->skip)
goto cont;

View file

@ -510,6 +510,23 @@ static struct nft_pipapo_elem *pipapo_get(const struct nft_pipapo_match *m,
*
* This function is called from the data path. It will search for
* an element matching the given key in the current active copy.
* Unlike other set types, this uses NFT_GENMASK_ANY instead of
* nft_genmask_cur().
*
* This is because new (future) elements are not reachable from
* priv->match, they get added to priv->clone instead.
* When the commit phase flips the generation bitmask, the
* 'now old' entries are skipped but without the 'now current'
* elements becoming visible. Using nft_genmask_cur() thus creates
* inconsistent state: matching old entries get skipped but thew
* newly matching entries are unreachable.
*
* GENMASK will still find the 'now old' entries which ensures consistent
* priv->match view.
*
* nft_pipapo_commit swaps ->clone and ->match shortly after the
* genbit flip. As ->clone doesn't contain the old entries in the first
* place, lookup will only find the now-current ones.
*
* Return: ntables API extension pointer or NULL if no match.
*/
@ -518,12 +535,11 @@ nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
const u32 *key)
{
struct nft_pipapo *priv = nft_set_priv(set);
u8 genmask = nft_genmask_cur(net);
const struct nft_pipapo_match *m;
const struct nft_pipapo_elem *e;
m = rcu_dereference(priv->match);
e = pipapo_get(m, (const u8 *)key, genmask, get_jiffies_64());
e = pipapo_get(m, (const u8 *)key, NFT_GENMASK_ANY, get_jiffies_64());
return e ? &e->ext : NULL;
}

View file

@ -1152,7 +1152,6 @@ nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
struct nft_pipapo *priv = nft_set_priv(set);
const struct nft_set_ext *ext = NULL;
struct nft_pipapo_scratch *scratch;
u8 genmask = nft_genmask_cur(net);
const struct nft_pipapo_match *m;
const struct nft_pipapo_field *f;
const u8 *rp = (const u8 *)key;
@ -1248,8 +1247,7 @@ nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
if (last) {
const struct nft_set_ext *e = &f->mt[ret].e->ext;
if (unlikely(nft_set_elem_expired(e) ||
!nft_set_elem_active(e, genmask)))
if (unlikely(nft_set_elem_expired(e)))
goto next_match;
ext = e;

View file

@ -77,7 +77,9 @@ __nft_rbtree_lookup(const struct net *net, const struct nft_set *set,
nft_rbtree_interval_end(rbe) &&
nft_rbtree_interval_start(interval))
continue;
interval = rbe;
if (nft_set_elem_active(&rbe->ext, genmask) &&
!nft_rbtree_elem_expired(rbe))
interval = rbe;
} else if (d > 0)
parent = rcu_dereference_raw(parent->rb_right);
else {
@ -102,8 +104,6 @@ __nft_rbtree_lookup(const struct net *net, const struct nft_set *set,
}
if (set->flags & NFT_SET_INTERVAL && interval != NULL &&
nft_set_elem_active(&interval->ext, genmask) &&
!nft_rbtree_elem_expired(interval) &&
nft_rbtree_interval_start(interval))
return &interval->ext;

View file

@ -1836,6 +1836,9 @@ static int genl_bind(struct net *net, int group)
!ns_capable(net->user_ns, CAP_SYS_ADMIN))
ret = -EPERM;
if (ret)
break;
if (family->bind)
family->bind(i);

View file

@ -7062,7 +7062,8 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
u32 seq, int flags,
struct cfg80211_registered_device *rdev,
struct net_device *dev,
const u8 *mac_addr, struct station_info *sinfo)
const u8 *mac_addr, struct station_info *sinfo,
bool link_stats)
{
void *hdr;
struct nlattr *sinfoattr, *bss_param;
@ -7283,7 +7284,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
goto nla_put_failure;
}
if (sinfo->valid_links) {
if (link_stats && sinfo->valid_links) {
links = nla_nest_start(msg, NL80211_ATTR_MLO_LINKS);
if (!links)
goto nla_put_failure;
@ -7574,7 +7575,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
rdev, wdev->netdev, mac_addr,
&sinfo) < 0)
&sinfo, false) < 0)
goto out;
sta_idx++;
@ -7635,7 +7636,7 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION,
info->snd_portid, info->snd_seq, 0,
rdev, dev, mac_addr, &sinfo) < 0) {
rdev, dev, mac_addr, &sinfo, false) < 0) {
nlmsg_free(msg);
return -ENOBUFS;
}
@ -19680,7 +19681,7 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
return;
if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION, 0, 0, 0,
rdev, dev, mac_addr, sinfo) < 0) {
rdev, dev, mac_addr, sinfo, false) < 0) {
nlmsg_free(msg);
return;
}
@ -19710,7 +19711,7 @@ void cfg80211_del_sta_sinfo(struct net_device *dev, const u8 *mac_addr,
}
if (nl80211_send_station(msg, NL80211_CMD_DEL_STATION, 0, 0, 0,
rdev, dev, mac_addr, sinfo) < 0) {
rdev, dev, mac_addr, sinfo, false) < 0) {
nlmsg_free(msg);
return;
}

View file

@ -116,6 +116,7 @@ TEST_PROGS += skf_net_off.sh
TEST_GEN_FILES += skf_net_off
TEST_GEN_FILES += tfo
TEST_PROGS += tfo_passive.sh
TEST_PROGS += broadcast_ether_dst.sh
TEST_PROGS += broadcast_pmtu.sh
TEST_PROGS += ipv6_force_forwarding.sh

View file

@ -0,0 +1,83 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Author: Brett A C Sheffield <bacs@librecast.net>
# Author: Oscar Maes <oscmaes92@gmail.com>
#
# Ensure destination ethernet field is correctly set for
# broadcast packets
source lib.sh
CLIENT_IP4="192.168.0.1"
GW_IP4="192.168.0.2"
setup() {
setup_ns CLIENT_NS SERVER_NS
ip -net "${SERVER_NS}" link add link1 type veth \
peer name link0 netns "${CLIENT_NS}"
ip -net "${CLIENT_NS}" link set link0 up
ip -net "${CLIENT_NS}" addr add "${CLIENT_IP4}"/24 dev link0
ip -net "${SERVER_NS}" link set link1 up
ip -net "${CLIENT_NS}" route add default via "${GW_IP4}"
ip netns exec "${CLIENT_NS}" arp -s "${GW_IP4}" 00:11:22:33:44:55
}
cleanup() {
rm -f "${CAPFILE}" "${OUTPUT}"
ip -net "${SERVER_NS}" link del link1
cleanup_ns "${CLIENT_NS}" "${SERVER_NS}"
}
test_broadcast_ether_dst() {
local rc=0
CAPFILE=$(mktemp -u cap.XXXXXXXXXX)
OUTPUT=$(mktemp -u out.XXXXXXXXXX)
echo "Testing ethernet broadcast destination"
# start tcpdump listening for icmp
# tcpdump will exit after receiving a single packet
# timeout will kill tcpdump if it is still running after 2s
timeout 2s ip netns exec "${CLIENT_NS}" \
tcpdump -i link0 -c 1 -w "${CAPFILE}" icmp &> "${OUTPUT}" &
pid=$!
slowwait 1 grep -qs "listening" "${OUTPUT}"
# send broadcast ping
ip netns exec "${CLIENT_NS}" \
ping -W0.01 -c1 -b 255.255.255.255 &> /dev/null
# wait for tcpdump for exit after receiving packet
wait "${pid}"
# compare ethernet destination field to ff:ff:ff:ff:ff:ff
ether_dst=$(tcpdump -r "${CAPFILE}" -tnne 2>/dev/null | \
awk '{sub(/,/,"",$3); print $3}')
if [[ "${ether_dst}" == "ff:ff:ff:ff:ff:ff" ]]; then
echo "[ OK ]"
rc="${ksft_pass}"
else
echo "[FAIL] expected dst ether addr to be ff:ff:ff:ff:ff:ff," \
"got ${ether_dst}"
rc="${ksft_fail}"
fi
return "${rc}"
}
if [ ! -x "$(command -v tcpdump)" ]; then
echo "SKIP: Could not run test without tcpdump tool"
exit "${ksft_skip}"
fi
trap cleanup EXIT
setup
test_broadcast_ether_dst
exit $?

View file

@ -0,0 +1,3 @@
CONFIG_CAN=m
CONFIG_CAN_DEV=m
CONFIG_CAN_VCAN=m

View file

@ -28,7 +28,7 @@ flush_pids()
}
# This function is used in the cleanup trap
#shellcheck disable=SC2317
#shellcheck disable=SC2317,SC2329
cleanup()
{
ip netns pids "${ns}" | xargs --no-run-if-empty kill -SIGKILL &>/dev/null

View file

@ -134,7 +134,7 @@ ns4=""
TEST_GROUP=""
# This function is used in the cleanup trap
#shellcheck disable=SC2317
#shellcheck disable=SC2317,SC2329
cleanup()
{
rm -f "$cin_disconnect"

View file

@ -8,7 +8,7 @@
# ShellCheck incorrectly believes that most of the code here is unreachable
# because it's invoked by variable name, see how the "tests" array is used
#shellcheck disable=SC2317
#shellcheck disable=SC2317,SC2329
. "$(dirname "${0}")/mptcp_lib.sh"

View file

@ -95,7 +95,7 @@ init()
}
# This function is used in the cleanup trap
#shellcheck disable=SC2317
#shellcheck disable=SC2317,SC2329
cleanup()
{
mptcp_lib_ns_exit "${ns1}" "${ns2}" "${ns_sbox}"

View file

@ -32,7 +32,7 @@ ns1=""
err=$(mktemp)
# This function is used in the cleanup trap
#shellcheck disable=SC2317
#shellcheck disable=SC2317,SC2329
cleanup()
{
rm -f "${err}"
@ -70,8 +70,9 @@ format_endpoints() {
mptcp_lib_pm_nl_format_endpoints "${@}"
}
# This function is invoked indirectly
#shellcheck disable=SC2317,SC2329
get_endpoint() {
# shellcheck disable=SC2317 # invoked indirectly
mptcp_lib_pm_nl_get_endpoint "${ns1}" "${@}"
}

View file

@ -35,7 +35,7 @@ usage() {
}
# This function is used in the cleanup trap
#shellcheck disable=SC2317
#shellcheck disable=SC2317,SC2329
cleanup()
{
rm -f "$cout" "$sout"

View file

@ -94,7 +94,7 @@ test_fail()
}
# This function is used in the cleanup trap
#shellcheck disable=SC2317
#shellcheck disable=SC2317,SC2329
cleanup()
{
print_title "Cleanup"