mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
Including fixes from netfilter.
As Paolo promised we continue to hammer out issues in our selftests. This is not the end but probably the peak. Current release - regressions: - smc: fix incorrect SMC-D link group matching logic Current release - new code bugs: - eth: bnxt: silence WARN() when device skips a timestamp, it happens Previous releases - regressions: - ipmr: fix null-deref when forwarding mcast packets - conntrack: evaluate window negotiation only for packets in the REPLY direction, otherwise SYN retransmissions trigger incorrect window scale negotiation - ipset: fix performance regression in swap operation Previous releases - always broken: - tcp: add sanity checks to types of pages getting into the rx zerocopy path, we only support basic NIC -> user, no page cache pages etc. - ip6_tunnel: make sure to pull inner header in __ip6_tnl_rcv() - nt_tables: more input sanitization changes - dsa: mt7530: fix 10M/100M speed on MediaTek MT7988 switch - bridge: mcast: fix loss of snooping after long uptime, jiffies do wrap on 32bit - xen-netback: properly sync TX responses, protect with locking - phy: mediatek-ge-soc: sync calibration values with MediaTek SDK, increase connection stability - eth: pds: fixes for various teardown, and reset races Misc: - hsr: silence WARN() if we can't alloc supervision frame, it happens Signed-off-by: Jakub Kicinski <kuba@kernel.org> -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE6jPA+I1ugmIBA4hXMUZtbf5SIrsFAmW74qQACgkQMUZtbf5S Irv8BxAAvGQ8js+HyzDsQ8RYLLzKP+YZbMDwQdpZYSXBEskLSxdEn/SoD+2VOtfD 5op+ZOusE098Zppj9XEdQoqLDpTuOK5+mVA/85PUVuumz+nh/PfXNDPKO0M6V+pO iNq/qR6/gScwPFOzkrNXQaH3gOO1CfFW1Khwf8SPPWx+qCgNQZw3HI6yncukdx/K TLLM9LOgOJkhLCjMc7o2zpySQA9ctnVQB/Z6iT+j9EDvB30eyv+gSTT0OJQdMgod HpIXh0En52Ndt1Z32vKNoxEIgEWDylgoFUMTTTbJ/mKTwCfseC7PXPs6Kv9CxTJr aqFXNJkkF1Lzj09QMtBnfqprST7LEmvdQvOX0B8CT6fdQg0o3l6oz2WiTcpBKV7H ArlLLSWq9ABJZZcElR8ESkK3zg1YT42VaXfHsOCduMN1pV+5BbMl0xNSkTJpj+QC +r1h/hd09dp+pehJmcT2Coi7kXT2VWJvyqGLWZU7bxmc9wYM/63WHUIWdFAirmRq 8i2e9WHH6lqmjtzKG2CUpjg92NTpkEPkUDUjpMc+VbUYo583AFt2noNpGvDRZgcq 3WtcDyyfmX1bOHbagVidtphyQpPki9xt6ZxfgMkIqjNq2qSAr8fWj+cxjSSQvZjR +XEc/2NKedXcSnMXSFitsZ4wPJpgCRs2oLBtLQ9SDq4/p6uBSF4= =UJVq -----END PGP SIGNATURE----- Merge tag 'net-6.8-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net Pull networking fixes from Jakub Kicinski: "Including fixes from netfilter. As Paolo promised we continue to hammer out issues in our selftests. This is not the end but probably the peak. Current release - regressions: - smc: fix incorrect SMC-D link group matching logic Current release - new code bugs: - eth: bnxt: silence WARN() when device skips a timestamp, it happens Previous releases - regressions: - ipmr: fix null-deref when forwarding mcast packets - conntrack: evaluate window negotiation only for packets in the REPLY direction, otherwise SYN retransmissions trigger incorrect window scale negotiation - ipset: fix performance regression in swap operation Previous releases - always broken: - tcp: add sanity checks to types of pages getting into the rx zerocopy path, we only support basic NIC -> user, no page cache pages etc. - ip6_tunnel: make sure to pull inner header in __ip6_tnl_rcv() - nt_tables: more input sanitization changes - dsa: mt7530: fix 10M/100M speed on MediaTek MT7988 switch - bridge: mcast: fix loss of snooping after long uptime, jiffies do wrap on 32bit - xen-netback: properly sync TX responses, protect with locking - phy: mediatek-ge-soc: sync calibration values with MediaTek SDK, increase connection stability - eth: pds: fixes for various teardown, and reset races Misc: - hsr: silence WARN() if we can't alloc supervision frame, it happens" * tag 'net-6.8-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (82 commits) doc/netlink/specs: Add missing attr in rt_link spec idpf: avoid compiler padding in virtchnl2_ptype struct selftests: mptcp: join: stop transfer when check is done (part 2) selftests: mptcp: join: stop transfer when check is done (part 1) selftests: mptcp: allow changing subtests prefix selftests: mptcp: decrease BW in simult flows selftests: mptcp: increase timeout to 30 min selftests: mptcp: add missing kconfig for NF Mangle selftests: mptcp: add missing kconfig for NF Filter in v6 selftests: mptcp: add missing kconfig for NF Filter mptcp: fix data re-injection from stale subflow selftests: net: enable some more knobs selftests: net: add missing config for NF_TARGET_TTL selftests: forwarding: List helper scripts in TEST_FILES Makefile variable selftests: net: List helper scripts in TEST_FILES Makefile variable selftests: net: Remove executable bits from library scripts selftests: bonding: Check initial state selftests: team: Add missing config options hv_netvsc: Fix race condition between netvsc_probe and netvsc_remove xen-netback: properly sync TX responses ...
This commit is contained in:
commit
41b9fb381a
@ -1,4 +1,4 @@
|
||||
What: /sys/class/<iface>/queues/rx-<queue>/rps_cpus
|
||||
What: /sys/class/net/<iface>/queues/rx-<queue>/rps_cpus
|
||||
Date: March 2010
|
||||
KernelVersion: 2.6.35
|
||||
Contact: netdev@vger.kernel.org
|
||||
@ -8,7 +8,7 @@ Description:
|
||||
network device queue. Possible values depend on the number
|
||||
of available CPU(s) in the system.
|
||||
|
||||
What: /sys/class/<iface>/queues/rx-<queue>/rps_flow_cnt
|
||||
What: /sys/class/net/<iface>/queues/rx-<queue>/rps_flow_cnt
|
||||
Date: April 2010
|
||||
KernelVersion: 2.6.35
|
||||
Contact: netdev@vger.kernel.org
|
||||
@ -16,7 +16,7 @@ Description:
|
||||
Number of Receive Packet Steering flows being currently
|
||||
processed by this particular network device receive queue.
|
||||
|
||||
What: /sys/class/<iface>/queues/tx-<queue>/tx_timeout
|
||||
What: /sys/class/net/<iface>/queues/tx-<queue>/tx_timeout
|
||||
Date: November 2011
|
||||
KernelVersion: 3.3
|
||||
Contact: netdev@vger.kernel.org
|
||||
@ -24,7 +24,7 @@ Description:
|
||||
Indicates the number of transmit timeout events seen by this
|
||||
network interface transmit queue.
|
||||
|
||||
What: /sys/class/<iface>/queues/tx-<queue>/tx_maxrate
|
||||
What: /sys/class/net/<iface>/queues/tx-<queue>/tx_maxrate
|
||||
Date: March 2015
|
||||
KernelVersion: 4.1
|
||||
Contact: netdev@vger.kernel.org
|
||||
@ -32,7 +32,7 @@ Description:
|
||||
A Mbps max-rate set for the queue, a value of zero means disabled,
|
||||
default is disabled.
|
||||
|
||||
What: /sys/class/<iface>/queues/tx-<queue>/xps_cpus
|
||||
What: /sys/class/net/<iface>/queues/tx-<queue>/xps_cpus
|
||||
Date: November 2010
|
||||
KernelVersion: 2.6.38
|
||||
Contact: netdev@vger.kernel.org
|
||||
@ -42,7 +42,7 @@ Description:
|
||||
network device transmit queue. Possible values depend on the
|
||||
number of available CPU(s) in the system.
|
||||
|
||||
What: /sys/class/<iface>/queues/tx-<queue>/xps_rxqs
|
||||
What: /sys/class/net/<iface>/queues/tx-<queue>/xps_rxqs
|
||||
Date: June 2018
|
||||
KernelVersion: 4.18.0
|
||||
Contact: netdev@vger.kernel.org
|
||||
@ -53,7 +53,7 @@ Description:
|
||||
number of available receive queue(s) in the network device.
|
||||
Default is disabled.
|
||||
|
||||
What: /sys/class/<iface>/queues/tx-<queue>/byte_queue_limits/hold_time
|
||||
What: /sys/class/net/<iface>/queues/tx-<queue>/byte_queue_limits/hold_time
|
||||
Date: November 2011
|
||||
KernelVersion: 3.3
|
||||
Contact: netdev@vger.kernel.org
|
||||
@ -62,7 +62,7 @@ Description:
|
||||
of this particular network device transmit queue.
|
||||
Default value is 1000.
|
||||
|
||||
What: /sys/class/<iface>/queues/tx-<queue>/byte_queue_limits/inflight
|
||||
What: /sys/class/net/<iface>/queues/tx-<queue>/byte_queue_limits/inflight
|
||||
Date: November 2011
|
||||
KernelVersion: 3.3
|
||||
Contact: netdev@vger.kernel.org
|
||||
@ -70,7 +70,7 @@ Description:
|
||||
Indicates the number of bytes (objects) in flight on this
|
||||
network device transmit queue.
|
||||
|
||||
What: /sys/class/<iface>/queues/tx-<queue>/byte_queue_limits/limit
|
||||
What: /sys/class/net/<iface>/queues/tx-<queue>/byte_queue_limits/limit
|
||||
Date: November 2011
|
||||
KernelVersion: 3.3
|
||||
Contact: netdev@vger.kernel.org
|
||||
@ -79,7 +79,7 @@ Description:
|
||||
on this network device transmit queue. This value is clamped
|
||||
to be within the bounds defined by limit_max and limit_min.
|
||||
|
||||
What: /sys/class/<iface>/queues/tx-<queue>/byte_queue_limits/limit_max
|
||||
What: /sys/class/net/<iface>/queues/tx-<queue>/byte_queue_limits/limit_max
|
||||
Date: November 2011
|
||||
KernelVersion: 3.3
|
||||
Contact: netdev@vger.kernel.org
|
||||
@ -88,7 +88,7 @@ Description:
|
||||
queued on this network device transmit queue. See
|
||||
include/linux/dynamic_queue_limits.h for the default value.
|
||||
|
||||
What: /sys/class/<iface>/queues/tx-<queue>/byte_queue_limits/limit_min
|
||||
What: /sys/class/net/<iface>/queues/tx-<queue>/byte_queue_limits/limit_min
|
||||
Date: November 2011
|
||||
KernelVersion: 3.3
|
||||
Contact: netdev@vger.kernel.org
|
||||
|
@ -942,6 +942,10 @@ attribute-sets:
|
||||
-
|
||||
name: gro-ipv4-max-size
|
||||
type: u32
|
||||
-
|
||||
name: dpll-pin
|
||||
type: nest
|
||||
nested-attributes: link-dpll-pin-attrs
|
||||
-
|
||||
name: af-spec-attrs
|
||||
attributes:
|
||||
@ -1627,6 +1631,12 @@ attribute-sets:
|
||||
-
|
||||
name: used
|
||||
type: u8
|
||||
-
|
||||
name: link-dpll-pin-attrs
|
||||
attributes:
|
||||
-
|
||||
name: id
|
||||
type: u32
|
||||
|
||||
sub-messages:
|
||||
-
|
||||
|
@ -15181,6 +15181,7 @@ F: Documentation/networking/net_cachelines/net_device.rst
|
||||
F: drivers/connector/
|
||||
F: drivers/net/
|
||||
F: include/dt-bindings/net/
|
||||
F: include/linux/cn_proc.h
|
||||
F: include/linux/etherdevice.h
|
||||
F: include/linux/fcdevice.h
|
||||
F: include/linux/fddidevice.h
|
||||
@ -15188,6 +15189,7 @@ F: include/linux/hippidevice.h
|
||||
F: include/linux/if_*
|
||||
F: include/linux/inetdevice.h
|
||||
F: include/linux/netdevice.h
|
||||
F: include/uapi/linux/cn_proc.h
|
||||
F: include/uapi/linux/if_*
|
||||
F: include/uapi/linux/netdevice.h
|
||||
X: drivers/net/wireless/
|
||||
@ -18085,7 +18087,6 @@ F: drivers/net/ethernet/qualcomm/emac/
|
||||
|
||||
QUALCOMM ETHQOS ETHERNET DRIVER
|
||||
M: Vinod Koul <vkoul@kernel.org>
|
||||
R: Bhupesh Sharma <bhupesh.sharma@linaro.org>
|
||||
L: netdev@vger.kernel.org
|
||||
L: linux-arm-msm@vger.kernel.org
|
||||
S: Maintained
|
||||
|
@ -2838,8 +2838,7 @@ static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port,
|
||||
/* MT753x MAC works in 1G full duplex mode for all up-clocked
|
||||
* variants.
|
||||
*/
|
||||
if (interface == PHY_INTERFACE_MODE_INTERNAL ||
|
||||
interface == PHY_INTERFACE_MODE_TRGMII ||
|
||||
if (interface == PHY_INTERFACE_MODE_TRGMII ||
|
||||
(phy_interface_mode_is_8023z(interface))) {
|
||||
speed = SPEED_1000;
|
||||
duplex = DUPLEX_FULL;
|
||||
|
@ -3659,7 +3659,7 @@ static int mv88e6xxx_mdio_read_c45(struct mii_bus *bus, int phy, int devad,
|
||||
int err;
|
||||
|
||||
if (!chip->info->ops->phy_read_c45)
|
||||
return -EOPNOTSUPP;
|
||||
return 0xffff;
|
||||
|
||||
mv88e6xxx_reg_lock(chip);
|
||||
err = chip->info->ops->phy_read_c45(chip, bus, phy, devad, reg, &val);
|
||||
|
@ -2051,12 +2051,11 @@ qca8k_sw_probe(struct mdio_device *mdiodev)
|
||||
priv->info = of_device_get_match_data(priv->dev);
|
||||
|
||||
priv->reset_gpio = devm_gpiod_get_optional(priv->dev, "reset",
|
||||
GPIOD_ASIS);
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(priv->reset_gpio))
|
||||
return PTR_ERR(priv->reset_gpio);
|
||||
|
||||
if (priv->reset_gpio) {
|
||||
gpiod_set_value_cansleep(priv->reset_gpio, 1);
|
||||
/* The active low duration must be greater than 10 ms
|
||||
* and checkpatch.pl wants 20 ms.
|
||||
*/
|
||||
|
@ -63,6 +63,15 @@ static int pdsc_process_notifyq(struct pdsc_qcq *qcq)
|
||||
return nq_work;
|
||||
}
|
||||
|
||||
static bool pdsc_adminq_inc_if_up(struct pdsc *pdsc)
|
||||
{
|
||||
if (pdsc->state & BIT_ULL(PDSC_S_STOPPING_DRIVER) ||
|
||||
pdsc->state & BIT_ULL(PDSC_S_FW_DEAD))
|
||||
return false;
|
||||
|
||||
return refcount_inc_not_zero(&pdsc->adminq_refcnt);
|
||||
}
|
||||
|
||||
void pdsc_process_adminq(struct pdsc_qcq *qcq)
|
||||
{
|
||||
union pds_core_adminq_comp *comp;
|
||||
@ -75,9 +84,9 @@ void pdsc_process_adminq(struct pdsc_qcq *qcq)
|
||||
int aq_work = 0;
|
||||
int credits;
|
||||
|
||||
/* Don't process AdminQ when shutting down */
|
||||
if (pdsc->state & BIT_ULL(PDSC_S_STOPPING_DRIVER)) {
|
||||
dev_err(pdsc->dev, "%s: called while PDSC_S_STOPPING_DRIVER\n",
|
||||
/* Don't process AdminQ when it's not up */
|
||||
if (!pdsc_adminq_inc_if_up(pdsc)) {
|
||||
dev_err(pdsc->dev, "%s: called while adminq is unavailable\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
@ -124,6 +133,7 @@ credits:
|
||||
pds_core_intr_credits(&pdsc->intr_ctrl[qcq->intx],
|
||||
credits,
|
||||
PDS_CORE_INTR_CRED_REARM);
|
||||
refcount_dec(&pdsc->adminq_refcnt);
|
||||
}
|
||||
|
||||
void pdsc_work_thread(struct work_struct *work)
|
||||
@ -135,18 +145,20 @@ void pdsc_work_thread(struct work_struct *work)
|
||||
|
||||
irqreturn_t pdsc_adminq_isr(int irq, void *data)
|
||||
{
|
||||
struct pdsc_qcq *qcq = data;
|
||||
struct pdsc *pdsc = qcq->pdsc;
|
||||
struct pdsc *pdsc = data;
|
||||
struct pdsc_qcq *qcq;
|
||||
|
||||
/* Don't process AdminQ when shutting down */
|
||||
if (pdsc->state & BIT_ULL(PDSC_S_STOPPING_DRIVER)) {
|
||||
dev_err(pdsc->dev, "%s: called while PDSC_S_STOPPING_DRIVER\n",
|
||||
/* Don't process AdminQ when it's not up */
|
||||
if (!pdsc_adminq_inc_if_up(pdsc)) {
|
||||
dev_err(pdsc->dev, "%s: called while adminq is unavailable\n",
|
||||
__func__);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
qcq = &pdsc->adminqcq;
|
||||
queue_work(pdsc->wq, &qcq->work);
|
||||
pds_core_intr_mask(&pdsc->intr_ctrl[qcq->intx], PDS_CORE_INTR_MASK_CLEAR);
|
||||
refcount_dec(&pdsc->adminq_refcnt);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -179,10 +191,16 @@ static int __pdsc_adminq_post(struct pdsc *pdsc,
|
||||
|
||||
/* Check that the FW is running */
|
||||
if (!pdsc_is_fw_running(pdsc)) {
|
||||
u8 fw_status = ioread8(&pdsc->info_regs->fw_status);
|
||||
if (pdsc->info_regs) {
|
||||
u8 fw_status =
|
||||
ioread8(&pdsc->info_regs->fw_status);
|
||||
|
||||
dev_info(pdsc->dev, "%s: post failed - fw not running %#02x:\n",
|
||||
__func__, fw_status);
|
||||
dev_info(pdsc->dev, "%s: post failed - fw not running %#02x:\n",
|
||||
__func__, fw_status);
|
||||
} else {
|
||||
dev_info(pdsc->dev, "%s: post failed - BARs not setup\n",
|
||||
__func__);
|
||||
}
|
||||
ret = -ENXIO;
|
||||
|
||||
goto err_out_unlock;
|
||||
@ -230,6 +248,12 @@ int pdsc_adminq_post(struct pdsc *pdsc,
|
||||
int err = 0;
|
||||
int index;
|
||||
|
||||
if (!pdsc_adminq_inc_if_up(pdsc)) {
|
||||
dev_dbg(pdsc->dev, "%s: preventing adminq cmd %u\n",
|
||||
__func__, cmd->opcode);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
wc.qcq = &pdsc->adminqcq;
|
||||
index = __pdsc_adminq_post(pdsc, &pdsc->adminqcq, cmd, comp, &wc);
|
||||
if (index < 0) {
|
||||
@ -248,10 +272,16 @@ int pdsc_adminq_post(struct pdsc *pdsc,
|
||||
break;
|
||||
|
||||
if (!pdsc_is_fw_running(pdsc)) {
|
||||
u8 fw_status = ioread8(&pdsc->info_regs->fw_status);
|
||||
if (pdsc->info_regs) {
|
||||
u8 fw_status =
|
||||
ioread8(&pdsc->info_regs->fw_status);
|
||||
|
||||
dev_dbg(pdsc->dev, "%s: post wait failed - fw not running %#02x:\n",
|
||||
__func__, fw_status);
|
||||
dev_dbg(pdsc->dev, "%s: post wait failed - fw not running %#02x:\n",
|
||||
__func__, fw_status);
|
||||
} else {
|
||||
dev_dbg(pdsc->dev, "%s: post wait failed - BARs not setup\n",
|
||||
__func__);
|
||||
}
|
||||
err = -ENXIO;
|
||||
break;
|
||||
}
|
||||
@ -285,6 +315,8 @@ err_out:
|
||||
queue_work(pdsc->wq, &pdsc->health_work);
|
||||
}
|
||||
|
||||
refcount_dec(&pdsc->adminq_refcnt);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pdsc_adminq_post);
|
||||
|
@ -125,7 +125,7 @@ static int pdsc_qcq_intr_alloc(struct pdsc *pdsc, struct pdsc_qcq *qcq)
|
||||
|
||||
snprintf(name, sizeof(name), "%s-%d-%s",
|
||||
PDS_CORE_DRV_NAME, pdsc->pdev->bus->number, qcq->q.name);
|
||||
index = pdsc_intr_alloc(pdsc, name, pdsc_adminq_isr, qcq);
|
||||
index = pdsc_intr_alloc(pdsc, name, pdsc_adminq_isr, pdsc);
|
||||
if (index < 0)
|
||||
return index;
|
||||
qcq->intx = index;
|
||||
@ -404,10 +404,7 @@ int pdsc_setup(struct pdsc *pdsc, bool init)
|
||||
int numdescs;
|
||||
int err;
|
||||
|
||||
if (init)
|
||||
err = pdsc_dev_init(pdsc);
|
||||
else
|
||||
err = pdsc_dev_reinit(pdsc);
|
||||
err = pdsc_dev_init(pdsc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -450,6 +447,7 @@ int pdsc_setup(struct pdsc *pdsc, bool init)
|
||||
pdsc_debugfs_add_viftype(pdsc);
|
||||
}
|
||||
|
||||
refcount_set(&pdsc->adminq_refcnt, 1);
|
||||
clear_bit(PDSC_S_FW_DEAD, &pdsc->state);
|
||||
return 0;
|
||||
|
||||
@ -464,6 +462,8 @@ void pdsc_teardown(struct pdsc *pdsc, bool removing)
|
||||
|
||||
if (!pdsc->pdev->is_virtfn)
|
||||
pdsc_devcmd_reset(pdsc);
|
||||
if (pdsc->adminqcq.work.func)
|
||||
cancel_work_sync(&pdsc->adminqcq.work);
|
||||
pdsc_qcq_free(pdsc, &pdsc->notifyqcq);
|
||||
pdsc_qcq_free(pdsc, &pdsc->adminqcq);
|
||||
|
||||
@ -476,10 +476,9 @@ void pdsc_teardown(struct pdsc *pdsc, bool removing)
|
||||
for (i = 0; i < pdsc->nintrs; i++)
|
||||
pdsc_intr_free(pdsc, i);
|
||||
|
||||
if (removing) {
|
||||
kfree(pdsc->intr_info);
|
||||
pdsc->intr_info = NULL;
|
||||
}
|
||||
kfree(pdsc->intr_info);
|
||||
pdsc->intr_info = NULL;
|
||||
pdsc->nintrs = 0;
|
||||
}
|
||||
|
||||
if (pdsc->kern_dbpage) {
|
||||
@ -487,6 +486,7 @@ void pdsc_teardown(struct pdsc *pdsc, bool removing)
|
||||
pdsc->kern_dbpage = NULL;
|
||||
}
|
||||
|
||||
pci_free_irq_vectors(pdsc->pdev);
|
||||
set_bit(PDSC_S_FW_DEAD, &pdsc->state);
|
||||
}
|
||||
|
||||
@ -512,6 +512,24 @@ void pdsc_stop(struct pdsc *pdsc)
|
||||
PDS_CORE_INTR_MASK_SET);
|
||||
}
|
||||
|
||||
static void pdsc_adminq_wait_and_dec_once_unused(struct pdsc *pdsc)
|
||||
{
|
||||
/* The driver initializes the adminq_refcnt to 1 when the adminq is
|
||||
* allocated and ready for use. Other users/requesters will increment
|
||||
* the refcnt while in use. If the refcnt is down to 1 then the adminq
|
||||
* is not in use and the refcnt can be cleared and adminq freed. Before
|
||||
* calling this function the driver will set PDSC_S_FW_DEAD, which
|
||||
* prevent subsequent attempts to use the adminq and increment the
|
||||
* refcnt to fail. This guarantees that this function will eventually
|
||||
* exit.
|
||||
*/
|
||||
while (!refcount_dec_if_one(&pdsc->adminq_refcnt)) {
|
||||
dev_dbg_ratelimited(pdsc->dev, "%s: adminq in use\n",
|
||||
__func__);
|
||||
cpu_relax();
|
||||
}
|
||||
}
|
||||
|
||||
void pdsc_fw_down(struct pdsc *pdsc)
|
||||
{
|
||||
union pds_core_notifyq_comp reset_event = {
|
||||
@ -527,6 +545,8 @@ void pdsc_fw_down(struct pdsc *pdsc)
|
||||
if (pdsc->pdev->is_virtfn)
|
||||
return;
|
||||
|
||||
pdsc_adminq_wait_and_dec_once_unused(pdsc);
|
||||
|
||||
/* Notify clients of fw_down */
|
||||
if (pdsc->fw_reporter)
|
||||
devlink_health_report(pdsc->fw_reporter, "FW down reported", pdsc);
|
||||
@ -577,7 +597,13 @@ err_out:
|
||||
|
||||
static void pdsc_check_pci_health(struct pdsc *pdsc)
|
||||
{
|
||||
u8 fw_status = ioread8(&pdsc->info_regs->fw_status);
|
||||
u8 fw_status;
|
||||
|
||||
/* some sort of teardown already in progress */
|
||||
if (!pdsc->info_regs)
|
||||
return;
|
||||
|
||||
fw_status = ioread8(&pdsc->info_regs->fw_status);
|
||||
|
||||
/* is PCI broken? */
|
||||
if (fw_status != PDS_RC_BAD_PCI)
|
||||
|
@ -184,6 +184,7 @@ struct pdsc {
|
||||
struct mutex devcmd_lock; /* lock for dev_cmd operations */
|
||||
struct mutex config_lock; /* lock for configuration operations */
|
||||
spinlock_t adminq_lock; /* lock for adminq operations */
|
||||
refcount_t adminq_refcnt;
|
||||
struct pds_core_dev_info_regs __iomem *info_regs;
|
||||
struct pds_core_dev_cmd_regs __iomem *cmd_regs;
|
||||
struct pds_core_intr __iomem *intr_ctrl;
|
||||
@ -280,7 +281,6 @@ int pdsc_devcmd_locked(struct pdsc *pdsc, union pds_core_dev_cmd *cmd,
|
||||
union pds_core_dev_comp *comp, int max_seconds);
|
||||
int pdsc_devcmd_init(struct pdsc *pdsc);
|
||||
int pdsc_devcmd_reset(struct pdsc *pdsc);
|
||||
int pdsc_dev_reinit(struct pdsc *pdsc);
|
||||
int pdsc_dev_init(struct pdsc *pdsc);
|
||||
|
||||
void pdsc_reset_prepare(struct pci_dev *pdev);
|
||||
|
@ -64,6 +64,10 @@ DEFINE_SHOW_ATTRIBUTE(identity);
|
||||
|
||||
void pdsc_debugfs_add_ident(struct pdsc *pdsc)
|
||||
{
|
||||
/* This file will already exist in the reset flow */
|
||||
if (debugfs_lookup("identity", pdsc->dentry))
|
||||
return;
|
||||
|
||||
debugfs_create_file("identity", 0400, pdsc->dentry,
|
||||
pdsc, &identity_fops);
|
||||
}
|
||||
|
@ -57,6 +57,9 @@ int pdsc_err_to_errno(enum pds_core_status_code code)
|
||||
|
||||
bool pdsc_is_fw_running(struct pdsc *pdsc)
|
||||
{
|
||||
if (!pdsc->info_regs)
|
||||
return false;
|
||||
|
||||
pdsc->fw_status = ioread8(&pdsc->info_regs->fw_status);
|
||||
pdsc->last_fw_time = jiffies;
|
||||
pdsc->last_hb = ioread32(&pdsc->info_regs->fw_heartbeat);
|
||||
@ -182,13 +185,17 @@ int pdsc_devcmd_locked(struct pdsc *pdsc, union pds_core_dev_cmd *cmd,
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!pdsc->cmd_regs)
|
||||
return -ENXIO;
|
||||
|
||||
memcpy_toio(&pdsc->cmd_regs->cmd, cmd, sizeof(*cmd));
|
||||
pdsc_devcmd_dbell(pdsc);
|
||||
err = pdsc_devcmd_wait(pdsc, cmd->opcode, max_seconds);
|
||||
memcpy_fromio(comp, &pdsc->cmd_regs->comp, sizeof(*comp));
|
||||
|
||||
if ((err == -ENXIO || err == -ETIMEDOUT) && pdsc->wq)
|
||||
queue_work(pdsc->wq, &pdsc->health_work);
|
||||
else
|
||||
memcpy_fromio(comp, &pdsc->cmd_regs->comp, sizeof(*comp));
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -309,13 +316,6 @@ static int pdsc_identify(struct pdsc *pdsc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pdsc_dev_reinit(struct pdsc *pdsc)
|
||||
{
|
||||
pdsc_init_devinfo(pdsc);
|
||||
|
||||
return pdsc_identify(pdsc);
|
||||
}
|
||||
|
||||
int pdsc_dev_init(struct pdsc *pdsc)
|
||||
{
|
||||
unsigned int nintrs;
|
||||
|
@ -111,7 +111,8 @@ int pdsc_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
|
||||
|
||||
mutex_lock(&pdsc->devcmd_lock);
|
||||
err = pdsc_devcmd_locked(pdsc, &cmd, &comp, pdsc->devcmd_timeout * 2);
|
||||
memcpy_fromio(&fw_list, pdsc->cmd_regs->data, sizeof(fw_list));
|
||||
if (!err)
|
||||
memcpy_fromio(&fw_list, pdsc->cmd_regs->data, sizeof(fw_list));
|
||||
mutex_unlock(&pdsc->devcmd_lock);
|
||||
if (err && err != -EIO)
|
||||
return err;
|
||||
|
@ -107,6 +107,9 @@ int pdsc_firmware_update(struct pdsc *pdsc, const struct firmware *fw,
|
||||
|
||||
dev_info(pdsc->dev, "Installing firmware\n");
|
||||
|
||||
if (!pdsc->cmd_regs)
|
||||
return -ENXIO;
|
||||
|
||||
dl = priv_to_devlink(pdsc);
|
||||
devlink_flash_update_status_notify(dl, "Preparing to flash",
|
||||
NULL, 0, 0);
|
||||
|
@ -37,6 +37,11 @@ static void pdsc_unmap_bars(struct pdsc *pdsc)
|
||||
struct pdsc_dev_bar *bars = pdsc->bars;
|
||||
unsigned int i;
|
||||
|
||||
pdsc->info_regs = NULL;
|
||||
pdsc->cmd_regs = NULL;
|
||||
pdsc->intr_status = NULL;
|
||||
pdsc->intr_ctrl = NULL;
|
||||
|
||||
for (i = 0; i < PDS_CORE_BARS_MAX; i++) {
|
||||
if (bars[i].vaddr)
|
||||
pci_iounmap(pdsc->pdev, bars[i].vaddr);
|
||||
@ -293,7 +298,7 @@ err_out_stop:
|
||||
err_out_teardown:
|
||||
pdsc_teardown(pdsc, PDSC_TEARDOWN_REMOVING);
|
||||
err_out_unmap_bars:
|
||||
del_timer_sync(&pdsc->wdtimer);
|
||||
timer_shutdown_sync(&pdsc->wdtimer);
|
||||
if (pdsc->wq)
|
||||
destroy_workqueue(pdsc->wq);
|
||||
mutex_destroy(&pdsc->config_lock);
|
||||
@ -420,7 +425,7 @@ static void pdsc_remove(struct pci_dev *pdev)
|
||||
*/
|
||||
pdsc_sriov_configure(pdev, 0);
|
||||
|
||||
del_timer_sync(&pdsc->wdtimer);
|
||||
timer_shutdown_sync(&pdsc->wdtimer);
|
||||
if (pdsc->wq)
|
||||
destroy_workqueue(pdsc->wq);
|
||||
|
||||
@ -433,7 +438,6 @@ static void pdsc_remove(struct pci_dev *pdev)
|
||||
mutex_destroy(&pdsc->config_lock);
|
||||
mutex_destroy(&pdsc->devcmd_lock);
|
||||
|
||||
pci_free_irq_vectors(pdev);
|
||||
pdsc_unmap_bars(pdsc);
|
||||
pci_release_regions(pdev);
|
||||
}
|
||||
@ -445,13 +449,26 @@ static void pdsc_remove(struct pci_dev *pdev)
|
||||
devlink_free(dl);
|
||||
}
|
||||
|
||||
static void pdsc_stop_health_thread(struct pdsc *pdsc)
|
||||
{
|
||||
timer_shutdown_sync(&pdsc->wdtimer);
|
||||
if (pdsc->health_work.func)
|
||||
cancel_work_sync(&pdsc->health_work);
|
||||
}
|
||||
|
||||
static void pdsc_restart_health_thread(struct pdsc *pdsc)
|
||||
{
|
||||
timer_setup(&pdsc->wdtimer, pdsc_wdtimer_cb, 0);
|
||||
mod_timer(&pdsc->wdtimer, jiffies + 1);
|
||||
}
|
||||
|
||||
void pdsc_reset_prepare(struct pci_dev *pdev)
|
||||
{
|
||||
struct pdsc *pdsc = pci_get_drvdata(pdev);
|
||||
|
||||
pdsc_stop_health_thread(pdsc);
|
||||
pdsc_fw_down(pdsc);
|
||||
|
||||
pci_free_irq_vectors(pdev);
|
||||
pdsc_unmap_bars(pdsc);
|
||||
pci_release_regions(pdev);
|
||||
pci_disable_device(pdev);
|
||||
@ -486,6 +503,7 @@ void pdsc_reset_done(struct pci_dev *pdev)
|
||||
}
|
||||
|
||||
pdsc_fw_up(pdsc);
|
||||
pdsc_restart_health_thread(pdsc);
|
||||
}
|
||||
|
||||
static const struct pci_error_handlers pdsc_err_handler = {
|
||||
|
@ -684,7 +684,7 @@ static void bnxt_stamp_tx_skb(struct bnxt *bp, struct sk_buff *skb)
|
||||
timestamp.hwtstamp = ns_to_ktime(ns);
|
||||
skb_tstamp_tx(ptp->tx_skb, ×tamp);
|
||||
} else {
|
||||
netdev_WARN_ONCE(bp->dev,
|
||||
netdev_warn_once(bp->dev,
|
||||
"TS query for TX timer failed rc = %x\n", rc);
|
||||
}
|
||||
|
||||
|
@ -356,7 +356,7 @@ static enum pkt_hash_types gve_rss_type(__be16 pkt_flags)
|
||||
|
||||
static struct sk_buff *gve_rx_add_frags(struct napi_struct *napi,
|
||||
struct gve_rx_slot_page_info *page_info,
|
||||
u16 packet_buffer_size, u16 len,
|
||||
unsigned int truesize, u16 len,
|
||||
struct gve_rx_ctx *ctx)
|
||||
{
|
||||
u32 offset = page_info->page_offset + page_info->pad;
|
||||
@ -389,10 +389,10 @@ static struct sk_buff *gve_rx_add_frags(struct napi_struct *napi,
|
||||
if (skb != ctx->skb_head) {
|
||||
ctx->skb_head->len += len;
|
||||
ctx->skb_head->data_len += len;
|
||||
ctx->skb_head->truesize += packet_buffer_size;
|
||||
ctx->skb_head->truesize += truesize;
|
||||
}
|
||||
skb_add_rx_frag(skb, num_frags, page_info->page,
|
||||
offset, len, packet_buffer_size);
|
||||
offset, len, truesize);
|
||||
|
||||
return ctx->skb_head;
|
||||
}
|
||||
@ -486,7 +486,7 @@ static struct sk_buff *gve_rx_copy_to_pool(struct gve_rx_ring *rx,
|
||||
|
||||
memcpy(alloc_page_info.page_address, src, page_info->pad + len);
|
||||
skb = gve_rx_add_frags(napi, &alloc_page_info,
|
||||
rx->packet_buffer_size,
|
||||
PAGE_SIZE,
|
||||
len, ctx);
|
||||
|
||||
u64_stats_update_begin(&rx->statss);
|
||||
|
@ -360,23 +360,43 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca);
|
||||
* As a result, a shift of INCVALUE_SHIFT_n is used to fit a value of
|
||||
* INCVALUE_n into the TIMINCA register allowing 32+8+(24-INCVALUE_SHIFT_n)
|
||||
* bits to count nanoseconds leaving the rest for fractional nonseconds.
|
||||
*
|
||||
* Any given INCVALUE also has an associated maximum adjustment value. This
|
||||
* maximum adjustment value is the largest increase (or decrease) which can be
|
||||
* safely applied without overflowing the INCVALUE. Since INCVALUE has
|
||||
* a maximum range of 24 bits, its largest value is 0xFFFFFF.
|
||||
*
|
||||
* To understand where the maximum value comes from, consider the following
|
||||
* equation:
|
||||
*
|
||||
* new_incval = base_incval + (base_incval * adjustment) / 1billion
|
||||
*
|
||||
* To avoid overflow that means:
|
||||
* max_incval = base_incval + (base_incval * max_adj) / billion
|
||||
*
|
||||
* Re-arranging:
|
||||
* max_adj = floor(((max_incval - base_incval) * 1billion) / 1billion)
|
||||
*/
|
||||
#define INCVALUE_96MHZ 125
|
||||
#define INCVALUE_SHIFT_96MHZ 17
|
||||
#define INCPERIOD_SHIFT_96MHZ 2
|
||||
#define INCPERIOD_96MHZ (12 >> INCPERIOD_SHIFT_96MHZ)
|
||||
#define MAX_PPB_96MHZ 23999900 /* 23,999,900 ppb */
|
||||
|
||||
#define INCVALUE_25MHZ 40
|
||||
#define INCVALUE_SHIFT_25MHZ 18
|
||||
#define INCPERIOD_25MHZ 1
|
||||
#define MAX_PPB_25MHZ 599999900 /* 599,999,900 ppb */
|
||||
|
||||
#define INCVALUE_24MHZ 125
|
||||
#define INCVALUE_SHIFT_24MHZ 14
|
||||
#define INCPERIOD_24MHZ 3
|
||||
#define MAX_PPB_24MHZ 999999999 /* 999,999,999 ppb */
|
||||
|
||||
#define INCVALUE_38400KHZ 26
|
||||
#define INCVALUE_SHIFT_38400KHZ 19
|
||||
#define INCPERIOD_38400KHZ 1
|
||||
#define MAX_PPB_38400KHZ 230769100 /* 230,769,100 ppb */
|
||||
|
||||
/* Another drawback of scaling the incvalue by a large factor is the
|
||||
* 64-bit SYSTIM register overflows more quickly. This is dealt with
|
||||
|
@ -280,8 +280,17 @@ void e1000e_ptp_init(struct e1000_adapter *adapter)
|
||||
|
||||
switch (hw->mac.type) {
|
||||
case e1000_pch2lan:
|
||||
adapter->ptp_clock_info.max_adj = MAX_PPB_96MHZ;
|
||||
break;
|
||||
case e1000_pch_lpt:
|
||||
if (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI)
|
||||
adapter->ptp_clock_info.max_adj = MAX_PPB_96MHZ;
|
||||
else
|
||||
adapter->ptp_clock_info.max_adj = MAX_PPB_25MHZ;
|
||||
break;
|
||||
case e1000_pch_spt:
|
||||
adapter->ptp_clock_info.max_adj = MAX_PPB_24MHZ;
|
||||
break;
|
||||
case e1000_pch_cnp:
|
||||
case e1000_pch_tgp:
|
||||
case e1000_pch_adp:
|
||||
@ -289,15 +298,14 @@ void e1000e_ptp_init(struct e1000_adapter *adapter)
|
||||
case e1000_pch_lnp:
|
||||
case e1000_pch_ptp:
|
||||
case e1000_pch_nvp:
|
||||
if ((hw->mac.type < e1000_pch_lpt) ||
|
||||
(er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI)) {
|
||||
adapter->ptp_clock_info.max_adj = 24000000 - 1;
|
||||
break;
|
||||
}
|
||||
fallthrough;
|
||||
if (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI)
|
||||
adapter->ptp_clock_info.max_adj = MAX_PPB_24MHZ;
|
||||
else
|
||||
adapter->ptp_clock_info.max_adj = MAX_PPB_38400KHZ;
|
||||
break;
|
||||
case e1000_82574:
|
||||
case e1000_82583:
|
||||
adapter->ptp_clock_info.max_adj = 600000000 - 1;
|
||||
adapter->ptp_clock_info.max_adj = MAX_PPB_25MHZ;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -978,7 +978,7 @@ struct virtchnl2_ptype {
|
||||
u8 proto_id_count;
|
||||
__le16 pad;
|
||||
__le16 proto_id[];
|
||||
};
|
||||
} __packed __aligned(2);
|
||||
VIRTCHNL2_CHECK_STRUCT_LEN(6, virtchnl2_ptype);
|
||||
|
||||
/**
|
||||
|
@ -716,7 +716,8 @@ static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
|
||||
if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
|
||||
error = FIELD_GET(IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK, command);
|
||||
hw_dbg(hw, "Failed to read, error %x\n", error);
|
||||
return -EIO;
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
|
@ -314,7 +314,6 @@ static int otx2_set_channels(struct net_device *dev,
|
||||
pfvf->hw.tx_queues = channel->tx_count;
|
||||
if (pfvf->xdp_prog)
|
||||
pfvf->hw.xdp_queues = channel->rx_count;
|
||||
pfvf->hw.non_qos_queues = pfvf->hw.tx_queues + pfvf->hw.xdp_queues;
|
||||
|
||||
if (if_up)
|
||||
err = dev->netdev_ops->ndo_open(dev);
|
||||
|
@ -1744,6 +1744,7 @@ int otx2_open(struct net_device *netdev)
|
||||
/* RQ and SQs are mapped to different CQs,
|
||||
* so find out max CQ IRQs (i.e CINTs) needed.
|
||||
*/
|
||||
pf->hw.non_qos_queues = pf->hw.tx_queues + pf->hw.xdp_queues;
|
||||
pf->hw.cint_cnt = max3(pf->hw.rx_queues, pf->hw.tx_queues,
|
||||
pf->hw.tc_tx_queues);
|
||||
|
||||
@ -2643,8 +2644,6 @@ static int otx2_xdp_setup(struct otx2_nic *pf, struct bpf_prog *prog)
|
||||
xdp_features_clear_redirect_target(dev);
|
||||
}
|
||||
|
||||
pf->hw.non_qos_queues += pf->hw.xdp_queues;
|
||||
|
||||
if (if_up)
|
||||
otx2_open(pf->netdev);
|
||||
|
||||
|
@ -1403,7 +1403,7 @@ static bool otx2_xdp_rcv_pkt_handler(struct otx2_nic *pfvf,
|
||||
struct otx2_cq_queue *cq,
|
||||
bool *need_xdp_flush)
|
||||
{
|
||||
unsigned char *hard_start, *data;
|
||||
unsigned char *hard_start;
|
||||
int qidx = cq->cq_idx;
|
||||
struct xdp_buff xdp;
|
||||
struct page *page;
|
||||
@ -1417,9 +1417,8 @@ static bool otx2_xdp_rcv_pkt_handler(struct otx2_nic *pfvf,
|
||||
|
||||
xdp_init_buff(&xdp, pfvf->rbsize, &cq->xdp_rxq);
|
||||
|
||||
data = (unsigned char *)phys_to_virt(pa);
|
||||
hard_start = page_address(page);
|
||||
xdp_prepare_buff(&xdp, hard_start, data - hard_start,
|
||||
hard_start = (unsigned char *)phys_to_virt(pa);
|
||||
xdp_prepare_buff(&xdp, hard_start, OTX2_HEAD_ROOM,
|
||||
cqe->sg.seg_size, false);
|
||||
|
||||
act = bpf_prog_run_xdp(prog, &xdp);
|
||||
|
@ -4761,7 +4761,10 @@ static int mtk_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) {
|
||||
err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36));
|
||||
err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(36));
|
||||
if (!err)
|
||||
err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
|
||||
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Wrong DMA config\n");
|
||||
return -EINVAL;
|
||||
|
@ -168,9 +168,10 @@ static void lan966x_port_link_up(struct lan966x_port *port)
|
||||
lan966x_taprio_speed_set(port, config->speed);
|
||||
|
||||
/* Also the GIGA_MODE_ENA(1) needs to be set regardless of the
|
||||
* port speed for QSGMII ports.
|
||||
* port speed for QSGMII or SGMII ports.
|
||||
*/
|
||||
if (phy_interface_num_ports(config->portmode) == 4)
|
||||
if (phy_interface_num_ports(config->portmode) == 4 ||
|
||||
config->portmode == PHY_INTERFACE_MODE_SGMII)
|
||||
mode = DEV_MAC_MODE_CFG_GIGA_MODE_ENA_SET(1);
|
||||
|
||||
lan_wr(config->duplex | mode,
|
||||
|
@ -1424,10 +1424,30 @@ static void nfp_nft_ct_translate_mangle_action(struct flow_action_entry *mangle_
|
||||
mangle_action->mangle.mask = (__force u32)cpu_to_be32(mangle_action->mangle.mask);
|
||||
return;
|
||||
|
||||
/* Both struct tcphdr and struct udphdr start with
|
||||
* __be16 source;
|
||||
* __be16 dest;
|
||||
* so we can use the same code for both.
|
||||
*/
|
||||
case FLOW_ACT_MANGLE_HDR_TYPE_TCP:
|
||||
case FLOW_ACT_MANGLE_HDR_TYPE_UDP:
|
||||
mangle_action->mangle.val = (__force u16)cpu_to_be16(mangle_action->mangle.val);
|
||||
mangle_action->mangle.mask = (__force u16)cpu_to_be16(mangle_action->mangle.mask);
|
||||
if (mangle_action->mangle.offset == offsetof(struct tcphdr, source)) {
|
||||
mangle_action->mangle.val =
|
||||
(__force u32)cpu_to_be32(mangle_action->mangle.val << 16);
|
||||
/* The mask of mangle action is inverse mask,
|
||||
* so clear the dest tp port with 0xFFFF to
|
||||
* instead of rotate-left operation.
|
||||
*/
|
||||
mangle_action->mangle.mask =
|
||||
(__force u32)cpu_to_be32(mangle_action->mangle.mask << 16 | 0xFFFF);
|
||||
}
|
||||
if (mangle_action->mangle.offset == offsetof(struct tcphdr, dest)) {
|
||||
mangle_action->mangle.offset = 0;
|
||||
mangle_action->mangle.val =
|
||||
(__force u32)cpu_to_be32(mangle_action->mangle.val);
|
||||
mangle_action->mangle.mask =
|
||||
(__force u32)cpu_to_be32(mangle_action->mangle.mask);
|
||||
}
|
||||
return;
|
||||
|
||||
default:
|
||||
@ -1864,10 +1884,30 @@ int nfp_fl_ct_handle_post_ct(struct nfp_flower_priv *priv,
|
||||
{
|
||||
struct flow_rule *rule = flow_cls_offload_flow_rule(flow);
|
||||
struct nfp_fl_ct_flow_entry *ct_entry;
|
||||
struct flow_action_entry *ct_goto;
|
||||
struct nfp_fl_ct_zone_entry *zt;
|
||||
struct flow_action_entry *act;
|
||||
bool wildcarded = false;
|
||||
struct flow_match_ct ct;
|
||||
struct flow_action_entry *ct_goto;
|
||||
int i;
|
||||
|
||||
flow_action_for_each(i, act, &rule->action) {
|
||||
switch (act->id) {
|
||||
case FLOW_ACTION_REDIRECT:
|
||||
case FLOW_ACTION_REDIRECT_INGRESS:
|
||||
case FLOW_ACTION_MIRRED:
|
||||
case FLOW_ACTION_MIRRED_INGRESS:
|
||||
if (act->dev->rtnl_link_ops &&
|
||||
!strcmp(act->dev->rtnl_link_ops->kind, "openvswitch")) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"unsupported offload: out port is openvswitch internal port");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
flow_rule_match_ct(rule, &ct);
|
||||
if (!ct.mask->ct_zone) {
|
||||
|
@ -353,6 +353,10 @@ static int imx_dwmac_probe(struct platform_device *pdev)
|
||||
if (data->flags & STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY)
|
||||
plat_dat->flags |= STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY;
|
||||
|
||||
/* Default TX Q0 to use TSO and rest TXQ for TBS */
|
||||
for (int i = 1; i < plat_dat->tx_queues_to_use; i++)
|
||||
plat_dat->tx_queues_cfg[i].tbs_en = 1;
|
||||
|
||||
plat_dat->host_dma_width = dwmac->ops->addr_width;
|
||||
plat_dat->init = imx_dwmac_init;
|
||||
plat_dat->exit = imx_dwmac_exit;
|
||||
|
@ -3932,6 +3932,9 @@ static int __stmmac_open(struct net_device *dev,
|
||||
priv->rx_copybreak = STMMAC_RX_COPYBREAK;
|
||||
|
||||
buf_sz = dma_conf->dma_buf_sz;
|
||||
for (int i = 0; i < MTL_MAX_TX_QUEUES; i++)
|
||||
if (priv->dma_conf.tx_queue[i].tbs & STMMAC_TBS_EN)
|
||||
dma_conf->tx_queue[i].tbs = priv->dma_conf.tx_queue[i].tbs;
|
||||
memcpy(&priv->dma_conf, dma_conf, sizeof(*dma_conf));
|
||||
|
||||
stmmac_reset_queues_param(priv);
|
||||
|
@ -708,7 +708,10 @@ void netvsc_device_remove(struct hv_device *device)
|
||||
/* Disable NAPI and disassociate its context from the device. */
|
||||
for (i = 0; i < net_device->num_chn; i++) {
|
||||
/* See also vmbus_reset_channel_cb(). */
|
||||
napi_disable(&net_device->chan_table[i].napi);
|
||||
/* only disable enabled NAPI channel */
|
||||
if (i < ndev->real_num_rx_queues)
|
||||
napi_disable(&net_device->chan_table[i].napi);
|
||||
|
||||
netif_napi_del(&net_device->chan_table[i].napi);
|
||||
}
|
||||
|
||||
|
@ -489,7 +489,7 @@ static int tx_r50_fill_result(struct phy_device *phydev, u16 tx_r50_cal_val,
|
||||
u16 reg, val;
|
||||
|
||||
if (phydev->drv->phy_id == MTK_GPHY_ID_MT7988)
|
||||
bias = -2;
|
||||
bias = -1;
|
||||
|
||||
val = clamp_val(bias + tx_r50_cal_val, 0, 63);
|
||||
|
||||
@ -705,6 +705,11 @@ restore:
|
||||
static void mt798x_phy_common_finetune(struct phy_device *phydev)
|
||||
{
|
||||
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
|
||||
/* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */
|
||||
__phy_write(phydev, 0x11, 0xc71);
|
||||
__phy_write(phydev, 0x12, 0xc);
|
||||
__phy_write(phydev, 0x10, 0x8fae);
|
||||
|
||||
/* EnabRandUpdTrig = 1 */
|
||||
__phy_write(phydev, 0x11, 0x2f00);
|
||||
__phy_write(phydev, 0x12, 0xe);
|
||||
@ -715,15 +720,56 @@ static void mt798x_phy_common_finetune(struct phy_device *phydev)
|
||||
__phy_write(phydev, 0x12, 0x0);
|
||||
__phy_write(phydev, 0x10, 0x83aa);
|
||||
|
||||
/* TrFreeze = 0 */
|
||||
/* FfeUpdGainForce = 1(Enable), FfeUpdGainForceVal = 4 */
|
||||
__phy_write(phydev, 0x11, 0x240);
|
||||
__phy_write(phydev, 0x12, 0x0);
|
||||
__phy_write(phydev, 0x10, 0x9680);
|
||||
|
||||
/* TrFreeze = 0 (mt7988 default) */
|
||||
__phy_write(phydev, 0x11, 0x0);
|
||||
__phy_write(phydev, 0x12, 0x0);
|
||||
__phy_write(phydev, 0x10, 0x9686);
|
||||
|
||||
/* SSTrKp100 = 5 */
|
||||
/* SSTrKf100 = 6 */
|
||||
/* SSTrKp1000Mas = 5 */
|
||||
/* SSTrKf1000Mas = 6 */
|
||||
/* SSTrKp1000Slv = 5 */
|
||||
/* SSTrKf1000Slv = 6 */
|
||||
__phy_write(phydev, 0x11, 0xbaef);
|
||||
__phy_write(phydev, 0x12, 0x2e);
|
||||
__phy_write(phydev, 0x10, 0x968c);
|
||||
phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
|
||||
}
|
||||
|
||||
static void mt7981_phy_finetune(struct phy_device *phydev)
|
||||
{
|
||||
u16 val[8] = { 0x01ce, 0x01c1,
|
||||
0x020f, 0x0202,
|
||||
0x03d0, 0x03c0,
|
||||
0x0013, 0x0005 };
|
||||
int i, k;
|
||||
|
||||
/* 100M eye finetune:
|
||||
* Keep middle level of TX MLT3 shapper as default.
|
||||
* Only change TX MLT3 overshoot level here.
|
||||
*/
|
||||
for (k = 0, i = 1; i < 12; i++) {
|
||||
if (i % 3 == 0)
|
||||
continue;
|
||||
phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[k++]);
|
||||
}
|
||||
|
||||
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
|
||||
/* ResetSyncOffset = 6 */
|
||||
__phy_write(phydev, 0x11, 0x600);
|
||||
__phy_write(phydev, 0x12, 0x0);
|
||||
__phy_write(phydev, 0x10, 0x8fc0);
|
||||
|
||||
/* VgaDecRate = 1 */
|
||||
__phy_write(phydev, 0x11, 0x4c2a);
|
||||
__phy_write(phydev, 0x12, 0x3e);
|
||||
__phy_write(phydev, 0x10, 0x8fa4);
|
||||
|
||||
/* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2,
|
||||
* MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2
|
||||
@ -738,7 +784,7 @@ static void mt798x_phy_common_finetune(struct phy_device *phydev)
|
||||
__phy_write(phydev, 0x10, 0x8ec0);
|
||||
phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
|
||||
|
||||
/* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9*/
|
||||
/* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9 */
|
||||
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
|
||||
MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK,
|
||||
BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9));
|
||||
@ -771,48 +817,6 @@ static void mt798x_phy_common_finetune(struct phy_device *phydev)
|
||||
phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_OUTPUT_V, 0x2222);
|
||||
}
|
||||
|
||||
static void mt7981_phy_finetune(struct phy_device *phydev)
|
||||
{
|
||||
u16 val[8] = { 0x01ce, 0x01c1,
|
||||
0x020f, 0x0202,
|
||||
0x03d0, 0x03c0,
|
||||
0x0013, 0x0005 };
|
||||
int i, k;
|
||||
|
||||
/* 100M eye finetune:
|
||||
* Keep middle level of TX MLT3 shapper as default.
|
||||
* Only change TX MLT3 overshoot level here.
|
||||
*/
|
||||
for (k = 0, i = 1; i < 12; i++) {
|
||||
if (i % 3 == 0)
|
||||
continue;
|
||||
phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[k++]);
|
||||
}
|
||||
|
||||
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
|
||||
/* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */
|
||||
__phy_write(phydev, 0x11, 0xc71);
|
||||
__phy_write(phydev, 0x12, 0xc);
|
||||
__phy_write(phydev, 0x10, 0x8fae);
|
||||
|
||||
/* ResetSyncOffset = 6 */
|
||||
__phy_write(phydev, 0x11, 0x600);
|
||||
__phy_write(phydev, 0x12, 0x0);
|
||||
__phy_write(phydev, 0x10, 0x8fc0);
|
||||
|
||||
/* VgaDecRate = 1 */
|
||||
__phy_write(phydev, 0x11, 0x4c2a);
|
||||
__phy_write(phydev, 0x12, 0x3e);
|
||||
__phy_write(phydev, 0x10, 0x8fa4);
|
||||
|
||||
/* FfeUpdGainForce = 4 */
|
||||
__phy_write(phydev, 0x11, 0x240);
|
||||
__phy_write(phydev, 0x12, 0x0);
|
||||
__phy_write(phydev, 0x10, 0x9680);
|
||||
|
||||
phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
|
||||
}
|
||||
|
||||
static void mt7988_phy_finetune(struct phy_device *phydev)
|
||||
{
|
||||
u16 val[12] = { 0x0187, 0x01cd, 0x01c8, 0x0182,
|
||||
@ -827,17 +831,7 @@ static void mt7988_phy_finetune(struct phy_device *phydev)
|
||||
/* TCT finetune */
|
||||
phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5);
|
||||
|
||||
/* Disable TX power saving */
|
||||
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7,
|
||||
MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8);
|
||||
|
||||
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
|
||||
|
||||
/* SlvDSPreadyTime = 24, MasDSPreadyTime = 12 */
|
||||
__phy_write(phydev, 0x11, 0x671);
|
||||
__phy_write(phydev, 0x12, 0xc);
|
||||
__phy_write(phydev, 0x10, 0x8fae);
|
||||
|
||||
/* ResetSyncOffset = 5 */
|
||||
__phy_write(phydev, 0x11, 0x500);
|
||||
__phy_write(phydev, 0x12, 0x0);
|
||||
@ -845,13 +839,27 @@ static void mt7988_phy_finetune(struct phy_device *phydev)
|
||||
|
||||
/* VgaDecRate is 1 at default on mt7988 */
|
||||
|
||||
/* MrvlTrFix100Kp = 6, MrvlTrFix100Kf = 7,
|
||||
* MrvlTrFix1000Kp = 6, MrvlTrFix1000Kf = 7
|
||||
*/
|
||||
__phy_write(phydev, 0x11, 0xb90a);
|
||||
__phy_write(phydev, 0x12, 0x6f);
|
||||
__phy_write(phydev, 0x10, 0x8f82);
|
||||
|
||||
/* RemAckCntLimitCtrl = 1 */
|
||||
__phy_write(phydev, 0x11, 0xfbba);
|
||||
__phy_write(phydev, 0x12, 0xc3);
|
||||
__phy_write(phydev, 0x10, 0x87f8);
|
||||
|
||||
phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
|
||||
|
||||
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_2A30);
|
||||
/* TxClkOffset = 2 */
|
||||
__phy_modify(phydev, MTK_PHY_ANARG_RG, MTK_PHY_TCLKOFFSET_MASK,
|
||||
FIELD_PREP(MTK_PHY_TCLKOFFSET_MASK, 0x2));
|
||||
phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
|
||||
/* TR_OPEN_LOOP_EN = 1, lpf_x_average = 10 */
|
||||
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
|
||||
MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK,
|
||||
BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0xa));
|
||||
|
||||
/* rg_tr_lpf_cnt_val = 1023 */
|
||||
phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x3ff);
|
||||
}
|
||||
|
||||
static void mt798x_phy_eee(struct phy_device *phydev)
|
||||
@ -884,11 +892,11 @@ static void mt798x_phy_eee(struct phy_device *phydev)
|
||||
MTK_PHY_LPI_SLV_SEND_TX_EN,
|
||||
FIELD_PREP(MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK, 0x120));
|
||||
|
||||
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239,
|
||||
MTK_PHY_LPI_SEND_LOC_TIMER_MASK |
|
||||
MTK_PHY_LPI_TXPCS_LOC_RCV,
|
||||
FIELD_PREP(MTK_PHY_LPI_SEND_LOC_TIMER_MASK, 0x117));
|
||||
/* Keep MTK_PHY_LPI_SEND_LOC_TIMER as 375 */
|
||||
phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239,
|
||||
MTK_PHY_LPI_TXPCS_LOC_RCV);
|
||||
|
||||
/* This also fixes some IoT issues, such as CH340 */
|
||||
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2C7,
|
||||
MTK_PHY_MAX_GAIN_MASK | MTK_PHY_MIN_GAIN_MASK,
|
||||
FIELD_PREP(MTK_PHY_MAX_GAIN_MASK, 0x8) |
|
||||
@ -922,7 +930,7 @@ static void mt798x_phy_eee(struct phy_device *phydev)
|
||||
__phy_write(phydev, 0x12, 0x0);
|
||||
__phy_write(phydev, 0x10, 0x9690);
|
||||
|
||||
/* REG_EEE_st2TrKf1000 = 3 */
|
||||
/* REG_EEE_st2TrKf1000 = 2 */
|
||||
__phy_write(phydev, 0x11, 0x114f);
|
||||
__phy_write(phydev, 0x12, 0x2);
|
||||
__phy_write(phydev, 0x10, 0x969a);
|
||||
@ -947,7 +955,7 @@ static void mt798x_phy_eee(struct phy_device *phydev)
|
||||
__phy_write(phydev, 0x12, 0x0);
|
||||
__phy_write(phydev, 0x10, 0x96b8);
|
||||
|
||||
/* REGEEE_wake_slv_tr_wait_dfesigdet_en = 1 */
|
||||
/* REGEEE_wake_slv_tr_wait_dfesigdet_en = 0 */
|
||||
__phy_write(phydev, 0x11, 0x1463);
|
||||
__phy_write(phydev, 0x12, 0x0);
|
||||
__phy_write(phydev, 0x10, 0x96ca);
|
||||
@ -1459,6 +1467,13 @@ static int mt7988_phy_probe(struct phy_device *phydev)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Disable TX power saving at probing to:
|
||||
* 1. Meet common mode compliance test criteria
|
||||
* 2. Make sure that TX-VCM calibration works fine
|
||||
*/
|
||||
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7,
|
||||
MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8);
|
||||
|
||||
return mt798x_phy_calibration(phydev);
|
||||
}
|
||||
|
||||
|
@ -104,13 +104,12 @@ bool provides_xdp_headroom = true;
|
||||
module_param(provides_xdp_headroom, bool, 0644);
|
||||
|
||||
static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx,
|
||||
u8 status);
|
||||
s8 status);
|
||||
|
||||
static void make_tx_response(struct xenvif_queue *queue,
|
||||
struct xen_netif_tx_request *txp,
|
||||
const struct xen_netif_tx_request *txp,
|
||||
unsigned int extra_count,
|
||||
s8 st);
|
||||
static void push_tx_responses(struct xenvif_queue *queue);
|
||||
s8 status);
|
||||
|
||||
static void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx);
|
||||
|
||||
@ -208,13 +207,9 @@ static void xenvif_tx_err(struct xenvif_queue *queue,
|
||||
unsigned int extra_count, RING_IDX end)
|
||||
{
|
||||
RING_IDX cons = queue->tx.req_cons;
|
||||
unsigned long flags;
|
||||
|
||||
do {
|
||||
spin_lock_irqsave(&queue->response_lock, flags);
|
||||
make_tx_response(queue, txp, extra_count, XEN_NETIF_RSP_ERROR);
|
||||
push_tx_responses(queue);
|
||||
spin_unlock_irqrestore(&queue->response_lock, flags);
|
||||
if (cons == end)
|
||||
break;
|
||||
RING_COPY_REQUEST(&queue->tx, cons++, txp);
|
||||
@ -465,12 +460,7 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
|
||||
for (shinfo->nr_frags = 0; nr_slots > 0 && shinfo->nr_frags < MAX_SKB_FRAGS;
|
||||
nr_slots--) {
|
||||
if (unlikely(!txp->size)) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&queue->response_lock, flags);
|
||||
make_tx_response(queue, txp, 0, XEN_NETIF_RSP_OKAY);
|
||||
push_tx_responses(queue);
|
||||
spin_unlock_irqrestore(&queue->response_lock, flags);
|
||||
++txp;
|
||||
continue;
|
||||
}
|
||||
@ -496,14 +486,8 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
|
||||
|
||||
for (shinfo->nr_frags = 0; shinfo->nr_frags < nr_slots; ++txp) {
|
||||
if (unlikely(!txp->size)) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&queue->response_lock, flags);
|
||||
make_tx_response(queue, txp, 0,
|
||||
XEN_NETIF_RSP_OKAY);
|
||||
push_tx_responses(queue);
|
||||
spin_unlock_irqrestore(&queue->response_lock,
|
||||
flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -995,7 +979,6 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
|
||||
(ret == 0) ?
|
||||
XEN_NETIF_RSP_OKAY :
|
||||
XEN_NETIF_RSP_ERROR);
|
||||
push_tx_responses(queue);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1007,7 +990,6 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
|
||||
|
||||
make_tx_response(queue, &txreq, extra_count,
|
||||
XEN_NETIF_RSP_OKAY);
|
||||
push_tx_responses(queue);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1433,44 +1415,17 @@ int xenvif_tx_action(struct xenvif_queue *queue, int budget)
|
||||
return work_done;
|
||||
}
|
||||
|
||||
static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx,
|
||||
u8 status)
|
||||
{
|
||||
struct pending_tx_info *pending_tx_info;
|
||||
pending_ring_idx_t index;
|
||||
unsigned long flags;
|
||||
|
||||
pending_tx_info = &queue->pending_tx_info[pending_idx];
|
||||
|
||||
spin_lock_irqsave(&queue->response_lock, flags);
|
||||
|
||||
make_tx_response(queue, &pending_tx_info->req,
|
||||
pending_tx_info->extra_count, status);
|
||||
|
||||
/* Release the pending index before pusing the Tx response so
|
||||
* its available before a new Tx request is pushed by the
|
||||
* frontend.
|
||||
*/
|
||||
index = pending_index(queue->pending_prod++);
|
||||
queue->pending_ring[index] = pending_idx;
|
||||
|
||||
push_tx_responses(queue);
|
||||
|
||||
spin_unlock_irqrestore(&queue->response_lock, flags);
|
||||
}
|
||||
|
||||
|
||||
static void make_tx_response(struct xenvif_queue *queue,
|
||||
struct xen_netif_tx_request *txp,
|
||||
static void _make_tx_response(struct xenvif_queue *queue,
|
||||
const struct xen_netif_tx_request *txp,
|
||||
unsigned int extra_count,
|
||||
s8 st)
|
||||
s8 status)
|
||||
{
|
||||
RING_IDX i = queue->tx.rsp_prod_pvt;
|
||||
struct xen_netif_tx_response *resp;
|
||||
|
||||
resp = RING_GET_RESPONSE(&queue->tx, i);
|
||||
resp->id = txp->id;
|
||||
resp->status = st;
|
||||
resp->status = status;
|
||||
|
||||
while (extra_count-- != 0)
|
||||
RING_GET_RESPONSE(&queue->tx, ++i)->status = XEN_NETIF_RSP_NULL;
|
||||
@ -1487,6 +1442,47 @@ static void push_tx_responses(struct xenvif_queue *queue)
|
||||
notify_remote_via_irq(queue->tx_irq);
|
||||
}
|
||||
|
||||
static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx,
|
||||
s8 status)
|
||||
{
|
||||
struct pending_tx_info *pending_tx_info;
|
||||
pending_ring_idx_t index;
|
||||
unsigned long flags;
|
||||
|
||||
pending_tx_info = &queue->pending_tx_info[pending_idx];
|
||||
|
||||
spin_lock_irqsave(&queue->response_lock, flags);
|
||||
|
||||
_make_tx_response(queue, &pending_tx_info->req,
|
||||
pending_tx_info->extra_count, status);
|
||||
|
||||
/* Release the pending index before pusing the Tx response so
|
||||
* its available before a new Tx request is pushed by the
|
||||
* frontend.
|
||||
*/
|
||||
index = pending_index(queue->pending_prod++);
|
||||
queue->pending_ring[index] = pending_idx;
|
||||
|
||||
push_tx_responses(queue);
|
||||
|
||||
spin_unlock_irqrestore(&queue->response_lock, flags);
|
||||
}
|
||||
|
||||
static void make_tx_response(struct xenvif_queue *queue,
|
||||
const struct xen_netif_tx_request *txp,
|
||||
unsigned int extra_count,
|
||||
s8 status)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&queue->response_lock, flags);
|
||||
|
||||
_make_tx_response(queue, txp, extra_count, status);
|
||||
push_tx_responses(queue);
|
||||
|
||||
spin_unlock_irqrestore(&queue->response_lock, flags);
|
||||
}
|
||||
|
||||
static void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx)
|
||||
{
|
||||
int ret;
|
||||
|
@ -186,6 +186,8 @@ struct ip_set_type_variant {
|
||||
/* Return true if "b" set is the same as "a"
|
||||
* according to the create set parameters */
|
||||
bool (*same_set)(const struct ip_set *a, const struct ip_set *b);
|
||||
/* Cancel ongoing garbage collectors before destroying the set*/
|
||||
void (*cancel_gc)(struct ip_set *set);
|
||||
/* Region-locking is used */
|
||||
bool region_lock;
|
||||
};
|
||||
@ -242,6 +244,8 @@ extern void ip_set_type_unregister(struct ip_set_type *set_type);
|
||||
|
||||
/* A generic IP set */
|
||||
struct ip_set {
|
||||
/* For call_cru in destroy */
|
||||
struct rcu_head rcu;
|
||||
/* The name of the set */
|
||||
char name[IPSET_MAXNAMELEN];
|
||||
/* Lock protecting the set data */
|
||||
|
@ -46,12 +46,6 @@ struct scm_stat {
|
||||
|
||||
#define UNIXCB(skb) (*(struct unix_skb_parms *)&((skb)->cb))
|
||||
|
||||
#define unix_state_lock(s) spin_lock(&unix_sk(s)->lock)
|
||||
#define unix_state_unlock(s) spin_unlock(&unix_sk(s)->lock)
|
||||
#define unix_state_lock_nested(s) \
|
||||
spin_lock_nested(&unix_sk(s)->lock, \
|
||||
SINGLE_DEPTH_NESTING)
|
||||
|
||||
/* The AF_UNIX socket */
|
||||
struct unix_sock {
|
||||
/* WARNING: sk has to be the first member */
|
||||
@ -77,6 +71,20 @@ struct unix_sock {
|
||||
#define unix_sk(ptr) container_of_const(ptr, struct unix_sock, sk)
|
||||
#define unix_peer(sk) (unix_sk(sk)->peer)
|
||||
|
||||
#define unix_state_lock(s) spin_lock(&unix_sk(s)->lock)
|
||||
#define unix_state_unlock(s) spin_unlock(&unix_sk(s)->lock)
|
||||
enum unix_socket_lock_class {
|
||||
U_LOCK_NORMAL,
|
||||
U_LOCK_SECOND, /* for double locking, see unix_state_double_lock(). */
|
||||
U_LOCK_DIAG, /* used while dumping icons, see sk_diag_dump_icons(). */
|
||||
};
|
||||
|
||||
static inline void unix_state_lock_nested(struct sock *sk,
|
||||
enum unix_socket_lock_class subclass)
|
||||
{
|
||||
spin_lock_nested(&unix_sk(sk)->lock, subclass);
|
||||
}
|
||||
|
||||
#define peer_wait peer_wq.wait
|
||||
|
||||
long unix_inq_len(struct sock *sk);
|
||||
|
@ -767,7 +767,7 @@ int ip_options_rcv_srr(struct sk_buff *skb, struct net_device *dev);
|
||||
* Functions provided by ip_sockglue.c
|
||||
*/
|
||||
|
||||
void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb);
|
||||
void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb, bool drop_dst);
|
||||
void ip_cmsg_recv_offset(struct msghdr *msg, struct sock *sk,
|
||||
struct sk_buff *skb, int tlen, int offset);
|
||||
int ip_cmsg_send(struct sock *sk, struct msghdr *msg,
|
||||
|
@ -1351,6 +1351,7 @@ void nft_obj_notify(struct net *net, const struct nft_table *table,
|
||||
* @type: stateful object numeric type
|
||||
* @owner: module owner
|
||||
* @maxattr: maximum netlink attribute
|
||||
* @family: address family for AF-specific object types
|
||||
* @policy: netlink attribute policy
|
||||
*/
|
||||
struct nft_object_type {
|
||||
@ -1360,6 +1361,7 @@ struct nft_object_type {
|
||||
struct list_head list;
|
||||
u32 type;
|
||||
unsigned int maxattr;
|
||||
u8 family;
|
||||
struct module *owner;
|
||||
const struct nla_policy *policy;
|
||||
};
|
||||
|
@ -2175,6 +2175,7 @@ void batadv_mcast_free(struct batadv_priv *bat_priv)
|
||||
cancel_delayed_work_sync(&bat_priv->mcast.work);
|
||||
|
||||
batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_MCAST, 2);
|
||||
batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_MCAST_TRACKER, 1);
|
||||
batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_MCAST, 2);
|
||||
|
||||
/* safely calling outside of worker, as worker was canceled above */
|
||||
@ -2198,6 +2199,8 @@ void batadv_mcast_purge_orig(struct batadv_orig_node *orig)
|
||||
BATADV_MCAST_WANT_NO_RTR4);
|
||||
batadv_mcast_want_rtr6_update(bat_priv, orig,
|
||||
BATADV_MCAST_WANT_NO_RTR6);
|
||||
batadv_mcast_have_mc_ptype_update(bat_priv, orig,
|
||||
BATADV_MCAST_HAVE_MC_PTYPE_CAPA);
|
||||
|
||||
spin_unlock_bh(&orig->mcast_handler_lock);
|
||||
}
|
||||
|
@ -1762,6 +1762,10 @@ static void br_ip6_multicast_querier_expired(struct timer_list *t)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void br_multicast_query_delay_expired(struct timer_list *t)
|
||||
{
|
||||
}
|
||||
|
||||
static void br_multicast_select_own_querier(struct net_bridge_mcast *brmctx,
|
||||
struct br_ip *ip,
|
||||
struct sk_buff *skb)
|
||||
@ -3198,7 +3202,7 @@ br_multicast_update_query_timer(struct net_bridge_mcast *brmctx,
|
||||
unsigned long max_delay)
|
||||
{
|
||||
if (!timer_pending(&query->timer))
|
||||
query->delay_time = jiffies + max_delay;
|
||||
mod_timer(&query->delay_timer, jiffies + max_delay);
|
||||
|
||||
mod_timer(&query->timer, jiffies + brmctx->multicast_querier_interval);
|
||||
}
|
||||
@ -4041,13 +4045,11 @@ void br_multicast_ctx_init(struct net_bridge *br,
|
||||
brmctx->multicast_querier_interval = 255 * HZ;
|
||||
brmctx->multicast_membership_interval = 260 * HZ;
|
||||
|
||||
brmctx->ip4_other_query.delay_time = 0;
|
||||
brmctx->ip4_querier.port_ifidx = 0;
|
||||
seqcount_spinlock_init(&brmctx->ip4_querier.seq, &br->multicast_lock);
|
||||
brmctx->multicast_igmp_version = 2;
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
brmctx->multicast_mld_version = 1;
|
||||
brmctx->ip6_other_query.delay_time = 0;
|
||||
brmctx->ip6_querier.port_ifidx = 0;
|
||||
seqcount_spinlock_init(&brmctx->ip6_querier.seq, &br->multicast_lock);
|
||||
#endif
|
||||
@ -4056,6 +4058,8 @@ void br_multicast_ctx_init(struct net_bridge *br,
|
||||
br_ip4_multicast_local_router_expired, 0);
|
||||
timer_setup(&brmctx->ip4_other_query.timer,
|
||||
br_ip4_multicast_querier_expired, 0);
|
||||
timer_setup(&brmctx->ip4_other_query.delay_timer,
|
||||
br_multicast_query_delay_expired, 0);
|
||||
timer_setup(&brmctx->ip4_own_query.timer,
|
||||
br_ip4_multicast_query_expired, 0);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
@ -4063,6 +4067,8 @@ void br_multicast_ctx_init(struct net_bridge *br,
|
||||
br_ip6_multicast_local_router_expired, 0);
|
||||
timer_setup(&brmctx->ip6_other_query.timer,
|
||||
br_ip6_multicast_querier_expired, 0);
|
||||
timer_setup(&brmctx->ip6_other_query.delay_timer,
|
||||
br_multicast_query_delay_expired, 0);
|
||||
timer_setup(&brmctx->ip6_own_query.timer,
|
||||
br_ip6_multicast_query_expired, 0);
|
||||
#endif
|
||||
@ -4197,10 +4203,12 @@ static void __br_multicast_stop(struct net_bridge_mcast *brmctx)
|
||||
{
|
||||
del_timer_sync(&brmctx->ip4_mc_router_timer);
|
||||
del_timer_sync(&brmctx->ip4_other_query.timer);
|
||||
del_timer_sync(&brmctx->ip4_other_query.delay_timer);
|
||||
del_timer_sync(&brmctx->ip4_own_query.timer);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
del_timer_sync(&brmctx->ip6_mc_router_timer);
|
||||
del_timer_sync(&brmctx->ip6_other_query.timer);
|
||||
del_timer_sync(&brmctx->ip6_other_query.delay_timer);
|
||||
del_timer_sync(&brmctx->ip6_own_query.timer);
|
||||
#endif
|
||||
}
|
||||
@ -4643,13 +4651,15 @@ int br_multicast_set_querier(struct net_bridge_mcast *brmctx, unsigned long val)
|
||||
max_delay = brmctx->multicast_query_response_interval;
|
||||
|
||||
if (!timer_pending(&brmctx->ip4_other_query.timer))
|
||||
brmctx->ip4_other_query.delay_time = jiffies + max_delay;
|
||||
mod_timer(&brmctx->ip4_other_query.delay_timer,
|
||||
jiffies + max_delay);
|
||||
|
||||
br_multicast_start_querier(brmctx, &brmctx->ip4_own_query);
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
if (!timer_pending(&brmctx->ip6_other_query.timer))
|
||||
brmctx->ip6_other_query.delay_time = jiffies + max_delay;
|
||||
mod_timer(&brmctx->ip6_other_query.delay_timer,
|
||||
jiffies + max_delay);
|
||||
|
||||
br_multicast_start_querier(brmctx, &brmctx->ip6_own_query);
|
||||
#endif
|
||||
|
@ -78,7 +78,7 @@ struct bridge_mcast_own_query {
|
||||
/* other querier */
|
||||
struct bridge_mcast_other_query {
|
||||
struct timer_list timer;
|
||||
unsigned long delay_time;
|
||||
struct timer_list delay_timer;
|
||||
};
|
||||
|
||||
/* selected querier */
|
||||
@ -1159,7 +1159,7 @@ __br_multicast_querier_exists(struct net_bridge_mcast *brmctx,
|
||||
own_querier_enabled = false;
|
||||
}
|
||||
|
||||
return time_is_before_jiffies(querier->delay_time) &&
|
||||
return !timer_pending(&querier->delay_timer) &&
|
||||
(own_querier_enabled || timer_pending(&querier->timer));
|
||||
}
|
||||
|
||||
|
@ -674,7 +674,7 @@ static int devlink_port_function_validate(struct devlink_port *devlink_port,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
if (tb[DEVLINK_PORT_FN_ATTR_STATE] && !ops->port_fn_state_set) {
|
||||
NL_SET_ERR_MSG_ATTR(extack, tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR],
|
||||
NL_SET_ERR_MSG_ATTR(extack, tb[DEVLINK_PORT_FN_ATTR_STATE],
|
||||
"Function does not support state setting");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
@ -308,7 +308,7 @@ static void send_hsr_supervision_frame(struct hsr_port *master,
|
||||
|
||||
skb = hsr_init_skb(master);
|
||||
if (!skb) {
|
||||
WARN_ONCE(1, "HSR: Could not send supervision frame\n");
|
||||
netdev_warn_once(master->dev, "HSR: Could not send supervision frame\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -355,7 +355,7 @@ static void send_prp_supervision_frame(struct hsr_port *master,
|
||||
|
||||
skb = hsr_init_skb(master);
|
||||
if (!skb) {
|
||||
WARN_ONCE(1, "PRP: Could not send supervision frame\n");
|
||||
netdev_warn_once(master->dev, "PRP: Could not send supervision frame\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1287,6 +1287,12 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork,
|
||||
if (unlikely(!rt))
|
||||
return -EFAULT;
|
||||
|
||||
cork->fragsize = ip_sk_use_pmtu(sk) ?
|
||||
dst_mtu(&rt->dst) : READ_ONCE(rt->dst.dev->mtu);
|
||||
|
||||
if (!inetdev_valid_mtu(cork->fragsize))
|
||||
return -ENETUNREACH;
|
||||
|
||||
/*
|
||||
* setup for corking.
|
||||
*/
|
||||
@ -1303,12 +1309,6 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork,
|
||||
cork->addr = ipc->addr;
|
||||
}
|
||||
|
||||
cork->fragsize = ip_sk_use_pmtu(sk) ?
|
||||
dst_mtu(&rt->dst) : READ_ONCE(rt->dst.dev->mtu);
|
||||
|
||||
if (!inetdev_valid_mtu(cork->fragsize))
|
||||
return -ENETUNREACH;
|
||||
|
||||
cork->gso_size = ipc->gso_size;
|
||||
|
||||
cork->dst = &rt->dst;
|
||||
|
@ -1363,12 +1363,13 @@ e_inval:
|
||||
* ipv4_pktinfo_prepare - transfer some info from rtable to skb
|
||||
* @sk: socket
|
||||
* @skb: buffer
|
||||
* @drop_dst: if true, drops skb dst
|
||||
*
|
||||
* To support IP_CMSG_PKTINFO option, we store rt_iif and specific
|
||||
* destination in skb->cb[] before dst drop.
|
||||
* This way, receiver doesn't make cache line misses to read rtable.
|
||||
*/
|
||||
void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb)
|
||||
void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb, bool drop_dst)
|
||||
{
|
||||
struct in_pktinfo *pktinfo = PKTINFO_SKB_CB(skb);
|
||||
bool prepare = inet_test_bit(PKTINFO, sk) ||
|
||||
@ -1397,7 +1398,8 @@ void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb)
|
||||
pktinfo->ipi_ifindex = 0;
|
||||
pktinfo->ipi_spec_dst.s_addr = 0;
|
||||
}
|
||||
skb_dst_drop(skb);
|
||||
if (drop_dst)
|
||||
skb_dst_drop(skb);
|
||||
}
|
||||
|
||||
int ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
|
||||
|
@ -1073,7 +1073,7 @@ static int ipmr_cache_report(const struct mr_table *mrt,
|
||||
msg = (struct igmpmsg *)skb_network_header(skb);
|
||||
msg->im_vif = vifi;
|
||||
msg->im_vif_hi = vifi >> 8;
|
||||
ipv4_pktinfo_prepare(mroute_sk, pkt);
|
||||
ipv4_pktinfo_prepare(mroute_sk, pkt, false);
|
||||
memcpy(skb->cb, pkt->cb, sizeof(skb->cb));
|
||||
/* Add our header */
|
||||
igmp = skb_put(skb, sizeof(struct igmphdr));
|
||||
|
@ -292,7 +292,7 @@ static int raw_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
||||
|
||||
/* Charge it to the socket. */
|
||||
|
||||
ipv4_pktinfo_prepare(sk, skb);
|
||||
ipv4_pktinfo_prepare(sk, skb, true);
|
||||
if (sock_queue_rcv_skb_reason(sk, skb, &reason) < 0) {
|
||||
kfree_skb_reason(skb, reason);
|
||||
return NET_RX_DROP;
|
||||
|
@ -1786,7 +1786,17 @@ static skb_frag_t *skb_advance_to_frag(struct sk_buff *skb, u32 offset_skb,
|
||||
|
||||
static bool can_map_frag(const skb_frag_t *frag)
|
||||
{
|
||||
return skb_frag_size(frag) == PAGE_SIZE && !skb_frag_off(frag);
|
||||
struct page *page;
|
||||
|
||||
if (skb_frag_size(frag) != PAGE_SIZE || skb_frag_off(frag))
|
||||
return false;
|
||||
|
||||
page = skb_frag_page(frag);
|
||||
|
||||
if (PageCompound(page) || page->mapping)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int find_next_mappable_frag(const skb_frag_t *frag,
|
||||
|
@ -2169,7 +2169,7 @@ static int udp_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
|
||||
|
||||
udp_csum_pull_header(skb);
|
||||
|
||||
ipv4_pktinfo_prepare(sk, skb);
|
||||
ipv4_pktinfo_prepare(sk, skb, true);
|
||||
return __udp_queue_rcv_skb(sk, skb);
|
||||
|
||||
csum_error:
|
||||
|
@ -220,19 +220,26 @@ const struct ipv6_stub *ipv6_stub __read_mostly = &(struct ipv6_stub) {
|
||||
EXPORT_SYMBOL_GPL(ipv6_stub);
|
||||
|
||||
/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
|
||||
const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
|
||||
const struct in6_addr in6addr_loopback __aligned(BITS_PER_LONG/8)
|
||||
= IN6ADDR_LOOPBACK_INIT;
|
||||
EXPORT_SYMBOL(in6addr_loopback);
|
||||
const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
|
||||
const struct in6_addr in6addr_any __aligned(BITS_PER_LONG/8)
|
||||
= IN6ADDR_ANY_INIT;
|
||||
EXPORT_SYMBOL(in6addr_any);
|
||||
const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
|
||||
const struct in6_addr in6addr_linklocal_allnodes __aligned(BITS_PER_LONG/8)
|
||||
= IN6ADDR_LINKLOCAL_ALLNODES_INIT;
|
||||
EXPORT_SYMBOL(in6addr_linklocal_allnodes);
|
||||
const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
|
||||
const struct in6_addr in6addr_linklocal_allrouters __aligned(BITS_PER_LONG/8)
|
||||
= IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
|
||||
EXPORT_SYMBOL(in6addr_linklocal_allrouters);
|
||||
const struct in6_addr in6addr_interfacelocal_allnodes = IN6ADDR_INTERFACELOCAL_ALLNODES_INIT;
|
||||
const struct in6_addr in6addr_interfacelocal_allnodes __aligned(BITS_PER_LONG/8)
|
||||
= IN6ADDR_INTERFACELOCAL_ALLNODES_INIT;
|
||||
EXPORT_SYMBOL(in6addr_interfacelocal_allnodes);
|
||||
const struct in6_addr in6addr_interfacelocal_allrouters = IN6ADDR_INTERFACELOCAL_ALLROUTERS_INIT;
|
||||
const struct in6_addr in6addr_interfacelocal_allrouters __aligned(BITS_PER_LONG/8)
|
||||
= IN6ADDR_INTERFACELOCAL_ALLROUTERS_INIT;
|
||||
EXPORT_SYMBOL(in6addr_interfacelocal_allrouters);
|
||||
const struct in6_addr in6addr_sitelocal_allrouters = IN6ADDR_SITELOCAL_ALLROUTERS_INIT;
|
||||
const struct in6_addr in6addr_sitelocal_allrouters __aligned(BITS_PER_LONG/8)
|
||||
= IN6ADDR_SITELOCAL_ALLROUTERS_INIT;
|
||||
EXPORT_SYMBOL(in6addr_sitelocal_allrouters);
|
||||
|
||||
static void snmp6_free_dev(struct inet6_dev *idev)
|
||||
|
@ -796,8 +796,8 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,
|
||||
struct sk_buff *skb),
|
||||
bool log_ecn_err)
|
||||
{
|
||||
const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
|
||||
int err;
|
||||
const struct ipv6hdr *ipv6h;
|
||||
int nh, err;
|
||||
|
||||
if ((!(tpi->flags & TUNNEL_CSUM) &&
|
||||
(tunnel->parms.i_flags & TUNNEL_CSUM)) ||
|
||||
@ -829,7 +829,6 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,
|
||||
goto drop;
|
||||
}
|
||||
|
||||
ipv6h = ipv6_hdr(skb);
|
||||
skb->protocol = eth_type_trans(skb, tunnel->dev);
|
||||
skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
|
||||
} else {
|
||||
@ -837,7 +836,23 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,
|
||||
skb_reset_mac_header(skb);
|
||||
}
|
||||
|
||||
/* Save offset of outer header relative to skb->head,
|
||||
* because we are going to reset the network header to the inner header
|
||||
* and might change skb->head.
|
||||
*/
|
||||
nh = skb_network_header(skb) - skb->head;
|
||||
|
||||
skb_reset_network_header(skb);
|
||||
|
||||
if (!pskb_inet_may_pull(skb)) {
|
||||
DEV_STATS_INC(tunnel->dev, rx_length_errors);
|
||||
DEV_STATS_INC(tunnel->dev, rx_errors);
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* Get the outer header. */
|
||||
ipv6h = (struct ipv6hdr *)(skb->head + nh);
|
||||
|
||||
memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
|
||||
|
||||
__skb_tunnel_rx(skb, tunnel->dev, tunnel->net);
|
||||
|
@ -226,6 +226,8 @@ static int llc_ui_release(struct socket *sock)
|
||||
}
|
||||
netdev_put(llc->dev, &llc->dev_tracker);
|
||||
sock_put(sk);
|
||||
sock_orphan(sk);
|
||||
sock->sk = NULL;
|
||||
llc_sk_free(sk);
|
||||
out:
|
||||
return 0;
|
||||
|
@ -2314,9 +2314,6 @@ bool __mptcp_retransmit_pending_data(struct sock *sk)
|
||||
if (__mptcp_check_fallback(msk))
|
||||
return false;
|
||||
|
||||
if (tcp_rtx_and_write_queues_empty(sk))
|
||||
return false;
|
||||
|
||||
/* the closing socket has some data untransmitted and/or unacked:
|
||||
* some data in the mptcp rtx queue has not really xmitted yet.
|
||||
* keep it simple and re-inject the whole mptcp level rtx queue
|
||||
|
@ -30,6 +30,7 @@
|
||||
#define mtype_del IPSET_TOKEN(MTYPE, _del)
|
||||
#define mtype_list IPSET_TOKEN(MTYPE, _list)
|
||||
#define mtype_gc IPSET_TOKEN(MTYPE, _gc)
|
||||
#define mtype_cancel_gc IPSET_TOKEN(MTYPE, _cancel_gc)
|
||||
#define mtype MTYPE
|
||||
|
||||
#define get_ext(set, map, id) ((map)->extensions + ((set)->dsize * (id)))
|
||||
@ -59,9 +60,6 @@ mtype_destroy(struct ip_set *set)
|
||||
{
|
||||
struct mtype *map = set->data;
|
||||
|
||||
if (SET_WITH_TIMEOUT(set))
|
||||
del_timer_sync(&map->gc);
|
||||
|
||||
if (set->dsize && set->extensions & IPSET_EXT_DESTROY)
|
||||
mtype_ext_cleanup(set);
|
||||
ip_set_free(map->members);
|
||||
@ -290,6 +288,15 @@ mtype_gc(struct timer_list *t)
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static void
|
||||
mtype_cancel_gc(struct ip_set *set)
|
||||
{
|
||||
struct mtype *map = set->data;
|
||||
|
||||
if (SET_WITH_TIMEOUT(set))
|
||||
del_timer_sync(&map->gc);
|
||||
}
|
||||
|
||||
static const struct ip_set_type_variant mtype = {
|
||||
.kadt = mtype_kadt,
|
||||
.uadt = mtype_uadt,
|
||||
@ -303,6 +310,7 @@ static const struct ip_set_type_variant mtype = {
|
||||
.head = mtype_head,
|
||||
.list = mtype_list,
|
||||
.same_set = mtype_same_set,
|
||||
.cancel_gc = mtype_cancel_gc,
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_BITMAP_IP_GEN_H */
|
||||
|
@ -1182,6 +1182,14 @@ ip_set_destroy_set(struct ip_set *set)
|
||||
kfree(set);
|
||||
}
|
||||
|
||||
static void
|
||||
ip_set_destroy_set_rcu(struct rcu_head *head)
|
||||
{
|
||||
struct ip_set *set = container_of(head, struct ip_set, rcu);
|
||||
|
||||
ip_set_destroy_set(set);
|
||||
}
|
||||
|
||||
static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
const struct nlattr * const attr[])
|
||||
{
|
||||
@ -1193,8 +1201,6 @@ static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
if (unlikely(protocol_min_failed(attr)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
/* Must wait for flush to be really finished in list:set */
|
||||
rcu_barrier();
|
||||
|
||||
/* Commands are serialized and references are
|
||||
* protected by the ip_set_ref_lock.
|
||||
@ -1206,8 +1212,10 @@ static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
* counter, so if it's already zero, we can proceed
|
||||
* without holding the lock.
|
||||
*/
|
||||
read_lock_bh(&ip_set_ref_lock);
|
||||
if (!attr[IPSET_ATTR_SETNAME]) {
|
||||
/* Must wait for flush to be really finished in list:set */
|
||||
rcu_barrier();
|
||||
read_lock_bh(&ip_set_ref_lock);
|
||||
for (i = 0; i < inst->ip_set_max; i++) {
|
||||
s = ip_set(inst, i);
|
||||
if (s && (s->ref || s->ref_netlink)) {
|
||||
@ -1221,6 +1229,8 @@ static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
s = ip_set(inst, i);
|
||||
if (s) {
|
||||
ip_set(inst, i) = NULL;
|
||||
/* Must cancel garbage collectors */
|
||||
s->variant->cancel_gc(s);
|
||||
ip_set_destroy_set(s);
|
||||
}
|
||||
}
|
||||
@ -1228,6 +1238,9 @@ static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
inst->is_destroyed = false;
|
||||
} else {
|
||||
u32 flags = flag_exist(info->nlh);
|
||||
u16 features = 0;
|
||||
|
||||
read_lock_bh(&ip_set_ref_lock);
|
||||
s = find_set_and_id(inst, nla_data(attr[IPSET_ATTR_SETNAME]),
|
||||
&i);
|
||||
if (!s) {
|
||||
@ -1238,10 +1251,16 @@ static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
ret = -IPSET_ERR_BUSY;
|
||||
goto out;
|
||||
}
|
||||
features = s->type->features;
|
||||
ip_set(inst, i) = NULL;
|
||||
read_unlock_bh(&ip_set_ref_lock);
|
||||
|
||||
ip_set_destroy_set(s);
|
||||
if (features & IPSET_TYPE_NAME) {
|
||||
/* Must wait for flush to be really finished */
|
||||
rcu_barrier();
|
||||
}
|
||||
/* Must cancel garbage collectors */
|
||||
s->variant->cancel_gc(s);
|
||||
call_rcu(&s->rcu, ip_set_destroy_set_rcu);
|
||||
}
|
||||
return 0;
|
||||
out:
|
||||
@ -1394,9 +1413,6 @@ static int ip_set_swap(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
ip_set(inst, to_id) = from;
|
||||
write_unlock_bh(&ip_set_ref_lock);
|
||||
|
||||
/* Make sure all readers of the old set pointers are completed. */
|
||||
synchronize_rcu();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2409,8 +2425,11 @@ ip_set_fini(void)
|
||||
{
|
||||
nf_unregister_sockopt(&so_set);
|
||||
nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
|
||||
|
||||
unregister_pernet_subsys(&ip_set_net_ops);
|
||||
|
||||
/* Wait for call_rcu() in destroy */
|
||||
rcu_barrier();
|
||||
|
||||
pr_debug("these are the famous last words\n");
|
||||
}
|
||||
|
||||
|
@ -222,6 +222,7 @@ static const union nf_inet_addr zeromask = {};
|
||||
#undef mtype_gc_do
|
||||
#undef mtype_gc
|
||||
#undef mtype_gc_init
|
||||
#undef mtype_cancel_gc
|
||||
#undef mtype_variant
|
||||
#undef mtype_data_match
|
||||
|
||||
@ -266,6 +267,7 @@ static const union nf_inet_addr zeromask = {};
|
||||
#define mtype_gc_do IPSET_TOKEN(MTYPE, _gc_do)
|
||||
#define mtype_gc IPSET_TOKEN(MTYPE, _gc)
|
||||
#define mtype_gc_init IPSET_TOKEN(MTYPE, _gc_init)
|
||||
#define mtype_cancel_gc IPSET_TOKEN(MTYPE, _cancel_gc)
|
||||
#define mtype_variant IPSET_TOKEN(MTYPE, _variant)
|
||||
#define mtype_data_match IPSET_TOKEN(MTYPE, _data_match)
|
||||
|
||||
@ -450,9 +452,6 @@ mtype_destroy(struct ip_set *set)
|
||||
struct htype *h = set->data;
|
||||
struct list_head *l, *lt;
|
||||
|
||||
if (SET_WITH_TIMEOUT(set))
|
||||
cancel_delayed_work_sync(&h->gc.dwork);
|
||||
|
||||
mtype_ahash_destroy(set, ipset_dereference_nfnl(h->table), true);
|
||||
list_for_each_safe(l, lt, &h->ad) {
|
||||
list_del(l);
|
||||
@ -599,6 +598,15 @@ mtype_gc_init(struct htable_gc *gc)
|
||||
queue_delayed_work(system_power_efficient_wq, &gc->dwork, HZ);
|
||||
}
|
||||
|
||||
static void
|
||||
mtype_cancel_gc(struct ip_set *set)
|
||||
{
|
||||
struct htype *h = set->data;
|
||||
|
||||
if (SET_WITH_TIMEOUT(set))
|
||||
cancel_delayed_work_sync(&h->gc.dwork);
|
||||
}
|
||||
|
||||
static int
|
||||
mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
|
||||
struct ip_set_ext *mext, u32 flags);
|
||||
@ -1441,6 +1449,7 @@ static const struct ip_set_type_variant mtype_variant = {
|
||||
.uref = mtype_uref,
|
||||
.resize = mtype_resize,
|
||||
.same_set = mtype_same_set,
|
||||
.cancel_gc = mtype_cancel_gc,
|
||||
.region_lock = true,
|
||||
};
|
||||
|
||||
|
@ -426,9 +426,6 @@ list_set_destroy(struct ip_set *set)
|
||||
struct list_set *map = set->data;
|
||||
struct set_elem *e, *n;
|
||||
|
||||
if (SET_WITH_TIMEOUT(set))
|
||||
timer_shutdown_sync(&map->gc);
|
||||
|
||||
list_for_each_entry_safe(e, n, &map->members, list) {
|
||||
list_del(&e->list);
|
||||
ip_set_put_byindex(map->net, e->id);
|
||||
@ -545,6 +542,15 @@ list_set_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
a->extensions == b->extensions;
|
||||
}
|
||||
|
||||
static void
|
||||
list_set_cancel_gc(struct ip_set *set)
|
||||
{
|
||||
struct list_set *map = set->data;
|
||||
|
||||
if (SET_WITH_TIMEOUT(set))
|
||||
timer_shutdown_sync(&map->gc);
|
||||
}
|
||||
|
||||
static const struct ip_set_type_variant set_variant = {
|
||||
.kadt = list_set_kadt,
|
||||
.uadt = list_set_uadt,
|
||||
@ -558,6 +564,7 @@ static const struct ip_set_type_variant set_variant = {
|
||||
.head = list_set_head,
|
||||
.list = list_set_list,
|
||||
.same_set = list_set_same_set,
|
||||
.cancel_gc = list_set_cancel_gc,
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -283,7 +283,7 @@ sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
|
||||
pr_debug("Setting vtag %x for secondary conntrack\n",
|
||||
sh->vtag);
|
||||
ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = sh->vtag;
|
||||
} else {
|
||||
} else if (sch->type == SCTP_CID_SHUTDOWN_ACK) {
|
||||
/* If it is a shutdown ack OOTB packet, we expect a return
|
||||
shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
|
||||
pr_debug("Setting vtag %x for new conn OOTB\n",
|
||||
|
@ -457,7 +457,8 @@ static void tcp_init_sender(struct ip_ct_tcp_state *sender,
|
||||
const struct sk_buff *skb,
|
||||
unsigned int dataoff,
|
||||
const struct tcphdr *tcph,
|
||||
u32 end, u32 win)
|
||||
u32 end, u32 win,
|
||||
enum ip_conntrack_dir dir)
|
||||
{
|
||||
/* SYN-ACK in reply to a SYN
|
||||
* or SYN from reply direction in simultaneous open.
|
||||
@ -471,7 +472,8 @@ static void tcp_init_sender(struct ip_ct_tcp_state *sender,
|
||||
* Both sides must send the Window Scale option
|
||||
* to enable window scaling in either direction.
|
||||
*/
|
||||
if (!(sender->flags & IP_CT_TCP_FLAG_WINDOW_SCALE &&
|
||||
if (dir == IP_CT_DIR_REPLY &&
|
||||
!(sender->flags & IP_CT_TCP_FLAG_WINDOW_SCALE &&
|
||||
receiver->flags & IP_CT_TCP_FLAG_WINDOW_SCALE)) {
|
||||
sender->td_scale = 0;
|
||||
receiver->td_scale = 0;
|
||||
@ -542,7 +544,7 @@ tcp_in_window(struct nf_conn *ct, enum ip_conntrack_dir dir,
|
||||
if (tcph->syn) {
|
||||
tcp_init_sender(sender, receiver,
|
||||
skb, dataoff, tcph,
|
||||
end, win);
|
||||
end, win, dir);
|
||||
if (!tcph->ack)
|
||||
/* Simultaneous open */
|
||||
return NFCT_TCP_ACCEPT;
|
||||
@ -585,7 +587,7 @@ tcp_in_window(struct nf_conn *ct, enum ip_conntrack_dir dir,
|
||||
*/
|
||||
tcp_init_sender(sender, receiver,
|
||||
skb, dataoff, tcph,
|
||||
end, win);
|
||||
end, win, dir);
|
||||
|
||||
if (dir == IP_CT_DIR_REPLY && !tcph->ack)
|
||||
return NFCT_TCP_ACCEPT;
|
||||
|
@ -193,11 +193,12 @@ void nf_logger_put(int pf, enum nf_log_type type)
|
||||
return;
|
||||
}
|
||||
|
||||
BUG_ON(loggers[pf][type] == NULL);
|
||||
|
||||
rcu_read_lock();
|
||||
logger = rcu_dereference(loggers[pf][type]);
|
||||
module_put(logger->me);
|
||||
if (!logger)
|
||||
WARN_ON_ONCE(1);
|
||||
else
|
||||
module_put(logger->me);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_logger_put);
|
||||
|
@ -7551,11 +7551,15 @@ nla_put_failure:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const struct nft_object_type *__nft_obj_type_get(u32 objtype)
|
||||
static const struct nft_object_type *__nft_obj_type_get(u32 objtype, u8 family)
|
||||
{
|
||||
const struct nft_object_type *type;
|
||||
|
||||
list_for_each_entry(type, &nf_tables_objects, list) {
|
||||
if (type->family != NFPROTO_UNSPEC &&
|
||||
type->family != family)
|
||||
continue;
|
||||
|
||||
if (objtype == type->type)
|
||||
return type;
|
||||
}
|
||||
@ -7563,11 +7567,11 @@ static const struct nft_object_type *__nft_obj_type_get(u32 objtype)
|
||||
}
|
||||
|
||||
static const struct nft_object_type *
|
||||
nft_obj_type_get(struct net *net, u32 objtype)
|
||||
nft_obj_type_get(struct net *net, u32 objtype, u8 family)
|
||||
{
|
||||
const struct nft_object_type *type;
|
||||
|
||||
type = __nft_obj_type_get(objtype);
|
||||
type = __nft_obj_type_get(objtype, family);
|
||||
if (type != NULL && try_module_get(type->owner))
|
||||
return type;
|
||||
|
||||
@ -7660,7 +7664,7 @@ static int nf_tables_newobj(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
if (info->nlh->nlmsg_flags & NLM_F_REPLACE)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
type = __nft_obj_type_get(objtype);
|
||||
type = __nft_obj_type_get(objtype, family);
|
||||
if (WARN_ON_ONCE(!type))
|
||||
return -ENOENT;
|
||||
|
||||
@ -7674,7 +7678,7 @@ static int nf_tables_newobj(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
if (!nft_use_inc(&table->use))
|
||||
return -EMFILE;
|
||||
|
||||
type = nft_obj_type_get(net, objtype);
|
||||
type = nft_obj_type_get(net, objtype, family);
|
||||
if (IS_ERR(type)) {
|
||||
err = PTR_ERR(type);
|
||||
goto err_type;
|
||||
|
@ -1250,7 +1250,31 @@ static int nft_ct_expect_obj_init(const struct nft_ctx *ctx,
|
||||
if (tb[NFTA_CT_EXPECT_L3PROTO])
|
||||
priv->l3num = ntohs(nla_get_be16(tb[NFTA_CT_EXPECT_L3PROTO]));
|
||||
|
||||
switch (priv->l3num) {
|
||||
case NFPROTO_IPV4:
|
||||
case NFPROTO_IPV6:
|
||||
if (priv->l3num != ctx->family)
|
||||
return -EINVAL;
|
||||
|
||||
fallthrough;
|
||||
case NFPROTO_INET:
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
priv->l4proto = nla_get_u8(tb[NFTA_CT_EXPECT_L4PROTO]);
|
||||
switch (priv->l4proto) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_UDPLITE:
|
||||
case IPPROTO_DCCP:
|
||||
case IPPROTO_SCTP:
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
priv->dport = nla_get_be16(tb[NFTA_CT_EXPECT_DPORT]);
|
||||
priv->timeout = nla_get_u32(tb[NFTA_CT_EXPECT_TIMEOUT]);
|
||||
priv->size = nla_get_u8(tb[NFTA_CT_EXPECT_SIZE]);
|
||||
|
@ -713,6 +713,7 @@ static const struct nft_object_ops nft_tunnel_obj_ops = {
|
||||
|
||||
static struct nft_object_type nft_tunnel_obj_type __read_mostly = {
|
||||
.type = NFT_OBJECT_TUNNEL,
|
||||
.family = NFPROTO_NETDEV,
|
||||
.ops = &nft_tunnel_obj_ops,
|
||||
.maxattr = NFTA_TUNNEL_KEY_MAX,
|
||||
.policy = nft_tunnel_key_policy,
|
||||
|
@ -1208,6 +1208,10 @@ void nci_free_device(struct nci_dev *ndev)
|
||||
{
|
||||
nfc_free_device(ndev->nfc_dev);
|
||||
nci_hci_deallocate(ndev);
|
||||
|
||||
/* drop partial rx data packet if present */
|
||||
if (ndev->rx_data_reassembly)
|
||||
kfree_skb(ndev->rx_data_reassembly);
|
||||
kfree(ndev);
|
||||
}
|
||||
EXPORT_SYMBOL(nci_free_device);
|
||||
|
@ -1877,9 +1877,15 @@ static bool smcd_lgr_match(struct smc_link_group *lgr,
|
||||
struct smcd_dev *smcismdev,
|
||||
struct smcd_gid *peer_gid)
|
||||
{
|
||||
return lgr->peer_gid.gid == peer_gid->gid && lgr->smcd == smcismdev &&
|
||||
smc_ism_is_virtual(smcismdev) ?
|
||||
(lgr->peer_gid.gid_ext == peer_gid->gid_ext) : 1;
|
||||
if (lgr->peer_gid.gid != peer_gid->gid ||
|
||||
lgr->smcd != smcismdev)
|
||||
return false;
|
||||
|
||||
if (smc_ism_is_virtual(smcismdev) &&
|
||||
lgr->peer_gid.gid_ext != peer_gid->gid_ext)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* create a new SMC connection (and a new link group if necessary) */
|
||||
|
@ -1344,13 +1344,11 @@ static void unix_state_double_lock(struct sock *sk1, struct sock *sk2)
|
||||
unix_state_lock(sk1);
|
||||
return;
|
||||
}
|
||||
if (sk1 < sk2) {
|
||||
unix_state_lock(sk1);
|
||||
unix_state_lock_nested(sk2);
|
||||
} else {
|
||||
unix_state_lock(sk2);
|
||||
unix_state_lock_nested(sk1);
|
||||
}
|
||||
if (sk1 > sk2)
|
||||
swap(sk1, sk2);
|
||||
|
||||
unix_state_lock(sk1);
|
||||
unix_state_lock_nested(sk2, U_LOCK_SECOND);
|
||||
}
|
||||
|
||||
static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2)
|
||||
@ -1591,7 +1589,7 @@ restart:
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
unix_state_lock_nested(sk);
|
||||
unix_state_lock_nested(sk, U_LOCK_SECOND);
|
||||
|
||||
if (sk->sk_state != st) {
|
||||
unix_state_unlock(sk);
|
||||
|
@ -84,7 +84,7 @@ static int sk_diag_dump_icons(struct sock *sk, struct sk_buff *nlskb)
|
||||
* queue lock. With the other's queue locked it's
|
||||
* OK to lock the state.
|
||||
*/
|
||||
unix_state_lock_nested(req);
|
||||
unix_state_lock_nested(req, U_LOCK_DIAG);
|
||||
peer = unix_sk(req)->peer;
|
||||
buf[i++] = (peer ? sock_i_ino(peer) : 0);
|
||||
unix_state_unlock(req);
|
||||
|
@ -48,6 +48,17 @@ test_LAG_cleanup()
|
||||
ip link add mv0 link "$name" up address "$ucaddr" type macvlan
|
||||
# Used to test dev->mc handling
|
||||
ip address add "$addr6" dev "$name"
|
||||
|
||||
# Check that addresses were added as expected
|
||||
(grep_bridge_fdb "$ucaddr" bridge fdb show dev dummy1 ||
|
||||
grep_bridge_fdb "$ucaddr" bridge fdb show dev dummy2) >/dev/null
|
||||
check_err $? "macvlan unicast address not found on a slave"
|
||||
|
||||
# mcaddr is added asynchronously by addrconf_dad_work(), use busywait
|
||||
(busywait 10000 grep_bridge_fdb "$mcaddr" bridge fdb show dev dummy1 ||
|
||||
grep_bridge_fdb "$mcaddr" bridge fdb show dev dummy2) >/dev/null
|
||||
check_err $? "IPv6 solicited-node multicast mac address not found on a slave"
|
||||
|
||||
ip link set dev "$name" down
|
||||
ip link del "$name"
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
CONFIG_DUMMY=y
|
||||
CONFIG_IPV6=y
|
||||
CONFIG_MACVLAN=y
|
||||
CONFIG_NET_TEAM=y
|
||||
CONFIG_NET_TEAM_MODE_LOADBALANCE=y
|
||||
CONFIG_MACVLAN=y
|
||||
|
@ -53,8 +53,7 @@ TEST_PROGS += bind_bhash.sh
|
||||
TEST_PROGS += ip_local_port_range.sh
|
||||
TEST_PROGS += rps_default_mask.sh
|
||||
TEST_PROGS += big_tcp.sh
|
||||
TEST_PROGS_EXTENDED := in_netns.sh setup_loopback.sh setup_veth.sh
|
||||
TEST_PROGS_EXTENDED += toeplitz_client.sh toeplitz.sh lib.sh
|
||||
TEST_PROGS_EXTENDED := toeplitz_client.sh toeplitz.sh
|
||||
TEST_GEN_FILES = socket nettest
|
||||
TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy reuseport_addr_any
|
||||
TEST_GEN_FILES += tcp_mmap tcp_inq psock_snd txring_overwrite
|
||||
@ -84,6 +83,7 @@ TEST_PROGS += sctp_vrf.sh
|
||||
TEST_GEN_FILES += sctp_hello
|
||||
TEST_GEN_FILES += csum
|
||||
TEST_GEN_FILES += nat6to4.o
|
||||
TEST_GEN_FILES += xdp_dummy.o
|
||||
TEST_GEN_FILES += ip_local_port_range
|
||||
TEST_GEN_FILES += bind_wildcard
|
||||
TEST_PROGS += test_vxlan_mdb.sh
|
||||
@ -95,6 +95,7 @@ TEST_PROGS += fq_band_pktlimit.sh
|
||||
TEST_PROGS += vlan_hw_filter.sh
|
||||
|
||||
TEST_FILES := settings
|
||||
TEST_FILES += in_netns.sh lib.sh net_helper.sh setup_loopback.sh setup_veth.sh
|
||||
|
||||
include ../lib.mk
|
||||
|
||||
@ -104,7 +105,7 @@ $(OUTPUT)/tcp_inq: LDLIBS += -lpthread
|
||||
$(OUTPUT)/bind_bhash: LDLIBS += -lpthread
|
||||
$(OUTPUT)/io_uring_zerocopy_tx: CFLAGS += -I../../../include/
|
||||
|
||||
# Rules to generate bpf obj nat6to4.o
|
||||
# Rules to generate bpf objs
|
||||
CLANG ?= clang
|
||||
SCRATCH_DIR := $(OUTPUT)/tools
|
||||
BUILD_DIR := $(SCRATCH_DIR)/build
|
||||
@ -139,7 +140,7 @@ endif
|
||||
|
||||
CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG),$(CLANG_TARGET_ARCH))
|
||||
|
||||
$(OUTPUT)/nat6to4.o: nat6to4.c $(BPFOBJ) | $(MAKE_DIRS)
|
||||
$(OUTPUT)/nat6to4.o $(OUTPUT)/xdp_dummy.o: $(OUTPUT)/%.o : %.c $(BPFOBJ) | $(MAKE_DIRS)
|
||||
$(CLANG) -O2 --target=bpf -c $< $(CCINCLUDE) $(CLANG_SYS_INCLUDES) -o $@
|
||||
|
||||
$(BPFOBJ): $(wildcard $(BPFDIR)/*.[ch] $(BPFDIR)/Makefile) \
|
||||
|
@ -19,8 +19,11 @@ CONFIG_BRIDGE_VLAN_FILTERING=y
|
||||
CONFIG_BRIDGE=y
|
||||
CONFIG_CRYPTO_CHACHA20POLY1305=m
|
||||
CONFIG_VLAN_8021Q=y
|
||||
CONFIG_GENEVE=m
|
||||
CONFIG_IFB=y
|
||||
CONFIG_INET_DIAG=y
|
||||
CONFIG_INET_ESP=y
|
||||
CONFIG_INET_ESP_OFFLOAD=y
|
||||
CONFIG_IP_GRE=m
|
||||
CONFIG_NETFILTER=y
|
||||
CONFIG_NETFILTER_ADVANCED=y
|
||||
@ -29,7 +32,10 @@ CONFIG_NF_NAT=m
|
||||
CONFIG_IP6_NF_IPTABLES=m
|
||||
CONFIG_IP_NF_IPTABLES=m
|
||||
CONFIG_IP6_NF_NAT=m
|
||||
CONFIG_IP6_NF_RAW=m
|
||||
CONFIG_IP_NF_NAT=m
|
||||
CONFIG_IP_NF_RAW=m
|
||||
CONFIG_IP_NF_TARGET_TTL=m
|
||||
CONFIG_IPV6_GRE=m
|
||||
CONFIG_IPV6_SEG6_LWTUNNEL=y
|
||||
CONFIG_L2TP_ETH=m
|
||||
@ -45,8 +51,14 @@ CONFIG_NF_TABLES=m
|
||||
CONFIG_NF_TABLES_IPV6=y
|
||||
CONFIG_NF_TABLES_IPV4=y
|
||||
CONFIG_NFT_NAT=m
|
||||
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
|
||||
CONFIG_NET_ACT_CSUM=m
|
||||
CONFIG_NET_ACT_CT=m
|
||||
CONFIG_NET_ACT_GACT=m
|
||||
CONFIG_NET_ACT_PEDIT=m
|
||||
CONFIG_NET_CLS_BASIC=m
|
||||
CONFIG_NET_CLS_BPF=m
|
||||
CONFIG_NET_CLS_MATCHALL=m
|
||||
CONFIG_NET_CLS_U32=m
|
||||
CONFIG_NET_IPGRE_DEMUX=m
|
||||
CONFIG_NET_IPGRE=m
|
||||
@ -55,6 +67,9 @@ CONFIG_NET_SCH_HTB=m
|
||||
CONFIG_NET_SCH_FQ=m
|
||||
CONFIG_NET_SCH_ETF=m
|
||||
CONFIG_NET_SCH_NETEM=y
|
||||
CONFIG_NET_SCH_PRIO=m
|
||||
CONFIG_NFT_COMPAT=m
|
||||
CONFIG_NF_FLOW_TABLE=m
|
||||
CONFIG_PSAMPLE=m
|
||||
CONFIG_TCP_MD5SIG=y
|
||||
CONFIG_TEST_BLACKHOLE_DEV=m
|
||||
@ -80,3 +95,4 @@ CONFIG_IP_SCTP=m
|
||||
CONFIG_NETFILTER_XT_MATCH_POLICY=m
|
||||
CONFIG_CRYPTO_ARIA=y
|
||||
CONFIG_XFRM_INTERFACE=m
|
||||
CONFIG_XFRM_USER=m
|
||||
|
@ -112,7 +112,7 @@ TEST_PROGS = bridge_fdb_learning_limit.sh \
|
||||
vxlan_symmetric_ipv6.sh \
|
||||
vxlan_symmetric.sh
|
||||
|
||||
TEST_PROGS_EXTENDED := devlink_lib.sh \
|
||||
TEST_FILES := devlink_lib.sh \
|
||||
ethtool_lib.sh \
|
||||
fib_offload_lib.sh \
|
||||
forwarding.config.sample \
|
||||
|
@ -4,6 +4,9 @@
|
||||
##############################################################################
|
||||
# Defines
|
||||
|
||||
WAIT_TIMEOUT=${WAIT_TIMEOUT:=20}
|
||||
BUSYWAIT_TIMEOUT=$((WAIT_TIMEOUT * 1000)) # ms
|
||||
|
||||
# Kselftest framework requirement - SKIP code is 4.
|
||||
ksft_skip=4
|
||||
# namespace list created by setup_ns
|
||||
@ -48,7 +51,7 @@ cleanup_ns()
|
||||
|
||||
for ns in "$@"; do
|
||||
ip netns delete "${ns}" &> /dev/null
|
||||
if ! busywait 2 ip netns list \| grep -vq "^$ns$" &> /dev/null; then
|
||||
if ! busywait $BUSYWAIT_TIMEOUT ip netns list \| grep -vq "^$ns$" &> /dev/null; then
|
||||
echo "Warn: Failed to remove namespace $ns"
|
||||
ret=1
|
||||
fi
|
||||
|
@ -22,8 +22,11 @@ CONFIG_NFT_TPROXY=m
|
||||
CONFIG_NFT_SOCKET=m
|
||||
CONFIG_IP_ADVANCED_ROUTER=y
|
||||
CONFIG_IP_MULTIPLE_TABLES=y
|
||||
CONFIG_IP_NF_FILTER=m
|
||||
CONFIG_IP_NF_MANGLE=m
|
||||
CONFIG_IP_NF_TARGET_REJECT=m
|
||||
CONFIG_IPV6_MULTIPLE_TABLES=y
|
||||
CONFIG_IP6_NF_FILTER=m
|
||||
CONFIG_NET_ACT_CSUM=m
|
||||
CONFIG_NET_ACT_PEDIT=m
|
||||
CONFIG_NET_CLS_ACT=y
|
||||
|
@ -643,13 +643,6 @@ kill_events_pids()
|
||||
mptcp_lib_kill_wait $evts_ns2_pid
|
||||
}
|
||||
|
||||
kill_tests_wait()
|
||||
{
|
||||
#shellcheck disable=SC2046
|
||||
kill -SIGUSR1 $(ip netns pids $ns2) $(ip netns pids $ns1)
|
||||
wait
|
||||
}
|
||||
|
||||
pm_nl_set_limits()
|
||||
{
|
||||
local ns=$1
|
||||
@ -3453,7 +3446,7 @@ userspace_tests()
|
||||
chk_mptcp_info subflows 0 subflows 0
|
||||
chk_subflows_total 1 1
|
||||
kill_events_pids
|
||||
wait $tests_pid
|
||||
mptcp_lib_kill_wait $tests_pid
|
||||
fi
|
||||
|
||||
# userspace pm create destroy subflow
|
||||
@ -3475,7 +3468,7 @@ userspace_tests()
|
||||
chk_mptcp_info subflows 0 subflows 0
|
||||
chk_subflows_total 1 1
|
||||
kill_events_pids
|
||||
wait $tests_pid
|
||||
mptcp_lib_kill_wait $tests_pid
|
||||
fi
|
||||
|
||||
# userspace pm create id 0 subflow
|
||||
@ -3494,7 +3487,7 @@ userspace_tests()
|
||||
chk_mptcp_info subflows 1 subflows 1
|
||||
chk_subflows_total 2 2
|
||||
kill_events_pids
|
||||
wait $tests_pid
|
||||
mptcp_lib_kill_wait $tests_pid
|
||||
fi
|
||||
|
||||
# userspace pm remove initial subflow
|
||||
@ -3518,7 +3511,7 @@ userspace_tests()
|
||||
chk_mptcp_info subflows 1 subflows 1
|
||||
chk_subflows_total 1 1
|
||||
kill_events_pids
|
||||
wait $tests_pid
|
||||
mptcp_lib_kill_wait $tests_pid
|
||||
fi
|
||||
|
||||
# userspace pm send RM_ADDR for ID 0
|
||||
@ -3544,7 +3537,7 @@ userspace_tests()
|
||||
chk_mptcp_info subflows 1 subflows 1
|
||||
chk_subflows_total 1 1
|
||||
kill_events_pids
|
||||
wait $tests_pid
|
||||
mptcp_lib_kill_wait $tests_pid
|
||||
fi
|
||||
}
|
||||
|
||||
@ -3558,7 +3551,8 @@ endpoint_tests()
|
||||
pm_nl_set_limits $ns2 2 2
|
||||
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
|
||||
speed=slow \
|
||||
run_tests $ns1 $ns2 10.0.1.1 2>/dev/null &
|
||||
run_tests $ns1 $ns2 10.0.1.1 &
|
||||
local tests_pid=$!
|
||||
|
||||
wait_mpj $ns1
|
||||
pm_nl_check_endpoint "creation" \
|
||||
@ -3573,7 +3567,7 @@ endpoint_tests()
|
||||
pm_nl_add_endpoint $ns2 10.0.2.2 flags signal
|
||||
pm_nl_check_endpoint "modif is allowed" \
|
||||
$ns2 10.0.2.2 id 1 flags signal
|
||||
kill_tests_wait
|
||||
mptcp_lib_kill_wait $tests_pid
|
||||
fi
|
||||
|
||||
if reset "delete and re-add" &&
|
||||
@ -3582,7 +3576,8 @@ endpoint_tests()
|
||||
pm_nl_set_limits $ns2 1 1
|
||||
pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow
|
||||
test_linkfail=4 speed=20 \
|
||||
run_tests $ns1 $ns2 10.0.1.1 2>/dev/null &
|
||||
run_tests $ns1 $ns2 10.0.1.1 &
|
||||
local tests_pid=$!
|
||||
|
||||
wait_mpj $ns2
|
||||
chk_subflow_nr "before delete" 2
|
||||
@ -3597,7 +3592,7 @@ endpoint_tests()
|
||||
wait_mpj $ns2
|
||||
chk_subflow_nr "after re-add" 2
|
||||
chk_mptcp_info subflows 1 subflows 1
|
||||
kill_tests_wait
|
||||
mptcp_lib_kill_wait $tests_pid
|
||||
fi
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ readonly KSFT_FAIL=1
|
||||
readonly KSFT_SKIP=4
|
||||
|
||||
# shellcheck disable=SC2155 # declare and assign separately
|
||||
readonly KSFT_TEST=$(basename "${0}" | sed 's/\.sh$//g')
|
||||
readonly KSFT_TEST="${MPTCP_LIB_KSFT_TEST:-$(basename "${0}" .sh)}"
|
||||
|
||||
MPTCP_LIB_SUBTESTS=()
|
||||
|
||||
|
@ -1 +1 @@
|
||||
timeout=1200
|
||||
timeout=1800
|
||||
|
@ -284,12 +284,12 @@ done
|
||||
|
||||
setup
|
||||
run_test 10 10 0 0 "balanced bwidth"
|
||||
run_test 10 10 1 50 "balanced bwidth with unbalanced delay"
|
||||
run_test 10 10 1 25 "balanced bwidth with unbalanced delay"
|
||||
|
||||
# we still need some additional infrastructure to pass the following test-cases
|
||||
run_test 30 10 0 0 "unbalanced bwidth"
|
||||
run_test 30 10 1 50 "unbalanced bwidth with unbalanced delay"
|
||||
run_test 30 10 50 1 "unbalanced bwidth with opposed, unbalanced delay"
|
||||
run_test 10 3 0 0 "unbalanced bwidth"
|
||||
run_test 10 3 1 25 "unbalanced bwidth with unbalanced delay"
|
||||
run_test 10 3 25 1 "unbalanced bwidth with opposed, unbalanced delay"
|
||||
|
||||
mptcp_lib_result_print_all_tap
|
||||
exit $ret
|
||||
|
0
tools/testing/selftests/net/net_helper.sh
Executable file → Normal file
0
tools/testing/selftests/net/net_helper.sh
Executable file → Normal file
@ -707,23 +707,23 @@ setup_xfrm6() {
|
||||
}
|
||||
|
||||
setup_xfrm4udp() {
|
||||
setup_xfrm 4 ${veth4_a_addr} ${veth4_b_addr} "encap espinudp 4500 4500 0.0.0.0"
|
||||
setup_nettest_xfrm 4 4500
|
||||
setup_xfrm 4 ${veth4_a_addr} ${veth4_b_addr} "encap espinudp 4500 4500 0.0.0.0" && \
|
||||
setup_nettest_xfrm 4 4500
|
||||
}
|
||||
|
||||
setup_xfrm6udp() {
|
||||
setup_xfrm 6 ${veth6_a_addr} ${veth6_b_addr} "encap espinudp 4500 4500 0.0.0.0"
|
||||
setup_nettest_xfrm 6 4500
|
||||
setup_xfrm 6 ${veth6_a_addr} ${veth6_b_addr} "encap espinudp 4500 4500 0.0.0.0" && \
|
||||
setup_nettest_xfrm 6 4500
|
||||
}
|
||||
|
||||
setup_xfrm4udprouted() {
|
||||
setup_xfrm 4 ${prefix4}.${a_r1}.1 ${prefix4}.${b_r1}.1 "encap espinudp 4500 4500 0.0.0.0"
|
||||
setup_nettest_xfrm 4 4500
|
||||
setup_xfrm 4 ${prefix4}.${a_r1}.1 ${prefix4}.${b_r1}.1 "encap espinudp 4500 4500 0.0.0.0" && \
|
||||
setup_nettest_xfrm 4 4500
|
||||
}
|
||||
|
||||
setup_xfrm6udprouted() {
|
||||
setup_xfrm 6 ${prefix6}:${a_r1}::1 ${prefix6}:${b_r1}::1 "encap espinudp 4500 4500 0.0.0.0"
|
||||
setup_nettest_xfrm 6 4500
|
||||
setup_xfrm 6 ${prefix6}:${a_r1}::1 ${prefix6}:${b_r1}::1 "encap espinudp 4500 4500 0.0.0.0" && \
|
||||
setup_nettest_xfrm 6 4500
|
||||
}
|
||||
|
||||
setup_routing_old() {
|
||||
@ -1339,7 +1339,7 @@ test_pmtu_ipvX_over_bridged_vxlanY_or_geneveY_exception() {
|
||||
|
||||
sleep 1
|
||||
|
||||
dd if=/dev/zero of=/dev/stdout status=none bs=1M count=1 | ${target} socat -T 3 -u STDIN $TCPDST,connect-timeout=3
|
||||
dd if=/dev/zero status=none bs=1M count=1 | ${target} socat -T 3 -u STDIN $TCPDST,connect-timeout=3
|
||||
|
||||
size=$(du -sb $tmpoutfile)
|
||||
size=${size%%/tmp/*}
|
||||
|
0
tools/testing/selftests/net/setup_loopback.sh
Executable file → Normal file
0
tools/testing/selftests/net/setup_loopback.sh
Executable file → Normal file
@ -11,7 +11,7 @@ setup_veth_ns() {
|
||||
local -r ns_mac="$4"
|
||||
|
||||
[[ -e /var/run/netns/"${ns_name}" ]] || ip netns add "${ns_name}"
|
||||
echo 100000 > "/sys/class/net/${ns_dev}/gro_flush_timeout"
|
||||
echo 1000000 > "/sys/class/net/${ns_dev}/gro_flush_timeout"
|
||||
ip link set dev "${ns_dev}" netns "${ns_name}" mtu 65535
|
||||
ip -netns "${ns_name}" link set dev "${ns_dev}" up
|
||||
|
||||
|
10
tools/testing/selftests/net/tcp_ao/config
Normal file
10
tools/testing/selftests/net/tcp_ao/config
Normal file
@ -0,0 +1,10 @@
|
||||
CONFIG_CRYPTO_HMAC=y
|
||||
CONFIG_CRYPTO_RMD160=y
|
||||
CONFIG_CRYPTO_SHA1=y
|
||||
CONFIG_IPV6_MULTIPLE_TABLES=y
|
||||
CONFIG_IPV6=y
|
||||
CONFIG_NET_L3_MASTER_DEV=y
|
||||
CONFIG_NET_VRF=y
|
||||
CONFIG_TCP_AO=y
|
||||
CONFIG_TCP_MD5SIG=y
|
||||
CONFIG_VETH=m
|
@ -417,9 +417,9 @@ struct test_key {
|
||||
matches_vrf : 1,
|
||||
is_current : 1,
|
||||
is_rnext : 1,
|
||||
used_on_handshake : 1,
|
||||
used_after_accept : 1,
|
||||
used_on_client : 1;
|
||||
used_on_server_tx : 1,
|
||||
used_on_client_tx : 1,
|
||||
skip_counters_checks : 1;
|
||||
};
|
||||
|
||||
struct key_collection {
|
||||
@ -609,16 +609,14 @@ static int key_collection_socket(bool server, unsigned int port)
|
||||
addr = &this_ip_dest;
|
||||
sndid = key->client_keyid;
|
||||
rcvid = key->server_keyid;
|
||||
set_current = key->is_current;
|
||||
set_rnext = key->is_rnext;
|
||||
key->used_on_client_tx = set_current = key->is_current;
|
||||
key->used_on_server_tx = set_rnext = key->is_rnext;
|
||||
}
|
||||
|
||||
if (test_add_key_cr(sk, key->password, key->len,
|
||||
*addr, vrf, sndid, rcvid, key->maclen,
|
||||
key->alg, set_current, set_rnext))
|
||||
test_key_error("setsockopt(TCP_AO_ADD_KEY)", key);
|
||||
if (set_current || set_rnext)
|
||||
key->used_on_handshake = 1;
|
||||
#ifdef DEBUG
|
||||
test_print("%s [%u/%u] key: { %s, %u:%u, %u, %u:%u:%u:%u (%u)}",
|
||||
server ? "server" : "client", i, collection.nr_keys,
|
||||
@ -640,22 +638,22 @@ static void verify_counters(const char *tst_name, bool is_listen_sk, bool server
|
||||
for (i = 0; i < collection.nr_keys; i++) {
|
||||
struct test_key *key = &collection.keys[i];
|
||||
uint8_t sndid, rcvid;
|
||||
bool was_used;
|
||||
bool rx_cnt_expected;
|
||||
|
||||
if (key->skip_counters_checks)
|
||||
continue;
|
||||
if (server) {
|
||||
sndid = key->server_keyid;
|
||||
rcvid = key->client_keyid;
|
||||
if (is_listen_sk)
|
||||
was_used = key->used_on_handshake;
|
||||
else
|
||||
was_used = key->used_after_accept;
|
||||
rx_cnt_expected = key->used_on_client_tx;
|
||||
} else {
|
||||
sndid = key->client_keyid;
|
||||
rcvid = key->server_keyid;
|
||||
was_used = key->used_on_client;
|
||||
rx_cnt_expected = key->used_on_server_tx;
|
||||
}
|
||||
|
||||
test_tcp_ao_key_counters_cmp(tst_name, a, b, was_used,
|
||||
test_tcp_ao_key_counters_cmp(tst_name, a, b,
|
||||
rx_cnt_expected ? TEST_CNT_KEY_GOOD : 0,
|
||||
sndid, rcvid);
|
||||
}
|
||||
test_tcp_ao_counters_free(a);
|
||||
@ -843,7 +841,7 @@ static void end_server(const char *tst_name, int sk,
|
||||
synchronize_threads(); /* 4: verified => closed */
|
||||
close(sk);
|
||||
|
||||
verify_counters(tst_name, true, false, begin, &end);
|
||||
verify_counters(tst_name, false, true, begin, &end);
|
||||
synchronize_threads(); /* 5: counters */
|
||||
}
|
||||
|
||||
@ -916,9 +914,8 @@ static int run_client(const char *tst_name, unsigned int port,
|
||||
current_index = nr_keys - 1;
|
||||
if (rnext_index < 0)
|
||||
rnext_index = nr_keys - 1;
|
||||
collection.keys[current_index].used_on_handshake = 1;
|
||||
collection.keys[rnext_index].used_after_accept = 1;
|
||||
collection.keys[rnext_index].used_on_client = 1;
|
||||
collection.keys[current_index].used_on_client_tx = 1;
|
||||
collection.keys[rnext_index].used_on_server_tx = 1;
|
||||
|
||||
synchronize_threads(); /* 3: accepted => send data */
|
||||
if (test_client_verify(sk, msg_sz, msg_nr, TEST_TIMEOUT_SEC)) {
|
||||
@ -1059,7 +1056,16 @@ static void check_current_back(const char *tst_name, unsigned int port,
|
||||
test_error("Can't change the current key");
|
||||
if (test_client_verify(sk, msg_len, nr_packets, TEST_TIMEOUT_SEC))
|
||||
test_fail("verify failed");
|
||||
collection.keys[rotate_to_index].used_after_accept = 1;
|
||||
/* There is a race here: between setting the current_key with
|
||||
* setsockopt(TCP_AO_INFO) and starting to send some data - there
|
||||
* might have been a segment received with the desired
|
||||
* RNext_key set. In turn that would mean that the first outgoing
|
||||
* segment will have the desired current_key (flipped back).
|
||||
* Which is what the user/test wants. As it's racy, skip checking
|
||||
* the counters, yet check what are the resulting current/rnext
|
||||
* keys on both sides.
|
||||
*/
|
||||
collection.keys[rotate_to_index].skip_counters_checks = 1;
|
||||
|
||||
end_client(tst_name, sk, nr_keys, current_index, rnext_index, &tmp);
|
||||
}
|
||||
@ -1089,7 +1095,7 @@ static void roll_over_keys(const char *tst_name, unsigned int port,
|
||||
}
|
||||
verify_current_rnext(tst_name, sk, -1,
|
||||
collection.keys[i].server_keyid);
|
||||
collection.keys[i].used_on_client = 1;
|
||||
collection.keys[i].used_on_server_tx = 1;
|
||||
synchronize_threads(); /* verify current/rnext */
|
||||
}
|
||||
end_client(tst_name, sk, nr_keys, current_index, rnext_index, &tmp);
|
||||
|
@ -62,7 +62,9 @@ int test_wait_fd(int sk, time_t sec, bool write)
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &slen) || ret)
|
||||
if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &slen))
|
||||
return -errno;
|
||||
if (ret)
|
||||
return -ret;
|
||||
return 0;
|
||||
}
|
||||
@ -584,9 +586,11 @@ int test_client_verify(int sk, const size_t msg_len, const size_t nr,
|
||||
{
|
||||
size_t buf_sz = msg_len * nr;
|
||||
char *buf = alloca(buf_sz);
|
||||
ssize_t ret;
|
||||
|
||||
randomize_buffer(buf, buf_sz);
|
||||
if (test_client_loop(sk, buf, buf_sz, msg_len, timeout_sec) != buf_sz)
|
||||
return -1;
|
||||
return 0;
|
||||
ret = test_client_loop(sk, buf, buf_sz, msg_len, timeout_sec);
|
||||
if (ret < 0)
|
||||
return (int)ret;
|
||||
return ret != buf_sz ? -1 : 0;
|
||||
}
|
||||
|
@ -1,10 +1,33 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Author: Dmitry Safonov <dima@arista.com> */
|
||||
/*
|
||||
* The test checks that both active and passive reset have correct TCP-AO
|
||||
* signature. An "active" reset (abort) here is procured from closing
|
||||
* listen() socket with non-accepted connections in the queue:
|
||||
* inet_csk_listen_stop() => inet_child_forget() =>
|
||||
* => tcp_disconnect() => tcp_send_active_reset()
|
||||
*
|
||||
* The passive reset is quite hard to get on established TCP connections.
|
||||
* It could be procured from non-established states, but the synchronization
|
||||
* part from userspace in order to reliably get RST seems uneasy.
|
||||
* So, instead it's procured by corrupting SEQ number on TIMED-WAIT state.
|
||||
*
|
||||
* It's important to test both passive and active RST as they go through
|
||||
* different code-paths:
|
||||
* - tcp_send_active_reset() makes no-data skb, sends it with tcp_transmit_skb()
|
||||
* - tcp_v*_send_reset() create their reply skbs and send them with
|
||||
* ip_send_unicast_reply()
|
||||
*
|
||||
* In both cases TCP-AO signatures have to be correct, which is verified by
|
||||
* (1) checking that the TCP-AO connection was reset and (2) TCP-AO counters.
|
||||
*
|
||||
* Author: Dmitry Safonov <dima@arista.com>
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include "../../../../include/linux/kernel.h"
|
||||
#include "aolib.h"
|
||||
|
||||
const size_t quota = 1000;
|
||||
const size_t packet_sz = 100;
|
||||
/*
|
||||
* Backlog == 0 means 1 connection in queue, see:
|
||||
* commit 64a146513f8f ("[NET]: Revert incorrect accept queue...")
|
||||
@ -59,26 +82,6 @@ static void close_forced(int sk)
|
||||
close(sk);
|
||||
}
|
||||
|
||||
static int test_wait_for_exception(int sk, time_t sec)
|
||||
{
|
||||
struct timeval tv = { .tv_sec = sec };
|
||||
struct timeval *ptv = NULL;
|
||||
fd_set efds;
|
||||
int ret;
|
||||
|
||||
FD_ZERO(&efds);
|
||||
FD_SET(sk, &efds);
|
||||
|
||||
if (sec)
|
||||
ptv = &tv;
|
||||
|
||||
errno = 0;
|
||||
ret = select(sk + 1, NULL, NULL, &efds, ptv);
|
||||
if (ret < 0)
|
||||
return -errno;
|
||||
return ret ? sk : 0;
|
||||
}
|
||||
|
||||
static void test_server_active_rst(unsigned int port)
|
||||
{
|
||||
struct tcp_ao_counters cnt1, cnt2;
|
||||
@ -155,17 +158,16 @@ static void test_server_passive_rst(unsigned int port)
|
||||
test_fail("server returned %zd", bytes);
|
||||
}
|
||||
|
||||
synchronize_threads(); /* 3: chekpoint/restore the connection */
|
||||
synchronize_threads(); /* 3: checkpoint the client */
|
||||
synchronize_threads(); /* 4: close the server, creating twsk */
|
||||
if (test_get_tcp_ao_counters(sk, &ao2))
|
||||
test_error("test_get_tcp_ao_counters()");
|
||||
|
||||
synchronize_threads(); /* 4: terminate server + send more on client */
|
||||
bytes = test_server_run(sk, quota, TEST_RETRANSMIT_SEC);
|
||||
close(sk);
|
||||
|
||||
synchronize_threads(); /* 5: restore the socket, send more data */
|
||||
test_tcp_ao_counters_cmp("passive RST server", &ao1, &ao2, TEST_CNT_GOOD);
|
||||
|
||||
synchronize_threads(); /* 5: verified => closed */
|
||||
close(sk);
|
||||
synchronize_threads(); /* 6: server exits */
|
||||
}
|
||||
|
||||
static void *server_fn(void *arg)
|
||||
@ -284,7 +286,7 @@ static void test_client_active_rst(unsigned int port)
|
||||
test_error("test_wait_fds(): %d", err);
|
||||
|
||||
synchronize_threads(); /* 3: close listen socket */
|
||||
if (test_client_verify(sk[0], 100, quota / 100, TEST_TIMEOUT_SEC))
|
||||
if (test_client_verify(sk[0], packet_sz, quota / packet_sz, TEST_TIMEOUT_SEC))
|
||||
test_fail("Failed to send data on connected socket");
|
||||
else
|
||||
test_ok("Verified established tcp connection");
|
||||
@ -323,7 +325,6 @@ static void test_client_passive_rst(unsigned int port)
|
||||
struct tcp_sock_state img;
|
||||
sockaddr_af saddr;
|
||||
int sk, err;
|
||||
socklen_t slen = sizeof(err);
|
||||
|
||||
sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (sk < 0)
|
||||
@ -337,18 +338,51 @@ static void test_client_passive_rst(unsigned int port)
|
||||
test_error("failed to connect()");
|
||||
|
||||
synchronize_threads(); /* 2: accepted => send data */
|
||||
if (test_client_verify(sk, 100, quota / 100, TEST_TIMEOUT_SEC))
|
||||
if (test_client_verify(sk, packet_sz, quota / packet_sz, TEST_TIMEOUT_SEC))
|
||||
test_fail("Failed to send data on connected socket");
|
||||
else
|
||||
test_ok("Verified established tcp connection");
|
||||
|
||||
synchronize_threads(); /* 3: chekpoint/restore the connection */
|
||||
synchronize_threads(); /* 3: checkpoint the client */
|
||||
test_enable_repair(sk);
|
||||
test_sock_checkpoint(sk, &img, &saddr);
|
||||
test_ao_checkpoint(sk, &ao_img);
|
||||
test_kill_sk(sk);
|
||||
test_disable_repair(sk);
|
||||
|
||||
img.out.seq += quota;
|
||||
synchronize_threads(); /* 4: close the server, creating twsk */
|
||||
|
||||
/*
|
||||
* The "corruption" in SEQ has to be small enough to fit into TCP
|
||||
* window, see tcp_timewait_state_process() for out-of-window
|
||||
* segments.
|
||||
*/
|
||||
img.out.seq += 5; /* 5 is more noticeable in tcpdump than 1 */
|
||||
|
||||
/*
|
||||
* FIXME: This is kind-of ugly and dirty, but it works.
|
||||
*
|
||||
* At this moment, the server has close'ed(sk).
|
||||
* The passive RST that is being targeted here is new data after
|
||||
* half-duplex close, see tcp_timewait_state_process() => TCP_TW_RST
|
||||
*
|
||||
* What is needed here is:
|
||||
* (1) wait for FIN from the server
|
||||
* (2) make sure that the ACK from the client went out
|
||||
* (3) make sure that the ACK was received and processed by the server
|
||||
*
|
||||
* Otherwise, the data that will be sent from "repaired" socket
|
||||
* post SEQ corruption may get to the server before it's in
|
||||
* TCP_FIN_WAIT2.
|
||||
*
|
||||
* (1) is easy with select()/poll()
|
||||
* (2) is possible by polling tcpi_state from TCP_INFO
|
||||
* (3) is quite complex: as server's socket was already closed,
|
||||
* probably the way to do it would be tcp-diag.
|
||||
*/
|
||||
sleep(TEST_RETRANSMIT_SEC);
|
||||
|
||||
synchronize_threads(); /* 5: restore the socket, send more data */
|
||||
test_kill_sk(sk);
|
||||
|
||||
sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (sk < 0)
|
||||
@ -366,25 +400,33 @@ static void test_client_passive_rst(unsigned int port)
|
||||
test_disable_repair(sk);
|
||||
test_sock_state_free(&img);
|
||||
|
||||
synchronize_threads(); /* 4: terminate server + send more on client */
|
||||
if (test_client_verify(sk, 100, quota / 100, 2 * TEST_TIMEOUT_SEC))
|
||||
test_ok("client connection broken post-seq-adjust");
|
||||
/*
|
||||
* This is how "passive reset" is acquired in this test from TCP_TW_RST:
|
||||
*
|
||||
* IP 10.0.254.1.7011 > 10.0.1.1.59772: Flags [P.], seq 901:1001, ack 1001, win 249,
|
||||
* options [tcp-ao keyid 100 rnextkeyid 100 mac 0x10217d6c36a22379086ef3b1], length 100
|
||||
* IP 10.0.254.1.7011 > 10.0.1.1.59772: Flags [F.], seq 1001, ack 1001, win 249,
|
||||
* options [tcp-ao keyid 100 rnextkeyid 100 mac 0x104ffc99b98c10a5298cc268], length 0
|
||||
* IP 10.0.1.1.59772 > 10.0.254.1.7011: Flags [.], ack 1002, win 251,
|
||||
* options [tcp-ao keyid 100 rnextkeyid 100 mac 0xe496dd4f7f5a8a66873c6f93,nop,nop,sack 1 {1001:1002}], length 0
|
||||
* IP 10.0.1.1.59772 > 10.0.254.1.7011: Flags [P.], seq 1006:1106, ack 1001, win 251,
|
||||
* options [tcp-ao keyid 100 rnextkeyid 100 mac 0x1b5f3330fb23fbcd0c77d0ca], length 100
|
||||
* IP 10.0.254.1.7011 > 10.0.1.1.59772: Flags [R], seq 3215596252, win 0,
|
||||
* options [tcp-ao keyid 100 rnextkeyid 100 mac 0x0bcfbbf497bce844312304b2], length 0
|
||||
*/
|
||||
err = test_client_verify(sk, packet_sz, quota / packet_sz, 2 * TEST_TIMEOUT_SEC);
|
||||
/* Make sure that the connection was reset, not timeouted */
|
||||
if (err && err == -ECONNRESET)
|
||||
test_ok("client sock was passively reset post-seq-adjust");
|
||||
else if (err)
|
||||
test_fail("client sock was not reset post-seq-adjust: %d", err);
|
||||
else
|
||||
test_fail("client connection still works post-seq-adjust");
|
||||
|
||||
test_wait_for_exception(sk, TEST_TIMEOUT_SEC);
|
||||
|
||||
if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &err, &slen))
|
||||
test_error("getsockopt()");
|
||||
if (err != ECONNRESET && err != EPIPE)
|
||||
test_fail("client connection was not reset: %d", err);
|
||||
else
|
||||
test_ok("client connection was reset");
|
||||
test_fail("client sock is yet connected post-seq-adjust");
|
||||
|
||||
if (test_get_tcp_ao_counters(sk, &ao2))
|
||||
test_error("test_get_tcp_ao_counters()");
|
||||
|
||||
synchronize_threads(); /* 5: verified => closed */
|
||||
synchronize_threads(); /* 6: server exits */
|
||||
close(sk);
|
||||
test_tcp_ao_counters_cmp("client passive RST", &ao1, &ao2, TEST_CNT_GOOD);
|
||||
}
|
||||
@ -410,6 +452,6 @@ static void *client_fn(void *arg)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
test_init(15, server_fn, client_fn);
|
||||
test_init(14, server_fn, client_fn);
|
||||
return 0;
|
||||
}
|
||||
|
1
tools/testing/selftests/net/tcp_ao/settings
Normal file
1
tools/testing/selftests/net/tcp_ao/settings
Normal file
@ -0,0 +1 @@
|
||||
timeout=120
|
@ -7,7 +7,7 @@ source net_helper.sh
|
||||
|
||||
readonly PEER_NS="ns-peer-$(mktemp -u XXXXXX)"
|
||||
|
||||
BPF_FILE="../bpf/xdp_dummy.bpf.o"
|
||||
BPF_FILE="xdp_dummy.o"
|
||||
|
||||
# set global exit status, but never reset nonzero one.
|
||||
check_err()
|
||||
@ -197,7 +197,7 @@ run_all() {
|
||||
}
|
||||
|
||||
if [ ! -f ${BPF_FILE} ]; then
|
||||
echo "Missing ${BPF_FILE}. Build bpf selftest first"
|
||||
echo "Missing ${BPF_FILE}. Run 'make' first"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
|
@ -7,7 +7,7 @@ source net_helper.sh
|
||||
|
||||
readonly PEER_NS="ns-peer-$(mktemp -u XXXXXX)"
|
||||
|
||||
BPF_FILE="../bpf/xdp_dummy.bpf.o"
|
||||
BPF_FILE="xdp_dummy.o"
|
||||
|
||||
cleanup() {
|
||||
local -r jobs="$(jobs -p)"
|
||||
@ -84,7 +84,7 @@ run_all() {
|
||||
}
|
||||
|
||||
if [ ! -f ${BPF_FILE} ]; then
|
||||
echo "Missing ${BPF_FILE}. Build bpf selftest first"
|
||||
echo "Missing ${BPF_FILE}. Run 'make' first"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
|
@ -7,7 +7,7 @@ source net_helper.sh
|
||||
|
||||
readonly PEER_NS="ns-peer-$(mktemp -u XXXXXX)"
|
||||
|
||||
BPF_FILE="../bpf/xdp_dummy.bpf.o"
|
||||
BPF_FILE="xdp_dummy.o"
|
||||
|
||||
cleanup() {
|
||||
local -r jobs="$(jobs -p)"
|
||||
@ -85,12 +85,12 @@ run_all() {
|
||||
}
|
||||
|
||||
if [ ! -f ${BPF_FILE} ]; then
|
||||
echo "Missing ${BPF_FILE}. Build bpf selftest first"
|
||||
echo "Missing ${BPF_FILE}. Run 'make' first"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
if [ ! -f nat6to4.o ]; then
|
||||
echo "Missing nat6to4 helper. Build bpf nat6to4.o selftest first"
|
||||
echo "Missing nat6to4 helper. Run 'make' first"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
BPF_FILE="../bpf/xdp_dummy.bpf.o"
|
||||
source net_helper.sh
|
||||
|
||||
BPF_FILE="xdp_dummy.o"
|
||||
readonly BASE="ns-$(mktemp -u XXXXXX)"
|
||||
readonly SRC=2
|
||||
readonly DST=1
|
||||
@ -119,7 +121,7 @@ run_test() {
|
||||
ip netns exec $NS_DST $ipt -A INPUT -p udp --dport 8000
|
||||
ip netns exec $NS_DST ./udpgso_bench_rx -C 1000 -R 10 -n 10 -l 1300 $rx_args &
|
||||
local spid=$!
|
||||
sleep 0.1
|
||||
wait_local_port_listen "$NS_DST" 8000 udp
|
||||
ip netns exec $NS_SRC ./udpgso_bench_tx $family -M 1 -s 13000 -S 1300 -D $dst
|
||||
local retc=$?
|
||||
wait $spid
|
||||
@ -168,7 +170,7 @@ run_bench() {
|
||||
ip netns exec $NS_DST bash -c "echo 2 > /sys/class/net/veth$DST/queues/rx-0/rps_cpus"
|
||||
ip netns exec $NS_DST taskset 0x2 ./udpgso_bench_rx -C 1000 -R 10 &
|
||||
local spid=$!
|
||||
sleep 0.1
|
||||
wait_local_port_listen "$NS_DST" 8000 udp
|
||||
ip netns exec $NS_SRC taskset 0x1 ./udpgso_bench_tx $family -l 3 -S 1300 -D $dst
|
||||
local retc=$?
|
||||
wait $spid
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
BPF_FILE="../bpf/xdp_dummy.bpf.o"
|
||||
BPF_FILE="xdp_dummy.o"
|
||||
readonly STATS="$(mktemp -p /tmp ns-XXXXXX)"
|
||||
readonly BASE=`basename $STATS`
|
||||
readonly SRC=2
|
||||
@ -218,7 +218,7 @@ while getopts "hs:" option; do
|
||||
done
|
||||
|
||||
if [ ! -f ${BPF_FILE} ]; then
|
||||
echo "Missing ${BPF_FILE}. Build bpf selftest first"
|
||||
echo "Missing ${BPF_FILE}. Run 'make' first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
13
tools/testing/selftests/net/xdp_dummy.c
Normal file
13
tools/testing/selftests/net/xdp_dummy.c
Normal file
@ -0,0 +1,13 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#define KBUILD_MODNAME "xdp_dummy"
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
SEC("xdp")
|
||||
int xdp_dummy_prog(struct xdp_md *ctx)
|
||||
{
|
||||
return XDP_PASS;
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
Loading…
Reference in New Issue
Block a user