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

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

  No known regressions outstanding.

  Current release - regressions:

   - wifi: nl80211: fix assoc link handling

   - eth: lan78xx: sanitize return values of register read/write
     functions

  Current release - new code bugs:

   - ethtool: tsinfo: fix dump command

   - bluetooth: btusb: configure altsetting for HCI_USER_CHANNEL

   - eth: mlx5: DR, use the right action structs for STEv3

  Previous releases - regressions:

   - netfilter: nf_tables: make destruction work queue pernet

   - gre: fix IPv6 link-local address generation.

   - wifi: iwlwifi: fix TSO preparation

   - bluetooth: revert "bluetooth: hci_core: fix sleeping function
     called from invalid context"

   - ovs: revert "openvswitch: switch to per-action label counting in
     conntrack"

   - eth:
       - ice: fix switchdev slow-path in LAG
       - bonding: fix incorrect MAC address setting to receive NS
         messages

  Previous releases - always broken:

   - core: prevent TX of unreadable skbs

   - sched: prevent creation of classes with TC_H_ROOT

   - netfilter: nft_exthdr: fix offset with ipv4_find_option()

   - wifi: cfg80211: cancel wiphy_work before freeing wiphy

   - mctp: copy headers if cloned

   - phy: nxp-c45-tja11xx: add errata for TJA112XA/B

   - eth:
       - bnxt: fix kernel panic in the bnxt_get_queue_stats{rx | tx}
       - mlx5: bridge, fix the crash caused by LAG state check"

* tag 'net-6.14-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (65 commits)
  net: mana: cleanup mana struct after debugfs_remove()
  net/mlx5e: Prevent bridge link show failure for non-eswitch-allowed devices
  net/mlx5: Bridge, fix the crash caused by LAG state check
  net/mlx5: Lag, Check shared fdb before creating MultiPort E-Switch
  net/mlx5: Fix incorrect IRQ pool usage when releasing IRQs
  net/mlx5: HWS, Rightsize bwc matcher priority
  net/mlx5: DR, use the right action structs for STEv3
  Revert "openvswitch: switch to per-action label counting in conntrack"
  net: openvswitch: remove misbehaving actions length check
  selftests: Add IPv6 link-local address generation tests for GRE devices.
  gre: Fix IPv6 link-local address generation.
  netfilter: nft_exthdr: fix offset with ipv4_find_option()
  selftests/tc-testing: Add a test case for DRR class with TC_H_ROOT
  net_sched: Prevent creation of classes with TC_H_ROOT
  ipvs: prevent integer overflow in do_ip_vs_get_ctl()
  selftests: netfilter: skip br_netfilter queue tests if kernel is tainted
  netfilter: nf_conncount: Fully initialize struct nf_conncount_tuple in insert_tree()
  wifi: mac80211: fix MPDU length parsing for EHT 5/6 GHz
  qlcnic: fix memory leak issues in qlcnic_sriov_common.c
  rtase: Fix improper release of ring list entries in rtase_sw_reset
  ...
This commit is contained in:
Linus Torvalds
2025-03-13 07:58:48 -10:00
86 changed files with 1251 additions and 360 deletions

View File

@@ -124,6 +124,7 @@ F: include/net/ieee80211_radiotap.h
F: include/net/iw_handler.h
F: include/net/wext.h
F: include/uapi/linux/nl80211.h
N: include/uapi/linux/nl80211-.*
F: include/uapi/linux/wireless.h
F: net/wireless/
@@ -514,7 +515,7 @@ F: drivers/hwmon/adm1029.c
ADM8211 WIRELESS DRIVER
L: linux-wireless@vger.kernel.org
S: Orphan
F: drivers/net/wireless/admtek/adm8211.*
F: drivers/net/wireless/admtek/
ADP1050 HARDWARE MONITOR DRIVER
M: Radu Sabau <radu.sabau@analog.com>
@@ -6207,7 +6208,7 @@ F: Documentation/process/cve.rst
CW1200 WLAN driver
S: Orphan
F: drivers/net/wireless/st/cw1200/
F: drivers/net/wireless/st/
F: include/linux/platform_data/net-cw1200.h
CX18 VIDEO4LINUX DRIVER
@@ -13994,6 +13995,7 @@ MARVELL LIBERTAS WIRELESS DRIVER
L: libertas-dev@lists.infradead.org
S: Orphan
F: drivers/net/wireless/marvell/libertas/
F: drivers/net/wireless/marvell/libertas_tf/
MARVELL MACCHIATOBIN SUPPORT
M: Russell King <linux@armlinux.org.uk>
@@ -15663,7 +15665,7 @@ M: Ajay Singh <ajay.kathat@microchip.com>
M: Claudiu Beznea <claudiu.beznea@tuxon.dev>
L: linux-wireless@vger.kernel.org
S: Supported
F: drivers/net/wireless/microchip/wilc1000/
F: drivers/net/wireless/microchip/
MICROSEMI MIPS SOCS
M: Alexandre Belloni <alexandre.belloni@bootlin.com>
@@ -16449,6 +16451,23 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git
F: Documentation/devicetree/bindings/net/wireless/
F: drivers/net/wireless/
X: drivers/net/wireless/ath/
X: drivers/net/wireless/broadcom/
X: drivers/net/wireless/intel/
X: drivers/net/wireless/intersil/
X: drivers/net/wireless/marvell/
X: drivers/net/wireless/mediatek/mt76/
X: drivers/net/wireless/mediatek/mt7601u/
X: drivers/net/wireless/microchip/
X: drivers/net/wireless/purelifi/
X: drivers/net/wireless/quantenna/
X: drivers/net/wireless/ralink/
X: drivers/net/wireless/realtek/
X: drivers/net/wireless/rsi/
X: drivers/net/wireless/silabs/
X: drivers/net/wireless/st/
X: drivers/net/wireless/ti/
X: drivers/net/wireless/zydas/
NETWORKING [DSA]
M: Andrew Lunn <andrew@lunn.ch>
@@ -17833,7 +17852,7 @@ M: Christian Lamparter <chunkeey@googlemail.com>
L: linux-wireless@vger.kernel.org
S: Maintained
W: https://wireless.wiki.kernel.org/en/users/Drivers/p54
F: drivers/net/wireless/intersil/p54/
F: drivers/net/wireless/intersil/
PACKET SOCKETS
M: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
@@ -19110,7 +19129,7 @@ PURELIFI PLFXLC DRIVER
M: Srinivasan Raju <srini.raju@purelifi.com>
L: linux-wireless@vger.kernel.org
S: Supported
F: drivers/net/wireless/purelifi/plfxlc/
F: drivers/net/wireless/purelifi/
PVRUSB2 VIDEO4LINUX DRIVER
M: Mike Isely <isely@pobox.com>
@@ -19661,7 +19680,7 @@ M: Igor Mitsyanko <imitsyanko@quantenna.com>
R: Sergey Matyukevich <geomatsi@gmail.com>
L: linux-wireless@vger.kernel.org
S: Maintained
F: drivers/net/wireless/quantenna
F: drivers/net/wireless/quantenna/
RADEON and AMDGPU DRM DRIVERS
M: Alex Deucher <alexander.deucher@amd.com>
@@ -19741,7 +19760,7 @@ RALINK RT2X00 WIRELESS LAN DRIVER
M: Stanislaw Gruszka <stf_xl@wp.pl>
L: linux-wireless@vger.kernel.org
S: Maintained
F: drivers/net/wireless/ralink/rt2x00/
F: drivers/net/wireless/ralink/
RAMDISK RAM BLOCK DEVICE DRIVER
M: Jens Axboe <axboe@kernel.dk>
@@ -21500,7 +21519,6 @@ F: include/linux/slimbus.h
SFC NETWORK DRIVER
M: Edward Cree <ecree.xilinx@gmail.com>
M: Martin Habets <habetsm.xilinx@gmail.com>
L: netdev@vger.kernel.org
L: linux-net-drivers@amd.com
S: Maintained
@@ -21709,7 +21727,7 @@ SILICON LABS WIRELESS DRIVERS (for WFxxx series)
M: Jérôme Pouiller <jerome.pouiller@silabs.com>
S: Supported
F: Documentation/devicetree/bindings/net/wireless/silabs,wfx.yaml
F: drivers/net/wireless/silabs/wfx/
F: drivers/net/wireless/silabs/
SILICON MOTION SM712 FRAME BUFFER DRIVER
M: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
@@ -26209,7 +26227,7 @@ F: mm/zbud.c
ZD1211RW WIRELESS DRIVER
L: linux-wireless@vger.kernel.org
S: Orphan
F: drivers/net/wireless/zydas/zd1211rw/
F: drivers/net/wireless/zydas/
ZD1301 MEDIA DRIVER
L: linux-media@vger.kernel.org

View File

@@ -56,6 +56,18 @@ config BT_HCIBTUSB_POLL_SYNC
Say Y here to enable USB poll_sync for Bluetooth USB devices by
default.
config BT_HCIBTUSB_AUTO_ISOC_ALT
bool "Automatically adjust alternate setting for Isoc endpoints"
depends on BT_HCIBTUSB
default y if CHROME_PLATFORMS
help
Say Y here to automatically adjusting the alternate setting for
HCI_USER_CHANNEL whenever a SCO link is established.
When enabled, btusb intercepts the HCI_EV_SYNC_CONN_COMPLETE packets
and configures isoc endpoint alternate setting automatically when
HCI_USER_CHANNEL is in use.
config BT_HCIBTUSB_BCM
bool "Broadcom protocol support"
depends on BT_HCIBTUSB

View File

@@ -34,6 +34,7 @@ static bool force_scofix;
static bool enable_autosuspend = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTOSUSPEND);
static bool enable_poll_sync = IS_ENABLED(CONFIG_BT_HCIBTUSB_POLL_SYNC);
static bool reset = true;
static bool auto_isoc_alt = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTO_ISOC_ALT);
static struct usb_driver btusb_driver;
@@ -1085,6 +1086,42 @@ static inline void btusb_free_frags(struct btusb_data *data)
spin_unlock_irqrestore(&data->rxlock, flags);
}
static void btusb_sco_connected(struct btusb_data *data, struct sk_buff *skb)
{
struct hci_event_hdr *hdr = (void *) skb->data;
struct hci_ev_sync_conn_complete *ev =
(void *) skb->data + sizeof(*hdr);
struct hci_dev *hdev = data->hdev;
unsigned int notify_air_mode;
if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT)
return;
if (skb->len < sizeof(*hdr) || hdr->evt != HCI_EV_SYNC_CONN_COMPLETE)
return;
if (skb->len != sizeof(*hdr) + sizeof(*ev) || ev->status)
return;
switch (ev->air_mode) {
case BT_CODEC_CVSD:
notify_air_mode = HCI_NOTIFY_ENABLE_SCO_CVSD;
break;
case BT_CODEC_TRANSPARENT:
notify_air_mode = HCI_NOTIFY_ENABLE_SCO_TRANSP;
break;
default:
return;
}
bt_dev_info(hdev, "enabling SCO with air mode %u", ev->air_mode);
data->sco_num = 1;
data->air_mode = notify_air_mode;
schedule_work(&data->work);
}
static int btusb_recv_event(struct btusb_data *data, struct sk_buff *skb)
{
if (data->intr_interval) {
@@ -1092,6 +1129,10 @@ static int btusb_recv_event(struct btusb_data *data, struct sk_buff *skb)
schedule_delayed_work(&data->rx_work, 0);
}
/* Configure altsetting for HCI_USER_CHANNEL on SCO connected */
if (auto_isoc_alt && hci_dev_test_flag(data->hdev, HCI_USER_CHANNEL))
btusb_sco_connected(data, skb);
return data->recv_event(data->hdev, skb);
}

View File

@@ -1242,10 +1242,28 @@ static bool slave_can_set_ns_maddr(const struct bonding *bond, struct slave *sla
slave->dev->flags & IFF_MULTICAST;
}
/**
* slave_set_ns_maddrs - add/del all NS mac addresses for slave
* @bond: bond device
* @slave: slave device
* @add: add or remove all the NS mac addresses
*
* This function tries to add or delete all the NS mac addresses on the slave
*
* Note, the IPv6 NS target address is the unicast address in Neighbor
* Solicitation (NS) message. The dest address of NS message should be
* solicited-node multicast address of the target. The dest mac of NS message
* is converted from the solicited-node multicast address.
*
* This function is called when
* * arp_validate changes
* * enslaving, releasing new slaves
*/
static void slave_set_ns_maddrs(struct bonding *bond, struct slave *slave, bool add)
{
struct in6_addr *targets = bond->params.ns_targets;
char slot_maddr[MAX_ADDR_LEN];
struct in6_addr mcaddr;
int i;
if (!slave_can_set_ns_maddr(bond, slave))
@@ -1255,7 +1273,8 @@ static void slave_set_ns_maddrs(struct bonding *bond, struct slave *slave, bool
if (ipv6_addr_any(&targets[i]))
break;
if (!ndisc_mc_map(&targets[i], slot_maddr, slave->dev, 0)) {
addrconf_addr_solict_mult(&targets[i], &mcaddr);
if (!ndisc_mc_map(&mcaddr, slot_maddr, slave->dev, 0)) {
if (add)
dev_mc_add(slave->dev, slot_maddr);
else
@@ -1278,23 +1297,43 @@ void bond_slave_ns_maddrs_del(struct bonding *bond, struct slave *slave)
slave_set_ns_maddrs(bond, slave, false);
}
/**
* slave_set_ns_maddr - set new NS mac address for slave
* @bond: bond device
* @slave: slave device
* @target: the new IPv6 target
* @slot: the old IPv6 target in the slot
*
* This function tries to replace the old mac address to new one on the slave.
*
* Note, the target/slot IPv6 address is the unicast address in Neighbor
* Solicitation (NS) message. The dest address of NS message should be
* solicited-node multicast address of the target. The dest mac of NS message
* is converted from the solicited-node multicast address.
*
* This function is called when
* * An IPv6 NS target is added or removed.
*/
static void slave_set_ns_maddr(struct bonding *bond, struct slave *slave,
struct in6_addr *target, struct in6_addr *slot)
{
char target_maddr[MAX_ADDR_LEN], slot_maddr[MAX_ADDR_LEN];
char mac_addr[MAX_ADDR_LEN];
struct in6_addr mcast_addr;
if (!bond->params.arp_validate || !slave_can_set_ns_maddr(bond, slave))
return;
/* remove the previous maddr from slave */
/* remove the previous mac addr from slave */
addrconf_addr_solict_mult(slot, &mcast_addr);
if (!ipv6_addr_any(slot) &&
!ndisc_mc_map(slot, slot_maddr, slave->dev, 0))
dev_mc_del(slave->dev, slot_maddr);
!ndisc_mc_map(&mcast_addr, mac_addr, slave->dev, 0))
dev_mc_del(slave->dev, mac_addr);
/* add new maddr on slave if target is set */
/* add new mac addr on slave if target is set */
addrconf_addr_solict_mult(target, &mcast_addr);
if (!ipv6_addr_any(target) &&
!ndisc_mc_map(target, target_maddr, slave->dev, 0))
dev_mc_add(slave->dev, target_maddr);
!ndisc_mc_map(&mcast_addr, mac_addr, slave->dev, 0))
dev_mc_add(slave->dev, mac_addr);
}
static void _bond_options_ns_ip6_target_set(struct bonding *bond, int slot,

View File

@@ -2208,13 +2208,11 @@ mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
return err;
}
static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port,
const unsigned char *addr, u16 vid,
u8 state)
static int mv88e6xxx_port_db_get(struct mv88e6xxx_chip *chip,
const unsigned char *addr, u16 vid,
u16 *fid, struct mv88e6xxx_atu_entry *entry)
{
struct mv88e6xxx_atu_entry entry;
struct mv88e6xxx_vtu_entry vlan;
u16 fid;
int err;
/* Ports have two private address databases: one for when the port is
@@ -2225,7 +2223,7 @@ static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port,
* VLAN ID into the port's database used for VLAN-unaware bridging.
*/
if (vid == 0) {
fid = MV88E6XXX_FID_BRIDGED;
*fid = MV88E6XXX_FID_BRIDGED;
} else {
err = mv88e6xxx_vtu_get(chip, vid, &vlan);
if (err)
@@ -2235,14 +2233,39 @@ static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port,
if (!vlan.valid)
return -EOPNOTSUPP;
fid = vlan.fid;
*fid = vlan.fid;
}
entry.state = 0;
ether_addr_copy(entry.mac, addr);
eth_addr_dec(entry.mac);
entry->state = 0;
ether_addr_copy(entry->mac, addr);
eth_addr_dec(entry->mac);
err = mv88e6xxx_g1_atu_getnext(chip, fid, &entry);
return mv88e6xxx_g1_atu_getnext(chip, *fid, entry);
}
static bool mv88e6xxx_port_db_find(struct mv88e6xxx_chip *chip,
const unsigned char *addr, u16 vid)
{
struct mv88e6xxx_atu_entry entry;
u16 fid;
int err;
err = mv88e6xxx_port_db_get(chip, addr, vid, &fid, &entry);
if (err)
return false;
return entry.state && ether_addr_equal(entry.mac, addr);
}
static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port,
const unsigned char *addr, u16 vid,
u8 state)
{
struct mv88e6xxx_atu_entry entry;
u16 fid;
int err;
err = mv88e6xxx_port_db_get(chip, addr, vid, &fid, &entry);
if (err)
return err;
@@ -2846,6 +2869,13 @@ static int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
mv88e6xxx_reg_lock(chip);
err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid,
MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC);
if (err)
goto out;
if (!mv88e6xxx_port_db_find(chip, addr, vid))
err = -ENOSPC;
out:
mv88e6xxx_reg_unlock(chip);
return err;
@@ -6614,6 +6644,13 @@ static int mv88e6xxx_port_mdb_add(struct dsa_switch *ds, int port,
mv88e6xxx_reg_lock(chip);
err = mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid,
MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC);
if (err)
goto out;
if (!mv88e6xxx_port_db_find(chip, mdb->addr, mdb->vid))
err = -ENOSPC;
out:
mv88e6xxx_reg_unlock(chip);
return err;

View File

@@ -2038,6 +2038,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
struct rx_cmp_ext *rxcmp1;
u32 tmp_raw_cons = *raw_cons;
u16 cons, prod, cp_cons = RING_CMP(tmp_raw_cons);
struct skb_shared_info *sinfo;
struct bnxt_sw_rx_bd *rx_buf;
unsigned int len;
u8 *data_ptr, agg_bufs, cmp_type;
@@ -2164,6 +2165,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
false);
if (!frag_len)
goto oom_next_rx;
}
xdp_active = true;
}
@@ -2173,6 +2175,12 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
rc = 1;
goto next_rx;
}
if (xdp_buff_has_frags(&xdp)) {
sinfo = xdp_get_shared_info_from_buff(&xdp);
agg_bufs = sinfo->nr_frags;
} else {
agg_bufs = 0;
}
}
if (len <= bp->rx_copybreak) {
@@ -2210,7 +2218,8 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
if (!skb)
goto oom_next_rx;
} else {
skb = bnxt_xdp_build_skb(bp, skb, agg_bufs, rxr->page_pool, &xdp, rxcmp1);
skb = bnxt_xdp_build_skb(bp, skb, agg_bufs,
rxr->page_pool, &xdp);
if (!skb) {
/* we should be able to free the old skb here */
bnxt_xdp_buff_frags_free(rxr, &xdp);
@@ -15375,6 +15384,9 @@ static void bnxt_get_queue_stats_rx(struct net_device *dev, int i,
struct bnxt_cp_ring_info *cpr;
u64 *sw;
if (!bp->bnapi)
return;
cpr = &bp->bnapi[i]->cp_ring;
sw = cpr->stats.sw_stats;
@@ -15398,6 +15410,9 @@ static void bnxt_get_queue_stats_tx(struct net_device *dev, int i,
struct bnxt_napi *bnapi;
u64 *sw;
if (!bp->tx_ring)
return;
bnapi = bp->tx_ring[bp->tx_ring_map[i]].bnapi;
sw = bnapi->cp_ring.stats.sw_stats;
@@ -15439,6 +15454,9 @@ static int bnxt_queue_mem_alloc(struct net_device *dev, void *qmem, int idx)
struct bnxt_ring_struct *ring;
int rc;
if (!bp->rx_ring)
return -ENETDOWN;
rxr = &bp->rx_ring[idx];
clone = qmem;
memcpy(clone, rxr, sizeof(*rxr));
@@ -15521,6 +15539,7 @@ static void bnxt_queue_mem_free(struct net_device *dev, void *qmem)
struct bnxt_ring_struct *ring;
bnxt_free_one_rx_ring_skbs(bp, rxr);
bnxt_free_one_tpa_info(bp, rxr);
xdp_rxq_info_unreg(&rxr->xdp_rxq);
@@ -15632,7 +15651,7 @@ static int bnxt_queue_start(struct net_device *dev, void *qmem, int idx)
cpr = &rxr->bnapi->cp_ring;
cpr->sw_stats->rx.rx_resets++;
for (i = 0; i <= BNXT_VNIC_NTUPLE; i++) {
for (i = 0; i <= bp->nr_vnics; i++) {
vnic = &bp->vnic_info[i];
rc = bnxt_hwrm_vnic_set_rss_p5(bp, vnic, true);
@@ -15660,7 +15679,7 @@ static int bnxt_queue_stop(struct net_device *dev, void *qmem, int idx)
struct bnxt_vnic_info *vnic;
int i;
for (i = 0; i <= BNXT_VNIC_NTUPLE; i++) {
for (i = 0; i <= bp->nr_vnics; i++) {
vnic = &bp->vnic_info[i];
vnic->mru = 0;
bnxt_hwrm_vnic_update(bp, vnic,

View File

@@ -460,23 +460,16 @@ int bnxt_xdp(struct net_device *dev, struct netdev_bpf *xdp)
struct sk_buff *
bnxt_xdp_build_skb(struct bnxt *bp, struct sk_buff *skb, u8 num_frags,
struct page_pool *pool, struct xdp_buff *xdp,
struct rx_cmp_ext *rxcmp1)
struct page_pool *pool, struct xdp_buff *xdp)
{
struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp);
if (!skb)
return NULL;
skb_checksum_none_assert(skb);
if (RX_CMP_L4_CS_OK(rxcmp1)) {
if (bp->dev->features & NETIF_F_RXCSUM) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb->csum_level = RX_CMP_ENCAP(rxcmp1);
}
}
xdp_update_skb_shared_info(skb, num_frags,
sinfo->xdp_frags_size,
BNXT_RX_PAGE_SIZE * sinfo->nr_frags,
BNXT_RX_PAGE_SIZE * num_frags,
xdp_buff_is_frag_pfmemalloc(xdp));
return skb;
}

View File

@@ -33,6 +33,5 @@ void bnxt_xdp_buff_frags_free(struct bnxt_rx_ring_info *rxr,
struct xdp_buff *xdp);
struct sk_buff *bnxt_xdp_build_skb(struct bnxt *bp, struct sk_buff *skb,
u8 num_frags, struct page_pool *pool,
struct xdp_buff *xdp,
struct rx_cmp_ext *rxcmp1);
struct xdp_buff *xdp);
#endif

View File

@@ -511,7 +511,7 @@ void ice_init_arfs(struct ice_vsi *vsi)
struct hlist_head *arfs_fltr_list;
unsigned int i;
if (!vsi || vsi->type != ICE_VSI_PF)
if (!vsi || vsi->type != ICE_VSI_PF || ice_is_arfs_active(vsi))
return;
arfs_fltr_list = kcalloc(ICE_MAX_ARFS_LIST, sizeof(*arfs_fltr_list),

View File

@@ -49,9 +49,6 @@ static int ice_eswitch_setup_env(struct ice_pf *pf)
if (vlan_ops->dis_rx_filtering(uplink_vsi))
goto err_vlan_filtering;
if (ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_set_allow_override))
goto err_override_uplink;
if (ice_vsi_update_local_lb(uplink_vsi, true))
goto err_override_local_lb;
@@ -63,8 +60,6 @@ static int ice_eswitch_setup_env(struct ice_pf *pf)
err_up:
ice_vsi_update_local_lb(uplink_vsi, false);
err_override_local_lb:
ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_clear_allow_override);
err_override_uplink:
vlan_ops->ena_rx_filtering(uplink_vsi);
err_vlan_filtering:
ice_cfg_dflt_vsi(uplink_vsi->port_info, uplink_vsi->idx, false,
@@ -275,7 +270,6 @@ static void ice_eswitch_release_env(struct ice_pf *pf)
vlan_ops = ice_get_compat_vsi_vlan_ops(uplink_vsi);
ice_vsi_update_local_lb(uplink_vsi, false);
ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_clear_allow_override);
vlan_ops->ena_rx_filtering(uplink_vsi);
ice_cfg_dflt_vsi(uplink_vsi->port_info, uplink_vsi->idx, false,
ICE_FLTR_TX);

View File

@@ -1000,6 +1000,28 @@ static void ice_lag_link(struct ice_lag *lag)
netdev_info(lag->netdev, "Shared SR-IOV resources in bond are active\n");
}
/**
* ice_lag_config_eswitch - configure eswitch to work with LAG
* @lag: lag info struct
* @netdev: active network interface device struct
*
* Updates all port representors in eswitch to use @netdev for Tx.
*
* Configures the netdev to keep dst metadata (also used in representor Tx).
* This is required for an uplink without switchdev mode configured.
*/
static void ice_lag_config_eswitch(struct ice_lag *lag,
struct net_device *netdev)
{
struct ice_repr *repr;
unsigned long id;
xa_for_each(&lag->pf->eswitch.reprs, id, repr)
repr->dst->u.port_info.lower_dev = netdev;
netif_keep_dst(netdev);
}
/**
* ice_lag_unlink - handle unlink event
* @lag: LAG info struct
@@ -1021,6 +1043,9 @@ static void ice_lag_unlink(struct ice_lag *lag)
ice_lag_move_vf_nodes(lag, act_port, pri_port);
lag->primary = false;
lag->active_port = ICE_LAG_INVALID_PORT;
/* Config primary's eswitch back to normal operation. */
ice_lag_config_eswitch(lag, lag->netdev);
} else {
struct ice_lag *primary_lag;
@@ -1419,6 +1444,7 @@ static void ice_lag_monitor_active(struct ice_lag *lag, void *ptr)
ice_lag_move_vf_nodes(lag, prim_port,
event_port);
lag->active_port = event_port;
ice_lag_config_eswitch(lag, event_netdev);
return;
}
@@ -1428,6 +1454,7 @@ static void ice_lag_monitor_active(struct ice_lag *lag, void *ptr)
/* new active port */
ice_lag_move_vf_nodes(lag, lag->active_port, event_port);
lag->active_port = event_port;
ice_lag_config_eswitch(lag, event_netdev);
} else {
/* port not set as currently active (e.g. new active port
* has already claimed the nodes and filters

View File

@@ -3936,24 +3936,6 @@ void ice_vsi_ctx_clear_antispoof(struct ice_vsi_ctx *ctx)
ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S);
}
/**
* ice_vsi_ctx_set_allow_override - allow destination override on VSI
* @ctx: pointer to VSI ctx structure
*/
void ice_vsi_ctx_set_allow_override(struct ice_vsi_ctx *ctx)
{
ctx->info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD;
}
/**
* ice_vsi_ctx_clear_allow_override - turn off destination override on VSI
* @ctx: pointer to VSI ctx structure
*/
void ice_vsi_ctx_clear_allow_override(struct ice_vsi_ctx *ctx)
{
ctx->info.sec_flags &= ~ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD;
}
/**
* ice_vsi_update_local_lb - update sw block in VSI with local loopback bit
* @vsi: pointer to VSI structure

View File

@@ -105,10 +105,6 @@ ice_vsi_update_security(struct ice_vsi *vsi, void (*fill)(struct ice_vsi_ctx *))
void ice_vsi_ctx_set_antispoof(struct ice_vsi_ctx *ctx);
void ice_vsi_ctx_clear_antispoof(struct ice_vsi_ctx *ctx);
void ice_vsi_ctx_set_allow_override(struct ice_vsi_ctx *ctx);
void ice_vsi_ctx_clear_allow_override(struct ice_vsi_ctx *ctx);
int ice_vsi_update_local_lb(struct ice_vsi *vsi, bool set);
int ice_vsi_add_vlan_zero(struct ice_vsi *vsi);
int ice_vsi_del_vlan_zero(struct ice_vsi *vsi);

View File

@@ -5065,16 +5065,16 @@ static int ice_init_devlink(struct ice_pf *pf)
return err;
ice_devlink_init_regions(pf);
ice_health_init(pf);
ice_devlink_register(pf);
ice_health_init(pf);
return 0;
}
static void ice_deinit_devlink(struct ice_pf *pf)
{
ice_devlink_unregister(pf);
ice_health_deinit(pf);
ice_devlink_unregister(pf);
ice_devlink_destroy_regions(pf);
ice_devlink_unregister_params(pf);
}

View File

@@ -2424,7 +2424,9 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)
ICE_TXD_CTX_QW1_CMD_S);
ice_tstamp(tx_ring, skb, first, &offload);
if (ice_is_switchdev_running(vsi->back) && vsi->type != ICE_VSI_SF)
if ((ice_is_switchdev_running(vsi->back) ||
ice_lag_is_switchdev_running(vsi->back)) &&
vsi->type != ICE_VSI_SF)
ice_eswitch_set_target_vsi(skb, &offload);
if (offload.cd_qw1 & ICE_TX_DESC_DTYPE_CTX) {

View File

@@ -46,6 +46,9 @@ mlx5_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
u32 running_fw, stored_fw;
int err;
if (!mlx5_core_is_pf(dev))
return 0;
err = devlink_info_version_fixed_put(req, "fw.psid", dev->board_id);
if (err)
return err;

View File

@@ -48,15 +48,10 @@ mlx5_esw_bridge_lag_rep_get(struct net_device *dev, struct mlx5_eswitch *esw)
struct list_head *iter;
netdev_for_each_lower_dev(dev, lower, iter) {
struct mlx5_core_dev *mdev;
struct mlx5e_priv *priv;
if (!mlx5e_eswitch_rep(lower))
continue;
priv = netdev_priv(lower);
mdev = priv->mdev;
if (mlx5_lag_is_shared_fdb(mdev) && mlx5_esw_bridge_dev_same_esw(lower, esw))
if (mlx5_esw_bridge_dev_same_esw(lower, esw))
return lower;
}
@@ -125,7 +120,7 @@ static bool mlx5_esw_bridge_is_local(struct net_device *dev, struct net_device *
priv = netdev_priv(rep);
mdev = priv->mdev;
if (netif_is_lag_master(dev))
return mlx5_lag_is_shared_fdb(mdev) && mlx5_lag_is_master(mdev);
return mlx5_lag_is_master(mdev);
return true;
}
@@ -455,6 +450,9 @@ static int mlx5_esw_bridge_switchdev_event(struct notifier_block *nb,
if (!rep)
return NOTIFY_DONE;
if (netif_is_lag_master(dev) && !mlx5_lag_is_shared_fdb(esw->dev))
return NOTIFY_DONE;
switch (event) {
case SWITCHDEV_FDB_ADD_TO_BRIDGE:
fdb_info = container_of(info,

View File

@@ -5132,11 +5132,9 @@ static int mlx5e_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
struct mlx5e_priv *priv = netdev_priv(dev);
struct mlx5_core_dev *mdev = priv->mdev;
u8 mode, setting;
int err;
err = mlx5_eswitch_get_vepa(mdev->priv.eswitch, &setting);
if (err)
return err;
if (mlx5_eswitch_get_vepa(mdev->priv.eswitch, &setting))
return -EOPNOTSUPP;
mode = setting ? BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB;
return ndo_dflt_bridge_getlink(skb, pid, seq, dev,
mode,

View File

@@ -871,8 +871,8 @@ static void comp_irq_release_sf(struct mlx5_core_dev *dev, u16 vecidx)
static int comp_irq_request_sf(struct mlx5_core_dev *dev, u16 vecidx)
{
struct mlx5_irq_pool *pool = mlx5_irq_table_get_comp_irq_pool(dev);
struct mlx5_eq_table *table = dev->priv.eq_table;
struct mlx5_irq_pool *pool = mlx5_irq_pool_get(dev);
struct irq_affinity_desc af_desc = {};
struct mlx5_irq *irq;

View File

@@ -175,7 +175,7 @@ unlock:
void mlx5_irq_affinity_irq_release(struct mlx5_core_dev *dev, struct mlx5_irq *irq)
{
struct mlx5_irq_pool *pool = mlx5_irq_pool_get(dev);
struct mlx5_irq_pool *pool = mlx5_irq_get_pool(irq);
int cpu;
cpu = cpumask_first(mlx5_irq_get_affinity_mask(irq));

View File

@@ -951,7 +951,7 @@ void mlx5_disable_lag(struct mlx5_lag *ldev)
mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch);
}
static bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev)
bool mlx5_lag_shared_fdb_supported(struct mlx5_lag *ldev)
{
int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
struct mlx5_core_dev *dev;
@@ -1038,7 +1038,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
}
if (do_bond && !__mlx5_lag_is_active(ldev)) {
bool shared_fdb = mlx5_shared_fdb_supported(ldev);
bool shared_fdb = mlx5_lag_shared_fdb_supported(ldev);
roce_lag = mlx5_lag_is_roce_lag(ldev);

View File

@@ -92,6 +92,7 @@ mlx5_lag_is_ready(struct mlx5_lag *ldev)
return test_bit(MLX5_LAG_FLAG_NDEVS_READY, &ldev->state_flags);
}
bool mlx5_lag_shared_fdb_supported(struct mlx5_lag *ldev);
bool mlx5_lag_check_prereq(struct mlx5_lag *ldev);
void mlx5_modify_lag(struct mlx5_lag *ldev,
struct lag_tracker *tracker);

View File

@@ -83,7 +83,8 @@ static int enable_mpesw(struct mlx5_lag *ldev)
if (mlx5_eswitch_mode(dev0) != MLX5_ESWITCH_OFFLOADS ||
!MLX5_CAP_PORT_SELECTION(dev0, port_select_flow_table) ||
!MLX5_CAP_GEN(dev0, create_lag_when_not_master_up) ||
!mlx5_lag_check_prereq(ldev))
!mlx5_lag_check_prereq(ldev) ||
!mlx5_lag_shared_fdb_supported(ldev))
return -EOPNOTSUPP;
err = mlx5_mpesw_metadata_set(ldev);

View File

@@ -196,6 +196,11 @@ mlx5_chains_create_table(struct mlx5_fs_chains *chains,
ns = mlx5_get_flow_namespace(chains->dev, chains->ns);
}
if (!ns) {
mlx5_core_warn(chains->dev, "Failed to get flow namespace\n");
return ERR_PTR(-EOPNOTSUPP);
}
ft_attr.autogroup.num_reserved_entries = 2;
ft_attr.autogroup.max_num_groups = chains->group_num;
ft = mlx5_create_auto_grouped_flow_table(ns, &ft_attr);

View File

@@ -10,12 +10,15 @@
struct mlx5_irq;
struct cpu_rmap;
struct mlx5_irq_pool;
int mlx5_irq_table_init(struct mlx5_core_dev *dev);
void mlx5_irq_table_cleanup(struct mlx5_core_dev *dev);
int mlx5_irq_table_create(struct mlx5_core_dev *dev);
void mlx5_irq_table_destroy(struct mlx5_core_dev *dev);
void mlx5_irq_table_free_irqs(struct mlx5_core_dev *dev);
struct mlx5_irq_pool *
mlx5_irq_table_get_comp_irq_pool(struct mlx5_core_dev *dev);
int mlx5_irq_table_get_num_comp(struct mlx5_irq_table *table);
int mlx5_irq_table_get_sfs_vec(struct mlx5_irq_table *table);
struct mlx5_irq_table *mlx5_irq_table_get(struct mlx5_core_dev *dev);
@@ -38,7 +41,6 @@ struct cpumask *mlx5_irq_get_affinity_mask(struct mlx5_irq *irq);
int mlx5_irq_get_index(struct mlx5_irq *irq);
int mlx5_irq_get_irq(const struct mlx5_irq *irq);
struct mlx5_irq_pool;
#ifdef CONFIG_MLX5_SF
struct mlx5_irq *mlx5_irq_affinity_irq_request_auto(struct mlx5_core_dev *dev,
struct cpumask *used_cpus, u16 vecidx);

View File

@@ -378,6 +378,11 @@ int mlx5_irq_get_index(struct mlx5_irq *irq)
return irq->map.index;
}
struct mlx5_irq_pool *mlx5_irq_get_pool(struct mlx5_irq *irq)
{
return irq->pool;
}
/* irq_pool API */
/* requesting an irq from a given pool according to given index */
@@ -405,18 +410,20 @@ static struct mlx5_irq_pool *sf_ctrl_irq_pool_get(struct mlx5_irq_table *irq_tab
return irq_table->sf_ctrl_pool;
}
static struct mlx5_irq_pool *sf_irq_pool_get(struct mlx5_irq_table *irq_table)
static struct mlx5_irq_pool *
sf_comp_irq_pool_get(struct mlx5_irq_table *irq_table)
{
return irq_table->sf_comp_pool;
}
struct mlx5_irq_pool *mlx5_irq_pool_get(struct mlx5_core_dev *dev)
struct mlx5_irq_pool *
mlx5_irq_table_get_comp_irq_pool(struct mlx5_core_dev *dev)
{
struct mlx5_irq_table *irq_table = mlx5_irq_table_get(dev);
struct mlx5_irq_pool *pool = NULL;
if (mlx5_core_is_sf(dev))
pool = sf_irq_pool_get(irq_table);
pool = sf_comp_irq_pool_get(irq_table);
/* In some configs, there won't be a pool of SFs IRQs. Hence, returning
* the PF IRQs pool in case the SF pool doesn't exist.

View File

@@ -28,7 +28,6 @@ struct mlx5_irq_pool {
struct mlx5_core_dev *dev;
};
struct mlx5_irq_pool *mlx5_irq_pool_get(struct mlx5_core_dev *dev);
static inline bool mlx5_irq_pool_is_sf_pool(struct mlx5_irq_pool *pool)
{
return !strncmp("mlx5_sf", pool->name, strlen("mlx5_sf"));
@@ -40,5 +39,6 @@ struct mlx5_irq *mlx5_irq_alloc(struct mlx5_irq_pool *pool, int i,
int mlx5_irq_get_locked(struct mlx5_irq *irq);
int mlx5_irq_read_locked(struct mlx5_irq *irq);
int mlx5_irq_put(struct mlx5_irq *irq);
struct mlx5_irq_pool *mlx5_irq_get_pool(struct mlx5_irq *irq);
#endif /* __PCI_IRQ_H__ */

View File

@@ -24,8 +24,8 @@ struct mlx5hws_bwc_matcher {
struct mlx5hws_matcher *matcher;
struct mlx5hws_match_template *mt;
struct mlx5hws_action_template *at[MLX5HWS_BWC_MATCHER_ATTACH_AT_NUM];
u32 priority;
u8 num_of_at;
u16 priority;
u8 size_log;
atomic_t num_of_rules;
struct list_head *rules;

View File

@@ -210,6 +210,10 @@ struct mlx5dr_ste_ctx {
void (*set_encap_l3)(u8 *hw_ste_p, u8 *frst_s_action,
u8 *scnd_d_action, u32 reformat_id,
int size);
void (*set_insert_hdr)(u8 *hw_ste_p, u8 *d_action, u32 reformat_id,
u8 anchor, u8 offset, int size);
void (*set_remove_hdr)(u8 *hw_ste_p, u8 *s_action, u8 anchor,
u8 offset, int size);
/* Send */
void (*prepare_for_postsend)(u8 *hw_ste_p, u32 ste_size);
};

View File

@@ -266,10 +266,10 @@ void dr_ste_v1_set_encap(u8 *hw_ste_p, u8 *d_action, u32 reformat_id, int size)
dr_ste_v1_set_reparse(hw_ste_p);
}
static void dr_ste_v1_set_insert_hdr(u8 *hw_ste_p, u8 *d_action,
u32 reformat_id,
u8 anchor, u8 offset,
int size)
void dr_ste_v1_set_insert_hdr(u8 *hw_ste_p, u8 *d_action,
u32 reformat_id,
u8 anchor, u8 offset,
int size)
{
MLX5_SET(ste_double_action_insert_with_ptr_v1, d_action,
action_id, DR_STE_V1_ACTION_ID_INSERT_POINTER);
@@ -286,9 +286,9 @@ static void dr_ste_v1_set_insert_hdr(u8 *hw_ste_p, u8 *d_action,
dr_ste_v1_set_reparse(hw_ste_p);
}
static void dr_ste_v1_set_remove_hdr(u8 *hw_ste_p, u8 *s_action,
u8 anchor, u8 offset,
int size)
void dr_ste_v1_set_remove_hdr(u8 *hw_ste_p, u8 *s_action,
u8 anchor, u8 offset,
int size)
{
MLX5_SET(ste_single_action_remove_header_size_v1, s_action,
action_id, DR_STE_V1_ACTION_ID_REMOVE_BY_SIZE);
@@ -584,11 +584,11 @@ void dr_ste_v1_set_actions_tx(struct mlx5dr_ste_ctx *ste_ctx,
action = MLX5_ADDR_OF(ste_mask_and_match_v1, last_ste, action);
action_sz = DR_STE_ACTION_TRIPLE_SZ;
}
dr_ste_v1_set_insert_hdr(last_ste, action,
attr->reformat.id,
attr->reformat.param_0,
attr->reformat.param_1,
attr->reformat.size);
ste_ctx->set_insert_hdr(last_ste, action,
attr->reformat.id,
attr->reformat.param_0,
attr->reformat.param_1,
attr->reformat.size);
action_sz -= DR_STE_ACTION_DOUBLE_SZ;
action += DR_STE_ACTION_DOUBLE_SZ;
} else if (action_type_set[DR_ACTION_TYP_REMOVE_HDR]) {
@@ -597,10 +597,10 @@ void dr_ste_v1_set_actions_tx(struct mlx5dr_ste_ctx *ste_ctx,
action = MLX5_ADDR_OF(ste_mask_and_match_v1, last_ste, action);
action_sz = DR_STE_ACTION_TRIPLE_SZ;
}
dr_ste_v1_set_remove_hdr(last_ste, action,
attr->reformat.param_0,
attr->reformat.param_1,
attr->reformat.size);
ste_ctx->set_remove_hdr(last_ste, action,
attr->reformat.param_0,
attr->reformat.param_1,
attr->reformat.size);
action_sz -= DR_STE_ACTION_SINGLE_SZ;
action += DR_STE_ACTION_SINGLE_SZ;
}
@@ -792,11 +792,11 @@ void dr_ste_v1_set_actions_rx(struct mlx5dr_ste_ctx *ste_ctx,
action = MLX5_ADDR_OF(ste_mask_and_match_v1, last_ste, action);
action_sz = DR_STE_ACTION_TRIPLE_SZ;
}
dr_ste_v1_set_insert_hdr(last_ste, action,
attr->reformat.id,
attr->reformat.param_0,
attr->reformat.param_1,
attr->reformat.size);
ste_ctx->set_insert_hdr(last_ste, action,
attr->reformat.id,
attr->reformat.param_0,
attr->reformat.param_1,
attr->reformat.size);
action_sz -= DR_STE_ACTION_DOUBLE_SZ;
action += DR_STE_ACTION_DOUBLE_SZ;
allow_modify_hdr = false;
@@ -808,10 +808,10 @@ void dr_ste_v1_set_actions_rx(struct mlx5dr_ste_ctx *ste_ctx,
allow_modify_hdr = true;
allow_ctr = true;
}
dr_ste_v1_set_remove_hdr(last_ste, action,
attr->reformat.param_0,
attr->reformat.param_1,
attr->reformat.size);
ste_ctx->set_remove_hdr(last_ste, action,
attr->reformat.param_0,
attr->reformat.param_1,
attr->reformat.size);
action_sz -= DR_STE_ACTION_SINGLE_SZ;
action += DR_STE_ACTION_SINGLE_SZ;
}
@@ -2200,6 +2200,8 @@ static struct mlx5dr_ste_ctx ste_ctx_v1 = {
.set_pop_vlan = &dr_ste_v1_set_pop_vlan,
.set_rx_decap = &dr_ste_v1_set_rx_decap,
.set_encap_l3 = &dr_ste_v1_set_encap_l3,
.set_insert_hdr = &dr_ste_v1_set_insert_hdr,
.set_remove_hdr = &dr_ste_v1_set_remove_hdr,
/* Send */
.prepare_for_postsend = &dr_ste_v1_prepare_for_postsend,
};

View File

@@ -156,6 +156,10 @@ void dr_ste_v1_set_pop_vlan(u8 *hw_ste_p, u8 *s_action, u8 vlans_num);
void dr_ste_v1_set_encap_l3(u8 *hw_ste_p, u8 *frst_s_action, u8 *scnd_d_action,
u32 reformat_id, int size);
void dr_ste_v1_set_rx_decap(u8 *hw_ste_p, u8 *s_action);
void dr_ste_v1_set_insert_hdr(u8 *hw_ste_p, u8 *d_action, u32 reformat_id,
u8 anchor, u8 offset, int size);
void dr_ste_v1_set_remove_hdr(u8 *hw_ste_p, u8 *s_action, u8 anchor,
u8 offset, int size);
void dr_ste_v1_set_actions_tx(struct mlx5dr_ste_ctx *ste_ctx, struct mlx5dr_domain *dmn,
u8 *action_type_set, u32 actions_caps, u8 *last_ste,
struct mlx5dr_ste_actions_attr *attr, u32 *added_stes);

View File

@@ -69,6 +69,8 @@ static struct mlx5dr_ste_ctx ste_ctx_v2 = {
.set_pop_vlan = &dr_ste_v1_set_pop_vlan,
.set_rx_decap = &dr_ste_v1_set_rx_decap,
.set_encap_l3 = &dr_ste_v1_set_encap_l3,
.set_insert_hdr = &dr_ste_v1_set_insert_hdr,
.set_remove_hdr = &dr_ste_v1_set_remove_hdr,
/* Send */
.prepare_for_postsend = &dr_ste_v1_prepare_for_postsend,
};

View File

@@ -79,6 +79,46 @@ static void dr_ste_v3_set_rx_decap(u8 *hw_ste_p, u8 *s_action)
dr_ste_v1_set_reparse(hw_ste_p);
}
static void dr_ste_v3_set_insert_hdr(u8 *hw_ste_p, u8 *d_action,
u32 reformat_id, u8 anchor,
u8 offset, int size)
{
MLX5_SET(ste_double_action_insert_with_ptr_v3, d_action,
action_id, DR_STE_V1_ACTION_ID_INSERT_POINTER);
MLX5_SET(ste_double_action_insert_with_ptr_v3, d_action,
start_anchor, anchor);
/* The hardware expects here size and offset in words (2 byte) */
MLX5_SET(ste_double_action_insert_with_ptr_v3, d_action,
size, size / 2);
MLX5_SET(ste_double_action_insert_with_ptr_v3, d_action,
start_offset, offset / 2);
MLX5_SET(ste_double_action_insert_with_ptr_v3, d_action,
pointer, reformat_id);
MLX5_SET(ste_double_action_insert_with_ptr_v3, d_action,
attributes, DR_STE_V1_ACTION_INSERT_PTR_ATTR_NONE);
dr_ste_v1_set_reparse(hw_ste_p);
}
static void dr_ste_v3_set_remove_hdr(u8 *hw_ste_p, u8 *s_action,
u8 anchor, u8 offset, int size)
{
MLX5_SET(ste_single_action_remove_header_size_v3, s_action,
action_id, DR_STE_V1_ACTION_ID_REMOVE_BY_SIZE);
MLX5_SET(ste_single_action_remove_header_size_v3, s_action,
start_anchor, anchor);
/* The hardware expects here size and offset in words (2 byte) */
MLX5_SET(ste_single_action_remove_header_size_v3, s_action,
remove_size, size / 2);
MLX5_SET(ste_single_action_remove_header_size_v3, s_action,
start_offset, offset / 2);
dr_ste_v1_set_reparse(hw_ste_p);
}
static int
dr_ste_v3_set_action_decap_l3_list(void *data, u32 data_sz,
u8 *hw_action, u32 hw_action_sz,
@@ -211,6 +251,8 @@ static struct mlx5dr_ste_ctx ste_ctx_v3 = {
.set_pop_vlan = &dr_ste_v3_set_pop_vlan,
.set_rx_decap = &dr_ste_v3_set_rx_decap,
.set_encap_l3 = &dr_ste_v3_set_encap_l3,
.set_insert_hdr = &dr_ste_v3_set_insert_hdr,
.set_remove_hdr = &dr_ste_v3_set_remove_hdr,
/* Send */
.prepare_for_postsend = &dr_ste_v1_prepare_for_postsend,
};

View File

@@ -1547,6 +1547,7 @@ unmap_bar:
* adapter-MTU file and apc->mana_pci_debugfs folder.
*/
debugfs_remove_recursive(gc->mana_pci_debugfs);
gc->mana_pci_debugfs = NULL;
pci_iounmap(pdev, bar0_va);
free_gc:
pci_set_drvdata(pdev, NULL);
@@ -1569,6 +1570,8 @@ static void mana_gd_remove(struct pci_dev *pdev)
debugfs_remove_recursive(gc->mana_pci_debugfs);
gc->mana_pci_debugfs = NULL;
pci_iounmap(pdev, gc->bar0_va);
vfree(gc);
@@ -1622,6 +1625,8 @@ static void mana_gd_shutdown(struct pci_dev *pdev)
debugfs_remove_recursive(gc->mana_pci_debugfs);
gc->mana_pci_debugfs = NULL;
pci_disable_device(pdev);
}
@@ -1648,8 +1653,10 @@ static int __init mana_driver_init(void)
mana_debugfs_root = debugfs_create_dir("mana", NULL);
err = pci_register_driver(&mana_driver);
if (err)
if (err) {
debugfs_remove(mana_debugfs_root);
mana_debugfs_root = NULL;
}
return err;
}
@@ -1659,6 +1666,8 @@ static void __exit mana_driver_exit(void)
pci_unregister_driver(&mana_driver);
debugfs_remove(mana_debugfs_root);
mana_debugfs_root = NULL;
}
module_init(mana_driver_init);

View File

@@ -738,12 +738,11 @@ static const struct net_device_ops mana_devops = {
static void mana_cleanup_port_context(struct mana_port_context *apc)
{
/*
* at this point all dir/files under the vport directory
* are already cleaned up.
* We are sure the apc->mana_port_debugfs remove will not
* cause any freed memory access issues
* make sure subsequent cleanup attempts don't end up removing already
* cleaned dentry pointer
*/
debugfs_remove(apc->mana_port_debugfs);
apc->mana_port_debugfs = NULL;
kfree(apc->rxqs);
apc->rxqs = NULL;
}
@@ -1254,6 +1253,7 @@ static void mana_destroy_eq(struct mana_context *ac)
return;
debugfs_remove_recursive(ac->mana_eqs_debugfs);
ac->mana_eqs_debugfs = NULL;
for (i = 0; i < gc->max_num_queues; i++) {
eq = ac->eqs[i].eq;
@@ -1914,6 +1914,7 @@ static void mana_destroy_txq(struct mana_port_context *apc)
for (i = 0; i < apc->num_queues; i++) {
debugfs_remove_recursive(apc->tx_qp[i].mana_tx_debugfs);
apc->tx_qp[i].mana_tx_debugfs = NULL;
napi = &apc->tx_qp[i].tx_cq.napi;
if (apc->tx_qp[i].txq.napi_initialized) {
@@ -2099,6 +2100,7 @@ static void mana_destroy_rxq(struct mana_port_context *apc,
return;
debugfs_remove_recursive(rxq->mana_rx_debugfs);
rxq->mana_rx_debugfs = NULL;
napi = &rxq->rx_cq.napi;

View File

@@ -454,8 +454,10 @@ static int qlcnic_sriov_set_guest_vlan_mode(struct qlcnic_adapter *adapter,
num_vlans = sriov->num_allowed_vlans;
sriov->allowed_vlans = kcalloc(num_vlans, sizeof(u16), GFP_KERNEL);
if (!sriov->allowed_vlans)
if (!sriov->allowed_vlans) {
qlcnic_sriov_free_vlans(adapter);
return -ENOMEM;
}
vlans = (u16 *)&cmd->rsp.arg[3];
for (i = 0; i < num_vlans; i++)
@@ -2167,8 +2169,10 @@ int qlcnic_sriov_alloc_vlans(struct qlcnic_adapter *adapter)
vf = &sriov->vf_info[i];
vf->sriov_vlans = kcalloc(sriov->num_allowed_vlans,
sizeof(*vf->sriov_vlans), GFP_KERNEL);
if (!vf->sriov_vlans)
if (!vf->sriov_vlans) {
qlcnic_sriov_free_vlans(adapter);
return -ENOMEM;
}
}
return 0;

View File

@@ -1501,7 +1501,10 @@ static void rtase_wait_for_quiescence(const struct net_device *dev)
static void rtase_sw_reset(struct net_device *dev)
{
struct rtase_private *tp = netdev_priv(dev);
struct rtase_ring *ring, *tmp;
struct rtase_int_vector *ivec;
int ret;
u32 i;
netif_stop_queue(dev);
netif_carrier_off(dev);
@@ -1512,6 +1515,13 @@ static void rtase_sw_reset(struct net_device *dev)
rtase_tx_clear(tp);
rtase_rx_clear(tp);
for (i = 0; i < tp->int_nums; i++) {
ivec = &tp->int_vector[i];
list_for_each_entry_safe(ring, tmp, &ivec->ring_list,
ring_entry)
list_del(&ring->ring_entry);
}
ret = rtase_init_ring(dev);
if (ret) {
netdev_err(dev, "unable to init ring\n");

View File

@@ -583,6 +583,7 @@ static int mctp_i2c_header_create(struct sk_buff *skb, struct net_device *dev,
struct mctp_i2c_hdr *hdr;
struct mctp_hdr *mhdr;
u8 lldst, llsrc;
int rc;
if (len > MCTP_I2C_MAXMTU)
return -EMSGSIZE;
@@ -593,6 +594,10 @@ static int mctp_i2c_header_create(struct sk_buff *skb, struct net_device *dev,
lldst = *((u8 *)daddr);
llsrc = *((u8 *)saddr);
rc = skb_cow_head(skb, sizeof(struct mctp_i2c_hdr));
if (rc)
return rc;
skb_push(skb, sizeof(struct mctp_i2c_hdr));
skb_reset_mac_header(skb);
hdr = (void *)skb_mac_header(skb);

View File

@@ -506,10 +506,15 @@ static int mctp_i3c_header_create(struct sk_buff *skb, struct net_device *dev,
const void *saddr, unsigned int len)
{
struct mctp_i3c_internal_hdr *ihdr;
int rc;
if (!daddr || !saddr)
return -EINVAL;
rc = skb_cow_head(skb, sizeof(struct mctp_i3c_internal_hdr));
if (rc)
return rc;
skb_push(skb, sizeof(struct mctp_i3c_internal_hdr));
skb_reset_mac_header(skb);
ihdr = (void *)skb_mac_header(skb);

View File

@@ -22,6 +22,11 @@
#define PHY_ID_TJA_1103 0x001BB010
#define PHY_ID_TJA_1120 0x001BB031
#define VEND1_DEVICE_ID3 0x0004
#define TJA1120_DEV_ID3_SILICON_VERSION GENMASK(15, 12)
#define TJA1120_DEV_ID3_SAMPLE_TYPE GENMASK(11, 8)
#define DEVICE_ID3_SAMPLE_TYPE_R 0x9
#define VEND1_DEVICE_CONTROL 0x0040
#define DEVICE_CONTROL_RESET BIT(15)
#define DEVICE_CONTROL_CONFIG_GLOBAL_EN BIT(14)
@@ -109,6 +114,9 @@
#define MII_BASIC_CONFIG_RMII 0x5
#define MII_BASIC_CONFIG_MII 0x4
#define VEND1_SGMII_BASIC_CONTROL 0xB000
#define SGMII_LPM BIT(11)
#define VEND1_SYMBOL_ERROR_CNT_XTD 0x8351
#define EXTENDED_CNT_EN BIT(15)
#define VEND1_MONITOR_STATUS 0xAC80
@@ -1593,6 +1601,63 @@ static int nxp_c45_set_phy_mode(struct phy_device *phydev)
return 0;
}
/* Errata: ES_TJA1120 and ES_TJA1121 Rev. 1.0 — 28 November 2024 Section 3.1 & 3.2 */
static void nxp_c45_tja1120_errata(struct phy_device *phydev)
{
bool macsec_ability, sgmii_ability;
int silicon_version, sample_type;
int phy_abilities;
int ret = 0;
ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_ID3);
if (ret < 0)
return;
sample_type = FIELD_GET(TJA1120_DEV_ID3_SAMPLE_TYPE, ret);
if (sample_type != DEVICE_ID3_SAMPLE_TYPE_R)
return;
silicon_version = FIELD_GET(TJA1120_DEV_ID3_SILICON_VERSION, ret);
phy_abilities = phy_read_mmd(phydev, MDIO_MMD_VEND1,
VEND1_PORT_ABILITIES);
macsec_ability = !!(phy_abilities & MACSEC_ABILITY);
sgmii_ability = !!(phy_abilities & SGMII_ABILITY);
if ((!macsec_ability && silicon_version == 2) ||
(macsec_ability && silicon_version == 1)) {
/* TJA1120/TJA1121 PHY configuration errata workaround.
* Apply PHY writes sequence before link up.
*/
if (!macsec_ability) {
phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F8, 0x4b95);
phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F9, 0xf3cd);
} else {
phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F8, 0x89c7);
phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F9, 0x0893);
}
phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0476, 0x58a0);
phy_write_mmd(phydev, MDIO_MMD_PMAPMD, 0x8921, 0xa3a);
phy_write_mmd(phydev, MDIO_MMD_PMAPMD, 0x89F1, 0x16c1);
phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F8, 0x0);
phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F9, 0x0);
if (sgmii_ability) {
/* TJA1120B/TJA1121B SGMII PCS restart errata workaround.
* Put SGMII PCS into power down mode and back up.
*/
phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
VEND1_SGMII_BASIC_CONTROL,
SGMII_LPM);
phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
VEND1_SGMII_BASIC_CONTROL,
SGMII_LPM);
}
}
}
static int nxp_c45_config_init(struct phy_device *phydev)
{
int ret;
@@ -1609,6 +1674,9 @@ static int nxp_c45_config_init(struct phy_device *phydev)
phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F8, 1);
phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F9, 2);
if (phy_id_compare(phydev->phy_id, PHY_ID_TJA_1120, GENMASK(31, 4)))
nxp_c45_tja1120_errata(phydev);
phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONFIG,
PHY_CONFIG_AUTO);

View File

@@ -627,7 +627,7 @@ static int lan78xx_read_reg(struct lan78xx_net *dev, u32 index, u32 *data)
kfree(buf);
return ret;
return ret < 0 ? ret : 0;
}
static int lan78xx_write_reg(struct lan78xx_net *dev, u32 index, u32 data)
@@ -658,7 +658,7 @@ static int lan78xx_write_reg(struct lan78xx_net *dev, u32 index, u32 data)
kfree(buf);
return ret;
return ret < 0 ? ret : 0;
}
static int lan78xx_update_reg(struct lan78xx_net *dev, u32 reg, u32 mask,

View File

@@ -403,6 +403,8 @@ void iwl_trans_op_mode_leave(struct iwl_trans *trans)
iwl_trans_pcie_op_mode_leave(trans);
cancel_work_sync(&trans->restart.wk);
trans->op_mode = NULL;
trans->state = IWL_TRANS_NO_FW;

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
* Copyright (C) 2012-2014, 2018-2025 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -422,6 +422,8 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
/* if reached this point, Alive notification was received */
iwl_mei_alive_notif(true);
iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr);
ret = iwl_pnvm_load(mvm->trans, &mvm->notif_wait,
&mvm->fw->ucode_capa);
if (ret) {
@@ -430,8 +432,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
return ret;
}
iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr);
/*
* Note: all the queues are enabled as part of the interface
* initialization, but in firmware restart scenarios they

View File

@@ -1869,12 +1869,12 @@ struct sg_table *iwl_pcie_prep_tso(struct iwl_trans *trans, struct sk_buff *skb,
unsigned int offset)
{
struct sg_table *sgt;
unsigned int n_segments;
unsigned int n_segments = skb_shinfo(skb)->nr_frags + 1;
int orig_nents;
if (WARN_ON_ONCE(skb_has_frag_list(skb)))
return NULL;
n_segments = DIV_ROUND_UP(skb->len - offset, skb_shinfo(skb)->gso_size);
*hdr = iwl_pcie_get_page_hdr(trans,
hdr_room + __alignof__(struct sg_table) +
sizeof(struct sg_table) +
@@ -1889,11 +1889,12 @@ struct sg_table *iwl_pcie_prep_tso(struct iwl_trans *trans, struct sk_buff *skb,
sg_init_table(sgt->sgl, n_segments);
/* Only map the data, not the header (it is copied to the TSO page) */
sgt->orig_nents = skb_to_sgvec(skb, sgt->sgl, offset,
skb->len - offset);
if (WARN_ON_ONCE(sgt->orig_nents <= 0))
orig_nents = skb_to_sgvec(skb, sgt->sgl, offset, skb->len - offset);
if (WARN_ON_ONCE(orig_nents <= 0))
return NULL;
sgt->orig_nents = orig_nents;
/* And map the entire SKB */
if (dma_map_sgtable(trans->dev, sgt, DMA_TO_DEVICE, 0) < 0)
return NULL;

View File

@@ -804,6 +804,7 @@ struct hci_conn_params {
extern struct list_head hci_dev_list;
extern struct list_head hci_cb_list;
extern rwlock_t hci_dev_list_lock;
extern struct mutex hci_cb_list_lock;
#define hci_dev_set_flag(hdev, nr) set_bit((nr), (hdev)->dev_flags)
#define hci_dev_clear_flag(hdev, nr) clear_bit((nr), (hdev)->dev_flags)
@@ -2010,47 +2011,24 @@ struct hci_cb {
char *name;
bool (*match) (struct hci_conn *conn);
void (*connect_cfm) (struct hci_conn *conn, __u8 status);
void (*disconn_cfm) (struct hci_conn *conn, __u8 status);
void (*security_cfm) (struct hci_conn *conn, __u8 status,
__u8 encrypt);
__u8 encrypt);
void (*key_change_cfm) (struct hci_conn *conn, __u8 status);
void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
};
static inline void hci_cb_lookup(struct hci_conn *conn, struct list_head *list)
{
struct hci_cb *cb, *cpy;
rcu_read_lock();
list_for_each_entry_rcu(cb, &hci_cb_list, list) {
if (cb->match && cb->match(conn)) {
cpy = kmalloc(sizeof(*cpy), GFP_ATOMIC);
if (!cpy)
break;
*cpy = *cb;
INIT_LIST_HEAD(&cpy->list);
list_add_rcu(&cpy->list, list);
}
}
rcu_read_unlock();
}
static inline void hci_connect_cfm(struct hci_conn *conn, __u8 status)
{
struct list_head list;
struct hci_cb *cb, *tmp;
struct hci_cb *cb;
INIT_LIST_HEAD(&list);
hci_cb_lookup(conn, &list);
list_for_each_entry_safe(cb, tmp, &list, list) {
mutex_lock(&hci_cb_list_lock);
list_for_each_entry(cb, &hci_cb_list, list) {
if (cb->connect_cfm)
cb->connect_cfm(conn, status);
kfree(cb);
}
mutex_unlock(&hci_cb_list_lock);
if (conn->connect_cfm_cb)
conn->connect_cfm_cb(conn, status);
@@ -2058,43 +2036,22 @@ static inline void hci_connect_cfm(struct hci_conn *conn, __u8 status)
static inline void hci_disconn_cfm(struct hci_conn *conn, __u8 reason)
{
struct list_head list;
struct hci_cb *cb, *tmp;
struct hci_cb *cb;
INIT_LIST_HEAD(&list);
hci_cb_lookup(conn, &list);
list_for_each_entry_safe(cb, tmp, &list, list) {
mutex_lock(&hci_cb_list_lock);
list_for_each_entry(cb, &hci_cb_list, list) {
if (cb->disconn_cfm)
cb->disconn_cfm(conn, reason);
kfree(cb);
}
mutex_unlock(&hci_cb_list_lock);
if (conn->disconn_cfm_cb)
conn->disconn_cfm_cb(conn, reason);
}
static inline void hci_security_cfm(struct hci_conn *conn, __u8 status,
__u8 encrypt)
{
struct list_head list;
struct hci_cb *cb, *tmp;
INIT_LIST_HEAD(&list);
hci_cb_lookup(conn, &list);
list_for_each_entry_safe(cb, tmp, &list, list) {
if (cb->security_cfm)
cb->security_cfm(conn, status, encrypt);
kfree(cb);
}
if (conn->security_cfm_cb)
conn->security_cfm_cb(conn, status);
}
static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
{
struct hci_cb *cb;
__u8 encrypt;
if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
@@ -2102,11 +2059,20 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
encrypt = test_bit(HCI_CONN_ENCRYPT, &conn->flags) ? 0x01 : 0x00;
hci_security_cfm(conn, status, encrypt);
mutex_lock(&hci_cb_list_lock);
list_for_each_entry(cb, &hci_cb_list, list) {
if (cb->security_cfm)
cb->security_cfm(conn, status, encrypt);
}
mutex_unlock(&hci_cb_list_lock);
if (conn->security_cfm_cb)
conn->security_cfm_cb(conn, status);
}
static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
{
struct hci_cb *cb;
__u8 encrypt;
if (conn->state == BT_CONFIG) {
@@ -2133,38 +2099,40 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
conn->sec_level = conn->pending_sec_level;
}
hci_security_cfm(conn, status, encrypt);
mutex_lock(&hci_cb_list_lock);
list_for_each_entry(cb, &hci_cb_list, list) {
if (cb->security_cfm)
cb->security_cfm(conn, status, encrypt);
}
mutex_unlock(&hci_cb_list_lock);
if (conn->security_cfm_cb)
conn->security_cfm_cb(conn, status);
}
static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
{
struct list_head list;
struct hci_cb *cb, *tmp;
struct hci_cb *cb;
INIT_LIST_HEAD(&list);
hci_cb_lookup(conn, &list);
list_for_each_entry_safe(cb, tmp, &list, list) {
mutex_lock(&hci_cb_list_lock);
list_for_each_entry(cb, &hci_cb_list, list) {
if (cb->key_change_cfm)
cb->key_change_cfm(conn, status);
kfree(cb);
}
mutex_unlock(&hci_cb_list_lock);
}
static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
__u8 role)
{
struct list_head list;
struct hci_cb *cb, *tmp;
struct hci_cb *cb;
INIT_LIST_HEAD(&list);
hci_cb_lookup(conn, &list);
list_for_each_entry_safe(cb, tmp, &list, list) {
mutex_lock(&hci_cb_list_lock);
list_for_each_entry(cb, &hci_cb_list, list) {
if (cb->role_switch_cfm)
cb->role_switch_cfm(conn, status, role);
kfree(cb);
}
mutex_unlock(&hci_cb_list_lock);
}
static inline bool hci_bdaddr_is_rpa(bdaddr_t *bdaddr, u8 addr_type)

View File

@@ -1891,7 +1891,7 @@ void nft_chain_filter_fini(void);
void __init nft_chain_route_init(void);
void nft_chain_route_fini(void);
void nf_tables_trans_destroy_flush_work(void);
void nf_tables_trans_destroy_flush_work(struct net *net);
int nf_msecs_to_jiffies64(const struct nlattr *nla, u64 *result);
__be64 nf_jiffies64_to_msecs(u64 input);
@@ -1905,6 +1905,7 @@ static inline int nft_request_module(struct net *net, const char *fmt, ...) { re
struct nftables_pernet {
struct list_head tables;
struct list_head commit_list;
struct list_head destroy_list;
struct list_head commit_set_list;
struct list_head binding_list;
struct list_head module_list;
@@ -1915,6 +1916,7 @@ struct nftables_pernet {
unsigned int base_seq;
unsigned int gc_seq;
u8 validate_state;
struct work_struct destroy_work;
};
extern unsigned int nf_tables_net_id;

View File

@@ -57,6 +57,7 @@ DEFINE_RWLOCK(hci_dev_list_lock);
/* HCI callback list */
LIST_HEAD(hci_cb_list);
DEFINE_MUTEX(hci_cb_list_lock);
/* HCI ID Numbering */
static DEFINE_IDA(hci_index_ida);
@@ -2972,7 +2973,9 @@ int hci_register_cb(struct hci_cb *cb)
{
BT_DBG("%p name %s", cb, cb->name);
list_add_tail_rcu(&cb->list, &hci_cb_list);
mutex_lock(&hci_cb_list_lock);
list_add_tail(&cb->list, &hci_cb_list);
mutex_unlock(&hci_cb_list_lock);
return 0;
}
@@ -2982,8 +2985,9 @@ int hci_unregister_cb(struct hci_cb *cb)
{
BT_DBG("%p name %s", cb, cb->name);
list_del_rcu(&cb->list);
synchronize_rcu();
mutex_lock(&hci_cb_list_lock);
list_del(&cb->list);
mutex_unlock(&hci_cb_list_lock);
return 0;
}

View File

@@ -3391,23 +3391,30 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, void *data,
hci_update_scan(hdev);
}
params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
if (params) {
switch (params->auto_connect) {
case HCI_AUTO_CONN_LINK_LOSS:
if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT)
/* Re-enable passive scanning if disconnected device is marked
* as auto-connectable.
*/
if (conn->type == LE_LINK) {
params = hci_conn_params_lookup(hdev, &conn->dst,
conn->dst_type);
if (params) {
switch (params->auto_connect) {
case HCI_AUTO_CONN_LINK_LOSS:
if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT)
break;
fallthrough;
case HCI_AUTO_CONN_DIRECT:
case HCI_AUTO_CONN_ALWAYS:
hci_pend_le_list_del_init(params);
hci_pend_le_list_add(params,
&hdev->pend_le_conns);
hci_update_passive_scan(hdev);
break;
fallthrough;
case HCI_AUTO_CONN_DIRECT:
case HCI_AUTO_CONN_ALWAYS:
hci_pend_le_list_del_init(params);
hci_pend_le_list_add(params, &hdev->pend_le_conns);
hci_update_passive_scan(hdev);
break;
default:
break;
default:
break;
}
}
}

View File

@@ -2187,11 +2187,6 @@ done:
return HCI_LM_ACCEPT;
}
static bool iso_match(struct hci_conn *hcon)
{
return hcon->type == ISO_LINK || hcon->type == LE_LINK;
}
static void iso_connect_cfm(struct hci_conn *hcon, __u8 status)
{
if (hcon->type != ISO_LINK) {
@@ -2373,7 +2368,6 @@ drop:
static struct hci_cb iso_cb = {
.name = "ISO",
.match = iso_match,
.connect_cfm = iso_connect_cfm,
.disconn_cfm = iso_disconn_cfm,
};

View File

@@ -7182,11 +7182,6 @@ static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c,
return NULL;
}
static bool l2cap_match(struct hci_conn *hcon)
{
return hcon->type == ACL_LINK || hcon->type == LE_LINK;
}
static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
{
struct hci_dev *hdev = hcon->hdev;
@@ -7194,6 +7189,9 @@ static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
struct l2cap_chan *pchan;
u8 dst_type;
if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
return;
BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
if (status) {
@@ -7258,6 +7256,9 @@ int l2cap_disconn_ind(struct hci_conn *hcon)
static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
{
if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
return;
BT_DBG("hcon %p reason %d", hcon, reason);
l2cap_conn_del(hcon, bt_to_errno(reason));
@@ -7565,7 +7566,6 @@ unlock:
static struct hci_cb l2cap_cb = {
.name = "L2CAP",
.match = l2cap_match,
.connect_cfm = l2cap_connect_cfm,
.disconn_cfm = l2cap_disconn_cfm,
.security_cfm = l2cap_security_cfm,

View File

@@ -2134,11 +2134,6 @@ static int rfcomm_run(void *unused)
return 0;
}
static bool rfcomm_match(struct hci_conn *hcon)
{
return hcon->type == ACL_LINK;
}
static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
{
struct rfcomm_session *s;
@@ -2185,7 +2180,6 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
static struct hci_cb rfcomm_cb = {
.name = "RFCOMM",
.match = rfcomm_match,
.security_cfm = rfcomm_security_cfm
};

View File

@@ -107,6 +107,14 @@ static void sco_conn_put(struct sco_conn *conn)
kref_put(&conn->ref, sco_conn_free);
}
static struct sco_conn *sco_conn_hold(struct sco_conn *conn)
{
BT_DBG("conn %p refcnt %u", conn, kref_read(&conn->ref));
kref_get(&conn->ref);
return conn;
}
static struct sco_conn *sco_conn_hold_unless_zero(struct sco_conn *conn)
{
if (!conn)
@@ -1353,6 +1361,7 @@ static void sco_conn_ready(struct sco_conn *conn)
bacpy(&sco_pi(sk)->src, &conn->hcon->src);
bacpy(&sco_pi(sk)->dst, &conn->hcon->dst);
sco_conn_hold(conn);
hci_conn_hold(conn->hcon);
__sco_chan_add(conn, sk, parent);
@@ -1398,27 +1407,30 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
return lm;
}
static bool sco_match(struct hci_conn *hcon)
{
return hcon->type == SCO_LINK || hcon->type == ESCO_LINK;
}
static void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
{
if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
return;
BT_DBG("hcon %p bdaddr %pMR status %u", hcon, &hcon->dst, status);
if (!status) {
struct sco_conn *conn;
conn = sco_conn_add(hcon);
if (conn)
if (conn) {
sco_conn_ready(conn);
sco_conn_put(conn);
}
} else
sco_conn_del(hcon, bt_to_errno(status));
}
static void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
{
if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
return;
BT_DBG("hcon %p reason %d", hcon, reason);
sco_conn_del(hcon, bt_to_errno(reason));
@@ -1444,7 +1456,6 @@ drop:
static struct hci_cb sco_cb = {
.name = "SCO",
.match = sco_match,
.connect_cfm = sco_connect_cfm,
.disconn_cfm = sco_disconn_cfm,
};

View File

@@ -3872,6 +3872,9 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device
{
netdev_features_t features;
if (!skb_frags_readable(skb))
goto out_kfree_skb;
features = netif_skb_features(skb);
skb = validate_xmit_vlan(skb, features);
if (unlikely(!skb))

View File

@@ -109,6 +109,7 @@ void net_devmem_unbind_dmabuf(struct net_devmem_dmabuf_binding *binding)
struct netdev_rx_queue *rxq;
unsigned long xa_idx;
unsigned int rxq_idx;
int err;
if (binding->list.next)
list_del(&binding->list);
@@ -120,7 +121,8 @@ void net_devmem_unbind_dmabuf(struct net_devmem_dmabuf_binding *binding)
rxq_idx = get_netdev_rx_queue_index(rxq);
WARN_ON(netdev_rx_queue_restart(binding->dev, rxq_idx));
err = netdev_rx_queue_restart(binding->dev, rxq_idx);
WARN_ON(err && err != -ENETDOWN);
}
xa_erase(&net_devmem_dmabuf_bindings, binding->id);

View File

@@ -319,6 +319,7 @@ static int netpoll_owner_active(struct net_device *dev)
static netdev_tx_t __netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
{
netdev_tx_t status = NETDEV_TX_BUSY;
netdev_tx_t ret = NET_XMIT_DROP;
struct net_device *dev;
unsigned long tries;
/* It is up to the caller to keep npinfo alive. */
@@ -327,11 +328,12 @@ static netdev_tx_t __netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
lockdep_assert_irqs_disabled();
dev = np->dev;
rcu_read_lock();
npinfo = rcu_dereference_bh(dev->npinfo);
if (!npinfo || !netif_running(dev) || !netif_device_present(dev)) {
dev_kfree_skb_irq(skb);
return NET_XMIT_DROP;
goto out;
}
/* don't get messages out of order, and no recursion */
@@ -370,7 +372,10 @@ static netdev_tx_t __netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
skb_queue_tail(&npinfo->txq, skb);
schedule_delayed_work(&npinfo->tx_work,0);
}
return NETDEV_TX_OK;
ret = NETDEV_TX_OK;
out:
rcu_read_unlock();
return ret;
}
netdev_tx_t netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)

View File

@@ -290,7 +290,8 @@ static void *ethnl_tsinfo_prepare_dump(struct sk_buff *skb,
reply_data = ctx->reply_data;
memset(reply_data, 0, sizeof(*reply_data));
reply_data->base.dev = dev;
memset(&reply_data->ts_info, 0, sizeof(reply_data->ts_info));
reply_data->ts_info.cmd = ETHTOOL_GET_TS_INFO;
reply_data->ts_info.phc_index = -1;
return ehdr;
}

View File

@@ -3209,16 +3209,13 @@ static void add_v4_addrs(struct inet6_dev *idev)
struct in6_addr addr;
struct net_device *dev;
struct net *net = dev_net(idev->dev);
int scope, plen, offset = 0;
int scope, plen;
u32 pflags = 0;
ASSERT_RTNL();
memset(&addr, 0, sizeof(struct in6_addr));
/* in case of IP6GRE the dev_addr is an IPv6 and therefore we use only the last 4 bytes */
if (idev->dev->addr_len == sizeof(struct in6_addr))
offset = sizeof(struct in6_addr) - 4;
memcpy(&addr.s6_addr32[3], idev->dev->dev_addr + offset, 4);
memcpy(&addr.s6_addr32[3], idev->dev->dev_addr, 4);
if (!(idev->dev->flags & IFF_POINTOPOINT) && idev->dev->type == ARPHRD_SIT) {
scope = IPV6_ADDR_COMPATv4;
@@ -3529,7 +3526,13 @@ static void addrconf_gre_config(struct net_device *dev)
return;
}
if (dev->type == ARPHRD_ETHER) {
/* Generate the IPv6 link-local address using addrconf_addr_gen(),
* unless we have an IPv4 GRE device not bound to an IP address and
* which is in EUI64 mode (as __ipv6_isatap_ifid() would fail in this
* case). Such devices fall back to add_v4_addrs() instead.
*/
if (!(dev->type == ARPHRD_IPGRE && *(__be32 *)dev->dev_addr == 0 &&
idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64)) {
addrconf_addr_gen(idev, true);
return;
}

View File

@@ -2,7 +2,7 @@
/*
* EHT handling
*
* Copyright(c) 2021-2024 Intel Corporation
* Copyright(c) 2021-2025 Intel Corporation
*/
#include "ieee80211_i.h"
@@ -76,6 +76,13 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(struct ieee80211_sub_if_data *sdata,
link_sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(link_sta);
link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta);
/*
* The MPDU length bits are reserved on all but 2.4 GHz and get set via
* VHT (5 GHz) or HE (6 GHz) capabilities.
*/
if (sband->band != NL80211_BAND_2GHZ)
return;
switch (u8_get_bits(eht_cap->eht_cap_elem.mac_cap_info[0],
IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK)) {
case IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_11454:

View File

@@ -6,7 +6,7 @@
* Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright (C) 2018-2024 Intel Corporation
* Copyright (C) 2018-2025 Intel Corporation
*/
#include <linux/jiffies.h>
@@ -3329,8 +3329,8 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata,
return;
}
if (!ether_addr_equal(mgmt->sa, sdata->deflink.u.mgd.bssid) ||
!ether_addr_equal(mgmt->bssid, sdata->deflink.u.mgd.bssid)) {
if (!ether_addr_equal(mgmt->sa, sdata->vif.cfg.ap_addr) ||
!ether_addr_equal(mgmt->bssid, sdata->vif.cfg.ap_addr)) {
/* Not from the current AP or not associated yet. */
return;
}
@@ -3346,9 +3346,9 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata,
skb_reserve(skb, local->hw.extra_tx_headroom);
resp = skb_put_zero(skb, 24);
memcpy(resp->da, mgmt->sa, ETH_ALEN);
memcpy(resp->da, sdata->vif.cfg.ap_addr, ETH_ALEN);
memcpy(resp->sa, sdata->vif.addr, ETH_ALEN);
memcpy(resp->bssid, sdata->deflink.u.mgd.bssid, ETH_ALEN);
memcpy(resp->bssid, sdata->vif.cfg.ap_addr, ETH_ALEN);
resp->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
skb_put(skb, 1 + sizeof(resp->u.action.u.sa_query));

View File

@@ -4,7 +4,7 @@
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015 - 2017 Intel Deutschland GmbH
* Copyright (C) 2018-2023 Intel Corporation
* Copyright (C) 2018-2024 Intel Corporation
*/
#include <linux/module.h>
@@ -1335,9 +1335,13 @@ static int _sta_info_move_state(struct sta_info *sta,
sta->sta.addr, new_state);
/* notify the driver before the actual changes so it can
* fail the transition
* fail the transition if the state is increasing.
* The driver is required not to fail when the transition
* is decreasing the state, so first, do all the preparation
* work and only then, notify the driver.
*/
if (test_sta_flag(sta, WLAN_STA_INSERTED)) {
if (new_state > sta->sta_state &&
test_sta_flag(sta, WLAN_STA_INSERTED)) {
int err = drv_sta_state(sta->local, sta->sdata, sta,
sta->sta_state, new_state);
if (err)
@@ -1413,6 +1417,16 @@ static int _sta_info_move_state(struct sta_info *sta,
break;
}
if (new_state < sta->sta_state &&
test_sta_flag(sta, WLAN_STA_INSERTED)) {
int err = drv_sta_state(sta->local, sta->sdata, sta,
sta->sta_state, new_state);
WARN_ONCE(err,
"Driver is not allowed to fail if the sta_state is transitioning down the list: %d\n",
err);
}
sta->sta_state = new_state;
return 0;

View File

@@ -6,7 +6,7 @@
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
* Copyright (C) 2018-2024 Intel Corporation
* Copyright (C) 2018-2025 Intel Corporation
*
* utilities for mac80211
*/
@@ -2193,8 +2193,10 @@ int ieee80211_reconfig(struct ieee80211_local *local)
ieee80211_reconfig_roc(local);
/* Requeue all works */
list_for_each_entry(sdata, &local->interfaces, list)
wiphy_work_queue(local->hw.wiphy, &sdata->work);
list_for_each_entry(sdata, &local->interfaces, list) {
if (ieee80211_sdata_running(sdata))
wiphy_work_queue(local->hw.wiphy, &sdata->work);
}
}
ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,

View File

@@ -332,8 +332,14 @@ static int mctp_frag_queue(struct mctp_sk_key *key, struct sk_buff *skb)
& MCTP_HDR_SEQ_MASK;
if (!key->reasm_head) {
key->reasm_head = skb;
key->reasm_tailp = &(skb_shinfo(skb)->frag_list);
/* Since we're manipulating the shared frag_list, ensure it isn't
* shared with any other SKBs.
*/
key->reasm_head = skb_unshare(skb, GFP_ATOMIC);
if (!key->reasm_head)
return -ENOMEM;
key->reasm_tailp = &(skb_shinfo(key->reasm_head)->frag_list);
key->last_seq = this_seq;
return 0;
}

View File

@@ -921,6 +921,114 @@ static void mctp_test_route_input_sk_fail_frag(struct kunit *test)
__mctp_route_test_fini(test, dev, rt, sock);
}
/* Input route to socket, using a fragmented message created from clones.
*/
static void mctp_test_route_input_cloned_frag(struct kunit *test)
{
/* 5 packet fragments, forming 2 complete messages */
const struct mctp_hdr hdrs[5] = {
RX_FRAG(FL_S, 0),
RX_FRAG(0, 1),
RX_FRAG(FL_E, 2),
RX_FRAG(FL_S, 0),
RX_FRAG(FL_E, 1),
};
struct mctp_test_route *rt;
struct mctp_test_dev *dev;
struct sk_buff *skb[5];
struct sk_buff *rx_skb;
struct socket *sock;
size_t data_len;
u8 compare[100];
u8 flat[100];
size_t total;
void *p;
int rc;
/* Arbitrary length */
data_len = 3;
total = data_len + sizeof(struct mctp_hdr);
__mctp_route_test_init(test, &dev, &rt, &sock, MCTP_NET_ANY);
/* Create a single skb initially with concatenated packets */
skb[0] = mctp_test_create_skb(&hdrs[0], 5 * total);
mctp_test_skb_set_dev(skb[0], dev);
memset(skb[0]->data, 0 * 0x11, skb[0]->len);
memcpy(skb[0]->data, &hdrs[0], sizeof(struct mctp_hdr));
/* Extract and populate packets */
for (int i = 1; i < 5; i++) {
skb[i] = skb_clone(skb[i - 1], GFP_ATOMIC);
KUNIT_ASSERT_TRUE(test, skb[i]);
p = skb_pull(skb[i], total);
KUNIT_ASSERT_TRUE(test, p);
skb_reset_network_header(skb[i]);
memcpy(skb[i]->data, &hdrs[i], sizeof(struct mctp_hdr));
memset(&skb[i]->data[sizeof(struct mctp_hdr)], i * 0x11, data_len);
}
for (int i = 0; i < 5; i++)
skb_trim(skb[i], total);
/* SOM packets have a type byte to match the socket */
skb[0]->data[4] = 0;
skb[3]->data[4] = 0;
skb_dump("pkt1 ", skb[0], false);
skb_dump("pkt2 ", skb[1], false);
skb_dump("pkt3 ", skb[2], false);
skb_dump("pkt4 ", skb[3], false);
skb_dump("pkt5 ", skb[4], false);
for (int i = 0; i < 5; i++) {
KUNIT_EXPECT_EQ(test, refcount_read(&skb[i]->users), 1);
/* Take a reference so we can check refcounts at the end */
skb_get(skb[i]);
}
/* Feed the fragments into MCTP core */
for (int i = 0; i < 5; i++) {
rc = mctp_route_input(&rt->rt, skb[i]);
KUNIT_EXPECT_EQ(test, rc, 0);
}
/* Receive first reassembled message */
rx_skb = skb_recv_datagram(sock->sk, MSG_DONTWAIT, &rc);
KUNIT_EXPECT_EQ(test, rc, 0);
KUNIT_EXPECT_EQ(test, rx_skb->len, 3 * data_len);
rc = skb_copy_bits(rx_skb, 0, flat, rx_skb->len);
for (int i = 0; i < rx_skb->len; i++)
compare[i] = (i / data_len) * 0x11;
/* Set type byte */
compare[0] = 0;
KUNIT_EXPECT_MEMEQ(test, flat, compare, rx_skb->len);
KUNIT_EXPECT_EQ(test, refcount_read(&rx_skb->users), 1);
kfree_skb(rx_skb);
/* Receive second reassembled message */
rx_skb = skb_recv_datagram(sock->sk, MSG_DONTWAIT, &rc);
KUNIT_EXPECT_EQ(test, rc, 0);
KUNIT_EXPECT_EQ(test, rx_skb->len, 2 * data_len);
rc = skb_copy_bits(rx_skb, 0, flat, rx_skb->len);
for (int i = 0; i < rx_skb->len; i++)
compare[i] = (i / data_len + 3) * 0x11;
/* Set type byte */
compare[0] = 0;
KUNIT_EXPECT_MEMEQ(test, flat, compare, rx_skb->len);
KUNIT_EXPECT_EQ(test, refcount_read(&rx_skb->users), 1);
kfree_skb(rx_skb);
/* Check input skb refcounts */
for (int i = 0; i < 5; i++) {
KUNIT_EXPECT_EQ(test, refcount_read(&skb[i]->users), 1);
kfree_skb(skb[i]);
}
__mctp_route_test_fini(test, dev, rt, sock);
}
#if IS_ENABLED(CONFIG_MCTP_FLOWS)
static void mctp_test_flow_init(struct kunit *test,
@@ -1144,6 +1252,7 @@ static struct kunit_case mctp_test_cases[] = {
KUNIT_CASE(mctp_test_packet_flow),
KUNIT_CASE(mctp_test_fragment_flow),
KUNIT_CASE(mctp_test_route_output_key_create),
KUNIT_CASE(mctp_test_route_input_cloned_frag),
{}
};

View File

@@ -3091,12 +3091,12 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
case IP_VS_SO_GET_SERVICES:
{
struct ip_vs_get_services *get;
int size;
size_t size;
get = (struct ip_vs_get_services *)arg;
size = struct_size(get, entrytable, get->num_services);
if (*len != size) {
pr_err("length: %u != %u\n", *len, size);
pr_err("length: %u != %zu\n", *len, size);
ret = -EINVAL;
goto out;
}
@@ -3132,12 +3132,12 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
case IP_VS_SO_GET_DESTS:
{
struct ip_vs_get_dests *get;
int size;
size_t size;
get = (struct ip_vs_get_dests *)arg;
size = struct_size(get, entrytable, get->num_dests);
if (*len != size) {
pr_err("length: %u != %u\n", *len, size);
pr_err("length: %u != %zu\n", *len, size);
ret = -EINVAL;
goto out;
}

View File

@@ -132,7 +132,7 @@ static int __nf_conncount_add(struct net *net,
struct nf_conn *found_ct;
unsigned int collect = 0;
if (time_is_after_eq_jiffies((unsigned long)list->last_gc))
if ((u32)jiffies == list->last_gc)
goto add_new_node;
/* check the saved connections */
@@ -234,7 +234,7 @@ bool nf_conncount_gc_list(struct net *net,
bool ret = false;
/* don't bother if we just did GC */
if (time_is_after_eq_jiffies((unsigned long)READ_ONCE(list->last_gc)))
if ((u32)jiffies == READ_ONCE(list->last_gc))
return false;
/* don't bother if other cpu is already doing GC */
@@ -377,6 +377,8 @@ restart:
conn->tuple = *tuple;
conn->zone = *zone;
conn->cpu = raw_smp_processor_id();
conn->jiffies32 = (u32)jiffies;
memcpy(rbconn->key, key, sizeof(u32) * data->keylen);
nf_conncount_list_init(&rbconn->list);

View File

@@ -34,7 +34,6 @@ unsigned int nf_tables_net_id __read_mostly;
static LIST_HEAD(nf_tables_expressions);
static LIST_HEAD(nf_tables_objects);
static LIST_HEAD(nf_tables_flowtables);
static LIST_HEAD(nf_tables_destroy_list);
static LIST_HEAD(nf_tables_gc_list);
static DEFINE_SPINLOCK(nf_tables_destroy_list_lock);
static DEFINE_SPINLOCK(nf_tables_gc_list_lock);
@@ -125,7 +124,6 @@ static void nft_validate_state_update(struct nft_table *table, u8 new_validate_s
table->validate_state = new_validate_state;
}
static void nf_tables_trans_destroy_work(struct work_struct *w);
static DECLARE_WORK(trans_destroy_work, nf_tables_trans_destroy_work);
static void nft_trans_gc_work(struct work_struct *work);
static DECLARE_WORK(trans_gc_work, nft_trans_gc_work);
@@ -10006,11 +10004,12 @@ static void nft_commit_release(struct nft_trans *trans)
static void nf_tables_trans_destroy_work(struct work_struct *w)
{
struct nftables_pernet *nft_net = container_of(w, struct nftables_pernet, destroy_work);
struct nft_trans *trans, *next;
LIST_HEAD(head);
spin_lock(&nf_tables_destroy_list_lock);
list_splice_init(&nf_tables_destroy_list, &head);
list_splice_init(&nft_net->destroy_list, &head);
spin_unlock(&nf_tables_destroy_list_lock);
if (list_empty(&head))
@@ -10024,9 +10023,11 @@ static void nf_tables_trans_destroy_work(struct work_struct *w)
}
}
void nf_tables_trans_destroy_flush_work(void)
void nf_tables_trans_destroy_flush_work(struct net *net)
{
flush_work(&trans_destroy_work);
struct nftables_pernet *nft_net = nft_pernet(net);
flush_work(&nft_net->destroy_work);
}
EXPORT_SYMBOL_GPL(nf_tables_trans_destroy_flush_work);
@@ -10484,11 +10485,11 @@ static void nf_tables_commit_release(struct net *net)
trans->put_net = true;
spin_lock(&nf_tables_destroy_list_lock);
list_splice_tail_init(&nft_net->commit_list, &nf_tables_destroy_list);
list_splice_tail_init(&nft_net->commit_list, &nft_net->destroy_list);
spin_unlock(&nf_tables_destroy_list_lock);
nf_tables_module_autoload_cleanup(net);
schedule_work(&trans_destroy_work);
schedule_work(&nft_net->destroy_work);
mutex_unlock(&nft_net->commit_mutex);
}
@@ -11853,7 +11854,7 @@ static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event,
gc_seq = nft_gc_seq_begin(nft_net);
nf_tables_trans_destroy_flush_work();
nf_tables_trans_destroy_flush_work(net);
again:
list_for_each_entry(table, &nft_net->tables, list) {
if (nft_table_has_owner(table) &&
@@ -11895,6 +11896,7 @@ static int __net_init nf_tables_init_net(struct net *net)
INIT_LIST_HEAD(&nft_net->tables);
INIT_LIST_HEAD(&nft_net->commit_list);
INIT_LIST_HEAD(&nft_net->destroy_list);
INIT_LIST_HEAD(&nft_net->commit_set_list);
INIT_LIST_HEAD(&nft_net->binding_list);
INIT_LIST_HEAD(&nft_net->module_list);
@@ -11903,6 +11905,7 @@ static int __net_init nf_tables_init_net(struct net *net)
nft_net->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);
return 0;
}
@@ -11931,14 +11934,17 @@ static void __net_exit nf_tables_exit_net(struct net *net)
if (!list_empty(&nft_net->module_list))
nf_tables_module_autoload_cleanup(net);
cancel_work_sync(&nft_net->destroy_work);
__nft_release_tables(net);
nft_gc_seq_end(nft_net, gc_seq);
mutex_unlock(&nft_net->commit_mutex);
WARN_ON_ONCE(!list_empty(&nft_net->tables));
WARN_ON_ONCE(!list_empty(&nft_net->module_list));
WARN_ON_ONCE(!list_empty(&nft_net->notify_list));
WARN_ON_ONCE(!list_empty(&nft_net->destroy_list));
}
static void nf_tables_exit_batch(struct list_head *net_exit_list)
@@ -12029,10 +12035,8 @@ static void __exit nf_tables_module_exit(void)
unregister_netdevice_notifier(&nf_tables_flowtable_notifier);
nft_chain_filter_fini();
nft_chain_route_fini();
nf_tables_trans_destroy_flush_work();
unregister_pernet_subsys(&nf_tables_net_ops);
cancel_work_sync(&trans_gc_work);
cancel_work_sync(&trans_destroy_work);
rcu_barrier();
rhltable_destroy(&nft_objname_ht);
nf_tables_core_module_exit();

View File

@@ -228,7 +228,7 @@ static int nft_parse_compat(const struct nlattr *attr, u16 *proto, bool *inv)
return 0;
}
static void nft_compat_wait_for_destructors(void)
static void nft_compat_wait_for_destructors(struct net *net)
{
/* xtables matches or targets can have side effects, e.g.
* creation/destruction of /proc files.
@@ -236,7 +236,7 @@ static void nft_compat_wait_for_destructors(void)
* work queue. If we have pending invocations we thus
* need to wait for those to finish.
*/
nf_tables_trans_destroy_flush_work();
nf_tables_trans_destroy_flush_work(net);
}
static int
@@ -262,7 +262,7 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
nft_target_set_tgchk_param(&par, ctx, target, info, &e, proto, inv);
nft_compat_wait_for_destructors();
nft_compat_wait_for_destructors(ctx->net);
ret = xt_check_target(&par, size, proto, inv);
if (ret < 0) {
@@ -515,7 +515,7 @@ __nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
nft_match_set_mtchk_param(&par, ctx, match, info, &e, proto, inv);
nft_compat_wait_for_destructors();
nft_compat_wait_for_destructors(ctx->net);
return xt_check_match(&par, size, proto, inv);
}

View File

@@ -230,6 +230,7 @@ static void nft_ct_set_zone_eval(const struct nft_expr *expr,
enum ip_conntrack_info ctinfo;
u16 value = nft_reg_load16(&regs->data[priv->sreg]);
struct nf_conn *ct;
int oldcnt;
ct = nf_ct_get(skb, &ctinfo);
if (ct) /* already tracked */
@@ -250,10 +251,11 @@ static void nft_ct_set_zone_eval(const struct nft_expr *expr,
ct = this_cpu_read(nft_ct_pcpu_template);
if (likely(refcount_read(&ct->ct_general.use) == 1)) {
refcount_inc(&ct->ct_general.use);
__refcount_inc(&ct->ct_general.use, &oldcnt);
if (likely(oldcnt == 1)) {
nf_ct_zone_add(ct, &zone);
} else {
refcount_dec(&ct->ct_general.use);
/* previous skb got queued to userspace, allocate temporary
* one until percpu template can be reused.
*/

View File

@@ -85,7 +85,6 @@ static int ipv4_find_option(struct net *net, struct sk_buff *skb,
unsigned char optbuf[sizeof(struct ip_options) + 40];
struct ip_options *opt = (struct ip_options *)optbuf;
struct iphdr *iph, _iph;
unsigned int start;
bool found = false;
__be32 info;
int optlen;
@@ -93,7 +92,6 @@ static int ipv4_find_option(struct net *net, struct sk_buff *skb,
iph = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
if (!iph)
return -EBADMSG;
start = sizeof(struct iphdr);
optlen = iph->ihl * 4 - (int)sizeof(struct iphdr);
if (optlen <= 0)
@@ -103,7 +101,7 @@ static int ipv4_find_option(struct net *net, struct sk_buff *skb,
/* Copy the options since __ip_options_compile() modifies
* the options.
*/
if (skb_copy_bits(skb, start, opt->__data, optlen))
if (skb_copy_bits(skb, sizeof(struct iphdr), opt->__data, optlen))
return -EBADMSG;
opt->optlen = optlen;
@@ -118,18 +116,18 @@ static int ipv4_find_option(struct net *net, struct sk_buff *skb,
found = target == IPOPT_SSRR ? opt->is_strictroute :
!opt->is_strictroute;
if (found)
*offset = opt->srr + start;
*offset = opt->srr;
break;
case IPOPT_RR:
if (!opt->rr)
break;
*offset = opt->rr + start;
*offset = opt->rr;
found = true;
break;
case IPOPT_RA:
if (!opt->router_alert)
break;
*offset = opt->router_alert + start;
*offset = opt->router_alert;
found = true;
break;
default:

View File

@@ -1368,8 +1368,11 @@ bool ovs_ct_verify(struct net *net, enum ovs_key_attr attr)
attr == OVS_KEY_ATTR_CT_MARK)
return true;
if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
attr == OVS_KEY_ATTR_CT_LABELS)
return true;
attr == OVS_KEY_ATTR_CT_LABELS) {
struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
return ovs_net->xt_label;
}
return false;
}
@@ -1378,7 +1381,6 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr,
const struct sw_flow_key *key,
struct sw_flow_actions **sfa, bool log)
{
unsigned int n_bits = sizeof(struct ovs_key_ct_labels) * BITS_PER_BYTE;
struct ovs_conntrack_info ct_info;
const char *helper = NULL;
u16 family;
@@ -1407,12 +1409,6 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr,
return -ENOMEM;
}
if (nf_connlabels_get(net, n_bits - 1)) {
nf_ct_tmpl_free(ct_info.ct);
OVS_NLERR(log, "Failed to set connlabel length");
return -EOPNOTSUPP;
}
if (ct_info.timeout[0]) {
if (nf_ct_set_timeout(net, ct_info.ct, family, key->ip.proto,
ct_info.timeout))
@@ -1581,7 +1577,6 @@ static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info)
if (ct_info->ct) {
if (ct_info->timeout[0])
nf_ct_destroy_timeout(ct_info->ct);
nf_connlabels_put(nf_ct_net(ct_info->ct));
nf_ct_tmpl_free(ct_info->ct);
}
}
@@ -2006,9 +2001,17 @@ struct genl_family dp_ct_limit_genl_family __ro_after_init = {
int ovs_ct_init(struct net *net)
{
#if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
unsigned int n_bits = sizeof(struct ovs_key_ct_labels) * BITS_PER_BYTE;
struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
if (nf_connlabels_get(net, n_bits - 1)) {
ovs_net->xt_label = false;
OVS_NLERR(true, "Failed to set connlabel length");
} else {
ovs_net->xt_label = true;
}
#if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
return ovs_ct_limit_init(net, ovs_net);
#else
return 0;
@@ -2017,9 +2020,12 @@ int ovs_ct_init(struct net *net)
void ovs_ct_exit(struct net *net)
{
#if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
#if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
ovs_ct_limit_exit(net, ovs_net);
#endif
if (ovs_net->xt_label)
nf_connlabels_put(net);
}

View File

@@ -160,6 +160,9 @@ struct ovs_net {
#if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
struct ovs_ct_limit_info *ct_limit_info;
#endif
/* Module reference for configuring conntrack. */
bool xt_label;
};
/**

View File

@@ -2317,14 +2317,10 @@ int ovs_nla_put_mask(const struct sw_flow *flow, struct sk_buff *skb)
OVS_FLOW_ATTR_MASK, true, skb);
}
#define MAX_ACTIONS_BUFSIZE (32 * 1024)
static struct sw_flow_actions *nla_alloc_flow_actions(int size)
{
struct sw_flow_actions *sfa;
WARN_ON_ONCE(size > MAX_ACTIONS_BUFSIZE);
sfa = kmalloc(kmalloc_size_roundup(sizeof(*sfa) + size), GFP_KERNEL);
if (!sfa)
return ERR_PTR(-ENOMEM);
@@ -2480,15 +2476,6 @@ static struct nlattr *reserve_sfa_size(struct sw_flow_actions **sfa,
new_acts_size = max(next_offset + req_size, ksize(*sfa) * 2);
if (new_acts_size > MAX_ACTIONS_BUFSIZE) {
if ((next_offset + req_size) > MAX_ACTIONS_BUFSIZE) {
OVS_NLERR(log, "Flow action size exceeds max %u",
MAX_ACTIONS_BUFSIZE);
return ERR_PTR(-EMSGSIZE);
}
new_acts_size = MAX_ACTIONS_BUFSIZE;
}
acts = nla_alloc_flow_actions(new_acts_size);
if (IS_ERR(acts))
return ERR_CAST(acts);
@@ -3545,7 +3532,7 @@ int ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
int err;
u32 mpls_label_count = 0;
*sfa = nla_alloc_flow_actions(min(nla_len(attr), MAX_ACTIONS_BUFSIZE));
*sfa = nla_alloc_flow_actions(nla_len(attr));
if (IS_ERR(*sfa))
return PTR_ERR(*sfa);

View File

@@ -2254,6 +2254,12 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n,
return -EOPNOTSUPP;
}
/* Prevent creation of traffic classes with classid TC_H_ROOT */
if (clid == TC_H_ROOT) {
NL_SET_ERR_MSG(extack, "Cannot create traffic class with classid TC_H_ROOT");
return -EINVAL;
}
new_cl = cl;
err = -EOPNOTSUPP;
if (cops->change)

View File

@@ -913,7 +913,8 @@ static void gred_destroy(struct Qdisc *sch)
for (i = 0; i < table->DPs; i++)
gred_destroy_vq(table->tab[i]);
gred_offload(sch, TC_GRED_DESTROY);
if (table->opt)
gred_offload(sch, TC_GRED_DESTROY);
kfree(table->opt);
}

View File

@@ -472,7 +472,7 @@ bool switchdev_port_obj_act_is_deferred(struct net_device *dev,
EXPORT_SYMBOL_GPL(switchdev_port_obj_act_is_deferred);
static ATOMIC_NOTIFIER_HEAD(switchdev_notif_chain);
static BLOCKING_NOTIFIER_HEAD(switchdev_blocking_notif_chain);
static RAW_NOTIFIER_HEAD(switchdev_blocking_notif_chain);
/**
* register_switchdev_notifier - Register notifier
@@ -518,17 +518,27 @@ EXPORT_SYMBOL_GPL(call_switchdev_notifiers);
int register_switchdev_blocking_notifier(struct notifier_block *nb)
{
struct blocking_notifier_head *chain = &switchdev_blocking_notif_chain;
struct raw_notifier_head *chain = &switchdev_blocking_notif_chain;
int err;
return blocking_notifier_chain_register(chain, nb);
rtnl_lock();
err = raw_notifier_chain_register(chain, nb);
rtnl_unlock();
return err;
}
EXPORT_SYMBOL_GPL(register_switchdev_blocking_notifier);
int unregister_switchdev_blocking_notifier(struct notifier_block *nb)
{
struct blocking_notifier_head *chain = &switchdev_blocking_notif_chain;
struct raw_notifier_head *chain = &switchdev_blocking_notif_chain;
int err;
return blocking_notifier_chain_unregister(chain, nb);
rtnl_lock();
err = raw_notifier_chain_unregister(chain, nb);
rtnl_unlock();
return err;
}
EXPORT_SYMBOL_GPL(unregister_switchdev_blocking_notifier);
@@ -536,10 +546,11 @@ int call_switchdev_blocking_notifiers(unsigned long val, struct net_device *dev,
struct switchdev_notifier_info *info,
struct netlink_ext_ack *extack)
{
ASSERT_RTNL();
info->dev = dev;
info->extack = extack;
return blocking_notifier_call_chain(&switchdev_blocking_notif_chain,
val, info);
return raw_notifier_call_chain(&switchdev_blocking_notif_chain,
val, info);
}
EXPORT_SYMBOL_GPL(call_switchdev_blocking_notifiers);

View File

@@ -1191,6 +1191,13 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
{
struct cfg80211_internal_bss *scan, *tmp;
struct cfg80211_beacon_registration *reg, *treg;
unsigned long flags;
spin_lock_irqsave(&rdev->wiphy_work_lock, flags);
WARN_ON(!list_empty(&rdev->wiphy_work_list));
spin_unlock_irqrestore(&rdev->wiphy_work_lock, flags);
cancel_work_sync(&rdev->wiphy_work);
rfkill_destroy(rdev->wiphy.rfkill);
list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) {
list_del(&reg->list);

View File

@@ -11123,6 +11123,7 @@ static struct cfg80211_bss *nl80211_assoc_bss(struct cfg80211_registered_device
static int nl80211_process_links(struct cfg80211_registered_device *rdev,
struct cfg80211_assoc_link *links,
int assoc_link_id,
const u8 *ssid, int ssid_len,
struct genl_info *info)
{
@@ -11153,7 +11154,7 @@ static int nl80211_process_links(struct cfg80211_registered_device *rdev,
}
links[link_id].bss =
nl80211_assoc_bss(rdev, ssid, ssid_len, attrs,
link_id, link_id);
assoc_link_id, link_id);
if (IS_ERR(links[link_id].bss)) {
err = PTR_ERR(links[link_id].bss);
links[link_id].bss = NULL;
@@ -11350,8 +11351,8 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
req.ap_mld_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
ap_addr = req.ap_mld_addr;
err = nl80211_process_links(rdev, req.links, ssid, ssid_len,
info);
err = nl80211_process_links(rdev, req.links, req.link_id,
ssid, ssid_len, info);
if (err)
goto free;
@@ -16506,7 +16507,10 @@ static int nl80211_assoc_ml_reconf(struct sk_buff *skb, struct genl_info *info)
add_links = 0;
if (info->attrs[NL80211_ATTR_MLO_LINKS]) {
err = nl80211_process_links(rdev, links, NULL, 0, info);
err = nl80211_process_links(rdev, links,
/* mark as MLO, but not assoc */
IEEE80211_MLD_MAX_NUM_LINKS,
NULL, 0, info);
if (err)
return err;

View File

@@ -11,8 +11,8 @@ ALL_TESTS="
lib_dir=$(dirname "$0")
source ${lib_dir}/bond_topo_3d1c.sh
c_maddr="33:33:00:00:00:10"
g_maddr="33:33:00:00:02:54"
c_maddr="33:33:ff:00:00:10"
g_maddr="33:33:ff:00:02:54"
skip_prio()
{

View File

@@ -1,49 +1,219 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0
import os
import random, string, time
from lib.py import ksft_run, ksft_exit
from lib.py import ksft_eq
from lib.py import NetDrvEpEnv
from lib.py import ksft_eq, KsftSkipEx, KsftFailEx
from lib.py import EthtoolFamily, NetDrvEpEnv
from lib.py import bkg, cmd, wait_port_listen, rand_port
from lib.py import ethtool, ip
remote_ifname=""
no_sleep=False
def test_v4(cfg) -> None:
def _test_v4(cfg) -> None:
cfg.require_v4()
cmd(f"ping -c 1 -W0.5 {cfg.remote_v4}")
cmd(f"ping -c 1 -W0.5 {cfg.v4}", host=cfg.remote)
cmd(f"ping -s 65000 -c 1 -W0.5 {cfg.remote_v4}")
cmd(f"ping -s 65000 -c 1 -W0.5 {cfg.v4}", host=cfg.remote)
def test_v6(cfg) -> None:
def _test_v6(cfg) -> None:
cfg.require_v6()
cmd(f"ping -c 1 -W0.5 {cfg.remote_v6}")
cmd(f"ping -c 1 -W0.5 {cfg.v6}", host=cfg.remote)
cmd(f"ping -c 1 -W5 {cfg.remote_v6}")
cmd(f"ping -c 1 -W5 {cfg.v6}", host=cfg.remote)
cmd(f"ping -s 65000 -c 1 -W0.5 {cfg.remote_v6}")
cmd(f"ping -s 65000 -c 1 -W0.5 {cfg.v6}", host=cfg.remote)
def test_tcp(cfg) -> None:
def _test_tcp(cfg) -> None:
cfg.require_cmd("socat", remote=True)
port = rand_port()
listen_cmd = f"socat -{cfg.addr_ipver} -t 2 -u TCP-LISTEN:{port},reuseport STDOUT"
test_string = ''.join(random.choice(string.ascii_lowercase) for _ in range(65536))
with bkg(listen_cmd, exit_wait=True) as nc:
wait_port_listen(port)
cmd(f"echo ping | socat -t 2 -u STDIN TCP:{cfg.baddr}:{port}",
cmd(f"echo {test_string} | socat -t 2 -u STDIN TCP:{cfg.baddr}:{port}",
shell=True, host=cfg.remote)
ksft_eq(nc.stdout.strip(), "ping")
ksft_eq(nc.stdout.strip(), test_string)
test_string = ''.join(random.choice(string.ascii_lowercase) for _ in range(65536))
with bkg(listen_cmd, host=cfg.remote, exit_wait=True) as nc:
wait_port_listen(port, host=cfg.remote)
cmd(f"echo ping | socat -t 2 -u STDIN TCP:{cfg.remote_baddr}:{port}", shell=True)
ksft_eq(nc.stdout.strip(), "ping")
cmd(f"echo {test_string} | socat -t 2 -u STDIN TCP:{cfg.remote_baddr}:{port}", shell=True)
ksft_eq(nc.stdout.strip(), test_string)
def _set_offload_checksum(cfg, netnl, on) -> None:
try:
ethtool(f" -K {cfg.ifname} rx {on} tx {on} ")
except:
return
def _set_xdp_generic_sb_on(cfg) -> None:
test_dir = os.path.dirname(os.path.realpath(__file__))
prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o"
cmd(f"ip link set dev {remote_ifname} mtu 1500", shell=True, host=cfg.remote)
cmd(f"ip link set dev {cfg.ifname} mtu 1500 xdpgeneric obj {prog} sec xdp", shell=True)
if no_sleep != True:
time.sleep(10)
def _set_xdp_generic_mb_on(cfg) -> None:
test_dir = os.path.dirname(os.path.realpath(__file__))
prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o"
cmd(f"ip link set dev {remote_ifname} mtu 9000", shell=True, host=cfg.remote)
ip("link set dev %s mtu 9000 xdpgeneric obj %s sec xdp.frags" % (cfg.ifname, prog))
if no_sleep != True:
time.sleep(10)
def _set_xdp_native_sb_on(cfg) -> None:
test_dir = os.path.dirname(os.path.realpath(__file__))
prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o"
cmd(f"ip link set dev {remote_ifname} mtu 1500", shell=True, host=cfg.remote)
cmd(f"ip -j link set dev {cfg.ifname} mtu 1500 xdp obj {prog} sec xdp", shell=True)
xdp_info = ip("-d link show %s" % (cfg.ifname), json=True)[0]
if xdp_info['xdp']['mode'] != 1:
"""
If the interface doesn't support native-mode, it falls back to generic mode.
The mode value 1 is native and 2 is generic.
So it raises an exception if mode is not 1(native mode).
"""
raise KsftSkipEx('device does not support native-XDP')
if no_sleep != True:
time.sleep(10)
def _set_xdp_native_mb_on(cfg) -> None:
test_dir = os.path.dirname(os.path.realpath(__file__))
prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o"
cmd(f"ip link set dev {remote_ifname} mtu 9000", shell=True, host=cfg.remote)
try:
cmd(f"ip link set dev {cfg.ifname} mtu 9000 xdp obj {prog} sec xdp.frags", shell=True)
except Exception as e:
cmd(f"ip link set dev {remote_ifname} mtu 1500", shell=True, host=cfg.remote)
raise KsftSkipEx('device does not support native-multi-buffer XDP')
if no_sleep != True:
time.sleep(10)
def _set_xdp_offload_on(cfg) -> None:
test_dir = os.path.dirname(os.path.realpath(__file__))
prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o"
cmd(f"ip link set dev {cfg.ifname} mtu 1500", shell=True)
try:
cmd(f"ip link set dev {cfg.ifname} xdpoffload obj {prog} sec xdp", shell=True)
except Exception as e:
raise KsftSkipEx('device does not support offloaded XDP')
cmd(f"ip link set dev {remote_ifname} mtu 1500", shell=True, host=cfg.remote)
if no_sleep != True:
time.sleep(10)
def get_interface_info(cfg) -> None:
global remote_ifname
global no_sleep
remote_info = cmd(f"ip -4 -o addr show to {cfg.remote_v4} | awk '{{print $2}}'", shell=True, host=cfg.remote).stdout
remote_ifname = remote_info.rstrip('\n')
if remote_ifname == "":
raise KsftFailEx('Can not get remote interface')
local_info = ip("-d link show %s" % (cfg.ifname), json=True)[0]
if 'parentbus' in local_info and local_info['parentbus'] == "netdevsim":
no_sleep=True
if 'linkinfo' in local_info and local_info['linkinfo']['info_kind'] == "veth":
no_sleep=True
def set_interface_init(cfg) -> None:
cmd(f"ip link set dev {cfg.ifname} mtu 1500", shell=True)
cmd(f"ip link set dev {cfg.ifname} xdp off ", shell=True)
cmd(f"ip link set dev {cfg.ifname} xdpgeneric off ", shell=True)
cmd(f"ip link set dev {cfg.ifname} xdpoffload off", shell=True)
cmd(f"ip link set dev {remote_ifname} mtu 1500", shell=True, host=cfg.remote)
def test_default(cfg, netnl) -> None:
_set_offload_checksum(cfg, netnl, "off")
_test_v4(cfg)
_test_v6(cfg)
_test_tcp(cfg)
_set_offload_checksum(cfg, netnl, "on")
_test_v4(cfg)
_test_v6(cfg)
_test_tcp(cfg)
def test_xdp_generic_sb(cfg, netnl) -> None:
_set_xdp_generic_sb_on(cfg)
_set_offload_checksum(cfg, netnl, "off")
_test_v4(cfg)
_test_v6(cfg)
_test_tcp(cfg)
_set_offload_checksum(cfg, netnl, "on")
_test_v4(cfg)
_test_v6(cfg)
_test_tcp(cfg)
ip("link set dev %s xdpgeneric off" % cfg.ifname)
def test_xdp_generic_mb(cfg, netnl) -> None:
_set_xdp_generic_mb_on(cfg)
_set_offload_checksum(cfg, netnl, "off")
_test_v4(cfg)
_test_v6(cfg)
_test_tcp(cfg)
_set_offload_checksum(cfg, netnl, "on")
_test_v4(cfg)
_test_v6(cfg)
_test_tcp(cfg)
ip("link set dev %s xdpgeneric off" % cfg.ifname)
def test_xdp_native_sb(cfg, netnl) -> None:
_set_xdp_native_sb_on(cfg)
_set_offload_checksum(cfg, netnl, "off")
_test_v4(cfg)
_test_v6(cfg)
_test_tcp(cfg)
_set_offload_checksum(cfg, netnl, "on")
_test_v4(cfg)
_test_v6(cfg)
_test_tcp(cfg)
ip("link set dev %s xdp off" % cfg.ifname)
def test_xdp_native_mb(cfg, netnl) -> None:
_set_xdp_native_mb_on(cfg)
_set_offload_checksum(cfg, netnl, "off")
_test_v4(cfg)
_test_v6(cfg)
_test_tcp(cfg)
_set_offload_checksum(cfg, netnl, "on")
_test_v4(cfg)
_test_v6(cfg)
_test_tcp(cfg)
ip("link set dev %s xdp off" % cfg.ifname)
def test_xdp_offload(cfg, netnl) -> None:
_set_xdp_offload_on(cfg)
_test_v4(cfg)
_test_v6(cfg)
_test_tcp(cfg)
ip("link set dev %s xdpoffload off" % cfg.ifname)
def main() -> None:
with NetDrvEpEnv(__file__) as cfg:
ksft_run(globs=globals(), case_pfx={"test_"}, args=(cfg, ))
get_interface_info(cfg)
set_interface_init(cfg)
ksft_run([test_default,
test_xdp_generic_sb,
test_xdp_generic_mb,
test_xdp_native_sb,
test_xdp_native_mb,
test_xdp_offload],
args=(cfg, EthtoolFamily()))
set_interface_init(cfg)
ksft_exit()

View File

@@ -31,6 +31,7 @@ TEST_PROGS += veth.sh
TEST_PROGS += ioam6.sh
TEST_PROGS += gro.sh
TEST_PROGS += gre_gso.sh
TEST_PROGS += gre_ipv6_lladdr.sh
TEST_PROGS += cmsg_so_mark.sh
TEST_PROGS += cmsg_so_priority.sh
TEST_PROGS += cmsg_time.sh cmsg_ipv6.sh

View File

@@ -0,0 +1,177 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
source ./lib.sh
PAUSE_ON_FAIL="no"
# The trap function handler
#
exit_cleanup_all()
{
cleanup_all_ns
exit "${EXIT_STATUS}"
}
# Add fake IPv4 and IPv6 networks on the loopback device, to be used as
# underlay by future GRE devices.
#
setup_basenet()
{
ip -netns "${NS0}" link set dev lo up
ip -netns "${NS0}" address add dev lo 192.0.2.10/24
ip -netns "${NS0}" address add dev lo 2001:db8::10/64 nodad
}
# Check if network device has an IPv6 link-local address assigned.
#
# Parameters:
#
# * $1: The network device to test
# * $2: An extra regular expression that should be matched (to verify the
# presence of extra attributes)
# * $3: The expected return code from grep (to allow checking the absence of
# a link-local address)
# * $4: The user visible name for the scenario being tested
#
check_ipv6_ll_addr()
{
local DEV="$1"
local EXTRA_MATCH="$2"
local XRET="$3"
local MSG="$4"
RET=0
set +e
ip -netns "${NS0}" -6 address show dev "${DEV}" scope link | grep "fe80::" | grep -q "${EXTRA_MATCH}"
check_err_fail "${XRET}" $? ""
log_test "${MSG}"
set -e
}
# Create a GRE device and verify that it gets an IPv6 link-local address as
# expected.
#
# Parameters:
#
# * $1: The device type (gre, ip6gre, gretap or ip6gretap)
# * $2: The local underlay IP address (can be an IPv4, an IPv6 or "any")
# * $3: The remote underlay IP address (can be an IPv4, an IPv6 or "any")
# * $4: The IPv6 interface identifier generation mode to use for the GRE
# device (eui64, none, stable-privacy or random).
#
test_gre_device()
{
local GRE_TYPE="$1"
local LOCAL_IP="$2"
local REMOTE_IP="$3"
local MODE="$4"
local ADDR_GEN_MODE
local MATCH_REGEXP
local MSG
ip link add netns "${NS0}" name gretest type "${GRE_TYPE}" local "${LOCAL_IP}" remote "${REMOTE_IP}"
case "${MODE}" in
"eui64")
ADDR_GEN_MODE=0
MATCH_REGEXP=""
MSG="${GRE_TYPE}, mode: 0 (EUI64), ${LOCAL_IP} -> ${REMOTE_IP}"
XRET=0
;;
"none")
ADDR_GEN_MODE=1
MATCH_REGEXP=""
MSG="${GRE_TYPE}, mode: 1 (none), ${LOCAL_IP} -> ${REMOTE_IP}"
XRET=1 # No link-local address should be generated
;;
"stable-privacy")
ADDR_GEN_MODE=2
MATCH_REGEXP="stable-privacy"
MSG="${GRE_TYPE}, mode: 2 (stable privacy), ${LOCAL_IP} -> ${REMOTE_IP}"
XRET=0
# Initialise stable_secret (required for stable-privacy mode)
ip netns exec "${NS0}" sysctl -qw net.ipv6.conf.gretest.stable_secret="2001:db8::abcd"
;;
"random")
ADDR_GEN_MODE=3
MATCH_REGEXP="stable-privacy"
MSG="${GRE_TYPE}, mode: 3 (random), ${LOCAL_IP} -> ${REMOTE_IP}"
XRET=0
;;
esac
# Check that IPv6 link-local address is generated when device goes up
ip netns exec "${NS0}" sysctl -qw net.ipv6.conf.gretest.addr_gen_mode="${ADDR_GEN_MODE}"
ip -netns "${NS0}" link set dev gretest up
check_ipv6_ll_addr gretest "${MATCH_REGEXP}" "${XRET}" "config: ${MSG}"
# Now disable link-local address generation
ip -netns "${NS0}" link set dev gretest down
ip netns exec "${NS0}" sysctl -qw net.ipv6.conf.gretest.addr_gen_mode=1
ip -netns "${NS0}" link set dev gretest up
# Check that link-local address generation works when re-enabled while
# the device is already up
ip netns exec "${NS0}" sysctl -qw net.ipv6.conf.gretest.addr_gen_mode="${ADDR_GEN_MODE}"
check_ipv6_ll_addr gretest "${MATCH_REGEXP}" "${XRET}" "update: ${MSG}"
ip -netns "${NS0}" link del dev gretest
}
test_gre4()
{
local GRE_TYPE
local MODE
for GRE_TYPE in "gre" "gretap"; do
printf "\n####\nTesting IPv6 link-local address generation on ${GRE_TYPE} devices\n####\n\n"
for MODE in "eui64" "none" "stable-privacy" "random"; do
test_gre_device "${GRE_TYPE}" 192.0.2.10 192.0.2.11 "${MODE}"
test_gre_device "${GRE_TYPE}" any 192.0.2.11 "${MODE}"
test_gre_device "${GRE_TYPE}" 192.0.2.10 any "${MODE}"
done
done
}
test_gre6()
{
local GRE_TYPE
local MODE
for GRE_TYPE in "ip6gre" "ip6gretap"; do
printf "\n####\nTesting IPv6 link-local address generation on ${GRE_TYPE} devices\n####\n\n"
for MODE in "eui64" "none" "stable-privacy" "random"; do
test_gre_device "${GRE_TYPE}" 2001:db8::10 2001:db8::11 "${MODE}"
test_gre_device "${GRE_TYPE}" any 2001:db8::11 "${MODE}"
test_gre_device "${GRE_TYPE}" 2001:db8::10 any "${MODE}"
done
done
}
usage()
{
echo "Usage: $0 [-p]"
exit 1
}
while getopts :p o
do
case $o in
p) PAUSE_ON_FAIL="yes";;
*) usage;;
esac
done
setup_ns NS0
set -e
trap exit_cleanup_all EXIT
setup_basenet
test_gre4
test_gre6

View File

@@ -10,4 +10,10 @@ int xdp_dummy_prog(struct xdp_md *ctx)
return XDP_PASS;
}
SEC("xdp.frags")
int xdp_dummy_prog_frags(struct xdp_md *ctx)
{
return XDP_PASS;
}
char _license[] SEC("license") = "GPL";

View File

@@ -13,6 +13,12 @@ source lib.sh
checktool "nft --version" "run test without nft tool"
read t < /proc/sys/kernel/tainted
if [ "$t" -ne 0 ];then
echo SKIP: kernel is tainted
exit $ksft_skip
fi
cleanup() {
cleanup_all_ns
}
@@ -165,6 +171,7 @@ if [ "$t" -eq 0 ];then
echo PASS: kernel not tainted
else
echo ERROR: kernel is tainted
dmesg
ret=1
fi

View File

@@ -4,6 +4,12 @@ source lib.sh
checktool "nft --version" "run test without nft tool"
read t < /proc/sys/kernel/tainted
if [ "$t" -ne 0 ];then
echo SKIP: kernel is tainted
exit $ksft_skip
fi
cleanup() {
cleanup_all_ns
}
@@ -72,6 +78,7 @@ if [ "$t" -eq 0 ];then
echo PASS: kernel not tainted
else
echo ERROR: kernel is tainted
dmesg
exit 1
fi

View File

@@ -593,6 +593,7 @@ EOF
echo "PASS: queue program exiting while packets queued"
else
echo "TAINT: queue program exiting while packets queued"
dmesg
ret=1
fi
}

View File

@@ -61,5 +61,30 @@
"teardown": [
"$TC qdisc del dev $DUMMY handle 1: root"
]
},
{
"id": "4009",
"name": "Reject creation of DRR class with classid TC_H_ROOT",
"category": [
"qdisc",
"drr"
],
"plugins": {
"requires": "nsPlugin"
},
"setup": [
"$TC qdisc add dev $DUMMY root handle ffff: drr",
"$TC filter add dev $DUMMY parent ffff: basic classid ffff:1",
"$TC class add dev $DUMMY parent ffff: classid ffff:1 drr",
"$TC filter add dev $DUMMY parent ffff: prio 1 u32 match u16 0x0000 0xfe00 at 2 flowid ffff:ffff"
],
"cmdUnderTest": "$TC class add dev $DUMMY parent ffff: classid ffff:ffff drr",
"expExitCode": "2",
"verifyCmd": "$TC class show dev $DUMMY",
"matchPattern": "class drr ffff:ffff",
"matchCount": "0",
"teardown": [
"$TC qdisc del dev $DUMMY root"
]
}
]