mirror of
https://github.com/torvalds/linux.git
synced 2025-12-01 07:26:02 +07:00
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:
38
MAINTAINERS
38
MAINTAINERS
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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(®s->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.
|
||||
*/
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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(®->list);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
177
tools/testing/selftests/net/gre_ipv6_lladdr.sh
Executable file
177
tools/testing/selftests/net/gre_ipv6_lladdr.sh
Executable 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
|
||||
@@ -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";
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user