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:
Linus Torvalds 2024-02-01 12:39:54 -08:00
commit 41b9fb381a
90 changed files with 845 additions and 409 deletions

View file

@ -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 Date: March 2010
KernelVersion: 2.6.35 KernelVersion: 2.6.35
Contact: netdev@vger.kernel.org Contact: netdev@vger.kernel.org
@ -8,7 +8,7 @@ Description:
network device queue. Possible values depend on the number network device queue. Possible values depend on the number
of available CPU(s) in the system. 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 Date: April 2010
KernelVersion: 2.6.35 KernelVersion: 2.6.35
Contact: netdev@vger.kernel.org Contact: netdev@vger.kernel.org
@ -16,7 +16,7 @@ Description:
Number of Receive Packet Steering flows being currently Number of Receive Packet Steering flows being currently
processed by this particular network device receive queue. 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 Date: November 2011
KernelVersion: 3.3 KernelVersion: 3.3
Contact: netdev@vger.kernel.org Contact: netdev@vger.kernel.org
@ -24,7 +24,7 @@ Description:
Indicates the number of transmit timeout events seen by this Indicates the number of transmit timeout events seen by this
network interface transmit queue. 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 Date: March 2015
KernelVersion: 4.1 KernelVersion: 4.1
Contact: netdev@vger.kernel.org Contact: netdev@vger.kernel.org
@ -32,7 +32,7 @@ Description:
A Mbps max-rate set for the queue, a value of zero means disabled, A Mbps max-rate set for the queue, a value of zero means disabled,
default is 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 Date: November 2010
KernelVersion: 2.6.38 KernelVersion: 2.6.38
Contact: netdev@vger.kernel.org Contact: netdev@vger.kernel.org
@ -42,7 +42,7 @@ Description:
network device transmit queue. Possible values depend on the network device transmit queue. Possible values depend on the
number of available CPU(s) in the system. 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 Date: June 2018
KernelVersion: 4.18.0 KernelVersion: 4.18.0
Contact: netdev@vger.kernel.org Contact: netdev@vger.kernel.org
@ -53,7 +53,7 @@ Description:
number of available receive queue(s) in the network device. number of available receive queue(s) in the network device.
Default is disabled. 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 Date: November 2011
KernelVersion: 3.3 KernelVersion: 3.3
Contact: netdev@vger.kernel.org Contact: netdev@vger.kernel.org
@ -62,7 +62,7 @@ Description:
of this particular network device transmit queue. of this particular network device transmit queue.
Default value is 1000. 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 Date: November 2011
KernelVersion: 3.3 KernelVersion: 3.3
Contact: netdev@vger.kernel.org Contact: netdev@vger.kernel.org
@ -70,7 +70,7 @@ Description:
Indicates the number of bytes (objects) in flight on this Indicates the number of bytes (objects) in flight on this
network device transmit queue. 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 Date: November 2011
KernelVersion: 3.3 KernelVersion: 3.3
Contact: netdev@vger.kernel.org Contact: netdev@vger.kernel.org
@ -79,7 +79,7 @@ Description:
on this network device transmit queue. This value is clamped on this network device transmit queue. This value is clamped
to be within the bounds defined by limit_max and limit_min. 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 Date: November 2011
KernelVersion: 3.3 KernelVersion: 3.3
Contact: netdev@vger.kernel.org Contact: netdev@vger.kernel.org
@ -88,7 +88,7 @@ Description:
queued on this network device transmit queue. See queued on this network device transmit queue. See
include/linux/dynamic_queue_limits.h for the default value. 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 Date: November 2011
KernelVersion: 3.3 KernelVersion: 3.3
Contact: netdev@vger.kernel.org Contact: netdev@vger.kernel.org

View file

@ -942,6 +942,10 @@ attribute-sets:
- -
name: gro-ipv4-max-size name: gro-ipv4-max-size
type: u32 type: u32
-
name: dpll-pin
type: nest
nested-attributes: link-dpll-pin-attrs
- -
name: af-spec-attrs name: af-spec-attrs
attributes: attributes:
@ -1627,6 +1631,12 @@ attribute-sets:
- -
name: used name: used
type: u8 type: u8
-
name: link-dpll-pin-attrs
attributes:
-
name: id
type: u32
sub-messages: sub-messages:
- -

View file

@ -15181,6 +15181,7 @@ F: Documentation/networking/net_cachelines/net_device.rst
F: drivers/connector/ F: drivers/connector/
F: drivers/net/ F: drivers/net/
F: include/dt-bindings/net/ F: include/dt-bindings/net/
F: include/linux/cn_proc.h
F: include/linux/etherdevice.h F: include/linux/etherdevice.h
F: include/linux/fcdevice.h F: include/linux/fcdevice.h
F: include/linux/fddidevice.h F: include/linux/fddidevice.h
@ -15188,6 +15189,7 @@ F: include/linux/hippidevice.h
F: include/linux/if_* F: include/linux/if_*
F: include/linux/inetdevice.h F: include/linux/inetdevice.h
F: include/linux/netdevice.h F: include/linux/netdevice.h
F: include/uapi/linux/cn_proc.h
F: include/uapi/linux/if_* F: include/uapi/linux/if_*
F: include/uapi/linux/netdevice.h F: include/uapi/linux/netdevice.h
X: drivers/net/wireless/ X: drivers/net/wireless/
@ -18085,7 +18087,6 @@ F: drivers/net/ethernet/qualcomm/emac/
QUALCOMM ETHQOS ETHERNET DRIVER QUALCOMM ETHQOS ETHERNET DRIVER
M: Vinod Koul <vkoul@kernel.org> M: Vinod Koul <vkoul@kernel.org>
R: Bhupesh Sharma <bhupesh.sharma@linaro.org>
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
L: linux-arm-msm@vger.kernel.org L: linux-arm-msm@vger.kernel.org
S: Maintained S: Maintained

View file

@ -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 /* MT753x MAC works in 1G full duplex mode for all up-clocked
* variants. * variants.
*/ */
if (interface == PHY_INTERFACE_MODE_INTERNAL || if (interface == PHY_INTERFACE_MODE_TRGMII ||
interface == PHY_INTERFACE_MODE_TRGMII ||
(phy_interface_mode_is_8023z(interface))) { (phy_interface_mode_is_8023z(interface))) {
speed = SPEED_1000; speed = SPEED_1000;
duplex = DUPLEX_FULL; duplex = DUPLEX_FULL;

View file

@ -3659,7 +3659,7 @@ static int mv88e6xxx_mdio_read_c45(struct mii_bus *bus, int phy, int devad,
int err; int err;
if (!chip->info->ops->phy_read_c45) if (!chip->info->ops->phy_read_c45)
return -EOPNOTSUPP; return 0xffff;
mv88e6xxx_reg_lock(chip); mv88e6xxx_reg_lock(chip);
err = chip->info->ops->phy_read_c45(chip, bus, phy, devad, reg, &val); err = chip->info->ops->phy_read_c45(chip, bus, phy, devad, reg, &val);

View file

@ -2051,12 +2051,11 @@ qca8k_sw_probe(struct mdio_device *mdiodev)
priv->info = of_device_get_match_data(priv->dev); priv->info = of_device_get_match_data(priv->dev);
priv->reset_gpio = devm_gpiod_get_optional(priv->dev, "reset", priv->reset_gpio = devm_gpiod_get_optional(priv->dev, "reset",
GPIOD_ASIS); GPIOD_OUT_HIGH);
if (IS_ERR(priv->reset_gpio)) if (IS_ERR(priv->reset_gpio))
return PTR_ERR(priv->reset_gpio); return PTR_ERR(priv->reset_gpio);
if (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 /* The active low duration must be greater than 10 ms
* and checkpatch.pl wants 20 ms. * and checkpatch.pl wants 20 ms.
*/ */

View file

@ -63,6 +63,15 @@ static int pdsc_process_notifyq(struct pdsc_qcq *qcq)
return nq_work; 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) void pdsc_process_adminq(struct pdsc_qcq *qcq)
{ {
union pds_core_adminq_comp *comp; union pds_core_adminq_comp *comp;
@ -75,9 +84,9 @@ void pdsc_process_adminq(struct pdsc_qcq *qcq)
int aq_work = 0; int aq_work = 0;
int credits; int credits;
/* Don't process AdminQ when shutting down */ /* Don't process AdminQ when it's not up */
if (pdsc->state & BIT_ULL(PDSC_S_STOPPING_DRIVER)) { if (!pdsc_adminq_inc_if_up(pdsc)) {
dev_err(pdsc->dev, "%s: called while PDSC_S_STOPPING_DRIVER\n", dev_err(pdsc->dev, "%s: called while adminq is unavailable\n",
__func__); __func__);
return; return;
} }
@ -124,6 +133,7 @@ void pdsc_process_adminq(struct pdsc_qcq *qcq)
pds_core_intr_credits(&pdsc->intr_ctrl[qcq->intx], pds_core_intr_credits(&pdsc->intr_ctrl[qcq->intx],
credits, credits,
PDS_CORE_INTR_CRED_REARM); PDS_CORE_INTR_CRED_REARM);
refcount_dec(&pdsc->adminq_refcnt);
} }
void pdsc_work_thread(struct work_struct *work) 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) irqreturn_t pdsc_adminq_isr(int irq, void *data)
{ {
struct pdsc_qcq *qcq = data; struct pdsc *pdsc = data;
struct pdsc *pdsc = qcq->pdsc; struct pdsc_qcq *qcq;
/* Don't process AdminQ when shutting down */ /* Don't process AdminQ when it's not up */
if (pdsc->state & BIT_ULL(PDSC_S_STOPPING_DRIVER)) { if (!pdsc_adminq_inc_if_up(pdsc)) {
dev_err(pdsc->dev, "%s: called while PDSC_S_STOPPING_DRIVER\n", dev_err(pdsc->dev, "%s: called while adminq is unavailable\n",
__func__); __func__);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
qcq = &pdsc->adminqcq;
queue_work(pdsc->wq, &qcq->work); queue_work(pdsc->wq, &qcq->work);
pds_core_intr_mask(&pdsc->intr_ctrl[qcq->intx], PDS_CORE_INTR_MASK_CLEAR); pds_core_intr_mask(&pdsc->intr_ctrl[qcq->intx], PDS_CORE_INTR_MASK_CLEAR);
refcount_dec(&pdsc->adminq_refcnt);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -179,10 +191,16 @@ static int __pdsc_adminq_post(struct pdsc *pdsc,
/* Check that the FW is running */ /* Check that the FW is running */
if (!pdsc_is_fw_running(pdsc)) { 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", dev_info(pdsc->dev, "%s: post failed - fw not running %#02x:\n",
__func__, fw_status); __func__, fw_status);
} else {
dev_info(pdsc->dev, "%s: post failed - BARs not setup\n",
__func__);
}
ret = -ENXIO; ret = -ENXIO;
goto err_out_unlock; goto err_out_unlock;
@ -230,6 +248,12 @@ int pdsc_adminq_post(struct pdsc *pdsc,
int err = 0; int err = 0;
int index; 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; wc.qcq = &pdsc->adminqcq;
index = __pdsc_adminq_post(pdsc, &pdsc->adminqcq, cmd, comp, &wc); index = __pdsc_adminq_post(pdsc, &pdsc->adminqcq, cmd, comp, &wc);
if (index < 0) { if (index < 0) {
@ -248,10 +272,16 @@ int pdsc_adminq_post(struct pdsc *pdsc,
break; break;
if (!pdsc_is_fw_running(pdsc)) { 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", dev_dbg(pdsc->dev, "%s: post wait failed - fw not running %#02x:\n",
__func__, fw_status); __func__, fw_status);
} else {
dev_dbg(pdsc->dev, "%s: post wait failed - BARs not setup\n",
__func__);
}
err = -ENXIO; err = -ENXIO;
break; break;
} }
@ -285,6 +315,8 @@ int pdsc_adminq_post(struct pdsc *pdsc,
queue_work(pdsc->wq, &pdsc->health_work); queue_work(pdsc->wq, &pdsc->health_work);
} }
refcount_dec(&pdsc->adminq_refcnt);
return err; return err;
} }
EXPORT_SYMBOL_GPL(pdsc_adminq_post); EXPORT_SYMBOL_GPL(pdsc_adminq_post);

View file

@ -125,7 +125,7 @@ static int pdsc_qcq_intr_alloc(struct pdsc *pdsc, struct pdsc_qcq *qcq)
snprintf(name, sizeof(name), "%s-%d-%s", snprintf(name, sizeof(name), "%s-%d-%s",
PDS_CORE_DRV_NAME, pdsc->pdev->bus->number, qcq->q.name); 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) if (index < 0)
return index; return index;
qcq->intx = index; qcq->intx = index;
@ -404,10 +404,7 @@ int pdsc_setup(struct pdsc *pdsc, bool init)
int numdescs; int numdescs;
int err; int err;
if (init)
err = pdsc_dev_init(pdsc); err = pdsc_dev_init(pdsc);
else
err = pdsc_dev_reinit(pdsc);
if (err) if (err)
return err; return err;
@ -450,6 +447,7 @@ int pdsc_setup(struct pdsc *pdsc, bool init)
pdsc_debugfs_add_viftype(pdsc); pdsc_debugfs_add_viftype(pdsc);
} }
refcount_set(&pdsc->adminq_refcnt, 1);
clear_bit(PDSC_S_FW_DEAD, &pdsc->state); clear_bit(PDSC_S_FW_DEAD, &pdsc->state);
return 0; return 0;
@ -464,6 +462,8 @@ void pdsc_teardown(struct pdsc *pdsc, bool removing)
if (!pdsc->pdev->is_virtfn) if (!pdsc->pdev->is_virtfn)
pdsc_devcmd_reset(pdsc); 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->notifyqcq);
pdsc_qcq_free(pdsc, &pdsc->adminqcq); 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++) for (i = 0; i < pdsc->nintrs; i++)
pdsc_intr_free(pdsc, i); pdsc_intr_free(pdsc, i);
if (removing) {
kfree(pdsc->intr_info); kfree(pdsc->intr_info);
pdsc->intr_info = NULL; pdsc->intr_info = NULL;
} pdsc->nintrs = 0;
} }
if (pdsc->kern_dbpage) { if (pdsc->kern_dbpage) {
@ -487,6 +486,7 @@ void pdsc_teardown(struct pdsc *pdsc, bool removing)
pdsc->kern_dbpage = NULL; pdsc->kern_dbpage = NULL;
} }
pci_free_irq_vectors(pdsc->pdev);
set_bit(PDSC_S_FW_DEAD, &pdsc->state); set_bit(PDSC_S_FW_DEAD, &pdsc->state);
} }
@ -512,6 +512,24 @@ void pdsc_stop(struct pdsc *pdsc)
PDS_CORE_INTR_MASK_SET); 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) void pdsc_fw_down(struct pdsc *pdsc)
{ {
union pds_core_notifyq_comp reset_event = { union pds_core_notifyq_comp reset_event = {
@ -527,6 +545,8 @@ void pdsc_fw_down(struct pdsc *pdsc)
if (pdsc->pdev->is_virtfn) if (pdsc->pdev->is_virtfn)
return; return;
pdsc_adminq_wait_and_dec_once_unused(pdsc);
/* Notify clients of fw_down */ /* Notify clients of fw_down */
if (pdsc->fw_reporter) if (pdsc->fw_reporter)
devlink_health_report(pdsc->fw_reporter, "FW down reported", pdsc); devlink_health_report(pdsc->fw_reporter, "FW down reported", pdsc);
@ -577,7 +597,13 @@ void pdsc_fw_up(struct pdsc *pdsc)
static void pdsc_check_pci_health(struct pdsc *pdsc) 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? */ /* is PCI broken? */
if (fw_status != PDS_RC_BAD_PCI) if (fw_status != PDS_RC_BAD_PCI)

View file

@ -184,6 +184,7 @@ struct pdsc {
struct mutex devcmd_lock; /* lock for dev_cmd operations */ struct mutex devcmd_lock; /* lock for dev_cmd operations */
struct mutex config_lock; /* lock for configuration operations */ struct mutex config_lock; /* lock for configuration operations */
spinlock_t adminq_lock; /* lock for adminq 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_info_regs __iomem *info_regs;
struct pds_core_dev_cmd_regs __iomem *cmd_regs; struct pds_core_dev_cmd_regs __iomem *cmd_regs;
struct pds_core_intr __iomem *intr_ctrl; 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); union pds_core_dev_comp *comp, int max_seconds);
int pdsc_devcmd_init(struct pdsc *pdsc); int pdsc_devcmd_init(struct pdsc *pdsc);
int pdsc_devcmd_reset(struct pdsc *pdsc); int pdsc_devcmd_reset(struct pdsc *pdsc);
int pdsc_dev_reinit(struct pdsc *pdsc);
int pdsc_dev_init(struct pdsc *pdsc); int pdsc_dev_init(struct pdsc *pdsc);
void pdsc_reset_prepare(struct pci_dev *pdev); void pdsc_reset_prepare(struct pci_dev *pdev);

View file

@ -64,6 +64,10 @@ DEFINE_SHOW_ATTRIBUTE(identity);
void pdsc_debugfs_add_ident(struct pdsc *pdsc) 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, debugfs_create_file("identity", 0400, pdsc->dentry,
pdsc, &identity_fops); pdsc, &identity_fops);
} }

View file

@ -57,6 +57,9 @@ int pdsc_err_to_errno(enum pds_core_status_code code)
bool pdsc_is_fw_running(struct pdsc *pdsc) bool pdsc_is_fw_running(struct pdsc *pdsc)
{ {
if (!pdsc->info_regs)
return false;
pdsc->fw_status = ioread8(&pdsc->info_regs->fw_status); pdsc->fw_status = ioread8(&pdsc->info_regs->fw_status);
pdsc->last_fw_time = jiffies; pdsc->last_fw_time = jiffies;
pdsc->last_hb = ioread32(&pdsc->info_regs->fw_heartbeat); 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; int err;
if (!pdsc->cmd_regs)
return -ENXIO;
memcpy_toio(&pdsc->cmd_regs->cmd, cmd, sizeof(*cmd)); memcpy_toio(&pdsc->cmd_regs->cmd, cmd, sizeof(*cmd));
pdsc_devcmd_dbell(pdsc); pdsc_devcmd_dbell(pdsc);
err = pdsc_devcmd_wait(pdsc, cmd->opcode, max_seconds); 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) if ((err == -ENXIO || err == -ETIMEDOUT) && pdsc->wq)
queue_work(pdsc->wq, &pdsc->health_work); queue_work(pdsc->wq, &pdsc->health_work);
else
memcpy_fromio(comp, &pdsc->cmd_regs->comp, sizeof(*comp));
return err; return err;
} }
@ -309,13 +316,6 @@ static int pdsc_identify(struct pdsc *pdsc)
return 0; return 0;
} }
int pdsc_dev_reinit(struct pdsc *pdsc)
{
pdsc_init_devinfo(pdsc);
return pdsc_identify(pdsc);
}
int pdsc_dev_init(struct pdsc *pdsc) int pdsc_dev_init(struct pdsc *pdsc)
{ {
unsigned int nintrs; unsigned int nintrs;

View file

@ -111,6 +111,7 @@ int pdsc_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
mutex_lock(&pdsc->devcmd_lock); mutex_lock(&pdsc->devcmd_lock);
err = pdsc_devcmd_locked(pdsc, &cmd, &comp, pdsc->devcmd_timeout * 2); err = pdsc_devcmd_locked(pdsc, &cmd, &comp, pdsc->devcmd_timeout * 2);
if (!err)
memcpy_fromio(&fw_list, pdsc->cmd_regs->data, sizeof(fw_list)); memcpy_fromio(&fw_list, pdsc->cmd_regs->data, sizeof(fw_list));
mutex_unlock(&pdsc->devcmd_lock); mutex_unlock(&pdsc->devcmd_lock);
if (err && err != -EIO) if (err && err != -EIO)

View file

@ -107,6 +107,9 @@ int pdsc_firmware_update(struct pdsc *pdsc, const struct firmware *fw,
dev_info(pdsc->dev, "Installing firmware\n"); dev_info(pdsc->dev, "Installing firmware\n");
if (!pdsc->cmd_regs)
return -ENXIO;
dl = priv_to_devlink(pdsc); dl = priv_to_devlink(pdsc);
devlink_flash_update_status_notify(dl, "Preparing to flash", devlink_flash_update_status_notify(dl, "Preparing to flash",
NULL, 0, 0); NULL, 0, 0);

View file

@ -37,6 +37,11 @@ static void pdsc_unmap_bars(struct pdsc *pdsc)
struct pdsc_dev_bar *bars = pdsc->bars; struct pdsc_dev_bar *bars = pdsc->bars;
unsigned int i; 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++) { for (i = 0; i < PDS_CORE_BARS_MAX; i++) {
if (bars[i].vaddr) if (bars[i].vaddr)
pci_iounmap(pdsc->pdev, bars[i].vaddr); pci_iounmap(pdsc->pdev, bars[i].vaddr);
@ -293,7 +298,7 @@ static int pdsc_init_pf(struct pdsc *pdsc)
err_out_teardown: err_out_teardown:
pdsc_teardown(pdsc, PDSC_TEARDOWN_REMOVING); pdsc_teardown(pdsc, PDSC_TEARDOWN_REMOVING);
err_out_unmap_bars: err_out_unmap_bars:
del_timer_sync(&pdsc->wdtimer); timer_shutdown_sync(&pdsc->wdtimer);
if (pdsc->wq) if (pdsc->wq)
destroy_workqueue(pdsc->wq); destroy_workqueue(pdsc->wq);
mutex_destroy(&pdsc->config_lock); mutex_destroy(&pdsc->config_lock);
@ -420,7 +425,7 @@ static void pdsc_remove(struct pci_dev *pdev)
*/ */
pdsc_sriov_configure(pdev, 0); pdsc_sriov_configure(pdev, 0);
del_timer_sync(&pdsc->wdtimer); timer_shutdown_sync(&pdsc->wdtimer);
if (pdsc->wq) if (pdsc->wq)
destroy_workqueue(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->config_lock);
mutex_destroy(&pdsc->devcmd_lock); mutex_destroy(&pdsc->devcmd_lock);
pci_free_irq_vectors(pdev);
pdsc_unmap_bars(pdsc); pdsc_unmap_bars(pdsc);
pci_release_regions(pdev); pci_release_regions(pdev);
} }
@ -445,13 +449,26 @@ static void pdsc_remove(struct pci_dev *pdev)
devlink_free(dl); 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) void pdsc_reset_prepare(struct pci_dev *pdev)
{ {
struct pdsc *pdsc = pci_get_drvdata(pdev); struct pdsc *pdsc = pci_get_drvdata(pdev);
pdsc_stop_health_thread(pdsc);
pdsc_fw_down(pdsc); pdsc_fw_down(pdsc);
pci_free_irq_vectors(pdev);
pdsc_unmap_bars(pdsc); pdsc_unmap_bars(pdsc);
pci_release_regions(pdev); pci_release_regions(pdev);
pci_disable_device(pdev); pci_disable_device(pdev);
@ -486,6 +503,7 @@ void pdsc_reset_done(struct pci_dev *pdev)
} }
pdsc_fw_up(pdsc); pdsc_fw_up(pdsc);
pdsc_restart_health_thread(pdsc);
} }
static const struct pci_error_handlers pdsc_err_handler = { static const struct pci_error_handlers pdsc_err_handler = {

View file

@ -684,7 +684,7 @@ static void bnxt_stamp_tx_skb(struct bnxt *bp, struct sk_buff *skb)
timestamp.hwtstamp = ns_to_ktime(ns); timestamp.hwtstamp = ns_to_ktime(ns);
skb_tstamp_tx(ptp->tx_skb, &timestamp); skb_tstamp_tx(ptp->tx_skb, &timestamp);
} else { } else {
netdev_WARN_ONCE(bp->dev, netdev_warn_once(bp->dev,
"TS query for TX timer failed rc = %x\n", rc); "TS query for TX timer failed rc = %x\n", rc);
} }

View file

@ -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, static struct sk_buff *gve_rx_add_frags(struct napi_struct *napi,
struct gve_rx_slot_page_info *page_info, struct gve_rx_slot_page_info *page_info,
u16 packet_buffer_size, u16 len, unsigned int truesize, u16 len,
struct gve_rx_ctx *ctx) struct gve_rx_ctx *ctx)
{ {
u32 offset = page_info->page_offset + page_info->pad; 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) { if (skb != ctx->skb_head) {
ctx->skb_head->len += len; ctx->skb_head->len += len;
ctx->skb_head->data_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, skb_add_rx_frag(skb, num_frags, page_info->page,
offset, len, packet_buffer_size); offset, len, truesize);
return ctx->skb_head; 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); memcpy(alloc_page_info.page_address, src, page_info->pad + len);
skb = gve_rx_add_frags(napi, &alloc_page_info, skb = gve_rx_add_frags(napi, &alloc_page_info,
rx->packet_buffer_size, PAGE_SIZE,
len, ctx); len, ctx);
u64_stats_update_begin(&rx->statss); u64_stats_update_begin(&rx->statss);

View file

@ -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 * 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) * INCVALUE_n into the TIMINCA register allowing 32+8+(24-INCVALUE_SHIFT_n)
* bits to count nanoseconds leaving the rest for fractional nonseconds. * 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_96MHZ 125
#define INCVALUE_SHIFT_96MHZ 17 #define INCVALUE_SHIFT_96MHZ 17
#define INCPERIOD_SHIFT_96MHZ 2 #define INCPERIOD_SHIFT_96MHZ 2
#define INCPERIOD_96MHZ (12 >> INCPERIOD_SHIFT_96MHZ) #define INCPERIOD_96MHZ (12 >> INCPERIOD_SHIFT_96MHZ)
#define MAX_PPB_96MHZ 23999900 /* 23,999,900 ppb */
#define INCVALUE_25MHZ 40 #define INCVALUE_25MHZ 40
#define INCVALUE_SHIFT_25MHZ 18 #define INCVALUE_SHIFT_25MHZ 18
#define INCPERIOD_25MHZ 1 #define INCPERIOD_25MHZ 1
#define MAX_PPB_25MHZ 599999900 /* 599,999,900 ppb */
#define INCVALUE_24MHZ 125 #define INCVALUE_24MHZ 125
#define INCVALUE_SHIFT_24MHZ 14 #define INCVALUE_SHIFT_24MHZ 14
#define INCPERIOD_24MHZ 3 #define INCPERIOD_24MHZ 3
#define MAX_PPB_24MHZ 999999999 /* 999,999,999 ppb */
#define INCVALUE_38400KHZ 26 #define INCVALUE_38400KHZ 26
#define INCVALUE_SHIFT_38400KHZ 19 #define INCVALUE_SHIFT_38400KHZ 19
#define INCPERIOD_38400KHZ 1 #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 /* Another drawback of scaling the incvalue by a large factor is the
* 64-bit SYSTIM register overflows more quickly. This is dealt with * 64-bit SYSTIM register overflows more quickly. This is dealt with

View file

@ -280,8 +280,17 @@ void e1000e_ptp_init(struct e1000_adapter *adapter)
switch (hw->mac.type) { switch (hw->mac.type) {
case e1000_pch2lan: case e1000_pch2lan:
adapter->ptp_clock_info.max_adj = MAX_PPB_96MHZ;
break;
case e1000_pch_lpt: 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: case e1000_pch_spt:
adapter->ptp_clock_info.max_adj = MAX_PPB_24MHZ;
break;
case e1000_pch_cnp: case e1000_pch_cnp:
case e1000_pch_tgp: case e1000_pch_tgp:
case e1000_pch_adp: case e1000_pch_adp:
@ -289,15 +298,14 @@ void e1000e_ptp_init(struct e1000_adapter *adapter)
case e1000_pch_lnp: case e1000_pch_lnp:
case e1000_pch_ptp: case e1000_pch_ptp:
case e1000_pch_nvp: case e1000_pch_nvp:
if ((hw->mac.type < e1000_pch_lpt) || if (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI)
(er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI)) { adapter->ptp_clock_info.max_adj = MAX_PPB_24MHZ;
adapter->ptp_clock_info.max_adj = 24000000 - 1; else
adapter->ptp_clock_info.max_adj = MAX_PPB_38400KHZ;
break; break;
}
fallthrough;
case e1000_82574: case e1000_82574:
case e1000_82583: case e1000_82583:
adapter->ptp_clock_info.max_adj = 600000000 - 1; adapter->ptp_clock_info.max_adj = MAX_PPB_25MHZ;
break; break;
default: default:
break; break;

View file

@ -978,7 +978,7 @@ struct virtchnl2_ptype {
u8 proto_id_count; u8 proto_id_count;
__le16 pad; __le16 pad;
__le16 proto_id[]; __le16 proto_id[];
}; } __packed __aligned(2);
VIRTCHNL2_CHECK_STRUCT_LEN(6, virtchnl2_ptype); VIRTCHNL2_CHECK_STRUCT_LEN(6, virtchnl2_ptype);
/** /**

View file

@ -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) { if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
error = FIELD_GET(IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK, command); error = FIELD_GET(IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK, command);
hw_dbg(hw, "Failed to read, error %x\n", error); hw_dbg(hw, "Failed to read, error %x\n", error);
return -EIO; ret = -EIO;
goto out;
} }
if (!ret) if (!ret)

View file

@ -314,7 +314,6 @@ static int otx2_set_channels(struct net_device *dev,
pfvf->hw.tx_queues = channel->tx_count; pfvf->hw.tx_queues = channel->tx_count;
if (pfvf->xdp_prog) if (pfvf->xdp_prog)
pfvf->hw.xdp_queues = channel->rx_count; pfvf->hw.xdp_queues = channel->rx_count;
pfvf->hw.non_qos_queues = pfvf->hw.tx_queues + pfvf->hw.xdp_queues;
if (if_up) if (if_up)
err = dev->netdev_ops->ndo_open(dev); err = dev->netdev_ops->ndo_open(dev);

View file

@ -1744,6 +1744,7 @@ int otx2_open(struct net_device *netdev)
/* RQ and SQs are mapped to different CQs, /* RQ and SQs are mapped to different CQs,
* so find out max CQ IRQs (i.e CINTs) needed. * 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.cint_cnt = max3(pf->hw.rx_queues, pf->hw.tx_queues,
pf->hw.tc_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); xdp_features_clear_redirect_target(dev);
} }
pf->hw.non_qos_queues += pf->hw.xdp_queues;
if (if_up) if (if_up)
otx2_open(pf->netdev); otx2_open(pf->netdev);

View file

@ -1403,7 +1403,7 @@ static bool otx2_xdp_rcv_pkt_handler(struct otx2_nic *pfvf,
struct otx2_cq_queue *cq, struct otx2_cq_queue *cq,
bool *need_xdp_flush) bool *need_xdp_flush)
{ {
unsigned char *hard_start, *data; unsigned char *hard_start;
int qidx = cq->cq_idx; int qidx = cq->cq_idx;
struct xdp_buff xdp; struct xdp_buff xdp;
struct page *page; 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); xdp_init_buff(&xdp, pfvf->rbsize, &cq->xdp_rxq);
data = (unsigned char *)phys_to_virt(pa); hard_start = (unsigned char *)phys_to_virt(pa);
hard_start = page_address(page); xdp_prepare_buff(&xdp, hard_start, OTX2_HEAD_ROOM,
xdp_prepare_buff(&xdp, hard_start, data - hard_start,
cqe->sg.seg_size, false); cqe->sg.seg_size, false);
act = bpf_prog_run_xdp(prog, &xdp); act = bpf_prog_run_xdp(prog, &xdp);

View file

@ -4761,7 +4761,10 @@ static int mtk_probe(struct platform_device *pdev)
} }
if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) { 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) { if (err) {
dev_err(&pdev->dev, "Wrong DMA config\n"); dev_err(&pdev->dev, "Wrong DMA config\n");
return -EINVAL; return -EINVAL;

View file

@ -168,9 +168,10 @@ static void lan966x_port_link_up(struct lan966x_port *port)
lan966x_taprio_speed_set(port, config->speed); lan966x_taprio_speed_set(port, config->speed);
/* Also the GIGA_MODE_ENA(1) needs to be set regardless of the /* 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); mode = DEV_MAC_MODE_CFG_GIGA_MODE_ENA_SET(1);
lan_wr(config->duplex | mode, lan_wr(config->duplex | mode,

View file

@ -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); mangle_action->mangle.mask = (__force u32)cpu_to_be32(mangle_action->mangle.mask);
return; 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_TCP:
case FLOW_ACT_MANGLE_HDR_TYPE_UDP: case FLOW_ACT_MANGLE_HDR_TYPE_UDP:
mangle_action->mangle.val = (__force u16)cpu_to_be16(mangle_action->mangle.val); if (mangle_action->mangle.offset == offsetof(struct tcphdr, source)) {
mangle_action->mangle.mask = (__force u16)cpu_to_be16(mangle_action->mangle.mask); 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; return;
default: 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 flow_rule *rule = flow_cls_offload_flow_rule(flow);
struct nfp_fl_ct_flow_entry *ct_entry; struct nfp_fl_ct_flow_entry *ct_entry;
struct flow_action_entry *ct_goto;
struct nfp_fl_ct_zone_entry *zt; struct nfp_fl_ct_zone_entry *zt;
struct flow_action_entry *act;
bool wildcarded = false; bool wildcarded = false;
struct flow_match_ct ct; 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); flow_rule_match_ct(rule, &ct);
if (!ct.mask->ct_zone) { if (!ct.mask->ct_zone) {

View file

@ -353,6 +353,10 @@ static int imx_dwmac_probe(struct platform_device *pdev)
if (data->flags & STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY) if (data->flags & STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY)
plat_dat->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->host_dma_width = dwmac->ops->addr_width;
plat_dat->init = imx_dwmac_init; plat_dat->init = imx_dwmac_init;
plat_dat->exit = imx_dwmac_exit; plat_dat->exit = imx_dwmac_exit;

View file

@ -3932,6 +3932,9 @@ static int __stmmac_open(struct net_device *dev,
priv->rx_copybreak = STMMAC_RX_COPYBREAK; priv->rx_copybreak = STMMAC_RX_COPYBREAK;
buf_sz = dma_conf->dma_buf_sz; 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)); memcpy(&priv->dma_conf, dma_conf, sizeof(*dma_conf));
stmmac_reset_queues_param(priv); stmmac_reset_queues_param(priv);

View file

@ -708,7 +708,10 @@ void netvsc_device_remove(struct hv_device *device)
/* Disable NAPI and disassociate its context from the device. */ /* Disable NAPI and disassociate its context from the device. */
for (i = 0; i < net_device->num_chn; i++) { for (i = 0; i < net_device->num_chn; i++) {
/* See also vmbus_reset_channel_cb(). */ /* See also vmbus_reset_channel_cb(). */
/* only disable enabled NAPI channel */
if (i < ndev->real_num_rx_queues)
napi_disable(&net_device->chan_table[i].napi); napi_disable(&net_device->chan_table[i].napi);
netif_napi_del(&net_device->chan_table[i].napi); netif_napi_del(&net_device->chan_table[i].napi);
} }

View file

@ -489,7 +489,7 @@ static int tx_r50_fill_result(struct phy_device *phydev, u16 tx_r50_cal_val,
u16 reg, val; u16 reg, val;
if (phydev->drv->phy_id == MTK_GPHY_ID_MT7988) if (phydev->drv->phy_id == MTK_GPHY_ID_MT7988)
bias = -2; bias = -1;
val = clamp_val(bias + tx_r50_cal_val, 0, 63); val = clamp_val(bias + tx_r50_cal_val, 0, 63);
@ -705,6 +705,11 @@ static int tx_vcm_cal_sw(struct phy_device *phydev, u8 rg_txreserve_x)
static void mt798x_phy_common_finetune(struct phy_device *phydev) static void mt798x_phy_common_finetune(struct phy_device *phydev)
{ {
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); 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 */ /* EnabRandUpdTrig = 1 */
__phy_write(phydev, 0x11, 0x2f00); __phy_write(phydev, 0x11, 0x2f00);
__phy_write(phydev, 0x12, 0xe); __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, 0x12, 0x0);
__phy_write(phydev, 0x10, 0x83aa); __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, 0x11, 0x0);
__phy_write(phydev, 0x12, 0x0); __phy_write(phydev, 0x12, 0x0);
__phy_write(phydev, 0x10, 0x9686); __phy_write(phydev, 0x10, 0x9686);
/* SSTrKp100 = 5 */
/* SSTrKf100 = 6 */
/* SSTrKp1000Mas = 5 */
/* SSTrKf1000Mas = 6 */
/* SSTrKp1000Slv = 5 */ /* SSTrKp1000Slv = 5 */
/* SSTrKf1000Slv = 6 */
__phy_write(phydev, 0x11, 0xbaef); __phy_write(phydev, 0x11, 0xbaef);
__phy_write(phydev, 0x12, 0x2e); __phy_write(phydev, 0x12, 0x2e);
__phy_write(phydev, 0x10, 0x968c); __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, /* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2,
* MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 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_write(phydev, 0x10, 0x8ec0);
phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); 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, 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, MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK,
BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9)); 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); 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) static void mt7988_phy_finetune(struct phy_device *phydev)
{ {
u16 val[12] = { 0x0187, 0x01cd, 0x01c8, 0x0182, u16 val[12] = { 0x0187, 0x01cd, 0x01c8, 0x0182,
@ -827,17 +831,7 @@ static void mt7988_phy_finetune(struct phy_device *phydev)
/* TCT finetune */ /* TCT finetune */
phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5); 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); 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 */ /* ResetSyncOffset = 5 */
__phy_write(phydev, 0x11, 0x500); __phy_write(phydev, 0x11, 0x500);
__phy_write(phydev, 0x12, 0x0); __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 */ /* 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_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_2A30); /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 10 */
/* TxClkOffset = 2 */ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
__phy_modify(phydev, MTK_PHY_ANARG_RG, MTK_PHY_TCLKOFFSET_MASK, MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK,
FIELD_PREP(MTK_PHY_TCLKOFFSET_MASK, 0x2)); BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0xa));
phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
/* 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) 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, MTK_PHY_LPI_SLV_SEND_TX_EN,
FIELD_PREP(MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK, 0x120)); FIELD_PREP(MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK, 0x120));
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239, /* Keep MTK_PHY_LPI_SEND_LOC_TIMER as 375 */
MTK_PHY_LPI_SEND_LOC_TIMER_MASK | phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239,
MTK_PHY_LPI_TXPCS_LOC_RCV, MTK_PHY_LPI_TXPCS_LOC_RCV);
FIELD_PREP(MTK_PHY_LPI_SEND_LOC_TIMER_MASK, 0x117));
/* This also fixes some IoT issues, such as CH340 */
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2C7, phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2C7,
MTK_PHY_MAX_GAIN_MASK | MTK_PHY_MIN_GAIN_MASK, MTK_PHY_MAX_GAIN_MASK | MTK_PHY_MIN_GAIN_MASK,
FIELD_PREP(MTK_PHY_MAX_GAIN_MASK, 0x8) | 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, 0x12, 0x0);
__phy_write(phydev, 0x10, 0x9690); __phy_write(phydev, 0x10, 0x9690);
/* REG_EEE_st2TrKf1000 = 3 */ /* REG_EEE_st2TrKf1000 = 2 */
__phy_write(phydev, 0x11, 0x114f); __phy_write(phydev, 0x11, 0x114f);
__phy_write(phydev, 0x12, 0x2); __phy_write(phydev, 0x12, 0x2);
__phy_write(phydev, 0x10, 0x969a); __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, 0x12, 0x0);
__phy_write(phydev, 0x10, 0x96b8); __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, 0x11, 0x1463);
__phy_write(phydev, 0x12, 0x0); __phy_write(phydev, 0x12, 0x0);
__phy_write(phydev, 0x10, 0x96ca); __phy_write(phydev, 0x10, 0x96ca);
@ -1459,6 +1467,13 @@ static int mt7988_phy_probe(struct phy_device *phydev)
if (err) if (err)
return 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); return mt798x_phy_calibration(phydev);
} }

View file

@ -104,13 +104,12 @@ bool provides_xdp_headroom = true;
module_param(provides_xdp_headroom, bool, 0644); module_param(provides_xdp_headroom, bool, 0644);
static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx, 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, 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, unsigned int extra_count,
s8 st); s8 status);
static void push_tx_responses(struct xenvif_queue *queue);
static void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx); 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) unsigned int extra_count, RING_IDX end)
{ {
RING_IDX cons = queue->tx.req_cons; RING_IDX cons = queue->tx.req_cons;
unsigned long flags;
do { do {
spin_lock_irqsave(&queue->response_lock, flags);
make_tx_response(queue, txp, extra_count, XEN_NETIF_RSP_ERROR); 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) if (cons == end)
break; break;
RING_COPY_REQUEST(&queue->tx, cons++, txp); 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; for (shinfo->nr_frags = 0; nr_slots > 0 && shinfo->nr_frags < MAX_SKB_FRAGS;
nr_slots--) { nr_slots--) {
if (unlikely(!txp->size)) { if (unlikely(!txp->size)) {
unsigned long flags;
spin_lock_irqsave(&queue->response_lock, flags);
make_tx_response(queue, txp, 0, XEN_NETIF_RSP_OKAY); make_tx_response(queue, txp, 0, XEN_NETIF_RSP_OKAY);
push_tx_responses(queue);
spin_unlock_irqrestore(&queue->response_lock, flags);
++txp; ++txp;
continue; 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) { for (shinfo->nr_frags = 0; shinfo->nr_frags < nr_slots; ++txp) {
if (unlikely(!txp->size)) { if (unlikely(!txp->size)) {
unsigned long flags;
spin_lock_irqsave(&queue->response_lock, flags);
make_tx_response(queue, txp, 0, make_tx_response(queue, txp, 0,
XEN_NETIF_RSP_OKAY); XEN_NETIF_RSP_OKAY);
push_tx_responses(queue);
spin_unlock_irqrestore(&queue->response_lock,
flags);
continue; continue;
} }
@ -995,7 +979,6 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
(ret == 0) ? (ret == 0) ?
XEN_NETIF_RSP_OKAY : XEN_NETIF_RSP_OKAY :
XEN_NETIF_RSP_ERROR); XEN_NETIF_RSP_ERROR);
push_tx_responses(queue);
continue; continue;
} }
@ -1007,7 +990,6 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
make_tx_response(queue, &txreq, extra_count, make_tx_response(queue, &txreq, extra_count,
XEN_NETIF_RSP_OKAY); XEN_NETIF_RSP_OKAY);
push_tx_responses(queue);
continue; continue;
} }
@ -1433,44 +1415,17 @@ int xenvif_tx_action(struct xenvif_queue *queue, int budget)
return work_done; return work_done;
} }
static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx, static void _make_tx_response(struct xenvif_queue *queue,
u8 status) const struct xen_netif_tx_request *txp,
{
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,
unsigned int extra_count, unsigned int extra_count,
s8 st) s8 status)
{ {
RING_IDX i = queue->tx.rsp_prod_pvt; RING_IDX i = queue->tx.rsp_prod_pvt;
struct xen_netif_tx_response *resp; struct xen_netif_tx_response *resp;
resp = RING_GET_RESPONSE(&queue->tx, i); resp = RING_GET_RESPONSE(&queue->tx, i);
resp->id = txp->id; resp->id = txp->id;
resp->status = st; resp->status = status;
while (extra_count-- != 0) while (extra_count-- != 0)
RING_GET_RESPONSE(&queue->tx, ++i)->status = XEN_NETIF_RSP_NULL; 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); 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) static void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx)
{ {
int ret; int ret;

View file

@ -186,6 +186,8 @@ struct ip_set_type_variant {
/* Return true if "b" set is the same as "a" /* Return true if "b" set is the same as "a"
* according to the create set parameters */ * according to the create set parameters */
bool (*same_set)(const struct ip_set *a, const struct ip_set *b); 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 */ /* Region-locking is used */
bool region_lock; bool region_lock;
}; };
@ -242,6 +244,8 @@ extern void ip_set_type_unregister(struct ip_set_type *set_type);
/* A generic IP set */ /* A generic IP set */
struct ip_set { struct ip_set {
/* For call_cru in destroy */
struct rcu_head rcu;
/* The name of the set */ /* The name of the set */
char name[IPSET_MAXNAMELEN]; char name[IPSET_MAXNAMELEN];
/* Lock protecting the set data */ /* Lock protecting the set data */

View file

@ -46,12 +46,6 @@ struct scm_stat {
#define UNIXCB(skb) (*(struct unix_skb_parms *)&((skb)->cb)) #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 */ /* The AF_UNIX socket */
struct unix_sock { struct unix_sock {
/* WARNING: sk has to be the first member */ /* 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_sk(ptr) container_of_const(ptr, struct unix_sock, sk)
#define unix_peer(sk) (unix_sk(sk)->peer) #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 #define peer_wait peer_wq.wait
long unix_inq_len(struct sock *sk); long unix_inq_len(struct sock *sk);

View file

@ -767,7 +767,7 @@ int ip_options_rcv_srr(struct sk_buff *skb, struct net_device *dev);
* Functions provided by ip_sockglue.c * 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, void ip_cmsg_recv_offset(struct msghdr *msg, struct sock *sk,
struct sk_buff *skb, int tlen, int offset); struct sk_buff *skb, int tlen, int offset);
int ip_cmsg_send(struct sock *sk, struct msghdr *msg, int ip_cmsg_send(struct sock *sk, struct msghdr *msg,

View file

@ -1351,6 +1351,7 @@ void nft_obj_notify(struct net *net, const struct nft_table *table,
* @type: stateful object numeric type * @type: stateful object numeric type
* @owner: module owner * @owner: module owner
* @maxattr: maximum netlink attribute * @maxattr: maximum netlink attribute
* @family: address family for AF-specific object types
* @policy: netlink attribute policy * @policy: netlink attribute policy
*/ */
struct nft_object_type { struct nft_object_type {
@ -1360,6 +1361,7 @@ struct nft_object_type {
struct list_head list; struct list_head list;
u32 type; u32 type;
unsigned int maxattr; unsigned int maxattr;
u8 family;
struct module *owner; struct module *owner;
const struct nla_policy *policy; const struct nla_policy *policy;
}; };

View file

@ -2175,6 +2175,7 @@ void batadv_mcast_free(struct batadv_priv *bat_priv)
cancel_delayed_work_sync(&bat_priv->mcast.work); cancel_delayed_work_sync(&bat_priv->mcast.work);
batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_MCAST, 2); 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); batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_MCAST, 2);
/* safely calling outside of worker, as worker was canceled above */ /* 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_NO_RTR4);
batadv_mcast_want_rtr6_update(bat_priv, orig, batadv_mcast_want_rtr6_update(bat_priv, orig,
BATADV_MCAST_WANT_NO_RTR6); 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); spin_unlock_bh(&orig->mcast_handler_lock);
} }

View file

@ -1762,6 +1762,10 @@ static void br_ip6_multicast_querier_expired(struct timer_list *t)
} }
#endif #endif
static void br_multicast_query_delay_expired(struct timer_list *t)
{
}
static void br_multicast_select_own_querier(struct net_bridge_mcast *brmctx, static void br_multicast_select_own_querier(struct net_bridge_mcast *brmctx,
struct br_ip *ip, struct br_ip *ip,
struct sk_buff *skb) struct sk_buff *skb)
@ -3198,7 +3202,7 @@ br_multicast_update_query_timer(struct net_bridge_mcast *brmctx,
unsigned long max_delay) unsigned long max_delay)
{ {
if (!timer_pending(&query->timer)) 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); 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_querier_interval = 255 * HZ;
brmctx->multicast_membership_interval = 260 * HZ; brmctx->multicast_membership_interval = 260 * HZ;
brmctx->ip4_other_query.delay_time = 0;
brmctx->ip4_querier.port_ifidx = 0; brmctx->ip4_querier.port_ifidx = 0;
seqcount_spinlock_init(&brmctx->ip4_querier.seq, &br->multicast_lock); seqcount_spinlock_init(&brmctx->ip4_querier.seq, &br->multicast_lock);
brmctx->multicast_igmp_version = 2; brmctx->multicast_igmp_version = 2;
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
brmctx->multicast_mld_version = 1; brmctx->multicast_mld_version = 1;
brmctx->ip6_other_query.delay_time = 0;
brmctx->ip6_querier.port_ifidx = 0; brmctx->ip6_querier.port_ifidx = 0;
seqcount_spinlock_init(&brmctx->ip6_querier.seq, &br->multicast_lock); seqcount_spinlock_init(&brmctx->ip6_querier.seq, &br->multicast_lock);
#endif #endif
@ -4056,6 +4058,8 @@ void br_multicast_ctx_init(struct net_bridge *br,
br_ip4_multicast_local_router_expired, 0); br_ip4_multicast_local_router_expired, 0);
timer_setup(&brmctx->ip4_other_query.timer, timer_setup(&brmctx->ip4_other_query.timer,
br_ip4_multicast_querier_expired, 0); 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, timer_setup(&brmctx->ip4_own_query.timer,
br_ip4_multicast_query_expired, 0); br_ip4_multicast_query_expired, 0);
#if IS_ENABLED(CONFIG_IPV6) #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); br_ip6_multicast_local_router_expired, 0);
timer_setup(&brmctx->ip6_other_query.timer, timer_setup(&brmctx->ip6_other_query.timer,
br_ip6_multicast_querier_expired, 0); 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, timer_setup(&brmctx->ip6_own_query.timer,
br_ip6_multicast_query_expired, 0); br_ip6_multicast_query_expired, 0);
#endif #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_mc_router_timer);
del_timer_sync(&brmctx->ip4_other_query.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); del_timer_sync(&brmctx->ip4_own_query.timer);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
del_timer_sync(&brmctx->ip6_mc_router_timer); del_timer_sync(&brmctx->ip6_mc_router_timer);
del_timer_sync(&brmctx->ip6_other_query.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); del_timer_sync(&brmctx->ip6_own_query.timer);
#endif #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; max_delay = brmctx->multicast_query_response_interval;
if (!timer_pending(&brmctx->ip4_other_query.timer)) 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); br_multicast_start_querier(brmctx, &brmctx->ip4_own_query);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
if (!timer_pending(&brmctx->ip6_other_query.timer)) 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); br_multicast_start_querier(brmctx, &brmctx->ip6_own_query);
#endif #endif

View file

@ -78,7 +78,7 @@ struct bridge_mcast_own_query {
/* other querier */ /* other querier */
struct bridge_mcast_other_query { struct bridge_mcast_other_query {
struct timer_list timer; struct timer_list timer;
unsigned long delay_time; struct timer_list delay_timer;
}; };
/* selected querier */ /* selected querier */
@ -1159,7 +1159,7 @@ __br_multicast_querier_exists(struct net_bridge_mcast *brmctx,
own_querier_enabled = false; 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)); (own_querier_enabled || timer_pending(&querier->timer));
} }

View file

@ -674,7 +674,7 @@ static int devlink_port_function_validate(struct devlink_port *devlink_port,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
if (tb[DEVLINK_PORT_FN_ATTR_STATE] && !ops->port_fn_state_set) { 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"); "Function does not support state setting");
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }

View file

@ -308,7 +308,7 @@ static void send_hsr_supervision_frame(struct hsr_port *master,
skb = hsr_init_skb(master); skb = hsr_init_skb(master);
if (!skb) { 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; return;
} }
@ -355,7 +355,7 @@ static void send_prp_supervision_frame(struct hsr_port *master,
skb = hsr_init_skb(master); skb = hsr_init_skb(master);
if (!skb) { 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; return;
} }

View file

@ -1287,6 +1287,12 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork,
if (unlikely(!rt)) if (unlikely(!rt))
return -EFAULT; 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. * setup for corking.
*/ */
@ -1303,12 +1309,6 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork,
cork->addr = ipc->addr; 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->gso_size = ipc->gso_size;
cork->dst = &rt->dst; cork->dst = &rt->dst;

View file

@ -1363,12 +1363,13 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
* ipv4_pktinfo_prepare - transfer some info from rtable to skb * ipv4_pktinfo_prepare - transfer some info from rtable to skb
* @sk: socket * @sk: socket
* @skb: buffer * @skb: buffer
* @drop_dst: if true, drops skb dst
* *
* To support IP_CMSG_PKTINFO option, we store rt_iif and specific * To support IP_CMSG_PKTINFO option, we store rt_iif and specific
* destination in skb->cb[] before dst drop. * destination in skb->cb[] before dst drop.
* This way, receiver doesn't make cache line misses to read rtable. * 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); struct in_pktinfo *pktinfo = PKTINFO_SKB_CB(skb);
bool prepare = inet_test_bit(PKTINFO, sk) || bool prepare = inet_test_bit(PKTINFO, sk) ||
@ -1397,6 +1398,7 @@ void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb)
pktinfo->ipi_ifindex = 0; pktinfo->ipi_ifindex = 0;
pktinfo->ipi_spec_dst.s_addr = 0; pktinfo->ipi_spec_dst.s_addr = 0;
} }
if (drop_dst)
skb_dst_drop(skb); skb_dst_drop(skb);
} }

View file

@ -1073,7 +1073,7 @@ static int ipmr_cache_report(const struct mr_table *mrt,
msg = (struct igmpmsg *)skb_network_header(skb); msg = (struct igmpmsg *)skb_network_header(skb);
msg->im_vif = vifi; msg->im_vif = vifi;
msg->im_vif_hi = vifi >> 8; 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)); memcpy(skb->cb, pkt->cb, sizeof(skb->cb));
/* Add our header */ /* Add our header */
igmp = skb_put(skb, sizeof(struct igmphdr)); igmp = skb_put(skb, sizeof(struct igmphdr));

View file

@ -292,7 +292,7 @@ static int raw_rcv_skb(struct sock *sk, struct sk_buff *skb)
/* Charge it to the socket. */ /* 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) { if (sock_queue_rcv_skb_reason(sk, skb, &reason) < 0) {
kfree_skb_reason(skb, reason); kfree_skb_reason(skb, reason);
return NET_RX_DROP; return NET_RX_DROP;

View file

@ -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) 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, static int find_next_mappable_frag(const skb_frag_t *frag,

View file

@ -2169,7 +2169,7 @@ static int udp_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
udp_csum_pull_header(skb); udp_csum_pull_header(skb);
ipv4_pktinfo_prepare(sk, skb); ipv4_pktinfo_prepare(sk, skb, true);
return __udp_queue_rcv_skb(sk, skb); return __udp_queue_rcv_skb(sk, skb);
csum_error: csum_error:

View file

@ -220,19 +220,26 @@ const struct ipv6_stub *ipv6_stub __read_mostly = &(struct ipv6_stub) {
EXPORT_SYMBOL_GPL(ipv6_stub); EXPORT_SYMBOL_GPL(ipv6_stub);
/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ /* 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); 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); 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); 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); 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); 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); 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); EXPORT_SYMBOL(in6addr_sitelocal_allrouters);
static void snmp6_free_dev(struct inet6_dev *idev) static void snmp6_free_dev(struct inet6_dev *idev)

View file

@ -796,8 +796,8 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,
struct sk_buff *skb), struct sk_buff *skb),
bool log_ecn_err) bool log_ecn_err)
{ {
const struct ipv6hdr *ipv6h = ipv6_hdr(skb); const struct ipv6hdr *ipv6h;
int err; int nh, err;
if ((!(tpi->flags & TUNNEL_CSUM) && if ((!(tpi->flags & TUNNEL_CSUM) &&
(tunnel->parms.i_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; goto drop;
} }
ipv6h = ipv6_hdr(skb);
skb->protocol = eth_type_trans(skb, tunnel->dev); skb->protocol = eth_type_trans(skb, tunnel->dev);
skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
} else { } else {
@ -837,7 +836,23 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,
skb_reset_mac_header(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); 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)); memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
__skb_tunnel_rx(skb, tunnel->dev, tunnel->net); __skb_tunnel_rx(skb, tunnel->dev, tunnel->net);

View file

@ -226,6 +226,8 @@ static int llc_ui_release(struct socket *sock)
} }
netdev_put(llc->dev, &llc->dev_tracker); netdev_put(llc->dev, &llc->dev_tracker);
sock_put(sk); sock_put(sk);
sock_orphan(sk);
sock->sk = NULL;
llc_sk_free(sk); llc_sk_free(sk);
out: out:
return 0; return 0;

View file

@ -2314,9 +2314,6 @@ bool __mptcp_retransmit_pending_data(struct sock *sk)
if (__mptcp_check_fallback(msk)) if (__mptcp_check_fallback(msk))
return false; return false;
if (tcp_rtx_and_write_queues_empty(sk))
return false;
/* the closing socket has some data untransmitted and/or unacked: /* the closing socket has some data untransmitted and/or unacked:
* some data in the mptcp rtx queue has not really xmitted yet. * some data in the mptcp rtx queue has not really xmitted yet.
* keep it simple and re-inject the whole mptcp level rtx queue * keep it simple and re-inject the whole mptcp level rtx queue

View file

@ -30,6 +30,7 @@
#define mtype_del IPSET_TOKEN(MTYPE, _del) #define mtype_del IPSET_TOKEN(MTYPE, _del)
#define mtype_list IPSET_TOKEN(MTYPE, _list) #define mtype_list IPSET_TOKEN(MTYPE, _list)
#define mtype_gc IPSET_TOKEN(MTYPE, _gc) #define mtype_gc IPSET_TOKEN(MTYPE, _gc)
#define mtype_cancel_gc IPSET_TOKEN(MTYPE, _cancel_gc)
#define mtype MTYPE #define mtype MTYPE
#define get_ext(set, map, id) ((map)->extensions + ((set)->dsize * (id))) #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; struct mtype *map = set->data;
if (SET_WITH_TIMEOUT(set))
del_timer_sync(&map->gc);
if (set->dsize && set->extensions & IPSET_EXT_DESTROY) if (set->dsize && set->extensions & IPSET_EXT_DESTROY)
mtype_ext_cleanup(set); mtype_ext_cleanup(set);
ip_set_free(map->members); ip_set_free(map->members);
@ -290,6 +288,15 @@ mtype_gc(struct timer_list *t)
add_timer(&map->gc); 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 = { static const struct ip_set_type_variant mtype = {
.kadt = mtype_kadt, .kadt = mtype_kadt,
.uadt = mtype_uadt, .uadt = mtype_uadt,
@ -303,6 +310,7 @@ static const struct ip_set_type_variant mtype = {
.head = mtype_head, .head = mtype_head,
.list = mtype_list, .list = mtype_list,
.same_set = mtype_same_set, .same_set = mtype_same_set,
.cancel_gc = mtype_cancel_gc,
}; };
#endif /* __IP_SET_BITMAP_IP_GEN_H */ #endif /* __IP_SET_BITMAP_IP_GEN_H */

View file

@ -1182,6 +1182,14 @@ ip_set_destroy_set(struct ip_set *set)
kfree(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, static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info,
const struct nlattr * const attr[]) 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))) if (unlikely(protocol_min_failed(attr)))
return -IPSET_ERR_PROTOCOL; return -IPSET_ERR_PROTOCOL;
/* Must wait for flush to be really finished in list:set */
rcu_barrier();
/* Commands are serialized and references are /* Commands are serialized and references are
* protected by the ip_set_ref_lock. * 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 * counter, so if it's already zero, we can proceed
* without holding the lock. * without holding the lock.
*/ */
read_lock_bh(&ip_set_ref_lock);
if (!attr[IPSET_ATTR_SETNAME]) { 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++) { for (i = 0; i < inst->ip_set_max; i++) {
s = ip_set(inst, i); s = ip_set(inst, i);
if (s && (s->ref || s->ref_netlink)) { 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); s = ip_set(inst, i);
if (s) { if (s) {
ip_set(inst, i) = NULL; ip_set(inst, i) = NULL;
/* Must cancel garbage collectors */
s->variant->cancel_gc(s);
ip_set_destroy_set(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; inst->is_destroyed = false;
} else { } else {
u32 flags = flag_exist(info->nlh); 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]), s = find_set_and_id(inst, nla_data(attr[IPSET_ATTR_SETNAME]),
&i); &i);
if (!s) { if (!s) {
@ -1238,10 +1251,16 @@ static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info,
ret = -IPSET_ERR_BUSY; ret = -IPSET_ERR_BUSY;
goto out; goto out;
} }
features = s->type->features;
ip_set(inst, i) = NULL; ip_set(inst, i) = NULL;
read_unlock_bh(&ip_set_ref_lock); read_unlock_bh(&ip_set_ref_lock);
if (features & IPSET_TYPE_NAME) {
ip_set_destroy_set(s); /* 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; return 0;
out: 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; ip_set(inst, to_id) = from;
write_unlock_bh(&ip_set_ref_lock); write_unlock_bh(&ip_set_ref_lock);
/* Make sure all readers of the old set pointers are completed. */
synchronize_rcu();
return 0; return 0;
} }
@ -2409,8 +2425,11 @@ ip_set_fini(void)
{ {
nf_unregister_sockopt(&so_set); nf_unregister_sockopt(&so_set);
nfnetlink_subsys_unregister(&ip_set_netlink_subsys); nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
unregister_pernet_subsys(&ip_set_net_ops); unregister_pernet_subsys(&ip_set_net_ops);
/* Wait for call_rcu() in destroy */
rcu_barrier();
pr_debug("these are the famous last words\n"); pr_debug("these are the famous last words\n");
} }

View file

@ -222,6 +222,7 @@ static const union nf_inet_addr zeromask = {};
#undef mtype_gc_do #undef mtype_gc_do
#undef mtype_gc #undef mtype_gc
#undef mtype_gc_init #undef mtype_gc_init
#undef mtype_cancel_gc
#undef mtype_variant #undef mtype_variant
#undef mtype_data_match #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_do IPSET_TOKEN(MTYPE, _gc_do)
#define mtype_gc IPSET_TOKEN(MTYPE, _gc) #define mtype_gc IPSET_TOKEN(MTYPE, _gc)
#define mtype_gc_init IPSET_TOKEN(MTYPE, _gc_init) #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_variant IPSET_TOKEN(MTYPE, _variant)
#define mtype_data_match IPSET_TOKEN(MTYPE, _data_match) #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 htype *h = set->data;
struct list_head *l, *lt; 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); mtype_ahash_destroy(set, ipset_dereference_nfnl(h->table), true);
list_for_each_safe(l, lt, &h->ad) { list_for_each_safe(l, lt, &h->ad) {
list_del(l); list_del(l);
@ -599,6 +598,15 @@ mtype_gc_init(struct htable_gc *gc)
queue_delayed_work(system_power_efficient_wq, &gc->dwork, HZ); 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 static int
mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext, mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
struct ip_set_ext *mext, u32 flags); struct ip_set_ext *mext, u32 flags);
@ -1441,6 +1449,7 @@ static const struct ip_set_type_variant mtype_variant = {
.uref = mtype_uref, .uref = mtype_uref,
.resize = mtype_resize, .resize = mtype_resize,
.same_set = mtype_same_set, .same_set = mtype_same_set,
.cancel_gc = mtype_cancel_gc,
.region_lock = true, .region_lock = true,
}; };

View file

@ -426,9 +426,6 @@ list_set_destroy(struct ip_set *set)
struct list_set *map = set->data; struct list_set *map = set->data;
struct set_elem *e, *n; 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_for_each_entry_safe(e, n, &map->members, list) {
list_del(&e->list); list_del(&e->list);
ip_set_put_byindex(map->net, e->id); 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; 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 = { static const struct ip_set_type_variant set_variant = {
.kadt = list_set_kadt, .kadt = list_set_kadt,
.uadt = list_set_uadt, .uadt = list_set_uadt,
@ -558,6 +564,7 @@ static const struct ip_set_type_variant set_variant = {
.head = list_set_head, .head = list_set_head,
.list = list_set_list, .list = list_set_list,
.same_set = list_set_same_set, .same_set = list_set_same_set,
.cancel_gc = list_set_cancel_gc,
}; };
static void static void

View file

@ -283,7 +283,7 @@ sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
pr_debug("Setting vtag %x for secondary conntrack\n", pr_debug("Setting vtag %x for secondary conntrack\n",
sh->vtag); sh->vtag);
ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = 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 /* If it is a shutdown ack OOTB packet, we expect a return
shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */ shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
pr_debug("Setting vtag %x for new conn OOTB\n", pr_debug("Setting vtag %x for new conn OOTB\n",

View file

@ -457,7 +457,8 @@ static void tcp_init_sender(struct ip_ct_tcp_state *sender,
const struct sk_buff *skb, const struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
const struct tcphdr *tcph, const struct tcphdr *tcph,
u32 end, u32 win) u32 end, u32 win,
enum ip_conntrack_dir dir)
{ {
/* SYN-ACK in reply to a SYN /* SYN-ACK in reply to a SYN
* or SYN from reply direction in simultaneous open. * 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 * Both sides must send the Window Scale option
* to enable window scaling in either direction. * 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)) { receiver->flags & IP_CT_TCP_FLAG_WINDOW_SCALE)) {
sender->td_scale = 0; sender->td_scale = 0;
receiver->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) { if (tcph->syn) {
tcp_init_sender(sender, receiver, tcp_init_sender(sender, receiver,
skb, dataoff, tcph, skb, dataoff, tcph,
end, win); end, win, dir);
if (!tcph->ack) if (!tcph->ack)
/* Simultaneous open */ /* Simultaneous open */
return NFCT_TCP_ACCEPT; 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, tcp_init_sender(sender, receiver,
skb, dataoff, tcph, skb, dataoff, tcph,
end, win); end, win, dir);
if (dir == IP_CT_DIR_REPLY && !tcph->ack) if (dir == IP_CT_DIR_REPLY && !tcph->ack)
return NFCT_TCP_ACCEPT; return NFCT_TCP_ACCEPT;

View file

@ -193,10 +193,11 @@ void nf_logger_put(int pf, enum nf_log_type type)
return; return;
} }
BUG_ON(loggers[pf][type] == NULL);
rcu_read_lock(); rcu_read_lock();
logger = rcu_dereference(loggers[pf][type]); logger = rcu_dereference(loggers[pf][type]);
if (!logger)
WARN_ON_ONCE(1);
else
module_put(logger->me); module_put(logger->me);
rcu_read_unlock(); rcu_read_unlock();
} }

View file

@ -7551,11 +7551,15 @@ static int nft_object_dump(struct sk_buff *skb, unsigned int attr,
return -1; 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; const struct nft_object_type *type;
list_for_each_entry(type, &nf_tables_objects, list) { list_for_each_entry(type, &nf_tables_objects, list) {
if (type->family != NFPROTO_UNSPEC &&
type->family != family)
continue;
if (objtype == type->type) if (objtype == type->type)
return 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 * 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; 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)) if (type != NULL && try_module_get(type->owner))
return type; 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) if (info->nlh->nlmsg_flags & NLM_F_REPLACE)
return -EOPNOTSUPP; return -EOPNOTSUPP;
type = __nft_obj_type_get(objtype); type = __nft_obj_type_get(objtype, family);
if (WARN_ON_ONCE(!type)) if (WARN_ON_ONCE(!type))
return -ENOENT; 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)) if (!nft_use_inc(&table->use))
return -EMFILE; return -EMFILE;
type = nft_obj_type_get(net, objtype); type = nft_obj_type_get(net, objtype, family);
if (IS_ERR(type)) { if (IS_ERR(type)) {
err = PTR_ERR(type); err = PTR_ERR(type);
goto err_type; goto err_type;

View file

@ -1250,7 +1250,31 @@ static int nft_ct_expect_obj_init(const struct nft_ctx *ctx,
if (tb[NFTA_CT_EXPECT_L3PROTO]) if (tb[NFTA_CT_EXPECT_L3PROTO])
priv->l3num = ntohs(nla_get_be16(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]); 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->dport = nla_get_be16(tb[NFTA_CT_EXPECT_DPORT]);
priv->timeout = nla_get_u32(tb[NFTA_CT_EXPECT_TIMEOUT]); priv->timeout = nla_get_u32(tb[NFTA_CT_EXPECT_TIMEOUT]);
priv->size = nla_get_u8(tb[NFTA_CT_EXPECT_SIZE]); priv->size = nla_get_u8(tb[NFTA_CT_EXPECT_SIZE]);

View file

@ -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 = { static struct nft_object_type nft_tunnel_obj_type __read_mostly = {
.type = NFT_OBJECT_TUNNEL, .type = NFT_OBJECT_TUNNEL,
.family = NFPROTO_NETDEV,
.ops = &nft_tunnel_obj_ops, .ops = &nft_tunnel_obj_ops,
.maxattr = NFTA_TUNNEL_KEY_MAX, .maxattr = NFTA_TUNNEL_KEY_MAX,
.policy = nft_tunnel_key_policy, .policy = nft_tunnel_key_policy,

View file

@ -1208,6 +1208,10 @@ void nci_free_device(struct nci_dev *ndev)
{ {
nfc_free_device(ndev->nfc_dev); nfc_free_device(ndev->nfc_dev);
nci_hci_deallocate(ndev); nci_hci_deallocate(ndev);
/* drop partial rx data packet if present */
if (ndev->rx_data_reassembly)
kfree_skb(ndev->rx_data_reassembly);
kfree(ndev); kfree(ndev);
} }
EXPORT_SYMBOL(nci_free_device); EXPORT_SYMBOL(nci_free_device);

View file

@ -1877,9 +1877,15 @@ static bool smcd_lgr_match(struct smc_link_group *lgr,
struct smcd_dev *smcismdev, struct smcd_dev *smcismdev,
struct smcd_gid *peer_gid) struct smcd_gid *peer_gid)
{ {
return lgr->peer_gid.gid == peer_gid->gid && lgr->smcd == smcismdev && if (lgr->peer_gid.gid != peer_gid->gid ||
smc_ism_is_virtual(smcismdev) ? lgr->smcd != smcismdev)
(lgr->peer_gid.gid_ext == peer_gid->gid_ext) : 1; 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) */ /* create a new SMC connection (and a new link group if necessary) */

View file

@ -1344,13 +1344,11 @@ static void unix_state_double_lock(struct sock *sk1, struct sock *sk2)
unix_state_lock(sk1); unix_state_lock(sk1);
return; return;
} }
if (sk1 < sk2) { if (sk1 > sk2)
swap(sk1, sk2);
unix_state_lock(sk1); unix_state_lock(sk1);
unix_state_lock_nested(sk2); unix_state_lock_nested(sk2, U_LOCK_SECOND);
} else {
unix_state_lock(sk2);
unix_state_lock_nested(sk1);
}
} }
static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2) static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2)
@ -1591,7 +1589,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
goto out_unlock; goto out_unlock;
} }
unix_state_lock_nested(sk); unix_state_lock_nested(sk, U_LOCK_SECOND);
if (sk->sk_state != st) { if (sk->sk_state != st) {
unix_state_unlock(sk); unix_state_unlock(sk);

View file

@ -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 * queue lock. With the other's queue locked it's
* OK to lock the state. * OK to lock the state.
*/ */
unix_state_lock_nested(req); unix_state_lock_nested(req, U_LOCK_DIAG);
peer = unix_sk(req)->peer; peer = unix_sk(req)->peer;
buf[i++] = (peer ? sock_i_ino(peer) : 0); buf[i++] = (peer ? sock_i_ino(peer) : 0);
unix_state_unlock(req); unix_state_unlock(req);

View file

@ -48,6 +48,17 @@ test_LAG_cleanup()
ip link add mv0 link "$name" up address "$ucaddr" type macvlan ip link add mv0 link "$name" up address "$ucaddr" type macvlan
# Used to test dev->mc handling # Used to test dev->mc handling
ip address add "$addr6" dev "$name" 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 set dev "$name" down
ip link del "$name" ip link del "$name"

View file

@ -1,3 +1,5 @@
CONFIG_DUMMY=y
CONFIG_IPV6=y
CONFIG_MACVLAN=y
CONFIG_NET_TEAM=y CONFIG_NET_TEAM=y
CONFIG_NET_TEAM_MODE_LOADBALANCE=y CONFIG_NET_TEAM_MODE_LOADBALANCE=y
CONFIG_MACVLAN=y

View file

@ -53,8 +53,7 @@ TEST_PROGS += bind_bhash.sh
TEST_PROGS += ip_local_port_range.sh TEST_PROGS += ip_local_port_range.sh
TEST_PROGS += rps_default_mask.sh TEST_PROGS += rps_default_mask.sh
TEST_PROGS += big_tcp.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
TEST_PROGS_EXTENDED += toeplitz_client.sh toeplitz.sh lib.sh
TEST_GEN_FILES = socket nettest TEST_GEN_FILES = socket nettest
TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy reuseport_addr_any TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy reuseport_addr_any
TEST_GEN_FILES += tcp_mmap tcp_inq psock_snd txring_overwrite 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 += sctp_hello
TEST_GEN_FILES += csum TEST_GEN_FILES += csum
TEST_GEN_FILES += nat6to4.o TEST_GEN_FILES += nat6to4.o
TEST_GEN_FILES += xdp_dummy.o
TEST_GEN_FILES += ip_local_port_range TEST_GEN_FILES += ip_local_port_range
TEST_GEN_FILES += bind_wildcard TEST_GEN_FILES += bind_wildcard
TEST_PROGS += test_vxlan_mdb.sh TEST_PROGS += test_vxlan_mdb.sh
@ -95,6 +95,7 @@ TEST_PROGS += fq_band_pktlimit.sh
TEST_PROGS += vlan_hw_filter.sh TEST_PROGS += vlan_hw_filter.sh
TEST_FILES := settings TEST_FILES := settings
TEST_FILES += in_netns.sh lib.sh net_helper.sh setup_loopback.sh setup_veth.sh
include ../lib.mk include ../lib.mk
@ -104,7 +105,7 @@ $(OUTPUT)/tcp_inq: LDLIBS += -lpthread
$(OUTPUT)/bind_bhash: LDLIBS += -lpthread $(OUTPUT)/bind_bhash: LDLIBS += -lpthread
$(OUTPUT)/io_uring_zerocopy_tx: CFLAGS += -I../../../include/ $(OUTPUT)/io_uring_zerocopy_tx: CFLAGS += -I../../../include/
# Rules to generate bpf obj nat6to4.o # Rules to generate bpf objs
CLANG ?= clang CLANG ?= clang
SCRATCH_DIR := $(OUTPUT)/tools SCRATCH_DIR := $(OUTPUT)/tools
BUILD_DIR := $(SCRATCH_DIR)/build BUILD_DIR := $(SCRATCH_DIR)/build
@ -139,7 +140,7 @@ endif
CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG),$(CLANG_TARGET_ARCH)) 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 $@ $(CLANG) -O2 --target=bpf -c $< $(CCINCLUDE) $(CLANG_SYS_INCLUDES) -o $@
$(BPFOBJ): $(wildcard $(BPFDIR)/*.[ch] $(BPFDIR)/Makefile) \ $(BPFOBJ): $(wildcard $(BPFDIR)/*.[ch] $(BPFDIR)/Makefile) \

View file

@ -19,8 +19,11 @@ CONFIG_BRIDGE_VLAN_FILTERING=y
CONFIG_BRIDGE=y CONFIG_BRIDGE=y
CONFIG_CRYPTO_CHACHA20POLY1305=m CONFIG_CRYPTO_CHACHA20POLY1305=m
CONFIG_VLAN_8021Q=y CONFIG_VLAN_8021Q=y
CONFIG_GENEVE=m
CONFIG_IFB=y CONFIG_IFB=y
CONFIG_INET_DIAG=y CONFIG_INET_DIAG=y
CONFIG_INET_ESP=y
CONFIG_INET_ESP_OFFLOAD=y
CONFIG_IP_GRE=m CONFIG_IP_GRE=m
CONFIG_NETFILTER=y CONFIG_NETFILTER=y
CONFIG_NETFILTER_ADVANCED=y CONFIG_NETFILTER_ADVANCED=y
@ -29,7 +32,10 @@ CONFIG_NF_NAT=m
CONFIG_IP6_NF_IPTABLES=m CONFIG_IP6_NF_IPTABLES=m
CONFIG_IP_NF_IPTABLES=m CONFIG_IP_NF_IPTABLES=m
CONFIG_IP6_NF_NAT=m CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_RAW=m
CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT=m
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_TARGET_TTL=m
CONFIG_IPV6_GRE=m CONFIG_IPV6_GRE=m
CONFIG_IPV6_SEG6_LWTUNNEL=y CONFIG_IPV6_SEG6_LWTUNNEL=y
CONFIG_L2TP_ETH=m CONFIG_L2TP_ETH=m
@ -45,8 +51,14 @@ CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_IPV6=y CONFIG_NF_TABLES_IPV6=y
CONFIG_NF_TABLES_IPV4=y CONFIG_NF_TABLES_IPV4=y
CONFIG_NFT_NAT=m 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_GACT=m
CONFIG_NET_ACT_PEDIT=m
CONFIG_NET_CLS_BASIC=m CONFIG_NET_CLS_BASIC=m
CONFIG_NET_CLS_BPF=m
CONFIG_NET_CLS_MATCHALL=m
CONFIG_NET_CLS_U32=m CONFIG_NET_CLS_U32=m
CONFIG_NET_IPGRE_DEMUX=m CONFIG_NET_IPGRE_DEMUX=m
CONFIG_NET_IPGRE=m CONFIG_NET_IPGRE=m
@ -55,6 +67,9 @@ CONFIG_NET_SCH_HTB=m
CONFIG_NET_SCH_FQ=m CONFIG_NET_SCH_FQ=m
CONFIG_NET_SCH_ETF=m CONFIG_NET_SCH_ETF=m
CONFIG_NET_SCH_NETEM=y CONFIG_NET_SCH_NETEM=y
CONFIG_NET_SCH_PRIO=m
CONFIG_NFT_COMPAT=m
CONFIG_NF_FLOW_TABLE=m
CONFIG_PSAMPLE=m CONFIG_PSAMPLE=m
CONFIG_TCP_MD5SIG=y CONFIG_TCP_MD5SIG=y
CONFIG_TEST_BLACKHOLE_DEV=m CONFIG_TEST_BLACKHOLE_DEV=m
@ -80,3 +95,4 @@ CONFIG_IP_SCTP=m
CONFIG_NETFILTER_XT_MATCH_POLICY=m CONFIG_NETFILTER_XT_MATCH_POLICY=m
CONFIG_CRYPTO_ARIA=y CONFIG_CRYPTO_ARIA=y
CONFIG_XFRM_INTERFACE=m CONFIG_XFRM_INTERFACE=m
CONFIG_XFRM_USER=m

View file

@ -112,7 +112,7 @@ TEST_PROGS = bridge_fdb_learning_limit.sh \
vxlan_symmetric_ipv6.sh \ vxlan_symmetric_ipv6.sh \
vxlan_symmetric.sh vxlan_symmetric.sh
TEST_PROGS_EXTENDED := devlink_lib.sh \ TEST_FILES := devlink_lib.sh \
ethtool_lib.sh \ ethtool_lib.sh \
fib_offload_lib.sh \ fib_offload_lib.sh \
forwarding.config.sample \ forwarding.config.sample \

View file

@ -4,6 +4,9 @@
############################################################################## ##############################################################################
# Defines # Defines
WAIT_TIMEOUT=${WAIT_TIMEOUT:=20}
BUSYWAIT_TIMEOUT=$((WAIT_TIMEOUT * 1000)) # ms
# Kselftest framework requirement - SKIP code is 4. # Kselftest framework requirement - SKIP code is 4.
ksft_skip=4 ksft_skip=4
# namespace list created by setup_ns # namespace list created by setup_ns
@ -48,7 +51,7 @@ cleanup_ns()
for ns in "$@"; do for ns in "$@"; do
ip netns delete "${ns}" &> /dev/null 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" echo "Warn: Failed to remove namespace $ns"
ret=1 ret=1
fi fi

View file

@ -22,8 +22,11 @@ CONFIG_NFT_TPROXY=m
CONFIG_NFT_SOCKET=m CONFIG_NFT_SOCKET=m
CONFIG_IP_ADVANCED_ROUTER=y CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IPV6_MULTIPLE_TABLES=y CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_IP6_NF_FILTER=m
CONFIG_NET_ACT_CSUM=m CONFIG_NET_ACT_CSUM=m
CONFIG_NET_ACT_PEDIT=m CONFIG_NET_ACT_PEDIT=m
CONFIG_NET_CLS_ACT=y CONFIG_NET_CLS_ACT=y

View file

@ -643,13 +643,6 @@ kill_events_pids()
mptcp_lib_kill_wait $evts_ns2_pid 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() pm_nl_set_limits()
{ {
local ns=$1 local ns=$1
@ -3453,7 +3446,7 @@ userspace_tests()
chk_mptcp_info subflows 0 subflows 0 chk_mptcp_info subflows 0 subflows 0
chk_subflows_total 1 1 chk_subflows_total 1 1
kill_events_pids kill_events_pids
wait $tests_pid mptcp_lib_kill_wait $tests_pid
fi fi
# userspace pm create destroy subflow # userspace pm create destroy subflow
@ -3475,7 +3468,7 @@ userspace_tests()
chk_mptcp_info subflows 0 subflows 0 chk_mptcp_info subflows 0 subflows 0
chk_subflows_total 1 1 chk_subflows_total 1 1
kill_events_pids kill_events_pids
wait $tests_pid mptcp_lib_kill_wait $tests_pid
fi fi
# userspace pm create id 0 subflow # userspace pm create id 0 subflow
@ -3494,7 +3487,7 @@ userspace_tests()
chk_mptcp_info subflows 1 subflows 1 chk_mptcp_info subflows 1 subflows 1
chk_subflows_total 2 2 chk_subflows_total 2 2
kill_events_pids kill_events_pids
wait $tests_pid mptcp_lib_kill_wait $tests_pid
fi fi
# userspace pm remove initial subflow # userspace pm remove initial subflow
@ -3518,7 +3511,7 @@ userspace_tests()
chk_mptcp_info subflows 1 subflows 1 chk_mptcp_info subflows 1 subflows 1
chk_subflows_total 1 1 chk_subflows_total 1 1
kill_events_pids kill_events_pids
wait $tests_pid mptcp_lib_kill_wait $tests_pid
fi fi
# userspace pm send RM_ADDR for ID 0 # userspace pm send RM_ADDR for ID 0
@ -3544,7 +3537,7 @@ userspace_tests()
chk_mptcp_info subflows 1 subflows 1 chk_mptcp_info subflows 1 subflows 1
chk_subflows_total 1 1 chk_subflows_total 1 1
kill_events_pids kill_events_pids
wait $tests_pid mptcp_lib_kill_wait $tests_pid
fi fi
} }
@ -3558,7 +3551,8 @@ endpoint_tests()
pm_nl_set_limits $ns2 2 2 pm_nl_set_limits $ns2 2 2
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
speed=slow \ 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 wait_mpj $ns1
pm_nl_check_endpoint "creation" \ pm_nl_check_endpoint "creation" \
@ -3573,7 +3567,7 @@ endpoint_tests()
pm_nl_add_endpoint $ns2 10.0.2.2 flags signal pm_nl_add_endpoint $ns2 10.0.2.2 flags signal
pm_nl_check_endpoint "modif is allowed" \ pm_nl_check_endpoint "modif is allowed" \
$ns2 10.0.2.2 id 1 flags signal $ns2 10.0.2.2 id 1 flags signal
kill_tests_wait mptcp_lib_kill_wait $tests_pid
fi fi
if reset "delete and re-add" && if reset "delete and re-add" &&
@ -3582,7 +3576,8 @@ endpoint_tests()
pm_nl_set_limits $ns2 1 1 pm_nl_set_limits $ns2 1 1
pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow
test_linkfail=4 speed=20 \ 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 wait_mpj $ns2
chk_subflow_nr "before delete" 2 chk_subflow_nr "before delete" 2
@ -3597,7 +3592,7 @@ endpoint_tests()
wait_mpj $ns2 wait_mpj $ns2
chk_subflow_nr "after re-add" 2 chk_subflow_nr "after re-add" 2
chk_mptcp_info subflows 1 subflows 1 chk_mptcp_info subflows 1 subflows 1
kill_tests_wait mptcp_lib_kill_wait $tests_pid
fi fi
} }

View file

@ -6,7 +6,7 @@ readonly KSFT_FAIL=1
readonly KSFT_SKIP=4 readonly KSFT_SKIP=4
# shellcheck disable=SC2155 # declare and assign separately # 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=() MPTCP_LIB_SUBTESTS=()

View file

@ -1 +1 @@
timeout=1200 timeout=1800

View file

@ -284,12 +284,12 @@ done
setup setup
run_test 10 10 0 0 "balanced bwidth" 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 # we still need some additional infrastructure to pass the following test-cases
run_test 30 10 0 0 "unbalanced bwidth" run_test 10 3 0 0 "unbalanced bwidth"
run_test 30 10 1 50 "unbalanced bwidth with unbalanced delay" run_test 10 3 1 25 "unbalanced bwidth with unbalanced delay"
run_test 30 10 50 1 "unbalanced bwidth with opposed, unbalanced delay" run_test 10 3 25 1 "unbalanced bwidth with opposed, unbalanced delay"
mptcp_lib_result_print_all_tap mptcp_lib_result_print_all_tap
exit $ret exit $ret

0
tools/testing/selftests/net/net_helper.sh Executable file → Normal file
View file

View file

@ -707,22 +707,22 @@ setup_xfrm6() {
} }
setup_xfrm4udp() { setup_xfrm4udp() {
setup_xfrm 4 ${veth4_a_addr} ${veth4_b_addr} "encap espinudp 4500 4500 0.0.0.0" setup_xfrm 4 ${veth4_a_addr} ${veth4_b_addr} "encap espinudp 4500 4500 0.0.0.0" && \
setup_nettest_xfrm 4 4500 setup_nettest_xfrm 4 4500
} }
setup_xfrm6udp() { setup_xfrm6udp() {
setup_xfrm 6 ${veth6_a_addr} ${veth6_b_addr} "encap espinudp 4500 4500 0.0.0.0" setup_xfrm 6 ${veth6_a_addr} ${veth6_b_addr} "encap espinudp 4500 4500 0.0.0.0" && \
setup_nettest_xfrm 6 4500 setup_nettest_xfrm 6 4500
} }
setup_xfrm4udprouted() { setup_xfrm4udprouted() {
setup_xfrm 4 ${prefix4}.${a_r1}.1 ${prefix4}.${b_r1}.1 "encap espinudp 4500 4500 0.0.0.0" 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_nettest_xfrm 4 4500
} }
setup_xfrm6udprouted() { setup_xfrm6udprouted() {
setup_xfrm 6 ${prefix6}:${a_r1}::1 ${prefix6}:${b_r1}::1 "encap espinudp 4500 4500 0.0.0.0" 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_nettest_xfrm 6 4500
} }
@ -1339,7 +1339,7 @@ test_pmtu_ipvX_over_bridged_vxlanY_or_geneveY_exception() {
sleep 1 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=$(du -sb $tmpoutfile)
size=${size%%/tmp/*} size=${size%%/tmp/*}

0
tools/testing/selftests/net/setup_loopback.sh Executable file → Normal file
View file

View file

@ -11,7 +11,7 @@ setup_veth_ns() {
local -r ns_mac="$4" local -r ns_mac="$4"
[[ -e /var/run/netns/"${ns_name}" ]] || ip netns add "${ns_name}" [[ -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 link set dev "${ns_dev}" netns "${ns_name}" mtu 65535
ip -netns "${ns_name}" link set dev "${ns_dev}" up ip -netns "${ns_name}" link set dev "${ns_dev}" up

View 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

View file

@ -417,9 +417,9 @@ struct test_key {
matches_vrf : 1, matches_vrf : 1,
is_current : 1, is_current : 1,
is_rnext : 1, is_rnext : 1,
used_on_handshake : 1, used_on_server_tx : 1,
used_after_accept : 1, used_on_client_tx : 1,
used_on_client : 1; skip_counters_checks : 1;
}; };
struct key_collection { struct key_collection {
@ -609,16 +609,14 @@ static int key_collection_socket(bool server, unsigned int port)
addr = &this_ip_dest; addr = &this_ip_dest;
sndid = key->client_keyid; sndid = key->client_keyid;
rcvid = key->server_keyid; rcvid = key->server_keyid;
set_current = key->is_current; key->used_on_client_tx = set_current = key->is_current;
set_rnext = key->is_rnext; key->used_on_server_tx = set_rnext = key->is_rnext;
} }
if (test_add_key_cr(sk, key->password, key->len, if (test_add_key_cr(sk, key->password, key->len,
*addr, vrf, sndid, rcvid, key->maclen, *addr, vrf, sndid, rcvid, key->maclen,
key->alg, set_current, set_rnext)) key->alg, set_current, set_rnext))
test_key_error("setsockopt(TCP_AO_ADD_KEY)", key); test_key_error("setsockopt(TCP_AO_ADD_KEY)", key);
if (set_current || set_rnext)
key->used_on_handshake = 1;
#ifdef DEBUG #ifdef DEBUG
test_print("%s [%u/%u] key: { %s, %u:%u, %u, %u:%u:%u:%u (%u)}", test_print("%s [%u/%u] key: { %s, %u:%u, %u, %u:%u:%u:%u (%u)}",
server ? "server" : "client", i, collection.nr_keys, 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++) { for (i = 0; i < collection.nr_keys; i++) {
struct test_key *key = &collection.keys[i]; struct test_key *key = &collection.keys[i];
uint8_t sndid, rcvid; uint8_t sndid, rcvid;
bool was_used; bool rx_cnt_expected;
if (key->skip_counters_checks)
continue;
if (server) { if (server) {
sndid = key->server_keyid; sndid = key->server_keyid;
rcvid = key->client_keyid; rcvid = key->client_keyid;
if (is_listen_sk) rx_cnt_expected = key->used_on_client_tx;
was_used = key->used_on_handshake;
else
was_used = key->used_after_accept;
} else { } else {
sndid = key->client_keyid; sndid = key->client_keyid;
rcvid = key->server_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); sndid, rcvid);
} }
test_tcp_ao_counters_free(a); 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 */ synchronize_threads(); /* 4: verified => closed */
close(sk); close(sk);
verify_counters(tst_name, true, false, begin, &end); verify_counters(tst_name, false, true, begin, &end);
synchronize_threads(); /* 5: counters */ synchronize_threads(); /* 5: counters */
} }
@ -916,9 +914,8 @@ static int run_client(const char *tst_name, unsigned int port,
current_index = nr_keys - 1; current_index = nr_keys - 1;
if (rnext_index < 0) if (rnext_index < 0)
rnext_index = nr_keys - 1; rnext_index = nr_keys - 1;
collection.keys[current_index].used_on_handshake = 1; collection.keys[current_index].used_on_client_tx = 1;
collection.keys[rnext_index].used_after_accept = 1; collection.keys[rnext_index].used_on_server_tx = 1;
collection.keys[rnext_index].used_on_client = 1;
synchronize_threads(); /* 3: accepted => send data */ synchronize_threads(); /* 3: accepted => send data */
if (test_client_verify(sk, msg_sz, msg_nr, TEST_TIMEOUT_SEC)) { 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"); test_error("Can't change the current key");
if (test_client_verify(sk, msg_len, nr_packets, TEST_TIMEOUT_SEC)) if (test_client_verify(sk, msg_len, nr_packets, TEST_TIMEOUT_SEC))
test_fail("verify failed"); 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); 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, verify_current_rnext(tst_name, sk, -1,
collection.keys[i].server_keyid); 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 */ synchronize_threads(); /* verify current/rnext */
} }
end_client(tst_name, sk, nr_keys, current_index, rnext_index, &tmp); end_client(tst_name, sk, nr_keys, current_index, rnext_index, &tmp);

View file

@ -62,7 +62,9 @@ int test_wait_fd(int sk, time_t sec, bool write)
return -ETIMEDOUT; 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 -ret;
return 0; 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; size_t buf_sz = msg_len * nr;
char *buf = alloca(buf_sz); char *buf = alloca(buf_sz);
ssize_t ret;
randomize_buffer(buf, buf_sz); randomize_buffer(buf, buf_sz);
if (test_client_loop(sk, buf, buf_sz, msg_len, timeout_sec) != buf_sz) ret = test_client_loop(sk, buf, buf_sz, msg_len, timeout_sec);
return -1; if (ret < 0)
return 0; return (int)ret;
return ret != buf_sz ? -1 : 0;
} }

View file

@ -1,10 +1,33 @@
// SPDX-License-Identifier: GPL-2.0 // 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 <inttypes.h>
#include "../../../../include/linux/kernel.h" #include "../../../../include/linux/kernel.h"
#include "aolib.h" #include "aolib.h"
const size_t quota = 1000; const size_t quota = 1000;
const size_t packet_sz = 100;
/* /*
* Backlog == 0 means 1 connection in queue, see: * Backlog == 0 means 1 connection in queue, see:
* commit 64a146513f8f ("[NET]: Revert incorrect accept queue...") * commit 64a146513f8f ("[NET]: Revert incorrect accept queue...")
@ -59,26 +82,6 @@ static void close_forced(int sk)
close(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) static void test_server_active_rst(unsigned int port)
{ {
struct tcp_ao_counters cnt1, cnt2; 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); 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)) if (test_get_tcp_ao_counters(sk, &ao2))
test_error("test_get_tcp_ao_counters()"); 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); close(sk);
synchronize_threads(); /* 5: restore the socket, send more data */
test_tcp_ao_counters_cmp("passive RST server", &ao1, &ao2, TEST_CNT_GOOD); test_tcp_ao_counters_cmp("passive RST server", &ao1, &ao2, TEST_CNT_GOOD);
synchronize_threads(); /* 5: verified => closed */ synchronize_threads(); /* 6: server exits */
close(sk);
} }
static void *server_fn(void *arg) 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); test_error("test_wait_fds(): %d", err);
synchronize_threads(); /* 3: close listen socket */ 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"); test_fail("Failed to send data on connected socket");
else else
test_ok("Verified established tcp connection"); test_ok("Verified established tcp connection");
@ -323,7 +325,6 @@ static void test_client_passive_rst(unsigned int port)
struct tcp_sock_state img; struct tcp_sock_state img;
sockaddr_af saddr; sockaddr_af saddr;
int sk, err; int sk, err;
socklen_t slen = sizeof(err);
sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP); sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
if (sk < 0) if (sk < 0)
@ -337,18 +338,51 @@ static void test_client_passive_rst(unsigned int port)
test_error("failed to connect()"); test_error("failed to connect()");
synchronize_threads(); /* 2: accepted => send data */ 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"); test_fail("Failed to send data on connected socket");
else else
test_ok("Verified established tcp connection"); test_ok("Verified established tcp connection");
synchronize_threads(); /* 3: chekpoint/restore the connection */ synchronize_threads(); /* 3: checkpoint the client */
test_enable_repair(sk); test_enable_repair(sk);
test_sock_checkpoint(sk, &img, &saddr); test_sock_checkpoint(sk, &img, &saddr);
test_ao_checkpoint(sk, &ao_img); 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); sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
if (sk < 0) if (sk < 0)
@ -366,25 +400,33 @@ static void test_client_passive_rst(unsigned int port)
test_disable_repair(sk); test_disable_repair(sk);
test_sock_state_free(&img); 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)) * This is how "passive reset" is acquired in this test from TCP_TW_RST:
test_ok("client connection broken post-seq-adjust"); *
* 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 else
test_fail("client connection still works post-seq-adjust"); test_fail("client sock is yet connected 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");
if (test_get_tcp_ao_counters(sk, &ao2)) if (test_get_tcp_ao_counters(sk, &ao2))
test_error("test_get_tcp_ao_counters()"); test_error("test_get_tcp_ao_counters()");
synchronize_threads(); /* 5: verified => closed */ synchronize_threads(); /* 6: server exits */
close(sk); close(sk);
test_tcp_ao_counters_cmp("client passive RST", &ao1, &ao2, TEST_CNT_GOOD); 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[]) int main(int argc, char *argv[])
{ {
test_init(15, server_fn, client_fn); test_init(14, server_fn, client_fn);
return 0; return 0;
} }

View file

@ -0,0 +1 @@
timeout=120

View file

@ -7,7 +7,7 @@ source net_helper.sh
readonly PEER_NS="ns-peer-$(mktemp -u XXXXXX)" 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. # set global exit status, but never reset nonzero one.
check_err() check_err()
@ -197,7 +197,7 @@ run_all() {
} }
if [ ! -f ${BPF_FILE} ]; then if [ ! -f ${BPF_FILE} ]; then
echo "Missing ${BPF_FILE}. Build bpf selftest first" echo "Missing ${BPF_FILE}. Run 'make' first"
exit -1 exit -1
fi fi

View file

@ -7,7 +7,7 @@ source net_helper.sh
readonly PEER_NS="ns-peer-$(mktemp -u XXXXXX)" readonly PEER_NS="ns-peer-$(mktemp -u XXXXXX)"
BPF_FILE="../bpf/xdp_dummy.bpf.o" BPF_FILE="xdp_dummy.o"
cleanup() { cleanup() {
local -r jobs="$(jobs -p)" local -r jobs="$(jobs -p)"
@ -84,7 +84,7 @@ run_all() {
} }
if [ ! -f ${BPF_FILE} ]; then if [ ! -f ${BPF_FILE} ]; then
echo "Missing ${BPF_FILE}. Build bpf selftest first" echo "Missing ${BPF_FILE}. Run 'make' first"
exit -1 exit -1
fi fi

View file

@ -7,7 +7,7 @@ source net_helper.sh
readonly PEER_NS="ns-peer-$(mktemp -u XXXXXX)" readonly PEER_NS="ns-peer-$(mktemp -u XXXXXX)"
BPF_FILE="../bpf/xdp_dummy.bpf.o" BPF_FILE="xdp_dummy.o"
cleanup() { cleanup() {
local -r jobs="$(jobs -p)" local -r jobs="$(jobs -p)"
@ -85,12 +85,12 @@ run_all() {
} }
if [ ! -f ${BPF_FILE} ]; then if [ ! -f ${BPF_FILE} ]; then
echo "Missing ${BPF_FILE}. Build bpf selftest first" echo "Missing ${BPF_FILE}. Run 'make' first"
exit -1 exit -1
fi fi
if [ ! -f nat6to4.o ]; then if [ ! -f nat6to4.o ]; then
echo "Missing nat6to4 helper. Build bpf nat6to4.o selftest first" echo "Missing nat6to4 helper. Run 'make' first"
exit -1 exit -1
fi fi

View file

@ -1,7 +1,9 @@
#!/bin/bash #!/bin/bash
# SPDX-License-Identifier: GPL-2.0 # 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 BASE="ns-$(mktemp -u XXXXXX)"
readonly SRC=2 readonly SRC=2
readonly DST=1 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 $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 & ip netns exec $NS_DST ./udpgso_bench_rx -C 1000 -R 10 -n 10 -l 1300 $rx_args &
local spid=$! 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 ip netns exec $NS_SRC ./udpgso_bench_tx $family -M 1 -s 13000 -S 1300 -D $dst
local retc=$? local retc=$?
wait $spid 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 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 & ip netns exec $NS_DST taskset 0x2 ./udpgso_bench_rx -C 1000 -R 10 &
local spid=$! 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 ip netns exec $NS_SRC taskset 0x1 ./udpgso_bench_tx $family -l 3 -S 1300 -D $dst
local retc=$? local retc=$?
wait $spid wait $spid

View file

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: GPL-2.0 # 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 STATS="$(mktemp -p /tmp ns-XXXXXX)"
readonly BASE=`basename $STATS` readonly BASE=`basename $STATS`
readonly SRC=2 readonly SRC=2
@ -218,7 +218,7 @@ while getopts "hs:" option; do
done done
if [ ! -f ${BPF_FILE} ]; then if [ ! -f ${BPF_FILE} ]; then
echo "Missing ${BPF_FILE}. Build bpf selftest first" echo "Missing ${BPF_FILE}. Run 'make' first"
exit 1 exit 1
fi fi

View 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";