Pull networking fixes from Jakub Kicinski: "Including fixes from netfilter. Current release - new code bugs: - clear msg_get_inq in __sys_recvfrom() and __copy_msghdr_from_user() - mptcp: - invoke MP_FAIL response only when needed - fix shutdown vs fallback race - consistent map handling on failure - octeon_ep: use bitwise AND Previous releases - regressions: - tipc: move bc link creation back to tipc_node_create, fix NPD Previous releases - always broken: - tcp: add a missing nf_reset_ct() in 3WHS handling to prevent socket buffered skbs from keeping refcount on the conntrack module - ipv6: take care of disable_policy when restoring routes - tun: make sure to always disable and unlink NAPI instances - phy: don't trigger state machine while in suspend - netfilter: nf_tables: avoid skb access on nf_stolen - asix: fix "can't send until first packet is send" issue - usb: asix: do not force pause frames support - nxp-nci: don't issue a zero length i2c_master_read() Misc: - ncsi: allow use of proper "mellanox" DT vendor prefix - act_api: add a message for user space if any actions were already flushed before the error was hit" * tag 'net-5.19-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (55 commits) net: dsa: felix: fix race between reading PSFP stats and port stats selftest: tun: add test for NAPI dismantle net: tun: avoid disabling NAPI twice net: sparx5: mdb add/del handle non-sparx5 devices net: sfp: fix memory leak in sfp_probe() mlxsw: spectrum_router: Fix rollback in tunnel next hop init net: rose: fix UAF bugs caused by timer handler net: usb: ax88179_178a: Fix packet receiving net: bonding: fix use-after-free after 802.3ad slave unbind ipv6: fix lockdep splat in in6_dump_addrs() net: phy: ax88772a: fix lost pause advertisement configuration net: phy: Don't trigger state machine while in suspend usbnet: fix memory allocation in helpers selftests net: fix kselftest net fatal error NFC: nxp-nci: don't print header length mismatch on i2c error NFC: nxp-nci: Don't issue a zero length i2c_master_read() net: tipc: fix possible refcount leak in tipc_sk_create() nfc: nfcmrvl: Fix irq_of_parse_and_map() return value net: ipv6: unexport __init-annotated seg6_hmac_net_init() ipv6/sit: fix ipip6_tunnel_get_prl return value ...
Unified · Split
| @@ -14397,9 +14397,8 @@ F: Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml · 14396 unmodified lines | |||
| 14397 | F: sound/soc/codecs/tfa989x.c | 14397 | F: sound/soc/codecs/tfa989x.c |
| 14398 | 14398 | ||
| 14399 | NXP-NCI NFC DRIVER | 14399 | NXP-NCI NFC DRIVER |
| 14400 | R: Charles Gorand <charles.gorand@effinnov.com> | ||
| 14401 | L: linux-nfc@lists.01.org (subscribers-only) | 14400 | L: linux-nfc@lists.01.org (subscribers-only) |
| 14402 | S: Supported | 14401 | S: Orphan |
| 14403 | F: Documentation/devicetree/bindings/net/nfc/nxp,nci.yaml | 14402 | F: Documentation/devicetree/bindings/net/nfc/nxp,nci.yaml |
| 14404 | F: drivers/nfc/nxp-nci | 14403 | F: drivers/nfc/nxp-nci |
| 14405 | 14404 | ||
| @@ -2228,7 +2228,8 @@ void bond_3ad_unbind_slave(struct slave *slave) · 2227 unmodified lines | |||
| 2228 | temp_aggregator->num_of_ports--; | 2228 | temp_aggregator->num_of_ports--; |
| 2229 | if (__agg_active_ports(temp_aggregator) == 0) { | 2229 | if (__agg_active_ports(temp_aggregator) == 0) { |
| 2230 | select_new_active_agg = temp_aggregator->is_active; | 2230 | select_new_active_agg = temp_aggregator->is_active; |
| 2231 | ad_clear_agg(temp_aggregator); | 2231 | if (temp_aggregator->num_of_ports == 0) |
| 2232 | ad_clear_agg(temp_aggregator); | ||
| 2232 | if (select_new_active_agg) { | 2233 | if (select_new_active_agg) { |
| 2233 | slave_info(bond->dev, slave->dev, "Removing an active aggregator\n"); | 2234 | slave_info(bond->dev, slave->dev, "Removing an active aggregator\n"); |
| 2234 | /* select new active aggregator */ | 2235 | /* select new active aggregator */ |
| @@ -1302,12 +1302,12 @@ int bond_alb_initialize(struct bonding *bond, int rlb_enabled) · 1301 unmodified lines | |||
| 1302 | return res; | 1302 | return res; |
| 1303 | 1303 | ||
| 1304 | if (rlb_enabled) { | 1304 | if (rlb_enabled) { |
| 1305 | bond->alb_info.rlb_enabled = 1; | ||
| 1306 | res = rlb_initialize(bond); | 1305 | res = rlb_initialize(bond); |
| 1307 | if (res) { | 1306 | if (res) { |
| 1308 | tlb_deinitialize(bond); | 1307 | tlb_deinitialize(bond); |
| 1309 | return res; | 1308 | return res; |
| 1310 | } | 1309 | } |
| 1310 | bond->alb_info.rlb_enabled = 1; | ||
| 1311 | } else { | 1311 | } else { |
| 1312 | bond->alb_info.rlb_enabled = 0; | 1312 | bond->alb_info.rlb_enabled = 0; |
| 1313 | } | 1313 | } |
| @@ -878,6 +878,11 @@ static void bcm_sf2_sw_mac_link_up(struct dsa_switch *ds, int port, · 877 unmodified lines | |||
| 878 | if (duplex == DUPLEX_FULL) | 878 | if (duplex == DUPLEX_FULL) |
| 879 | reg |= DUPLX_MODE; | 879 | reg |= DUPLX_MODE; |
| 880 | 880 | ||
| 881 | if (tx_pause) | ||
| 882 | reg |= TXFLOW_CNTL; | ||
| 883 | if (rx_pause) | ||
| 884 | reg |= RXFLOW_CNTL; | ||
| 885 | |||
| 881 | core_writel(priv, reg, offset); | 886 | core_writel(priv, reg, offset); |
| 882 | } | 887 | } |
| 883 | 888 | ||
| @@ -300,6 +300,7 @@ static int hellcreek_led_setup(struct hellcreek *hellcreek) · 299 unmodified lines | |||
| 300 | const char *label, *state; | 300 | const char *label, *state; |
| 301 | int ret = -EINVAL; | 301 | int ret = -EINVAL; |
| 302 | 302 | ||
| 303 | of_node_get(hellcreek->dev->of_node); | ||
| 303 | leds = of_find_node_by_name(hellcreek->dev->of_node, "leds"); | 304 | leds = of_find_node_by_name(hellcreek->dev->of_node, "leds"); |
| 304 | if (!leds) { | 305 | if (!leds) { |
| 305 | dev_err(hellcreek->dev, "No LEDs specified in device tree!\n"); | 306 | dev_err(hellcreek->dev, "No LEDs specified in device tree!\n"); |
| @@ -1886,6 +1886,8 @@ static void vsc9959_psfp_sgi_table_del(struct ocelot *ocelot, · 1885 unmodified lines | |||
| 1886 | static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index, | 1886 | static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index, |
| 1887 | struct felix_stream_filter_counters *counters) | 1887 | struct felix_stream_filter_counters *counters) |
| 1888 | { | 1888 | { |
| 1889 | mutex_lock(&ocelot->stats_lock); | ||
| 1890 | |||
| 1889 | ocelot_rmw(ocelot, SYS_STAT_CFG_STAT_VIEW(index), | 1891 | ocelot_rmw(ocelot, SYS_STAT_CFG_STAT_VIEW(index), |
| 1890 | SYS_STAT_CFG_STAT_VIEW_M, | 1892 | SYS_STAT_CFG_STAT_VIEW_M, |
| 1891 | SYS_STAT_CFG); | 1893 | SYS_STAT_CFG); |
| @@ -1900,6 +1902,8 @@ static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index, · 8 unmodified lines | |||
| 1900 | SYS_STAT_CFG_STAT_VIEW(index) | | 1902 | SYS_STAT_CFG_STAT_VIEW(index) | |
| 1901 | SYS_STAT_CFG_STAT_CLEAR_SHOT(0x10), | 1903 | SYS_STAT_CFG_STAT_CLEAR_SHOT(0x10), |
| 1902 | SYS_STAT_CFG); | 1904 | SYS_STAT_CFG); |
| 1905 | |||
| 1906 | mutex_unlock(&ocelot->stats_lock); | ||
| 1903 | } | 1907 | } |
| 1904 | 1908 | ||
| 1905 | static int vsc9959_psfp_filter_add(struct ocelot *ocelot, int port, | 1909 | static int vsc9959_psfp_filter_add(struct ocelot *ocelot, int port, |
| @@ -52,7 +52,7 @@ · 51 unmodified lines | |||
| 52 | 52 | ||
| 53 | #define CN93_SDP_EPF_RINFO_SRN(val) ((val) & 0xFF) | 53 | #define CN93_SDP_EPF_RINFO_SRN(val) ((val) & 0xFF) |
| 54 | #define CN93_SDP_EPF_RINFO_RPVF(val) (((val) >> 32) & 0xF) | 54 | #define CN93_SDP_EPF_RINFO_RPVF(val) (((val) >> 32) & 0xF) |
| 55 | #define CN93_SDP_EPF_RINFO_NVFS(val) (((val) >> 48) && 0xFF) | 55 | #define CN93_SDP_EPF_RINFO_NVFS(val) (((val) >> 48) & 0xFF) |
| 56 | 56 | ||
| 57 | /* SDP Function select */ | 57 | /* SDP Function select */ |
| 58 | #define CN93_SDP_FUNC_SEL_EPF_BIT_POS 8 | 58 | #define CN93_SDP_FUNC_SEL_EPF_BIT_POS 8 |
| @@ -4415,6 +4415,8 @@ static int mlxsw_sp_nexthop4_init(struct mlxsw_sp *mlxsw_sp, · 4414 unmodified lines | |||
| 4415 | return 0; | 4415 | return 0; |
| 4416 | 4416 | ||
| 4417 | err_nexthop_neigh_init: | 4417 | err_nexthop_neigh_init: |
| 4418 | list_del(&nh->router_list_node); | ||
| 4419 | mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh); | ||
| 4418 | mlxsw_sp_nexthop_remove(mlxsw_sp, nh); | 4420 | mlxsw_sp_nexthop_remove(mlxsw_sp, nh); |
| 4419 | return err; | 4421 | return err; |
| 4420 | } | 4422 | } |
| @@ -6740,6 +6742,7 @@ static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp, · 2319 unmodified lines | |||
| 6740 | const struct fib6_info *rt) | 6742 | const struct fib6_info *rt) |
| 6741 | { | 6743 | { |
| 6742 | struct net_device *dev = rt->fib6_nh->fib_nh_dev; | 6744 | struct net_device *dev = rt->fib6_nh->fib_nh_dev; |
| 6745 | int err; | ||
| 6743 | 6746 | ||
| 6744 | nh->nhgi = nh_grp->nhgi; | 6747 | nh->nhgi = nh_grp->nhgi; |
| 6745 | nh->nh_weight = rt->fib6_nh->fib_nh_weight; | 6748 | nh->nh_weight = rt->fib6_nh->fib_nh_weight; |
| @@ -6755,7 +6758,16 @@ static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp, · 9 unmodified lines | |||
| 6755 | return 0; | 6758 | return 0; |
| 6756 | nh->ifindex = dev->ifindex; | 6759 | nh->ifindex = dev->ifindex; |
| 6757 | 6760 | ||
| 6758 | return mlxsw_sp_nexthop_type_init(mlxsw_sp, nh, dev); | 6761 | err = mlxsw_sp_nexthop_type_init(mlxsw_sp, nh, dev); |
| 6762 | if (err) | ||
| 6763 | goto err_nexthop_type_init; | ||
| 6764 | |||
| 6765 | return 0; | ||
| 6766 | |||
| 6767 | err_nexthop_type_init: | ||
| 6768 | list_del(&nh->router_list_node); | ||
| 6769 | mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh); | ||
| 6770 | return err; | ||
| 6759 | } | 6771 | } |
| 6760 | 6772 | ||
| 6761 | static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp *mlxsw_sp, | 6773 | static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp *mlxsw_sp, |
| @@ -396,6 +396,9 @@ static int sparx5_handle_port_mdb_add(struct net_device *dev, · 395 unmodified lines | |||
| 396 | u32 mact_entry; | 396 | u32 mact_entry; |
| 397 | int res, err; | 397 | int res, err; |
| 398 | 398 | ||
| 399 | if (!sparx5_netdevice_check(dev)) | ||
| 400 | return -EOPNOTSUPP; | ||
| 401 | |||
| 399 | if (netif_is_bridge_master(v->obj.orig_dev)) { | 402 | if (netif_is_bridge_master(v->obj.orig_dev)) { |
| 400 | sparx5_mact_learn(spx5, PGID_CPU, v->addr, v->vid); | 403 | sparx5_mact_learn(spx5, PGID_CPU, v->addr, v->vid); |
| 401 | return 0; | 404 | return 0; |
| @@ -466,6 +469,9 @@ static int sparx5_handle_port_mdb_del(struct net_device *dev, · 64 unmodified lines | |||
| 466 | u32 mact_entry, res, pgid_entry[3]; | 469 | u32 mact_entry, res, pgid_entry[3]; |
| 467 | int err; | 470 | int err; |
| 468 | 471 | ||
| 472 | if (!sparx5_netdevice_check(dev)) | ||
| 473 | return -EOPNOTSUPP; | ||
| 474 | |||
| 469 | if (netif_is_bridge_master(v->obj.orig_dev)) { | 475 | if (netif_is_bridge_master(v->obj.orig_dev)) { |
| 470 | sparx5_mact_forget(spx5, v->addr, v->vid); | 476 | sparx5_mact_forget(spx5, v->addr, v->vid); |
| 471 | return 0; | 477 | return 0; |
| @@ -1515,14 +1515,14 @@ static void epic_remove_one(struct pci_dev *pdev) · 1514 unmodified lines | |||
| 1515 | struct net_device *dev = pci_get_drvdata(pdev); | 1515 | struct net_device *dev = pci_get_drvdata(pdev); |
| 1516 | struct epic_private *ep = netdev_priv(dev); | 1516 | struct epic_private *ep = netdev_priv(dev); |
| 1517 | 1517 | ||
| 1518 | unregister_netdev(dev); | ||
| 1518 | dma_free_coherent(&pdev->dev, TX_TOTAL_SIZE, ep->tx_ring, | 1519 | dma_free_coherent(&pdev->dev, TX_TOTAL_SIZE, ep->tx_ring, |
| 1519 | ep->tx_ring_dma); | 1520 | ep->tx_ring_dma); |
| 1520 | dma_free_coherent(&pdev->dev, RX_TOTAL_SIZE, ep->rx_ring, | 1521 | dma_free_coherent(&pdev->dev, RX_TOTAL_SIZE, ep->rx_ring, |
| 1521 | ep->rx_ring_dma); | 1522 | ep->rx_ring_dma); |
| 1522 | unregister_netdev(dev); | ||
| 1523 | pci_iounmap(pdev, ep->ioaddr); | 1523 | pci_iounmap(pdev, ep->ioaddr); |
| 1524 | pci_release_regions(pdev); | ||
| 1525 | free_netdev(dev); | 1524 | free_netdev(dev); |
| 1525 | pci_release_regions(pdev); | ||
| 1526 | pci_disable_device(pdev); | 1526 | pci_disable_device(pdev); |
| 1527 | /* pci_power_off(pdev, -1); */ | 1527 | /* pci_power_off(pdev, -1); */ |
| 1528 | } | 1528 | } |
| @@ -88,8 +88,10 @@ static void asix_ax88772a_link_change_notify(struct phy_device *phydev) · 87 unmodified lines | |||
| 88 | /* Reset PHY, otherwise MII_LPA will provide outdated information. | 88 | /* Reset PHY, otherwise MII_LPA will provide outdated information. |
| 89 | * This issue is reproducible only with some link partner PHYs | 89 | * This issue is reproducible only with some link partner PHYs |
| 90 | */ | 90 | */ |
| 91 | if (phydev->state == PHY_NOLINK && phydev->drv->soft_reset) | 91 | if (phydev->state == PHY_NOLINK) { |
| 92 | phydev->drv->soft_reset(phydev); | 92 | phy_init_hw(phydev); |
| 93 | phy_start_aneg(phydev); | ||
| 94 | } | ||
| 93 | } | 95 | } |
| 94 | 96 | ||
| 95 | static struct phy_driver asix_driver[] = { | 97 | static struct phy_driver asix_driver[] = { |
| @@ -229,9 +229,7 @@ static int dp83822_config_intr(struct phy_device *phydev) · 228 unmodified lines | |||
| 229 | if (misr_status < 0) | 229 | if (misr_status < 0) |
| 230 | return misr_status; | 230 | return misr_status; |
| 231 | 231 | ||
| 232 | misr_status |= (DP83822_RX_ERR_HF_INT_EN | | 232 | misr_status |= (DP83822_LINK_STAT_INT_EN | |
| 233 | DP83822_FALSE_CARRIER_HF_INT_EN | | ||
| 234 | DP83822_LINK_STAT_INT_EN | | ||
| 235 | DP83822_ENERGY_DET_INT_EN | | 233 | DP83822_ENERGY_DET_INT_EN | |
| 236 | DP83822_LINK_QUAL_INT_EN); | 234 | DP83822_LINK_QUAL_INT_EN); |
| 237 | 235 | ||
| @@ -31,6 +31,7 @@ · 30 unmodified lines | |||
| 31 | #include <linux/io.h> | 31 | #include <linux/io.h> |
| 32 | #include <linux/uaccess.h> | 32 | #include <linux/uaccess.h> |
| 33 | #include <linux/atomic.h> | 33 | #include <linux/atomic.h> |
| 34 | #include <linux/suspend.h> | ||
| 34 | #include <net/netlink.h> | 35 | #include <net/netlink.h> |
| 35 | #include <net/genetlink.h> | 36 | #include <net/genetlink.h> |
| 36 | #include <net/sock.h> | 37 | #include <net/sock.h> |
| @@ -976,6 +977,28 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat) · 939 unmodified lines | |||
| 976 | struct phy_driver *drv = phydev->drv; | 977 | struct phy_driver *drv = phydev->drv; |
| 977 | irqreturn_t ret; | 978 | irqreturn_t ret; |
| 978 | 979 | ||
| 980 | /* Wakeup interrupts may occur during a system sleep transition. | ||
| 981 | * Postpone handling until the PHY has resumed. | ||
| 982 | */ | ||
| 983 | if (IS_ENABLED(CONFIG_PM_SLEEP) && phydev->irq_suspended) { | ||
| 984 | struct net_device *netdev = phydev->attached_dev; | ||
| 985 | |||
| 986 | if (netdev) { | ||
| 987 | struct device *parent = netdev->dev.parent; | ||
| 988 | |||
| 989 | if (netdev->wol_enabled) | ||
| 990 | pm_system_wakeup(); | ||
| 991 | else if (device_may_wakeup(&netdev->dev)) | ||
| 992 | pm_wakeup_dev_event(&netdev->dev, 0, true); | ||
| 993 | else if (parent && device_may_wakeup(parent)) | ||
| 994 | pm_wakeup_dev_event(parent, 0, true); | ||
| 995 | } | ||
| 996 | |||
| 997 | phydev->irq_rerun = 1; | ||
| 998 | disable_irq_nosync(irq); | ||
| 999 | return IRQ_HANDLED; | ||
| 1000 | } | ||
| 1001 | |||
| 979 | mutex_lock(&phydev->lock); | 1002 | mutex_lock(&phydev->lock); |
| 980 | ret = drv->handle_interrupt(phydev); | 1003 | ret = drv->handle_interrupt(phydev); |
| 981 | mutex_unlock(&phydev->lock); | 1004 | mutex_unlock(&phydev->lock); |
| @@ -278,6 +278,15 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev) · 277 unmodified lines | |||
| 278 | if (phydev->mac_managed_pm) | 278 | if (phydev->mac_managed_pm) |
| 279 | return 0; | 279 | return 0; |
| 280 | 280 | ||
| 281 | /* Wakeup interrupts may occur during the system sleep transition when | ||
| 282 | * the PHY is inaccessible. Set flag to postpone handling until the PHY | ||
| 283 | * has resumed. Wait for concurrent interrupt handler to complete. | ||
| 284 | */ | ||
| 285 | if (phy_interrupt_is_valid(phydev)) { | ||
| 286 | phydev->irq_suspended = 1; | ||
| 287 | synchronize_irq(phydev->irq); | ||
| 288 | } | ||
| 289 | |||
| 281 | /* We must stop the state machine manually, otherwise it stops out of | 290 | /* We must stop the state machine manually, otherwise it stops out of |
| 282 | * control, possibly with the phydev->lock held. Upon resume, netdev | 291 | * control, possibly with the phydev->lock held. Upon resume, netdev |
| 283 | * may call phy routines that try to grab the same lock, and that may | 292 | * may call phy routines that try to grab the same lock, and that may |
| @@ -315,6 +324,20 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev) · 31 unmodified lines | |||
| 315 | if (ret < 0) | 324 | if (ret < 0) |
| 316 | return ret; | 325 | return ret; |
| 317 | no_resume: | 326 | no_resume: |
| 327 | if (phy_interrupt_is_valid(phydev)) { | ||
| 328 | phydev->irq_suspended = 0; | ||
| 329 | synchronize_irq(phydev->irq); | ||
| 330 | |||
| 331 | /* Rerun interrupts which were postponed by phy_interrupt() | ||
| 332 | * because they occurred during the system sleep transition. | ||
| 333 | */ | ||
| 334 | if (phydev->irq_rerun) { | ||
| 335 | phydev->irq_rerun = 0; | ||
| 336 | enable_irq(phydev->irq); | ||
| 337 | irq_wake_thread(phydev->irq, phydev); | ||
| 338 | } | ||
| 339 | } | ||
| 340 | |||
| 318 | if (phydev->attached_dev && phydev->adjust_link) | 341 | if (phydev->attached_dev && phydev->adjust_link) |
| 319 | phy_start_machine(phydev); | 342 | phy_start_machine(phydev); |
| 320 | 343 | ||
| @@ -2516,7 +2516,7 @@ static int sfp_probe(struct platform_device *pdev) · 2515 unmodified lines | |||
| 2516 | 2516 | ||
| 2517 | platform_set_drvdata(pdev, sfp); | 2517 | platform_set_drvdata(pdev, sfp); |
| 2518 | 2518 | ||
| 2519 | err = devm_add_action(sfp->dev, sfp_cleanup, sfp); | 2519 | err = devm_add_action_or_reset(sfp->dev, sfp_cleanup, sfp); |
| 2520 | if (err < 0) | 2520 | if (err < 0) |
| 2521 | return err; | 2521 | return err; |
| 2522 | 2522 | ||
| @@ -273,6 +273,12 @@ static void tun_napi_init(struct tun_struct *tun, struct tun_file *tfile, · 272 unmodified lines | |||
| 273 | } | 273 | } |
| 274 | } | 274 | } |
| 275 | 275 | ||
| 276 | static void tun_napi_enable(struct tun_file *tfile) | ||
| 277 | { | ||
| 278 | if (tfile->napi_enabled) | ||
| 279 | napi_enable(&tfile->napi); | ||
| 280 | } | ||
| 281 | |||
| 276 | static void tun_napi_disable(struct tun_file *tfile) | 282 | static void tun_napi_disable(struct tun_file *tfile) |
| 277 | { | 283 | { |
| 278 | if (tfile->napi_enabled) | 284 | if (tfile->napi_enabled) |
| @@ -634,7 +640,8 @@ static void __tun_detach(struct tun_file *tfile, bool clean) · 355 unmodified lines | |||
| 634 | tun = rtnl_dereference(tfile->tun); | 640 | tun = rtnl_dereference(tfile->tun); |
| 635 | 641 | ||
| 636 | if (tun && clean) { | 642 | if (tun && clean) { |
| 637 | tun_napi_disable(tfile); | 643 | if (!tfile->detached) |
| 644 | tun_napi_disable(tfile); | ||
| 638 | tun_napi_del(tfile); | 645 | tun_napi_del(tfile); |
| 639 | } | 646 | } |
| 640 | 647 | ||
| @@ -653,8 +660,10 @@ static void __tun_detach(struct tun_file *tfile, bool clean) · 12 unmodified lines | |||
| 653 | if (clean) { | 660 | if (clean) { |
| 654 | RCU_INIT_POINTER(tfile->tun, NULL); | 661 | RCU_INIT_POINTER(tfile->tun, NULL); |
| 655 | sock_put(&tfile->sk); | 662 | sock_put(&tfile->sk); |
| 656 | } else | 663 | } else { |
| 657 | tun_disable_queue(tun, tfile); | 664 | tun_disable_queue(tun, tfile); |
| 665 | tun_napi_disable(tfile); | ||
| 666 | } | ||
| 658 | 667 | ||
| 659 | synchronize_net(); | 668 | synchronize_net(); |
| 660 | tun_flow_delete_by_queue(tun, tun->numqueues + 1); | 669 | tun_flow_delete_by_queue(tun, tun->numqueues + 1); |
| @@ -727,6 +736,7 @@ static void tun_detach_all(struct net_device *dev) · 66 unmodified lines | |||
| 727 | sock_put(&tfile->sk); | 736 | sock_put(&tfile->sk); |
| 728 | } | 737 | } |
| 729 | list_for_each_entry_safe(tfile, tmp, &tun->disabled, next) { | 738 | list_for_each_entry_safe(tfile, tmp, &tun->disabled, next) { |
| 739 | tun_napi_del(tfile); | ||
| 730 | tun_enable_queue(tfile); | 740 | tun_enable_queue(tfile); |
| 731 | tun_queue_purge(tfile); | 741 | tun_queue_purge(tfile); |
| 732 | xdp_rxq_info_unreg(&tfile->xdp_rxq); | 742 | xdp_rxq_info_unreg(&tfile->xdp_rxq); |
| @@ -807,6 +817,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file, · 74 unmodified lines | |||
| 807 | 817 | ||
| 808 | if (tfile->detached) { | 818 | if (tfile->detached) { |
| 809 | tun_enable_queue(tfile); | 819 | tun_enable_queue(tfile); |
| 820 | tun_napi_enable(tfile); | ||
| 810 | } else { | 821 | } else { |
| 811 | sock_hold(&tfile->sk); | 822 | sock_hold(&tfile->sk); |
| 812 | tun_napi_init(tun, tfile, napi, napi_frags); | 823 | tun_napi_init(tun, tfile, napi, napi_frags); |
| @@ -126,8 +126,7 @@ · 125 unmodified lines | |||
| 126 | AX_MEDIUM_RE) | 126 | AX_MEDIUM_RE) |
| 127 | 127 | ||
| 128 | #define AX88772_MEDIUM_DEFAULT \ | 128 | #define AX88772_MEDIUM_DEFAULT \ |
| 129 | (AX_MEDIUM_FD | AX_MEDIUM_RFC | \ | 129 | (AX_MEDIUM_FD | AX_MEDIUM_PS | \ |
| 130 | AX_MEDIUM_TFC | AX_MEDIUM_PS | \ | ||
| 131 | AX_MEDIUM_AC | AX_MEDIUM_RE) | 130 | AX_MEDIUM_AC | AX_MEDIUM_RE) |
| 132 | 131 | ||
| 133 | /* AX88772 & AX88178 RX_CTL values */ | 132 | /* AX88772 & AX88178 RX_CTL values */ |
| @@ -431,6 +431,7 @@ void asix_adjust_link(struct net_device *netdev) · 430 unmodified lines | |||
| 431 | 431 | ||
| 432 | asix_write_medium_mode(dev, mode, 0); | 432 | asix_write_medium_mode(dev, mode, 0); |
| 433 | phy_print_status(phydev); | 433 | phy_print_status(phydev); |
| 434 | usbnet_link_change(dev, phydev->link, 0); | ||
| 434 | } | 435 | } |
| 435 | 436 | ||
| 436 | int asix_write_gpio(struct usbnet *dev, u16 value, int sleep, int in_pm) | 437 | int asix_write_gpio(struct usbnet *dev, u16 value, int sleep, int in_pm) |
| @@ -1472,6 +1472,42 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb) · 1471 unmodified lines | |||
| 1472 | * are bundled into this buffer and where we can find an array of | 1472 | * are bundled into this buffer and where we can find an array of |
| 1473 | * per-packet metadata (which contains elements encoded into u16). | 1473 | * per-packet metadata (which contains elements encoded into u16). |
| 1474 | */ | 1474 | */ |
| 1475 | |||
| 1476 | /* SKB contents for current firmware: | ||
| 1477 | * <packet 1> <padding> | ||
| 1478 | * ... | ||
| 1479 | * <packet N> <padding> | ||
| 1480 | * <per-packet metadata entry 1> <dummy header> | ||
| 1481 | * ... | ||
| 1482 | * <per-packet metadata entry N> <dummy header> | ||
| 1483 | * <padding2> <rx_hdr> | ||
| 1484 | * | ||
| 1485 | * where: | ||
| 1486 | * <packet N> contains pkt_len bytes: | ||
| 1487 | * 2 bytes of IP alignment pseudo header | ||
| 1488 | * packet received | ||
| 1489 | * <per-packet metadata entry N> contains 4 bytes: | ||
| 1490 | * pkt_len and fields AX_RXHDR_* | ||
| 1491 | * <padding> 0-7 bytes to terminate at | ||
| 1492 | * 8 bytes boundary (64-bit). | ||
| 1493 | * <padding2> 4 bytes to make rx_hdr terminate at | ||
| 1494 | * 8 bytes boundary (64-bit) | ||
| 1495 | * <dummy-header> contains 4 bytes: | ||
| 1496 | * pkt_len=0 and AX_RXHDR_DROP_ERR | ||
| 1497 | * <rx-hdr> contains 4 bytes: | ||
| 1498 | * pkt_cnt and hdr_off (offset of | ||
| 1499 | * <per-packet metadata entry 1>) | ||
| 1500 | * | ||
| 1501 | * pkt_cnt is number of entrys in the per-packet metadata. | ||
| 1502 | * In current firmware there is 2 entrys per packet. | ||
| 1503 | * The first points to the packet and the | ||
| 1504 | * second is a dummy header. | ||
| 1505 | * This was done probably to align fields in 64-bit and | ||
| 1506 | * maintain compatibility with old firmware. | ||
| 1507 | * This code assumes that <dummy header> and <padding2> are | ||
| 1508 | * optional. | ||
| 1509 | */ | ||
| 1510 | |||
| 1475 | if (skb->len < 4) | 1511 | if (skb->len < 4) |
| 1476 | return 0; | 1512 | return 0; |
| 1477 | skb_trim(skb, skb->len - 4); | 1513 | skb_trim(skb, skb->len - 4); |
| @@ -1485,51 +1521,66 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb) · 7 unmodified lines | |||
| 1485 | /* Make sure that the bounds of the metadata array are inside the SKB | 1521 | /* Make sure that the bounds of the metadata array are inside the SKB |
| 1486 | * (and in front of the counter at the end). | 1522 | * (and in front of the counter at the end). |
| 1487 | */ | 1523 | */ |
| 1488 | if (pkt_cnt * 2 + hdr_off > skb->len) | 1524 | if (pkt_cnt * 4 + hdr_off > skb->len) |
| 1489 | return 0; | 1525 | return 0; |
| 1490 | pkt_hdr = (u32 *)(skb->data + hdr_off); | 1526 | pkt_hdr = (u32 *)(skb->data + hdr_off); |
| 1491 | 1527 | ||
| 1492 | /* Packets must not overlap the metadata array */ | 1528 | /* Packets must not overlap the metadata array */ |
| 1493 | skb_trim(skb, hdr_off); | 1529 | skb_trim(skb, hdr_off); |
| 1494 | 1530 | ||
| 1495 | for (; ; pkt_cnt--, pkt_hdr++) { | 1531 | for (; pkt_cnt > 0; pkt_cnt--, pkt_hdr++) { |
| 1532 | u16 pkt_len_plus_padd; | ||
| 1496 | u16 pkt_len; | 1533 | u16 pkt_len; |
| 1497 | 1534 | ||
| 1498 | le32_to_cpus(pkt_hdr); | 1535 | le32_to_cpus(pkt_hdr); |
| 1499 | pkt_len = (*pkt_hdr >> 16) & 0x1fff; | 1536 | pkt_len = (*pkt_hdr >> 16) & 0x1fff; |
| 1537 | pkt_len_plus_padd = (pkt_len + 7) & 0xfff8; | ||
| 1500 | 1538 | ||
| 1501 | if (pkt_len > skb->len) | 1539 | /* Skip dummy header used for alignment |
| 1540 | */ | ||
| 1541 | if (pkt_len == 0) | ||
| 1542 | continue; | ||
| 1543 | |||
| 1544 | if (pkt_len_plus_padd > skb->len) | ||
| 1502 | return 0; | 1545 | return 0; |
| 1503 | 1546 | ||
| 1504 | /* Check CRC or runt packet */ | 1547 | /* Check CRC or runt packet */ |
| 1505 | if (((*pkt_hdr & (AX_RXHDR_CRC_ERR | AX_RXHDR_DROP_ERR)) == 0) && | 1548 | if ((*pkt_hdr & (AX_RXHDR_CRC_ERR | AX_RXHDR_DROP_ERR)) || |
| 1506 | pkt_len >= 2 + ETH_HLEN) { | 1549 | pkt_len < 2 + ETH_HLEN) { |
| 1507 | bool last = (pkt_cnt == 0); | 1550 | dev->net->stats.rx_errors++; |
| 1508 | 1551 | skb_pull(skb, pkt_len_plus_padd); | |
| 1509 | if (last) { | 1552 | continue; |
| 1510 | ax_skb = skb; | 1553 | } |
| 1511 | } else { | ||
| 1512 | ax_skb = skb_clone(skb, GFP_ATOMIC); | ||
| 1513 | if (!ax_skb) | ||
| 1514 | return 0; | ||
| 1515 | } | ||
| 1516 | ax_skb->len = pkt_len; | ||
| 1517 | /* Skip IP alignment pseudo header */ | ||
| 1518 | skb_pull(ax_skb, 2); | ||
| 1519 | skb_set_tail_pointer(ax_skb, ax_skb->len); | ||
| 1520 | ax_skb->truesize = pkt_len + sizeof(struct sk_buff); | ||
| 1521 | ax88179_rx_checksum(ax_skb, pkt_hdr); | ||
| 1522 | 1554 | ||
| 1523 | if (last) | 1555 | /* last packet */ |
| 1524 | return 1; | 1556 | if (pkt_len_plus_padd == skb->len) { |
| 1557 | skb_trim(skb, pkt_len); | ||
| 1525 | 1558 | ||
| 1526 | usbnet_skb_return(dev, ax_skb); | 1559 | /* Skip IP alignment pseudo header */ |
| 1560 | skb_pull(skb, 2); | ||
| 1561 | |||
| 1562 | skb->truesize = SKB_TRUESIZE(pkt_len_plus_padd); | ||
| 1563 | ax88179_rx_checksum(skb, pkt_hdr); | ||
| 1564 | return 1; | ||
| 1527 | } | 1565 | } |
| 1528 | 1566 | ||
| 1529 | /* Trim this packet away from the SKB */ | 1567 | ax_skb = skb_clone(skb, GFP_ATOMIC); |
| 1530 | if (!skb_pull(skb, (pkt_len + 7) & 0xFFF8)) | 1568 | if (!ax_skb) |
| 1531 | return 0; | 1569 | return 0; |
| 1570 | skb_trim(ax_skb, pkt_len); | ||
| 1571 | |||
| 1572 | /* Skip IP alignment pseudo header */ | ||
| 1573 | skb_pull(ax_skb, 2); | ||
| 1574 | |||
| 1575 | skb->truesize = pkt_len_plus_padd + | ||
| 1576 | SKB_DATA_ALIGN(sizeof(struct sk_buff)); | ||
| 1577 | ax88179_rx_checksum(ax_skb, pkt_hdr); | ||
| 1578 | usbnet_skb_return(dev, ax_skb); | ||
| 1579 | |||
| 1580 | skb_pull(skb, pkt_len_plus_padd); | ||
| 1532 | } | 1581 | } |
| 1582 | |||
| 1583 | return 0; | ||
| 1533 | } | 1584 | } |
| 1534 | 1585 | ||
| 1535 | static struct sk_buff * | 1586 | static struct sk_buff * |
| @@ -2004,7 +2004,7 @@ static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype, · 2003 unmodified lines | |||
| 2004 | cmd, reqtype, value, index, size); | 2004 | cmd, reqtype, value, index, size); |
| 2005 | 2005 | ||
| 2006 | if (size) { | 2006 | if (size) { |
| 2007 | buf = kmalloc(size, GFP_KERNEL); | 2007 | buf = kmalloc(size, GFP_NOIO); |
| 2008 | if (!buf) | 2008 | if (!buf) |
| 2009 | goto out; | 2009 | goto out; |
| 2010 | } | 2010 | } |
| @@ -2036,7 +2036,7 @@ static int __usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype, · 25 unmodified lines | |||
| 2036 | cmd, reqtype, value, index, size); | 2036 | cmd, reqtype, value, index, size); |
| 2037 | 2037 | ||
| 2038 | if (data) { | 2038 | if (data) { |
| 2039 | buf = kmemdup(data, size, GFP_KERNEL); | 2039 | buf = kmemdup(data, size, GFP_NOIO); |
| 2040 | if (!buf) | 2040 | if (!buf) |
| 2041 | goto out; | 2041 | goto out; |
| 2042 | } else { | 2042 | } else { |
| @@ -167,9 +167,9 @@ static int nfcmrvl_i2c_parse_dt(struct device_node *node, · 166 unmodified lines | |||
| 167 | pdata->irq_polarity = IRQF_TRIGGER_RISING; | 167 | pdata->irq_polarity = IRQF_TRIGGER_RISING; |
| 168 | 168 | ||
| 169 | ret = irq_of_parse_and_map(node, 0); | 169 | ret = irq_of_parse_and_map(node, 0); |
| 170 | if (ret < 0) { | 170 | if (!ret) { |
| 171 | pr_err("Unable to get irq, error: %d\n", ret); | 171 | pr_err("Unable to get irq\n"); |
| 172 | return ret; | 172 | return -EINVAL; |
| 173 | } | 173 | } |
| 174 | pdata->irq = ret; | 174 | pdata->irq = ret; |
| 175 | 175 | ||
| @@ -115,9 +115,9 @@ static int nfcmrvl_spi_parse_dt(struct device_node *node, · 114 unmodified lines | |||
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | ret = irq_of_parse_and_map(node, 0); | 117 | ret = irq_of_parse_and_map(node, 0); |
| 118 | if (ret < 0) { | 118 | if (!ret) { |
| 119 | pr_err("Unable to get irq, error: %d\n", ret); | 119 | pr_err("Unable to get irq\n"); |
| 120 | return ret; | 120 | return -EINVAL; |
| 121 | } | 121 | } |
| 122 | pdata->irq = ret; | 122 | pdata->irq = ret; |
| 123 | 123 | ||
| @@ -122,7 +122,9 @@ static int nxp_nci_i2c_fw_read(struct nxp_nci_i2c_phy *phy, · 121 unmodified lines | |||
| 122 | skb_put_data(*skb, &header, NXP_NCI_FW_HDR_LEN); | 122 | skb_put_data(*skb, &header, NXP_NCI_FW_HDR_LEN); |
| 123 | 123 | ||
| 124 | r = i2c_master_recv(client, skb_put(*skb, frame_len), frame_len); | 124 | r = i2c_master_recv(client, skb_put(*skb, frame_len), frame_len); |
| 125 | if (r != frame_len) { | 125 | if (r < 0) { |
| 126 | goto fw_read_exit_free_skb; | ||
| 127 | } else if (r != frame_len) { | ||
| 126 | nfc_err(&client->dev, | 128 | nfc_err(&client->dev, |
| 127 | "Invalid frame length: %u (expected %zu)\n", | 129 | "Invalid frame length: %u (expected %zu)\n", |
| 128 | r, frame_len); | 130 | r, frame_len); |
| @@ -162,8 +164,13 @@ static int nxp_nci_i2c_nci_read(struct nxp_nci_i2c_phy *phy, · 33 unmodified lines | |||
| 162 | 164 | ||
| 163 | skb_put_data(*skb, (void *)&header, NCI_CTRL_HDR_SIZE); | 165 | skb_put_data(*skb, (void *)&header, NCI_CTRL_HDR_SIZE); |
| 164 | 166 | ||
| 167 | if (!header.plen) | ||
| 168 | return 0; | ||
| 169 | |||
| 165 | r = i2c_master_recv(client, skb_put(*skb, header.plen), header.plen); | 170 | r = i2c_master_recv(client, skb_put(*skb, header.plen), header.plen); |
| 166 | if (r != header.plen) { | 171 | if (r < 0) { |
| 172 | goto nci_read_exit_free_skb; | ||
| 173 | } else if (r != header.plen) { | ||
| 167 | nfc_err(&client->dev, | 174 | nfc_err(&client->dev, |
| 168 | "Invalid frame payload length: %u (expected %u)\n", | 175 | "Invalid frame payload length: %u (expected %u)\n", |
| 169 | r, header.plen); | 176 | r, header.plen); |
| @@ -1671,7 +1671,7 @@ enum netdev_priv_flags { · 1670 unmodified lines | |||
| 1671 | IFF_FAILOVER_SLAVE = 1<<28, | 1671 | IFF_FAILOVER_SLAVE = 1<<28, |
| 1672 | IFF_L3MDEV_RX_HANDLER = 1<<29, | 1672 | IFF_L3MDEV_RX_HANDLER = 1<<29, |
| 1673 | IFF_LIVE_RENAME_OK = 1<<30, | 1673 | IFF_LIVE_RENAME_OK = 1<<30, |
| 1674 | IFF_TX_SKB_NO_LINEAR = 1<<31, | 1674 | IFF_TX_SKB_NO_LINEAR = BIT_ULL(31), |
| 1675 | IFF_CHANGE_PROTO_DOWN = BIT_ULL(32), | 1675 | IFF_CHANGE_PROTO_DOWN = BIT_ULL(32), |
| 1676 | }; | 1676 | }; |
| 1677 | 1677 | ||
| @@ -572,6 +572,10 @@ struct macsec_ops; · 571 unmodified lines | |||
| 572 | * @mdix_ctrl: User setting of crossover | 572 | * @mdix_ctrl: User setting of crossover |
| 573 | * @pma_extable: Cached value of PMA/PMD Extended Abilities Register | 573 | * @pma_extable: Cached value of PMA/PMD Extended Abilities Register |
| 574 | * @interrupts: Flag interrupts have been enabled | 574 | * @interrupts: Flag interrupts have been enabled |
| 575 | * @irq_suspended: Flag indicating PHY is suspended and therefore interrupt | ||
| 576 | * handling shall be postponed until PHY has resumed | ||
| 577 | * @irq_rerun: Flag indicating interrupts occurred while PHY was suspended, | ||
| 578 | * requiring a rerun of the interrupt handler after resume | ||
| 575 | * @interface: enum phy_interface_t value | 579 | * @interface: enum phy_interface_t value |
| 576 | * @skb: Netlink message for cable diagnostics | 580 | * @skb: Netlink message for cable diagnostics |
| 577 | * @nest: Netlink nest used for cable diagnostics | 581 | * @nest: Netlink nest used for cable diagnostics |
| @@ -626,6 +630,8 @@ struct phy_device { · 48 unmodified lines | |||
| 626 | 630 | ||
| 627 | /* Interrupts are enabled */ | 631 | /* Interrupts are enabled */ |
| 628 | unsigned interrupts:1; | 632 | unsigned interrupts:1; |
| 633 | unsigned irq_suspended:1; | ||
| 634 | unsigned irq_rerun:1; | ||
| 629 | 635 | ||
| 630 | enum phy_state state; | 636 | enum phy_state state; |
| 631 | 637 | ||
| @@ -1338,24 +1338,28 @@ void nft_unregister_flowtable_type(struct nf_flowtable_type *type); · 1337 unmodified lines | |||
| 1338 | /** | 1338 | /** |
| 1339 | * struct nft_traceinfo - nft tracing information and state | 1339 | * struct nft_traceinfo - nft tracing information and state |
| 1340 | * | 1340 | * |
| 1341 | * @trace: other struct members are initialised | ||
| 1342 | * @nf_trace: copy of skb->nf_trace before rule evaluation | ||
| 1343 | * @type: event type (enum nft_trace_types) | ||
| 1344 | * @skbid: hash of skb to be used as trace id | ||
| 1345 | * @packet_dumped: packet headers sent in a previous traceinfo message | ||
| 1341 | * @pkt: pktinfo currently processed | 1346 | * @pkt: pktinfo currently processed |
| 1342 | * @basechain: base chain currently processed | 1347 | * @basechain: base chain currently processed |
| 1343 | * @chain: chain currently processed | 1348 | * @chain: chain currently processed |
| 1344 | * @rule: rule that was evaluated | 1349 | * @rule: rule that was evaluated |
| 1345 | * @verdict: verdict given by rule | 1350 | * @verdict: verdict given by rule |
| 1346 | * @type: event type (enum nft_trace_types) | ||
| 1347 | * @packet_dumped: packet headers sent in a previous traceinfo message | ||
| 1348 | * @trace: other struct members are initialised | ||
| 1349 | */ | 1351 | */ |
| 1350 | struct nft_traceinfo { | 1352 | struct nft_traceinfo { |
| 1353 | bool trace; | ||
| 1354 | bool nf_trace; | ||
| 1355 | bool packet_dumped; | ||
| 1356 | enum nft_trace_types type:8; | ||
| 1357 | u32 skbid; | ||
| 1351 | const struct nft_pktinfo *pkt; | 1358 | const struct nft_pktinfo *pkt; |
| 1352 | const struct nft_base_chain *basechain; | 1359 | const struct nft_base_chain *basechain; |
| 1353 | const struct nft_chain *chain; | 1360 | const struct nft_chain *chain; |
| 1354 | const struct nft_rule_dp *rule; | 1361 | const struct nft_rule_dp *rule; |
| 1355 | const struct nft_verdict *verdict; | 1362 | const struct nft_verdict *verdict; |
| 1356 | enum nft_trace_types type; | ||
| 1357 | bool packet_dumped; | ||
| 1358 | bool trace; | ||
| 1359 | }; | 1363 | }; |
| 1360 | 1364 | ||
| 1361 | void nft_trace_init(struct nft_traceinfo *info, const struct nft_pktinfo *pkt, | 1365 | void nft_trace_init(struct nft_traceinfo *info, const struct nft_pktinfo *pkt, |
| @@ -2,16 +2,17 @@ · 1 unmodified line | |||
| 2 | #ifndef _UAPI_MPTCP_H | 2 | #ifndef _UAPI_MPTCP_H |
| 3 | #define _UAPI_MPTCP_H | 3 | #define _UAPI_MPTCP_H |
| 4 | 4 | ||
| 5 | #ifndef __KERNEL__ | ||
| 6 | #include <netinet/in.h> /* for sockaddr_in and sockaddr_in6 */ | ||
| 7 | #include <sys/socket.h> /* for struct sockaddr */ | ||
| 8 | #endif | ||
| 9 | |||
| 5 | #include <linux/const.h> | 10 | #include <linux/const.h> |
| 6 | #include <linux/types.h> | 11 | #include <linux/types.h> |
| 7 | #include <linux/in.h> /* for sockaddr_in */ | 12 | #include <linux/in.h> /* for sockaddr_in */ |
| 8 | #include <linux/in6.h> /* for sockaddr_in6 */ | 13 | #include <linux/in6.h> /* for sockaddr_in6 */ |
| 9 | #include <linux/socket.h> /* for sockaddr_storage and sa_family */ | 14 | #include <linux/socket.h> /* for sockaddr_storage and sa_family */ |
| 10 | 15 | ||
| 11 | #ifndef __KERNEL__ | ||
| 12 | #include <sys/socket.h> /* for struct sockaddr */ | ||
| 13 | #endif | ||
| 14 | |||
| 15 | #define MPTCP_SUBFLOW_FLAG_MCAP_REM _BITUL(0) | 16 | #define MPTCP_SUBFLOW_FLAG_MCAP_REM _BITUL(0) |
| 16 | #define MPTCP_SUBFLOW_FLAG_MCAP_LOC _BITUL(1) | 17 | #define MPTCP_SUBFLOW_FLAG_MCAP_LOC _BITUL(1) |
| 17 | #define MPTCP_SUBFLOW_FLAG_JOIN_REM _BITUL(2) | 18 | #define MPTCP_SUBFLOW_FLAG_JOIN_REM _BITUL(2) |
| @@ -1012,9 +1012,24 @@ int br_nf_hook_thresh(unsigned int hook, struct net *net, · 1011 unmodified lines | |||
| 1012 | return okfn(net, sk, skb); | 1012 | return okfn(net, sk, skb); |
| 1013 | 1013 | ||
| 1014 | ops = nf_hook_entries_get_hook_ops(e); | 1014 | ops = nf_hook_entries_get_hook_ops(e); |
| 1015 | for (i = 0; i < e->num_hook_entries && | 1015 | for (i = 0; i < e->num_hook_entries; i++) { |
| 1016 | ops[i]->priority <= NF_BR_PRI_BRNF; i++) | 1016 | /* These hooks have already been called */ |
| 1017 | ; | 1017 | if (ops[i]->priority < NF_BR_PRI_BRNF) |
| 1018 | continue; | ||
| 1019 | |||
| 1020 | /* These hooks have not been called yet, run them. */ | ||
| 1021 | if (ops[i]->priority > NF_BR_PRI_BRNF) | ||
| 1022 | break; | ||
| 1023 | |||
| 1024 | /* take a closer look at NF_BR_PRI_BRNF. */ | ||
| 1025 | if (ops[i]->hook == br_nf_pre_routing) { | ||
| 1026 | /* This hook diverted the skb to this function, | ||
| 1027 | * hooks after this have not been run yet. | ||
| 1028 | */ | ||
| 1029 | i++; | ||
| 1030 | break; | ||
| 1031 | } | ||
| 1032 | } | ||
| 1018 | 1033 | ||
| 1019 | nf_hook_state_init(&state, hook, NFPROTO_BRIDGE, indev, outdev, | 1034 | nf_hook_state_init(&state, hook, NFPROTO_BRIDGE, indev, outdev, |
| 1020 | sk, net, okfn); | 1035 | sk, net, okfn); |
| @@ -410,7 +410,7 @@ int skb_tunnel_check_pmtu(struct sk_buff *skb, struct dst_entry *encap_dst, · 409 unmodified lines | |||
| 410 | u32 mtu = dst_mtu(encap_dst) - headroom; | 410 | u32 mtu = dst_mtu(encap_dst) - headroom; |
| 411 | 411 | ||
| 412 | if ((skb_is_gso(skb) && skb_gso_validate_network_len(skb, mtu)) || | 412 | if ((skb_is_gso(skb) && skb_gso_validate_network_len(skb, mtu)) || |
| 413 | (!skb_is_gso(skb) && (skb->len - skb_mac_header_len(skb)) <= mtu)) | 413 | (!skb_is_gso(skb) && (skb->len - skb_network_offset(skb)) <= mtu)) |
| 414 | return 0; | 414 | return 0; |
| 415 | 415 | ||
| 416 | skb_dst_update_pmtu_no_confirm(skb, mtu); | 416 | skb_dst_update_pmtu_no_confirm(skb, mtu); |
| @@ -1964,7 +1964,10 @@ process: · 1963 unmodified lines | |||
| 1964 | struct sock *nsk; | 1964 | struct sock *nsk; |
| 1965 | 1965 | ||
| 1966 | sk = req->rsk_listener; | 1966 | sk = req->rsk_listener; |
| 1967 | drop_reason = tcp_inbound_md5_hash(sk, skb, | 1967 | if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) |
| 1968 | drop_reason = SKB_DROP_REASON_XFRM_POLICY; | ||
| 1969 | else | ||
| 1970 | drop_reason = tcp_inbound_md5_hash(sk, skb, | ||
| 1968 | &iph->saddr, &iph->daddr, | 1971 | &iph->saddr, &iph->daddr, |
| 1969 | AF_INET, dif, sdif); | 1972 | AF_INET, dif, sdif); |
| 1970 | if (unlikely(drop_reason)) { | 1973 | if (unlikely(drop_reason)) { |
| @@ -2016,6 +2019,7 @@ process: · 45 unmodified lines | |||
| 2016 | } | 2019 | } |
| 2017 | goto discard_and_relse; | 2020 | goto discard_and_relse; |
| 2018 | } | 2021 | } |
| 2022 | nf_reset_ct(skb); | ||
| 2019 | if (nsk == sk) { | 2023 | if (nsk == sk) { |
| 2020 | reqsk_put(req); | 2024 | reqsk_put(req); |
| 2021 | tcp_v4_restore_cb(skb); | 2025 | tcp_v4_restore_cb(skb); |
| @@ -1109,10 +1109,6 @@ ipv6_add_addr(struct inet6_dev *idev, struct ifa6_config *cfg, · 1108 unmodified lines | |||
| 1109 | goto out; | 1109 | goto out; |
| 1110 | } | 1110 | } |
| 1111 | 1111 | ||
| 1112 | if (net->ipv6.devconf_all->disable_policy || | ||
| 1113 | idev->cnf.disable_policy) | ||
| 1114 | f6i->dst_nopolicy = true; | ||
| 1115 | |||
| 1116 | neigh_parms_data_state_setall(idev->nd_parms); | 1112 | neigh_parms_data_state_setall(idev->nd_parms); |
| 1117 | 1113 | ||
| 1118 | ifa->addr = *cfg->pfx; | 1114 | ifa->addr = *cfg->pfx; |
| @@ -5172,9 +5168,9 @@ next: · 4053 unmodified lines | |||
| 5172 | fillargs->event = RTM_GETMULTICAST; | 5168 | fillargs->event = RTM_GETMULTICAST; |
| 5173 | 5169 | ||
| 5174 | /* multicast address */ | 5170 | /* multicast address */ |
| 5175 | for (ifmca = rcu_dereference(idev->mc_list); | 5171 | for (ifmca = rtnl_dereference(idev->mc_list); |
| 5176 | ifmca; | 5172 | ifmca; |
| 5177 | ifmca = rcu_dereference(ifmca->next), ip_idx++) { | 5173 | ifmca = rtnl_dereference(ifmca->next), ip_idx++) { |
| 5178 | if (ip_idx < s_ip_idx) | 5174 | if (ip_idx < s_ip_idx) |
| 5179 | continue; | 5175 | continue; |
| 5180 | err = inet6_fill_ifmcaddr(skb, ifmca, fillargs); | 5176 | err = inet6_fill_ifmcaddr(skb, ifmca, fillargs); |
| @@ -4569,8 +4569,15 @@ struct fib6_info *addrconf_f6i_alloc(struct net *net, · 4568 unmodified lines | |||
| 4569 | } | 4569 | } |
| 4570 | 4570 | ||
| 4571 | f6i = ip6_route_info_create(&cfg, gfp_flags, NULL); | 4571 | f6i = ip6_route_info_create(&cfg, gfp_flags, NULL); |
| 4572 | if (!IS_ERR(f6i)) | 4572 | if (!IS_ERR(f6i)) { |
| 4573 | f6i->dst_nocount = true; | 4573 | f6i->dst_nocount = true; |
| 4574 | |||
| 4575 | if (!anycast && | ||
| 4576 | (net->ipv6.devconf_all->disable_policy || | ||
| 4577 | idev->cnf.disable_policy)) | ||
| 4578 | f6i->dst_nopolicy = true; | ||
| 4579 | } | ||
| 4580 | |||
| 4574 | return f6i; | 4581 | return f6i; |
| 4575 | } | 4582 | } |
| 4576 | 4583 | ||
| @@ -406,7 +406,6 @@ int __net_init seg6_hmac_net_init(struct net *net) · 405 unmodified lines | |||
| 406 | 406 | ||
| 407 | return rhashtable_init(&sdata->hmac_infos, &rht_params); | 407 | return rhashtable_init(&sdata->hmac_infos, &rht_params); |
| 408 | } | 408 | } |
| 409 | EXPORT_SYMBOL(seg6_hmac_net_init); | ||
| 410 | 409 | ||
| 411 | void seg6_hmac_exit(void) | 410 | void seg6_hmac_exit(void) |
| 412 | { | 411 | { |
| @@ -323,8 +323,6 @@ static int ipip6_tunnel_get_prl(struct net_device *dev, struct ip_tunnel_prl __u · 322 unmodified lines | |||
| 323 | kcalloc(cmax, sizeof(*kp), GFP_KERNEL_ACCOUNT | __GFP_NOWARN) : | 323 | kcalloc(cmax, sizeof(*kp), GFP_KERNEL_ACCOUNT | __GFP_NOWARN) : |
| 324 | NULL; | 324 | NULL; |
| 325 | 325 | ||
| 326 | rcu_read_lock(); | ||
| 327 | |||
| 328 | ca = min(t->prl_count, cmax); | 326 | ca = min(t->prl_count, cmax); |
| 329 | 327 | ||
| 330 | if (!kp) { | 328 | if (!kp) { |
| @@ -341,7 +339,7 @@ static int ipip6_tunnel_get_prl(struct net_device *dev, struct ip_tunnel_prl __u · 10 unmodified lines | |||
| 341 | } | 339 | } |
| 342 | } | 340 | } |
| 343 | 341 | ||
| 344 | c = 0; | 342 | rcu_read_lock(); |
| 345 | for_each_prl_rcu(t->prl) { | 343 | for_each_prl_rcu(t->prl) { |
| 346 | if (c >= cmax) | 344 | if (c >= cmax) |
| 347 | break; | 345 | break; |
| @@ -353,7 +351,7 @@ static int ipip6_tunnel_get_prl(struct net_device *dev, struct ip_tunnel_prl __u · 5 unmodified lines | |||
| 353 | if (kprl.addr != htonl(INADDR_ANY)) | 351 | if (kprl.addr != htonl(INADDR_ANY)) |
| 354 | break; | 352 | break; |
| 355 | } | 353 | } |
| 356 | out: | 354 | |
| 357 | rcu_read_unlock(); | 355 | rcu_read_unlock(); |
| 358 | 356 | ||
| 359 | len = sizeof(*kp) * c; | 357 | len = sizeof(*kp) * c; |
| @@ -362,7 +360,7 @@ out: · 2 unmodified lines | |||
| 362 | ret = -EFAULT; | 360 | ret = -EFAULT; |
| 363 | 361 | ||
| 364 | kfree(kp); | 362 | kfree(kp); |
| 365 | 363 | out: | |
| 366 | return ret; | 364 | return ret; |
| 367 | } | 365 | } |
| 368 | 366 | ||
| @@ -765,6 +765,7 @@ static noinline bool mptcp_established_options_rst(struct sock *sk, struct sk_bu · 764 unmodified lines | |||
| 765 | opts->suboptions |= OPTION_MPTCP_RST; | 765 | opts->suboptions |= OPTION_MPTCP_RST; |
| 766 | opts->reset_transient = subflow->reset_transient; | 766 | opts->reset_transient = subflow->reset_transient; |
| 767 | opts->reset_reason = subflow->reset_reason; | 767 | opts->reset_reason = subflow->reset_reason; |
| 768 | MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPRSTTX); | ||
| 768 | 769 | ||
| 769 | return true; | 770 | return true; |
| 770 | } | 771 | } |
| @@ -788,6 +789,7 @@ static bool mptcp_established_options_fastclose(struct sock *sk, · 17 unmodified lines | |||
| 788 | opts->rcvr_key = msk->remote_key; | 789 | opts->rcvr_key = msk->remote_key; |
| 789 | 790 | ||
| 790 | pr_debug("FASTCLOSE key=%llu", opts->rcvr_key); | 791 | pr_debug("FASTCLOSE key=%llu", opts->rcvr_key); |
| 792 | MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFASTCLOSETX); | ||
| 791 | return true; | 793 | return true; |
| 792 | } | 794 | } |
| 793 | 795 | ||
| @@ -809,6 +811,7 @@ static bool mptcp_established_options_mp_fail(struct sock *sk, · 15 unmodified lines | |||
| 809 | opts->fail_seq = subflow->map_seq; | 811 | opts->fail_seq = subflow->map_seq; |
| 810 | 812 | ||
| 811 | pr_debug("MP_FAIL fail_seq=%llu", opts->fail_seq); | 813 | pr_debug("MP_FAIL fail_seq=%llu", opts->fail_seq); |
| 814 | MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFAILTX); | ||
| 812 | 815 | ||
| 813 | return true; | 816 | return true; |
| 814 | } | 817 | } |
| @@ -833,13 +836,11 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb, · 18 unmodified lines | |||
| 833 | mptcp_established_options_mp_fail(sk, &opt_size, remaining, opts)) { | 836 | mptcp_established_options_mp_fail(sk, &opt_size, remaining, opts)) { |
| 834 | *size += opt_size; | 837 | *size += opt_size; |
| 835 | remaining -= opt_size; | 838 | remaining -= opt_size; |
| 836 | MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFASTCLOSETX); | ||
| 837 | } | 839 | } |
| 838 | /* MP_RST can be used with MP_FASTCLOSE and MP_FAIL if there is room */ | 840 | /* MP_RST can be used with MP_FASTCLOSE and MP_FAIL if there is room */ |
| 839 | if (mptcp_established_options_rst(sk, skb, &opt_size, remaining, opts)) { | 841 | if (mptcp_established_options_rst(sk, skb, &opt_size, remaining, opts)) { |
| 840 | *size += opt_size; | 842 | *size += opt_size; |
| 841 | remaining -= opt_size; | 843 | remaining -= opt_size; |
| 842 | MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPRSTTX); | ||
| 843 | } | 844 | } |
| 844 | return true; | 845 | return true; |
| 845 | } | 846 | } |
| @@ -966,7 +967,7 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk, · 120 unmodified lines | |||
| 966 | goto reset; | 967 | goto reset; |
| 967 | subflow->mp_capable = 0; | 968 | subflow->mp_capable = 0; |
| 968 | pr_fallback(msk); | 969 | pr_fallback(msk); |
| 969 | __mptcp_do_fallback(msk); | 970 | mptcp_do_fallback(ssk); |
| 970 | return false; | 971 | return false; |
| 971 | } | 972 | } |
| 972 | 973 | ||
| @@ -299,23 +299,21 @@ void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq) · 298 unmodified lines | |||
| 299 | { | 299 | { |
| 300 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); | 300 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); |
| 301 | struct mptcp_sock *msk = mptcp_sk(subflow->conn); | 301 | struct mptcp_sock *msk = mptcp_sk(subflow->conn); |
| 302 | struct sock *s = (struct sock *)msk; | ||
| 303 | 302 | ||
| 304 | pr_debug("fail_seq=%llu", fail_seq); | 303 | pr_debug("fail_seq=%llu", fail_seq); |
| 305 | 304 | ||
| 306 | if (!READ_ONCE(msk->allow_infinite_fallback)) | 305 | if (!READ_ONCE(msk->allow_infinite_fallback)) |
| 307 | return; | 306 | return; |
| 308 | 307 | ||
| 309 | if (!READ_ONCE(subflow->mp_fail_response_expect)) { | 308 | if (!subflow->fail_tout) { |
| 310 | pr_debug("send MP_FAIL response and infinite map"); | 309 | pr_debug("send MP_FAIL response and infinite map"); |
| 311 | 310 | ||
| 312 | subflow->send_mp_fail = 1; | 311 | subflow->send_mp_fail = 1; |
| 313 | MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFAILTX); | ||
| 314 | subflow->send_infinite_map = 1; | 312 | subflow->send_infinite_map = 1; |
| 315 | } else if (!sock_flag(sk, SOCK_DEAD)) { | 313 | tcp_send_ack(sk); |
| 314 | } else { | ||
| 316 | pr_debug("MP_FAIL response received"); | 315 | pr_debug("MP_FAIL response received"); |
| 317 | 316 | WRITE_ONCE(subflow->fail_tout, 0); | |
| 318 | sk_stop_timer(s, &s->sk_timer); | ||
| 319 | } | 317 | } |
| 320 | } | 318 | } |
| 321 | 319 | ||
| @@ -500,7 +500,7 @@ static void mptcp_set_timeout(struct sock *sk) · 499 unmodified lines | |||
| 500 | __mptcp_set_timeout(sk, tout); | 500 | __mptcp_set_timeout(sk, tout); |
| 501 | } | 501 | } |
| 502 | 502 | ||
| 503 | static bool tcp_can_send_ack(const struct sock *ssk) | 503 | static inline bool tcp_can_send_ack(const struct sock *ssk) |
| 504 | { | 504 | { |
| 505 | return !((1 << inet_sk_state_load(ssk)) & | 505 | return !((1 << inet_sk_state_load(ssk)) & |
| 506 | (TCPF_SYN_SENT | TCPF_SYN_RECV | TCPF_TIME_WAIT | TCPF_CLOSE | TCPF_LISTEN)); | 506 | (TCPF_SYN_SENT | TCPF_SYN_RECV | TCPF_TIME_WAIT | TCPF_CLOSE | TCPF_LISTEN)); |
| @@ -1245,7 +1245,7 @@ static void mptcp_update_infinite_map(struct mptcp_sock *msk, · 738 unmodified lines | |||
| 1245 | MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_INFINITEMAPTX); | 1245 | MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_INFINITEMAPTX); |
| 1246 | mptcp_subflow_ctx(ssk)->send_infinite_map = 0; | 1246 | mptcp_subflow_ctx(ssk)->send_infinite_map = 0; |
| 1247 | pr_fallback(msk); | 1247 | pr_fallback(msk); |
| 1248 | __mptcp_do_fallback(msk); | 1248 | mptcp_do_fallback(ssk); |
| 1249 | } | 1249 | } |
| 1250 | 1250 | ||
| 1251 | static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk, | 1251 | static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk, |
| @@ -2175,21 +2175,6 @@ static void mptcp_retransmit_timer(struct timer_list *t) · 923 unmodified lines | |||
| 2175 | sock_put(sk); | 2175 | sock_put(sk); |
| 2176 | } | 2176 | } |
| 2177 | 2177 | ||
| 2178 | static struct mptcp_subflow_context * | ||
| 2179 | mp_fail_response_expect_subflow(struct mptcp_sock *msk) | ||
| 2180 | { | ||
| 2181 | struct mptcp_subflow_context *subflow, *ret = NULL; | ||
| 2182 | |||
| 2183 | mptcp_for_each_subflow(msk, subflow) { | ||
| 2184 | if (READ_ONCE(subflow->mp_fail_response_expect)) { | ||
| 2185 | ret = subflow; | ||
| 2186 | break; | ||
| 2187 | } | ||
| 2188 | } | ||
| 2189 | |||
| 2190 | return ret; | ||
| 2191 | } | ||
| 2192 | |||
| 2193 | static void mptcp_timeout_timer(struct timer_list *t) | 2178 | static void mptcp_timeout_timer(struct timer_list *t) |
| 2194 | { | 2179 | { |
| 2195 | struct sock *sk = from_timer(sk, t, sk_timer); | 2180 | struct sock *sk = from_timer(sk, t, sk_timer); |
| @@ -2346,6 +2331,11 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk, · 150 unmodified lines | |||
| 2346 | kfree_rcu(subflow, rcu); | 2331 | kfree_rcu(subflow, rcu); |
| 2347 | } else { | 2332 | } else { |
| 2348 | /* otherwise tcp will dispose of the ssk and subflow ctx */ | 2333 | /* otherwise tcp will dispose of the ssk and subflow ctx */ |
| 2334 | if (ssk->sk_state == TCP_LISTEN) { | ||
| 2335 | tcp_set_state(ssk, TCP_CLOSE); | ||
| 2336 | mptcp_subflow_queue_clean(ssk); | ||
| 2337 | inet_csk_listen_stop(ssk); | ||
| 2338 | } | ||
| 2349 | __tcp_close(ssk, 0); | 2339 | __tcp_close(ssk, 0); |
| 2350 | 2340 | ||
| 2351 | /* close acquired an extra ref */ | 2341 | /* close acquired an extra ref */ |
| @@ -2518,27 +2508,50 @@ reset_timer: · 166 unmodified lines | |||
| 2518 | mptcp_reset_timer(sk); | 2508 | mptcp_reset_timer(sk); |
| 2519 | } | 2509 | } |
| 2520 | 2510 | ||
| 2511 | /* schedule the timeout timer for the relevant event: either close timeout | ||
| 2512 | * or mp_fail timeout. The close timeout takes precedence on the mp_fail one | ||
| 2513 | */ | ||
| 2514 | void mptcp_reset_timeout(struct mptcp_sock *msk, unsigned long fail_tout) | ||
| 2515 | { | ||
| 2516 | struct sock *sk = (struct sock *)msk; | ||
| 2517 | unsigned long timeout, close_timeout; | ||
| 2518 | |||
| 2519 | if (!fail_tout && !sock_flag(sk, SOCK_DEAD)) | ||
| 2520 | return; | ||
| 2521 | |||
| 2522 | close_timeout = inet_csk(sk)->icsk_mtup.probe_timestamp - tcp_jiffies32 + jiffies + TCP_TIMEWAIT_LEN; | ||
| 2523 | |||
| 2524 | /* the close timeout takes precedence on the fail one, and here at least one of | ||
| 2525 | * them is active | ||
| 2526 | */ | ||
| 2527 | timeout = sock_flag(sk, SOCK_DEAD) ? close_timeout : fail_tout; | ||
| 2528 | |||
| 2529 | sk_reset_timer(sk, &sk->sk_timer, timeout); | ||
| 2530 | } | ||
| 2531 | |||
| 2521 | static void mptcp_mp_fail_no_response(struct mptcp_sock *msk) | 2532 | static void mptcp_mp_fail_no_response(struct mptcp_sock *msk) |
| 2522 | { | 2533 | { |
| 2523 | struct mptcp_subflow_context *subflow; | 2534 | struct sock *ssk = msk->first; |
| 2524 | struct sock *ssk; | ||
| 2525 | bool slow; | 2535 | bool slow; |
| 2526 | 2536 | ||
| 2527 | subflow = mp_fail_response_expect_subflow(msk); | 2537 | if (!ssk) |
| 2528 | if (subflow) { | 2538 | return; |
| 2529 | pr_debug("MP_FAIL doesn't respond, reset the subflow"); | ||
| 2530 | 2539 | ||
| 2531 | ssk = mptcp_subflow_tcp_sock(subflow); | 2540 | pr_debug("MP_FAIL doesn't respond, reset the subflow"); |
| 2532 | slow = lock_sock_fast(ssk); | 2541 | |
| 2533 | mptcp_subflow_reset(ssk); | 2542 | slow = lock_sock_fast(ssk); |
| 2534 | unlock_sock_fast(ssk, slow); | 2543 | mptcp_subflow_reset(ssk); |
| 2535 | } | 2544 | WRITE_ONCE(mptcp_subflow_ctx(ssk)->fail_tout, 0); |
| 2545 | unlock_sock_fast(ssk, slow); | ||
| 2546 | |||
| 2547 | mptcp_reset_timeout(msk, 0); | ||
| 2536 | } | 2548 | } |
| 2537 | 2549 | ||
| 2538 | static void mptcp_worker(struct work_struct *work) | 2550 | static void mptcp_worker(struct work_struct *work) |
| 2539 | { | 2551 | { |
| 2540 | struct mptcp_sock *msk = container_of(work, struct mptcp_sock, work); | 2552 | struct mptcp_sock *msk = container_of(work, struct mptcp_sock, work); |
| 2541 | struct sock *sk = &msk->sk.icsk_inet.sk; | 2553 | struct sock *sk = &msk->sk.icsk_inet.sk; |
| 2554 | unsigned long fail_tout; | ||
| 2542 | int state; | 2555 | int state; |
| 2543 | 2556 | ||
| 2544 | lock_sock(sk); | 2557 | lock_sock(sk); |
| @@ -2575,7 +2588,9 @@ static void mptcp_worker(struct work_struct *work) · 30 unmodified lines | |||
| 2575 | if (test_and_clear_bit(MPTCP_WORK_RTX, &msk->flags)) | 2588 | if (test_and_clear_bit(MPTCP_WORK_RTX, &msk->flags)) |
| 2576 | __mptcp_retrans(sk); | 2589 | __mptcp_retrans(sk); |
| 2577 | 2590 | ||
| 2578 | mptcp_mp_fail_no_response(msk); | 2591 | fail_tout = msk->first ? READ_ONCE(mptcp_subflow_ctx(msk->first)->fail_tout) : 0; |
| 2592 | if (fail_tout && time_after(jiffies, fail_tout)) | ||
| 2593 | mptcp_mp_fail_no_response(msk); | ||
| 2579 | 2594 | ||
| 2580 | unlock: | 2595 | unlock: |
| 2581 | release_sock(sk); | 2596 | release_sock(sk); |
| @@ -2822,6 +2837,7 @@ static void __mptcp_destroy_sock(struct sock *sk) · 240 unmodified lines | |||
| 2822 | static void mptcp_close(struct sock *sk, long timeout) | 2837 | static void mptcp_close(struct sock *sk, long timeout) |
| 2823 | { | 2838 | { |
| 2824 | struct mptcp_subflow_context *subflow; | 2839 | struct mptcp_subflow_context *subflow; |
| 2840 | struct mptcp_sock *msk = mptcp_sk(sk); | ||
| 2825 | bool do_cancel_work = false; | 2841 | bool do_cancel_work = false; |
| 2826 | 2842 | ||
| 2827 | lock_sock(sk); | 2843 | lock_sock(sk); |
| @@ -2840,10 +2856,16 @@ static void mptcp_close(struct sock *sk, long timeout) · 12 unmodified lines | |||
| 2840 | cleanup: | 2856 | cleanup: |
| 2841 | /* orphan all the subflows */ | 2857 | /* orphan all the subflows */ |
| 2842 | inet_csk(sk)->icsk_mtup.probe_timestamp = tcp_jiffies32; | 2858 | inet_csk(sk)->icsk_mtup.probe_timestamp = tcp_jiffies32; |
| 2843 | mptcp_for_each_subflow(mptcp_sk(sk), subflow) { | 2859 | mptcp_for_each_subflow(msk, subflow) { |
| 2844 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); | 2860 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); |
| 2845 | bool slow = lock_sock_fast_nested(ssk); | 2861 | bool slow = lock_sock_fast_nested(ssk); |
| 2846 | 2862 | ||
| 2863 | /* since the close timeout takes precedence on the fail one, | ||
| 2864 | * cancel the latter | ||
| 2865 | */ | ||
| 2866 | if (ssk == msk->first) | ||
| 2867 | subflow->fail_tout = 0; | ||
| 2868 | |||
| 2847 | sock_orphan(ssk); | 2869 | sock_orphan(ssk); |
| 2848 | unlock_sock_fast(ssk, slow); | 2870 | unlock_sock_fast(ssk, slow); |
| 2849 | } | 2871 | } |
| @@ -2852,13 +2874,13 @@ cleanup: · 2 unmodified lines | |||
| 2852 | sock_hold(sk); | 2874 | sock_hold(sk); |
| 2853 | pr_debug("msk=%p state=%d", sk, sk->sk_state); | 2875 | pr_debug("msk=%p state=%d", sk, sk->sk_state); |
| 2854 | if (mptcp_sk(sk)->token) | 2876 | if (mptcp_sk(sk)->token) |
| 2855 | mptcp_event(MPTCP_EVENT_CLOSED, mptcp_sk(sk), NULL, GFP_KERNEL); | 2877 | mptcp_event(MPTCP_EVENT_CLOSED, msk, NULL, GFP_KERNEL); |
| 2856 | 2878 | ||
| 2857 | if (sk->sk_state == TCP_CLOSE) { | 2879 | if (sk->sk_state == TCP_CLOSE) { |
| 2858 | __mptcp_destroy_sock(sk); | 2880 | __mptcp_destroy_sock(sk); |
| 2859 | do_cancel_work = true; | 2881 | do_cancel_work = true; |
| 2860 | } else { | 2882 | } else { |
| 2861 | sk_reset_timer(sk, &sk->sk_timer, jiffies + TCP_TIMEWAIT_LEN); | 2883 | mptcp_reset_timeout(msk, 0); |
| 2862 | } | 2884 | } |
| 2863 | release_sock(sk); | 2885 | release_sock(sk); |
| 2864 | if (do_cancel_work) | 2886 | if (do_cancel_work) |
| @@ -306,6 +306,7 @@ struct mptcp_sock { · 305 unmodified lines | |||
| 306 | 306 | ||
| 307 | u32 setsockopt_seq; | 307 | u32 setsockopt_seq; |
| 308 | char ca_name[TCP_CA_NAME_MAX]; | 308 | char ca_name[TCP_CA_NAME_MAX]; |
| 309 | struct mptcp_sock *dl_next; | ||
| 309 | }; | 310 | }; |
| 310 | 311 | ||
| 311 | #define mptcp_data_lock(sk) spin_lock_bh(&(sk)->sk_lock.slock) | 312 | #define mptcp_data_lock(sk) spin_lock_bh(&(sk)->sk_lock.slock) |
| @@ -468,7 +469,6 @@ struct mptcp_subflow_context { · 156 unmodified lines | |||
| 468 | local_id_valid : 1, /* local_id is correctly initialized */ | 469 | local_id_valid : 1, /* local_id is correctly initialized */ |
| 469 | valid_csum_seen : 1; /* at least one csum validated */ | 470 | valid_csum_seen : 1; /* at least one csum validated */ |
| 470 | enum mptcp_data_avail data_avail; | 471 | enum mptcp_data_avail data_avail; |
| 471 | bool mp_fail_response_expect; | ||
| 472 | u32 remote_nonce; | 472 | u32 remote_nonce; |
| 473 | u64 thmac; | 473 | u64 thmac; |
| 474 | u32 local_nonce; | 474 | u32 local_nonce; |
| @@ -482,6 +482,7 @@ struct mptcp_subflow_context { · 7 unmodified lines | |||
| 482 | u8 stale_count; | 482 | u8 stale_count; |
| 483 | 483 | ||
| 484 | long delegated_status; | 484 | long delegated_status; |
| 485 | unsigned long fail_tout; | ||
| 485 | 486 | ||
| 486 | ); | 487 | ); |
| 487 | 488 | ||
| @@ -608,6 +609,7 @@ void mptcp_close_ssk(struct sock *sk, struct sock *ssk, · 120 unmodified lines | |||
| 608 | struct mptcp_subflow_context *subflow); | 609 | struct mptcp_subflow_context *subflow); |
| 609 | void mptcp_subflow_send_ack(struct sock *ssk); | 610 | void mptcp_subflow_send_ack(struct sock *ssk); |
| 610 | void mptcp_subflow_reset(struct sock *ssk); | 611 | void mptcp_subflow_reset(struct sock *ssk); |
| 612 | void mptcp_subflow_queue_clean(struct sock *ssk); | ||
| 611 | void mptcp_sock_graft(struct sock *sk, struct socket *parent); | 613 | void mptcp_sock_graft(struct sock *sk, struct socket *parent); |
| 612 | struct socket *__mptcp_nmpc_socket(const struct mptcp_sock *msk); | 614 | struct socket *__mptcp_nmpc_socket(const struct mptcp_sock *msk); |
| 613 | 615 | ||
| @@ -662,6 +664,7 @@ void mptcp_get_options(const struct sk_buff *skb, · 48 unmodified lines | |||
| 662 | 664 | ||
| 663 | void mptcp_finish_connect(struct sock *sk); | 665 | void mptcp_finish_connect(struct sock *sk); |
| 664 | void __mptcp_set_connected(struct sock *sk); | 666 | void __mptcp_set_connected(struct sock *sk); |
| 667 | void mptcp_reset_timeout(struct mptcp_sock *msk, unsigned long fail_tout); | ||
| 665 | static inline bool mptcp_is_fully_established(struct sock *sk) | 668 | static inline bool mptcp_is_fully_established(struct sock *sk) |
| 666 | { | 669 | { |
| 667 | return inet_sk_state_load(sk) == TCP_ESTABLISHED && | 670 | return inet_sk_state_load(sk) == TCP_ESTABLISHED && |
| @@ -926,12 +929,25 @@ static inline void __mptcp_do_fallback(struct mptcp_sock *msk) · 258 unmodified lines | |||
| 926 | set_bit(MPTCP_FALLBACK_DONE, &msk->flags); | 929 | set_bit(MPTCP_FALLBACK_DONE, &msk->flags); |
| 927 | } | 930 | } |
| 928 | 931 | ||
| 929 | static inline void mptcp_do_fallback(struct sock *sk) | 932 | static inline void mptcp_do_fallback(struct sock *ssk) |
| 930 | { | 933 | { |
| 931 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); | 934 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); |
| 932 | struct mptcp_sock *msk = mptcp_sk(subflow->conn); | 935 | struct sock *sk = subflow->conn; |
| 936 | struct mptcp_sock *msk; | ||
| 933 | 937 | ||
| 938 | msk = mptcp_sk(sk); | ||
| 934 | __mptcp_do_fallback(msk); | 939 | __mptcp_do_fallback(msk); |
| 940 | if (READ_ONCE(msk->snd_data_fin_enable) && !(ssk->sk_shutdown & SEND_SHUTDOWN)) { | ||
| 941 | gfp_t saved_allocation = ssk->sk_allocation; | ||
| 942 | |||
| 943 | /* we are in a atomic (BH) scope, override ssk default for data | ||
| 944 | * fin allocation | ||
| 945 | */ | ||
| 946 | ssk->sk_allocation = GFP_ATOMIC; | ||
| 947 | ssk->sk_shutdown |= SEND_SHUTDOWN; | ||
| 948 | tcp_shutdown(ssk, SEND_SHUTDOWN); | ||
| 949 | ssk->sk_allocation = saved_allocation; | ||
| 950 | } | ||
| 935 | } | 951 | } |
| 936 | 952 | ||
| 937 | #define pr_fallback(a) pr_debug("%s:fallback to TCP (msk=%p)", __func__, a) | 953 | #define pr_fallback(a) pr_debug("%s:fallback to TCP (msk=%p)", __func__, a) |
| @@ -843,7 +843,8 @@ enum mapping_status { · 842 unmodified lines | |||
| 843 | MAPPING_INVALID, | 843 | MAPPING_INVALID, |
| 844 | MAPPING_EMPTY, | 844 | MAPPING_EMPTY, |
| 845 | MAPPING_DATA_FIN, | 845 | MAPPING_DATA_FIN, |
| 846 | MAPPING_DUMMY | 846 | MAPPING_DUMMY, |
| 847 | MAPPING_BAD_CSUM | ||
| 847 | }; | 848 | }; |
| 848 | 849 | ||
| 849 | static void dbg_bad_map(struct mptcp_subflow_context *subflow, u32 ssn) | 850 | static void dbg_bad_map(struct mptcp_subflow_context *subflow, u32 ssn) |
| @@ -958,11 +959,7 @@ static enum mapping_status validate_data_csum(struct sock *ssk, struct sk_buff * · 108 unmodified lines | |||
| 958 | subflow->map_data_csum); | 959 | subflow->map_data_csum); |
| 959 | if (unlikely(csum)) { | 960 | if (unlikely(csum)) { |
| 960 | MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DATACSUMERR); | 961 | MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DATACSUMERR); |
| 961 | if (subflow->mp_join || subflow->valid_csum_seen) { | 962 | return MAPPING_BAD_CSUM; |
| 962 | subflow->send_mp_fail = 1; | ||
| 963 | MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_MPFAILTX); | ||
| 964 | } | ||
| 965 | return subflow->mp_join ? MAPPING_INVALID : MAPPING_DUMMY; | ||
| 966 | } | 963 | } |
| 967 | 964 | ||
| 968 | subflow->valid_csum_seen = 1; | 965 | subflow->valid_csum_seen = 1; |
| @@ -974,7 +971,6 @@ static enum mapping_status get_mapping_status(struct sock *ssk, · 5 unmodified lines | |||
| 974 | { | 971 | { |
| 975 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); | 972 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); |
| 976 | bool csum_reqd = READ_ONCE(msk->csum_enabled); | 973 | bool csum_reqd = READ_ONCE(msk->csum_enabled); |
| 977 | struct sock *sk = (struct sock *)msk; | ||
| 978 | struct mptcp_ext *mpext; | 974 | struct mptcp_ext *mpext; |
| 979 | struct sk_buff *skb; | 975 | struct sk_buff *skb; |
| 980 | u16 data_len; | 976 | u16 data_len; |
| @@ -1016,9 +1012,6 @@ static enum mapping_status get_mapping_status(struct sock *ssk, · 35 unmodified lines | |||
| 1016 | pr_debug("infinite mapping received"); | 1012 | pr_debug("infinite mapping received"); |
| 1017 | MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_INFINITEMAPRX); | 1013 | MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_INFINITEMAPRX); |
| 1018 | subflow->map_data_len = 0; | 1014 | subflow->map_data_len = 0; |
| 1019 | if (!sock_flag(ssk, SOCK_DEAD)) | ||
| 1020 | sk_stop_timer(sk, &sk->sk_timer); | ||
| 1021 | |||
| 1022 | return MAPPING_INVALID; | 1015 | return MAPPING_INVALID; |
| 1023 | } | 1016 | } |
| 1024 | 1017 | ||
| @@ -1165,6 +1158,33 @@ static bool subflow_can_fallback(struct mptcp_subflow_context *subflow) · 140 unmodified lines | |||
| 1165 | return !subflow->fully_established; | 1158 | return !subflow->fully_established; |
| 1166 | } | 1159 | } |
| 1167 | 1160 | ||
| 1161 | static void mptcp_subflow_fail(struct mptcp_sock *msk, struct sock *ssk) | ||
| 1162 | { | ||
| 1163 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); | ||
| 1164 | unsigned long fail_tout; | ||
| 1165 | |||
| 1166 | /* greceful failure can happen only on the MPC subflow */ | ||
| 1167 | if (WARN_ON_ONCE(ssk != READ_ONCE(msk->first))) | ||
| 1168 | return; | ||
| 1169 | |||
| 1170 | /* since the close timeout take precedence on the fail one, | ||
| 1171 | * no need to start the latter when the first is already set | ||
| 1172 | */ | ||
| 1173 | if (sock_flag((struct sock *)msk, SOCK_DEAD)) | ||
| 1174 | return; | ||
| 1175 | |||
| 1176 | /* we don't need extreme accuracy here, use a zero fail_tout as special | ||
| 1177 | * value meaning no fail timeout at all; | ||
| 1178 | */ | ||
| 1179 | fail_tout = jiffies + TCP_RTO_MAX; | ||
| 1180 | if (!fail_tout) | ||
| 1181 | fail_tout = 1; | ||
| 1182 | WRITE_ONCE(subflow->fail_tout, fail_tout); | ||
| 1183 | tcp_send_ack(ssk); | ||
| 1184 | |||
| 1185 | mptcp_reset_timeout(msk, subflow->fail_tout); | ||
| 1186 | } | ||
| 1187 | |||
| 1168 | static bool subflow_check_data_avail(struct sock *ssk) | 1188 | static bool subflow_check_data_avail(struct sock *ssk) |
| 1169 | { | 1189 | { |
| 1170 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); | 1190 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); |
| @@ -1184,10 +1204,8 @@ static bool subflow_check_data_avail(struct sock *ssk) · 13 unmodified lines | |||
| 1184 | 1204 | ||
| 1185 | status = get_mapping_status(ssk, msk); | 1205 | status = get_mapping_status(ssk, msk); |
| 1186 | trace_subflow_check_data_avail(status, skb_peek(&ssk->sk_receive_queue)); | 1206 | trace_subflow_check_data_avail(status, skb_peek(&ssk->sk_receive_queue)); |
| 1187 | if (unlikely(status == MAPPING_INVALID)) | 1207 | if (unlikely(status == MAPPING_INVALID || status == MAPPING_DUMMY || |
| 1188 | goto fallback; | 1208 | status == MAPPING_BAD_CSUM)) |
| 1189 | |||
| 1190 | if (unlikely(status == MAPPING_DUMMY)) | ||
| 1191 | goto fallback; | 1209 | goto fallback; |
| 1192 | 1210 | ||
| 1193 | if (status != MAPPING_OK) | 1211 | if (status != MAPPING_OK) |
| @@ -1229,22 +1247,17 @@ no_data: · 35 unmodified lines | |||
| 1229 | fallback: | 1247 | fallback: |
| 1230 | if (!__mptcp_check_fallback(msk)) { | 1248 | if (!__mptcp_check_fallback(msk)) { |
| 1231 | /* RFC 8684 section 3.7. */ | 1249 | /* RFC 8684 section 3.7. */ |
| 1232 | if (subflow->send_mp_fail) { | 1250 | if (status == MAPPING_BAD_CSUM && |
| 1251 | (subflow->mp_join || subflow->valid_csum_seen)) { | ||
| 1252 | subflow->send_mp_fail = 1; | ||
| 1253 | |||
| 1233 | if (!READ_ONCE(msk->allow_infinite_fallback)) { | 1254 | if (!READ_ONCE(msk->allow_infinite_fallback)) { |
| 1234 | ssk->sk_err = EBADMSG; | ||
| 1235 | tcp_set_state(ssk, TCP_CLOSE); | ||
| 1236 | subflow->reset_transient = 0; | 1255 | subflow->reset_transient = 0; |
| 1237 | subflow->reset_reason = MPTCP_RST_EMIDDLEBOX; | 1256 | subflow->reset_reason = MPTCP_RST_EMIDDLEBOX; |
| 1238 | tcp_send_active_reset(ssk, GFP_ATOMIC); | 1257 | goto reset; |
| 1239 | while ((skb = skb_peek(&ssk->sk_receive_queue))) | ||
| 1240 | sk_eat_skb(ssk, skb); | ||
| 1241 | } else if (!sock_flag(ssk, SOCK_DEAD)) { | ||
| 1242 | WRITE_ONCE(subflow->mp_fail_response_expect, true); | ||
| 1243 | sk_reset_timer((struct sock *)msk, | ||
| 1244 | &((struct sock *)msk)->sk_timer, | ||
| 1245 | jiffies + TCP_RTO_MAX); | ||
| 1246 | } | 1258 | } |
| 1247 | WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA); | 1259 | mptcp_subflow_fail(msk, ssk); |
| 1260 | WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_DATA_AVAIL); | ||
| 1248 | return true; | 1261 | return true; |
| 1249 | } | 1262 | } |
| 1250 | 1263 | ||
| @@ -1252,16 +1265,20 @@ fallback: · 1 unmodified line | |||
| 1252 | /* fatal protocol error, close the socket. | 1265 | /* fatal protocol error, close the socket. |
| 1253 | * subflow_error_report() will introduce the appropriate barriers | 1266 | * subflow_error_report() will introduce the appropriate barriers |
| 1254 | */ | 1267 | */ |
| 1255 | ssk->sk_err = EBADMSG; | ||
| 1256 | tcp_set_state(ssk, TCP_CLOSE); | ||
| 1257 | subflow->reset_transient = 0; | 1268 | subflow->reset_transient = 0; |
| 1258 | subflow->reset_reason = MPTCP_RST_EMPTCP; | 1269 | subflow->reset_reason = MPTCP_RST_EMPTCP; |
| 1270 | |||
| 1271 | reset: | ||
| 1272 | ssk->sk_err = EBADMSG; | ||
| 1273 | tcp_set_state(ssk, TCP_CLOSE); | ||
| 1274 | while ((skb = skb_peek(&ssk->sk_receive_queue))) | ||
| 1275 | sk_eat_skb(ssk, skb); | ||
| 1259 | tcp_send_active_reset(ssk, GFP_ATOMIC); | 1276 | tcp_send_active_reset(ssk, GFP_ATOMIC); |
| 1260 | WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA); | 1277 | WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA); |
| 1261 | return false; | 1278 | return false; |
| 1262 | } | 1279 | } |
| 1263 | 1280 | ||
| 1264 | __mptcp_do_fallback(msk); | 1281 | mptcp_do_fallback(ssk); |
| 1265 | } | 1282 | } |
| 1266 | 1283 | ||
| 1267 | skb = skb_peek(&ssk->sk_receive_queue); | 1284 | skb = skb_peek(&ssk->sk_receive_queue); |
| @@ -1706,6 +1723,58 @@ static void subflow_state_change(struct sock *sk) · 438 unmodified lines | |||
| 1706 | } | 1723 | } |
| 1707 | } | 1724 | } |
| 1708 | 1725 | ||
| 1726 | void mptcp_subflow_queue_clean(struct sock *listener_ssk) | ||
| 1727 | { | ||
| 1728 | struct request_sock_queue *queue = &inet_csk(listener_ssk)->icsk_accept_queue; | ||
| 1729 | struct mptcp_sock *msk, *next, *head = NULL; | ||
| 1730 | struct request_sock *req; | ||
| 1731 | |||
| 1732 | /* build a list of all unaccepted mptcp sockets */ | ||
| 1733 | spin_lock_bh(&queue->rskq_lock); | ||
| 1734 | for (req = queue->rskq_accept_head; req; req = req->dl_next) { | ||
| 1735 | struct mptcp_subflow_context *subflow; | ||
| 1736 | struct sock *ssk = req->sk; | ||
| 1737 | struct mptcp_sock *msk; | ||
| 1738 | |||
| 1739 | if (!sk_is_mptcp(ssk)) | ||
| 1740 | continue; | ||
| 1741 | |||
| 1742 | subflow = mptcp_subflow_ctx(ssk); | ||
| 1743 | if (!subflow || !subflow->conn) | ||
| 1744 | continue; | ||
| 1745 | |||
| 1746 | /* skip if already in list */ | ||
| 1747 | msk = mptcp_sk(subflow->conn); | ||
| 1748 | if (msk->dl_next || msk == head) | ||
| 1749 | continue; | ||
| 1750 | |||
| 1751 | msk->dl_next = head; | ||
| 1752 | head = msk; | ||
| 1753 | } | ||
| 1754 | spin_unlock_bh(&queue->rskq_lock); | ||
| 1755 | if (!head) | ||
| 1756 | return; | ||
| 1757 | |||
| 1758 | /* can't acquire the msk socket lock under the subflow one, | ||
| 1759 | * or will cause ABBA deadlock | ||
| 1760 | */ | ||
| 1761 | release_sock(listener_ssk); | ||
| 1762 | |||
| 1763 | for (msk = head; msk; msk = next) { | ||
| 1764 | struct sock *sk = (struct sock *)msk; | ||
| 1765 | bool slow; | ||
| 1766 | |||
| 1767 | slow = lock_sock_fast_nested(sk); | ||
| 1768 | next = msk->dl_next; | ||
| 1769 | msk->first = NULL; | ||
| 1770 | msk->dl_next = NULL; | ||
| 1771 | unlock_sock_fast(sk, slow); | ||
| 1772 | } | ||
| 1773 | |||
| 1774 | /* we are still under the listener msk socket lock */ | ||
| 1775 | lock_sock_nested(listener_ssk, SINGLE_DEPTH_NESTING); | ||
| 1776 | } | ||
| 1777 | |||
| 1709 | static int subflow_ulp_init(struct sock *sk) | 1778 | static int subflow_ulp_init(struct sock *sk) |
| 1710 | { | 1779 | { |
| 1711 | struct inet_connection_sock *icsk = inet_csk(sk); | 1780 | struct inet_connection_sock *icsk = inet_csk(sk); |
| @@ -1803,7 +1803,8 @@ struct ncsi_dev *ncsi_register_dev(struct net_device *dev, · 1802 unmodified lines | |||
| 1803 | pdev = to_platform_device(dev->dev.parent); | 1803 | pdev = to_platform_device(dev->dev.parent); |
| 1804 | if (pdev) { | 1804 | if (pdev) { |
| 1805 | np = pdev->dev.of_node; | 1805 | np = pdev->dev.of_node; |
| 1806 | if (np && of_get_property(np, "mlx,multi-host", NULL)) | 1806 | if (np && (of_get_property(np, "mellanox,multi-host", NULL) || |
| 1807 | of_get_property(np, "mlx,multi-host", NULL))) | ||
| 1807 | ndp->mlx_multi_host = true; | 1808 | ndp->mlx_multi_host = true; |
| 1808 | } | 1809 | } |
| 1809 | 1810 | ||
| @@ -25,9 +25,7 @@ static noinline void __nft_trace_packet(struct nft_traceinfo *info, · 24 unmodified lines | |||
| 25 | const struct nft_chain *chain, | 25 | const struct nft_chain *chain, |
| 26 | enum nft_trace_types type) | 26 | enum nft_trace_types type) |
| 27 | { | 27 | { |
| 28 | const struct nft_pktinfo *pkt = info->pkt; | 28 | if (!info->trace || !info->nf_trace) |
| 29 | |||
| 30 | if (!info->trace || !pkt->skb->nf_trace) | ||
| 31 | return; | 29 | return; |
| 32 | 30 | ||
| 33 | info->chain = chain; | 31 | info->chain = chain; |
| @@ -42,11 +40,24 @@ static inline void nft_trace_packet(struct nft_traceinfo *info, · 8 unmodified lines | |||
| 42 | enum nft_trace_types type) | 40 | enum nft_trace_types type) |
| 43 | { | 41 | { |
| 44 | if (static_branch_unlikely(&nft_trace_enabled)) { | 42 | if (static_branch_unlikely(&nft_trace_enabled)) { |
| 43 | const struct nft_pktinfo *pkt = info->pkt; | ||
| 44 | |||
| 45 | info->nf_trace = pkt->skb->nf_trace; | ||
| 45 | info->rule = rule; | 46 | info->rule = rule; |
| 46 | __nft_trace_packet(info, chain, type); | 47 | __nft_trace_packet(info, chain, type); |
| 47 | } | 48 | } |
| 48 | } | 49 | } |
| 49 | 50 | ||
| 51 | static inline void nft_trace_copy_nftrace(struct nft_traceinfo *info) | ||
| 52 | { | ||
| 53 | if (static_branch_unlikely(&nft_trace_enabled)) { | ||
| 54 | const struct nft_pktinfo *pkt = info->pkt; | ||
| 55 | |||
| 56 | if (info->trace) | ||
| 57 | info->nf_trace = pkt->skb->nf_trace; | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 50 | static void nft_bitwise_fast_eval(const struct nft_expr *expr, | 61 | static void nft_bitwise_fast_eval(const struct nft_expr *expr, |
| 51 | struct nft_regs *regs) | 62 | struct nft_regs *regs) |
| 52 | { | 63 | { |
| @@ -85,6 +96,7 @@ static noinline void __nft_trace_verdict(struct nft_traceinfo *info, · 32 unmodified lines | |||
| 85 | const struct nft_chain *chain, | 96 | const struct nft_chain *chain, |
| 86 | const struct nft_regs *regs) | 97 | const struct nft_regs *regs) |
| 87 | { | 98 | { |
| 99 | const struct nft_pktinfo *pkt = info->pkt; | ||
| 88 | enum nft_trace_types type; | 100 | enum nft_trace_types type; |
| 89 | 101 | ||
| 90 | switch (regs->verdict.code) { | 102 | switch (regs->verdict.code) { |
| @@ -92,8 +104,13 @@ static noinline void __nft_trace_verdict(struct nft_traceinfo *info, · 1 unmodified line | |||
| 92 | case NFT_RETURN: | 104 | case NFT_RETURN: |
| 93 | type = NFT_TRACETYPE_RETURN; | 105 | type = NFT_TRACETYPE_RETURN; |
| 94 | break; | 106 | break; |
| 107 | case NF_STOLEN: | ||
| 108 | type = NFT_TRACETYPE_RULE; | ||
| 109 | /* can't access skb->nf_trace; use copy */ | ||
| 110 | break; | ||
| 95 | default: | 111 | default: |
| 96 | type = NFT_TRACETYPE_RULE; | 112 | type = NFT_TRACETYPE_RULE; |
| 113 | info->nf_trace = pkt->skb->nf_trace; | ||
| 97 | break; | 114 | break; |
| 98 | } | 115 | } |
| 99 | 116 | ||
| @@ -254,6 +271,7 @@ next_rule: · 154 unmodified lines | |||
| 254 | switch (regs.verdict.code) { | 271 | switch (regs.verdict.code) { |
| 255 | case NFT_BREAK: | 272 | case NFT_BREAK: |
| 256 | regs.verdict.code = NFT_CONTINUE; | 273 | regs.verdict.code = NFT_CONTINUE; |
| 274 | nft_trace_copy_nftrace(&info); | ||
| 257 | continue; | 275 | continue; |
| 258 | case NFT_CONTINUE: | 276 | case NFT_CONTINUE: |
| 259 | nft_trace_packet(&info, chain, rule, | 277 | nft_trace_packet(&info, chain, rule, |
| @@ -7,7 +7,7 @@ · 6 unmodified lines | |||
| 7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
| 8 | #include <linux/static_key.h> | 8 | #include <linux/static_key.h> |
| 9 | #include <linux/hash.h> | 9 | #include <linux/hash.h> |
| 10 | #include <linux/jhash.h> | 10 | #include <linux/siphash.h> |
| 11 | #include <linux/if_vlan.h> | 11 | #include <linux/if_vlan.h> |
| 12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
| 13 | #include <linux/skbuff.h> | 13 | #include <linux/skbuff.h> |
| @@ -25,22 +25,6 @@ · 11 unmodified lines | |||
| 25 | DEFINE_STATIC_KEY_FALSE(nft_trace_enabled); | 25 | DEFINE_STATIC_KEY_FALSE(nft_trace_enabled); |
| 26 | EXPORT_SYMBOL_GPL(nft_trace_enabled); | 26 | EXPORT_SYMBOL_GPL(nft_trace_enabled); |
| 27 | 27 | ||
| 28 | static int trace_fill_id(struct sk_buff *nlskb, struct sk_buff *skb) | ||
| 29 | { | ||
| 30 | __be32 id; | ||
| 31 | |||
| 32 | /* using skb address as ID results in a limited number of | ||
| 33 | * values (and quick reuse). | ||
| 34 | * | ||
| 35 | * So we attempt to use as many skb members that will not | ||
| 36 | * change while skb is with netfilter. | ||
| 37 | */ | ||
| 38 | id = (__be32)jhash_2words(hash32_ptr(skb), skb_get_hash(skb), | ||
| 39 | skb->skb_iif); | ||
| 40 | |||
| 41 | return nla_put_be32(nlskb, NFTA_TRACE_ID, id); | ||
| 42 | } | ||
| 43 | |||
| 44 | static int trace_fill_header(struct sk_buff *nlskb, u16 type, | 28 | static int trace_fill_header(struct sk_buff *nlskb, u16 type, |
| 45 | const struct sk_buff *skb, | 29 | const struct sk_buff *skb, |
| 46 | int off, unsigned int len) | 30 | int off, unsigned int len) |
| @@ -186,6 +170,7 @@ void nft_trace_notify(struct nft_traceinfo *info) · 139 unmodified lines | |||
| 186 | struct nlmsghdr *nlh; | 170 | struct nlmsghdr *nlh; |
| 187 | struct sk_buff *skb; | 171 | struct sk_buff *skb; |
| 188 | unsigned int size; | 172 | unsigned int size; |
| 173 | u32 mark = 0; | ||
| 189 | u16 event; | 174 | u16 event; |
| 190 | 175 | ||
| 191 | if (!nfnetlink_has_listeners(nft_net(pkt), NFNLGRP_NFTRACE)) | 176 | if (!nfnetlink_has_listeners(nft_net(pkt), NFNLGRP_NFTRACE)) |
| @@ -229,7 +214,7 @@ void nft_trace_notify(struct nft_traceinfo *info) · 37 unmodified lines | |||
| 229 | if (nla_put_be32(skb, NFTA_TRACE_TYPE, htonl(info->type))) | 214 | if (nla_put_be32(skb, NFTA_TRACE_TYPE, htonl(info->type))) |
| 230 | goto nla_put_failure; | 215 | goto nla_put_failure; |
| 231 | 216 | ||
| 232 | if (trace_fill_id(skb, pkt->skb)) | 217 | if (nla_put_u32(skb, NFTA_TRACE_ID, info->skbid)) |
| 233 | goto nla_put_failure; | 218 | goto nla_put_failure; |
| 234 | 219 | ||
| 235 | if (nla_put_string(skb, NFTA_TRACE_CHAIN, info->chain->name)) | 220 | if (nla_put_string(skb, NFTA_TRACE_CHAIN, info->chain->name)) |
| @@ -249,16 +234,24 @@ void nft_trace_notify(struct nft_traceinfo *info) · 13 unmodified lines | |||
| 249 | case NFT_TRACETYPE_RULE: | 234 | case NFT_TRACETYPE_RULE: |
| 250 | if (nft_verdict_dump(skb, NFTA_TRACE_VERDICT, info->verdict)) | 235 | if (nft_verdict_dump(skb, NFTA_TRACE_VERDICT, info->verdict)) |
| 251 | goto nla_put_failure; | 236 | goto nla_put_failure; |
| 237 | |||
| 238 | /* pkt->skb undefined iff NF_STOLEN, disable dump */ | ||
| 239 | if (info->verdict->code == NF_STOLEN) | ||
| 240 | info->packet_dumped = true; | ||
| 241 | else | ||
| 242 | mark = pkt->skb->mark; | ||
| 243 | |||
| 252 | break; | 244 | break; |
| 253 | case NFT_TRACETYPE_POLICY: | 245 | case NFT_TRACETYPE_POLICY: |
| 246 | mark = pkt->skb->mark; | ||
| 247 | |||
| 254 | if (nla_put_be32(skb, NFTA_TRACE_POLICY, | 248 | if (nla_put_be32(skb, NFTA_TRACE_POLICY, |
| 255 | htonl(info->basechain->policy))) | 249 | htonl(info->basechain->policy))) |
| 256 | goto nla_put_failure; | 250 | goto nla_put_failure; |
| 257 | break; | 251 | break; |
| 258 | } | 252 | } |
| 259 | 253 | ||
| 260 | if (pkt->skb->mark && | 254 | if (mark && nla_put_be32(skb, NFTA_TRACE_MARK, htonl(mark))) |
| 261 | nla_put_be32(skb, NFTA_TRACE_MARK, htonl(pkt->skb->mark))) | ||
| 262 | goto nla_put_failure; | 255 | goto nla_put_failure; |
| 263 | 256 | ||
| 264 | if (!info->packet_dumped) { | 257 | if (!info->packet_dumped) { |
| @@ -283,9 +276,20 @@ void nft_trace_init(struct nft_traceinfo *info, const struct nft_pktinfo *pkt, · 18 unmodified lines | |||
| 283 | const struct nft_verdict *verdict, | 276 | const struct nft_verdict *verdict, |
| 284 | const struct nft_chain *chain) | 277 | const struct nft_chain *chain) |
| 285 | { | 278 | { |
| 279 | static siphash_key_t trace_key __read_mostly; | ||
| 280 | struct sk_buff *skb = pkt->skb; | ||
| 281 | |||
| 286 | info->basechain = nft_base_chain(chain); | 282 | info->basechain = nft_base_chain(chain); |
| 287 | info->trace = true; | 283 | info->trace = true; |
| 284 | info->nf_trace = pkt->skb->nf_trace; | ||
| 288 | info->packet_dumped = false; | 285 | info->packet_dumped = false; |
| 289 | info->pkt = pkt; | 286 | info->pkt = pkt; |
| 290 | info->verdict = verdict; | 287 | info->verdict = verdict; |
| 288 | |||
| 289 | net_get_random_once(&trace_key, sizeof(trace_key)); | ||
| 290 | |||
| 291 | info->skbid = (u32)siphash_3u32(hash32_ptr(skb), | ||
| 292 | skb_get_hash(skb), | ||
| 293 | skb->skb_iif, | ||
| 294 | &trace_key); | ||
| 291 | } | 295 | } |
| @@ -143,6 +143,7 @@ static bool nft_rhash_update(struct nft_set *set, const u32 *key, · 142 unmodified lines | |||
| 143 | /* Another cpu may race to insert the element with the same key */ | 143 | /* Another cpu may race to insert the element with the same key */ |
| 144 | if (prev) { | 144 | if (prev) { |
| 145 | nft_set_elem_destroy(set, he, true); | 145 | nft_set_elem_destroy(set, he, true); |
| 146 | atomic_dec(&set->nelems); | ||
| 146 | he = prev; | 147 | he = prev; |
| 147 | } | 148 | } |
| 148 | 149 | ||
| @@ -152,6 +153,7 @@ out: · 3 unmodified lines | |||
| 152 | 153 | ||
| 153 | err2: | 154 | err2: |
| 154 | nft_set_elem_destroy(set, he, true); | 155 | nft_set_elem_destroy(set, he, true); |
| 156 | atomic_dec(&set->nelems); | ||
| 155 | err1: | 157 | err1: |
| 156 | return false; | 158 | return false; |
| 157 | } | 159 | } |
| @@ -31,89 +31,89 @@ static void rose_idletimer_expiry(struct timer_list *); · 30 unmodified lines | |||
| 31 | 31 | ||
| 32 | void rose_start_heartbeat(struct sock *sk) | 32 | void rose_start_heartbeat(struct sock *sk) |
| 33 | { | 33 | { |
| 34 | del_timer(&sk->sk_timer); | 34 | sk_stop_timer(sk, &sk->sk_timer); |
| 35 | 35 | ||
| 36 | sk->sk_timer.function = rose_heartbeat_expiry; | 36 | sk->sk_timer.function = rose_heartbeat_expiry; |
| 37 | sk->sk_timer.expires = jiffies + 5 * HZ; | 37 | sk->sk_timer.expires = jiffies + 5 * HZ; |
| 38 | 38 | ||
| 39 | add_timer(&sk->sk_timer); | 39 | sk_reset_timer(sk, &sk->sk_timer, sk->sk_timer.expires); |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | void rose_start_t1timer(struct sock *sk) | 42 | void rose_start_t1timer(struct sock *sk) |
| 43 | { | 43 | { |
| 44 | struct rose_sock *rose = rose_sk(sk); | 44 | struct rose_sock *rose = rose_sk(sk); |
| 45 | 45 | ||
| 46 | del_timer(&rose->timer); | 46 | sk_stop_timer(sk, &rose->timer); |
| 47 | 47 | ||
| 48 | rose->timer.function = rose_timer_expiry; | 48 | rose->timer.function = rose_timer_expiry; |
| 49 | rose->timer.expires = jiffies + rose->t1; | 49 | rose->timer.expires = jiffies + rose->t1; |
| 50 | 50 | ||
| 51 | add_timer(&rose->timer); | 51 | sk_reset_timer(sk, &rose->timer, rose->timer.expires); |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | void rose_start_t2timer(struct sock *sk) | 54 | void rose_start_t2timer(struct sock *sk) |
| 55 | { | 55 | { |
| 56 | struct rose_sock *rose = rose_sk(sk); | 56 | struct rose_sock *rose = rose_sk(sk); |
| 57 | 57 | ||
| 58 | del_timer(&rose->timer); | 58 | sk_stop_timer(sk, &rose->timer); |
| 59 | 59 | ||
| 60 | rose->timer.function = rose_timer_expiry; | 60 | rose->timer.function = rose_timer_expiry; |
| 61 | rose->timer.expires = jiffies + rose->t2; | 61 | rose->timer.expires = jiffies + rose->t2; |
| 62 | 62 | ||
| 63 | add_timer(&rose->timer); | 63 | sk_reset_timer(sk, &rose->timer, rose->timer.expires); |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | void rose_start_t3timer(struct sock *sk) | 66 | void rose_start_t3timer(struct sock *sk) |
| 67 | { | 67 | { |
| 68 | struct rose_sock *rose = rose_sk(sk); | 68 | struct rose_sock *rose = rose_sk(sk); |
| 69 | 69 | ||
| 70 | del_timer(&rose->timer); | 70 | sk_stop_timer(sk, &rose->timer); |
| 71 | 71 | ||
| 72 | rose->timer.function = rose_timer_expiry; | 72 | rose->timer.function = rose_timer_expiry; |
| 73 | rose->timer.expires = jiffies + rose->t3; | 73 | rose->timer.expires = jiffies + rose->t3; |
| 74 | 74 | ||
| 75 | add_timer(&rose->timer); | 75 | sk_reset_timer(sk, &rose->timer, rose->timer.expires); |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | void rose_start_hbtimer(struct sock *sk) | 78 | void rose_start_hbtimer(struct sock *sk) |
| 79 | { | 79 | { |
| 80 | struct rose_sock *rose = rose_sk(sk); | 80 | struct rose_sock *rose = rose_sk(sk); |
| 81 | 81 | ||
| 82 | del_timer(&rose->timer); | 82 | sk_stop_timer(sk, &rose->timer); |
| 83 | 83 | ||
| 84 | rose->timer.function = rose_timer_expiry; | 84 | rose->timer.function = rose_timer_expiry; |
| 85 | rose->timer.expires = jiffies + rose->hb; | 85 | rose->timer.expires = jiffies + rose->hb; |
| 86 | 86 | ||
| 87 | add_timer(&rose->timer); | 87 | sk_reset_timer(sk, &rose->timer, rose->timer.expires); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | void rose_start_idletimer(struct sock *sk) | 90 | void rose_start_idletimer(struct sock *sk) |
| 91 | { | 91 | { |
| 92 | struct rose_sock *rose = rose_sk(sk); | 92 | struct rose_sock *rose = rose_sk(sk); |
| 93 | 93 | ||
| 94 | del_timer(&rose->idletimer); | 94 | sk_stop_timer(sk, &rose->idletimer); |
| 95 | 95 | ||
| 96 | if (rose->idle > 0) { | 96 | if (rose->idle > 0) { |
| 97 | rose->idletimer.function = rose_idletimer_expiry; | 97 | rose->idletimer.function = rose_idletimer_expiry; |
| 98 | rose->idletimer.expires = jiffies + rose->idle; | 98 | rose->idletimer.expires = jiffies + rose->idle; |
| 99 | 99 | ||
| 100 | add_timer(&rose->idletimer); | 100 | sk_reset_timer(sk, &rose->idletimer, rose->idletimer.expires); |
| 101 | } | 101 | } |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | void rose_stop_heartbeat(struct sock *sk) | 104 | void rose_stop_heartbeat(struct sock *sk) |
| 105 | { | 105 | { |
| 106 | del_timer(&sk->sk_timer); | 106 | sk_stop_timer(sk, &sk->sk_timer); |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | void rose_stop_timer(struct sock *sk) | 109 | void rose_stop_timer(struct sock *sk) |
| 110 | { | 110 | { |
| 111 | del_timer(&rose_sk(sk)->timer); | 111 | sk_stop_timer(sk, &rose_sk(sk)->timer); |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | void rose_stop_idletimer(struct sock *sk) | 114 | void rose_stop_idletimer(struct sock *sk) |
| 115 | { | 115 | { |
| 116 | del_timer(&rose_sk(sk)->idletimer); | 116 | sk_stop_timer(sk, &rose_sk(sk)->idletimer); |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | static void rose_heartbeat_expiry(struct timer_list *t) | 119 | static void rose_heartbeat_expiry(struct timer_list *t) |
| @@ -130,6 +130,7 @@ static void rose_heartbeat_expiry(struct timer_list *t) · 10 unmodified lines | |||
| 130 | (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) { | 130 | (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) { |
| 131 | bh_unlock_sock(sk); | 131 | bh_unlock_sock(sk); |
| 132 | rose_destroy_socket(sk); | 132 | rose_destroy_socket(sk); |
| 133 | sock_put(sk); | ||
| 133 | return; | 134 | return; |
| 134 | } | 135 | } |
| 135 | break; | 136 | break; |
| @@ -152,6 +153,7 @@ static void rose_heartbeat_expiry(struct timer_list *t) · 16 unmodified lines | |||
| 152 | 153 | ||
| 153 | rose_start_heartbeat(sk); | 154 | rose_start_heartbeat(sk); |
| 154 | bh_unlock_sock(sk); | 155 | bh_unlock_sock(sk); |
| 156 | sock_put(sk); | ||
| 155 | } | 157 | } |
| 156 | 158 | ||
| 157 | static void rose_timer_expiry(struct timer_list *t) | 159 | static void rose_timer_expiry(struct timer_list *t) |
| @@ -181,6 +183,7 @@ static void rose_timer_expiry(struct timer_list *t) · 23 unmodified lines | |||
| 181 | break; | 183 | break; |
| 182 | } | 184 | } |
| 183 | bh_unlock_sock(sk); | 185 | bh_unlock_sock(sk); |
| 186 | sock_put(sk); | ||
| 184 | } | 187 | } |
| 185 | 188 | ||
| 186 | static void rose_idletimer_expiry(struct timer_list *t) | 189 | static void rose_idletimer_expiry(struct timer_list *t) |
| @@ -205,4 +208,5 @@ static void rose_idletimer_expiry(struct timer_list *t) · 18 unmodified lines | |||
| 205 | sock_set_flag(sk, SOCK_DEAD); | 208 | sock_set_flag(sk, SOCK_DEAD); |
| 206 | } | 209 | } |
| 207 | bh_unlock_sock(sk); | 210 | bh_unlock_sock(sk); |
| 211 | sock_put(sk); | ||
| 208 | } | 212 | } |
| @@ -588,7 +588,8 @@ static int tcf_idr_release_unsafe(struct tc_action *p) · 587 unmodified lines | |||
| 588 | } | 588 | } |
| 589 | 589 | ||
| 590 | static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb, | 590 | static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb, |
| 591 | const struct tc_action_ops *ops) | 591 | const struct tc_action_ops *ops, |
| 592 | struct netlink_ext_ack *extack) | ||
| 592 | { | 593 | { |
| 593 | struct nlattr *nest; | 594 | struct nlattr *nest; |
| 594 | int n_i = 0; | 595 | int n_i = 0; |
| @@ -604,20 +605,25 @@ static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb, · 9 unmodified lines | |||
| 604 | if (nla_put_string(skb, TCA_KIND, ops->kind)) | 605 | if (nla_put_string(skb, TCA_KIND, ops->kind)) |
| 605 | goto nla_put_failure; | 606 | goto nla_put_failure; |
| 606 | 607 | ||
| 608 | ret = 0; | ||
| 607 | mutex_lock(&idrinfo->lock); | 609 | mutex_lock(&idrinfo->lock); |
| 608 | idr_for_each_entry_ul(idr, p, tmp, id) { | 610 | idr_for_each_entry_ul(idr, p, tmp, id) { |
| 609 | if (IS_ERR(p)) | 611 | if (IS_ERR(p)) |
| 610 | continue; | 612 | continue; |
| 611 | ret = tcf_idr_release_unsafe(p); | 613 | ret = tcf_idr_release_unsafe(p); |
| 612 | if (ret == ACT_P_DELETED) { | 614 | if (ret == ACT_P_DELETED) |
| 613 | module_put(ops->owner); | 615 | module_put(ops->owner); |
| 614 | n_i++; | 616 | else if (ret < 0) |
| 615 | } else if (ret < 0) { | 617 | break; |
| 616 | mutex_unlock(&idrinfo->lock); | 618 | n_i++; |
| 617 | goto nla_put_failure; | ||
| 618 | } | ||
| 619 | } | 619 | } |
| 620 | mutex_unlock(&idrinfo->lock); | 620 | mutex_unlock(&idrinfo->lock); |
| 621 | if (ret < 0) { | ||
| 622 | if (n_i) | ||
| 623 | NL_SET_ERR_MSG(extack, "Unable to flush all TC actions"); | ||
| 624 | else | ||
| 625 | goto nla_put_failure; | ||
| 626 | } | ||
| 621 | 627 | ||
| 622 | ret = nla_put_u32(skb, TCA_FCNT, n_i); | 628 | ret = nla_put_u32(skb, TCA_FCNT, n_i); |
| 623 | if (ret) | 629 | if (ret) |
| @@ -638,7 +644,7 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb, · 14 unmodified lines | |||
| 638 | struct tcf_idrinfo *idrinfo = tn->idrinfo; | 644 | struct tcf_idrinfo *idrinfo = tn->idrinfo; |
| 639 | 645 | ||
| 640 | if (type == RTM_DELACTION) { | 646 | if (type == RTM_DELACTION) { |
| 641 | return tcf_del_walker(idrinfo, skb, ops); | 647 | return tcf_del_walker(idrinfo, skb, ops, extack); |
| 642 | } else if (type == RTM_GETACTION) { | 648 | } else if (type == RTM_GETACTION) { |
| 643 | return tcf_dump_walker(idrinfo, skb, cb); | 649 | return tcf_dump_walker(idrinfo, skb, cb); |
| 644 | } else { | 650 | } else { |
| @@ -2149,10 +2149,13 @@ SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len, · 2148 unmodified lines | |||
| 2149 | int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags, | 2149 | int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags, |
| 2150 | struct sockaddr __user *addr, int __user *addr_len) | 2150 | struct sockaddr __user *addr, int __user *addr_len) |
| 2151 | { | 2151 | { |
| 2152 | struct sockaddr_storage address; | ||
| 2153 | struct msghdr msg = { | ||
| 2154 | /* Save some cycles and don't copy the address if not needed */ | ||
| 2155 | .msg_name = addr ? (struct sockaddr *)&address : NULL, | ||
| 2156 | }; | ||
| 2152 | struct socket *sock; | 2157 | struct socket *sock; |
| 2153 | struct iovec iov; | 2158 | struct iovec iov; |
| 2154 | struct msghdr msg; | ||
| 2155 | struct sockaddr_storage address; | ||
| 2156 | int err, err2; | 2159 | int err, err2; |
| 2157 | int fput_needed; | 2160 | int fput_needed; |
| 2158 | 2161 | ||
| @@ -2163,14 +2166,6 @@ int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags, · 4 unmodified lines | |||
| 2163 | if (!sock) | 2166 | if (!sock) |
| 2164 | goto out; | 2167 | goto out; |
| 2165 | 2168 | ||
| 2166 | msg.msg_control = NULL; | ||
| 2167 | msg.msg_controllen = 0; | ||
| 2168 | /* Save some cycles and don't copy the address if not needed */ | ||
| 2169 | msg.msg_name = addr ? (struct sockaddr *)&address : NULL; | ||
| 2170 | /* We assume all kernel code knows the size of sockaddr_storage */ | ||
| 2171 | msg.msg_namelen = 0; | ||
| 2172 | msg.msg_iocb = NULL; | ||
| 2173 | msg.msg_flags = 0; | ||
| 2174 | if (sock->file->f_flags & O_NONBLOCK) | 2169 | if (sock->file->f_flags & O_NONBLOCK) |
| 2175 | flags |= MSG_DONTWAIT; | 2170 | flags |= MSG_DONTWAIT; |
| 2176 | err = sock_recvmsg(sock, &msg, flags); | 2171 | err = sock_recvmsg(sock, &msg, flags); |
| @@ -2375,6 +2370,7 @@ int __copy_msghdr_from_user(struct msghdr *kmsg, · 198 unmodified lines | |||
| 2375 | return -EFAULT; | 2370 | return -EFAULT; |
| 2376 | 2371 | ||
| 2377 | kmsg->msg_control_is_user = true; | 2372 | kmsg->msg_control_is_user = true; |
| 2373 | kmsg->msg_get_inq = 0; | ||
| 2378 | kmsg->msg_control_user = msg.msg_control; | 2374 | kmsg->msg_control_user = msg.msg_control; |
| 2379 | kmsg->msg_controllen = msg.msg_controllen; | 2375 | kmsg->msg_controllen = msg.msg_controllen; |
| 2380 | kmsg->msg_flags = msg.msg_flags; | 2376 | kmsg->msg_flags = msg.msg_flags; |
| @@ -472,8 +472,8 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u8 *peer_id, · 471 unmodified lines | |||
| 472 | bool preliminary) | 472 | bool preliminary) |
| 473 | { | 473 | { |
| 474 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 474 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
| 475 | struct tipc_link *l, *snd_l = tipc_bc_sndlink(net); | ||
| 475 | struct tipc_node *n, *temp_node; | 476 | struct tipc_node *n, *temp_node; |
| 476 | struct tipc_link *l; | ||
| 477 | unsigned long intv; | 477 | unsigned long intv; |
| 478 | int bearer_id; | 478 | int bearer_id; |
| 479 | int i; | 479 | int i; |
| @@ -488,6 +488,16 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr, u8 *peer_id, · 8 unmodified lines | |||
| 488 | goto exit; | 488 | goto exit; |
| 489 | /* A preliminary node becomes "real" now, refresh its data */ | 489 | /* A preliminary node becomes "real" now, refresh its data */ |
| 490 | tipc_node_write_lock(n); | 490 | tipc_node_write_lock(n); |
| 491 | if (!tipc_link_bc_create(net, tipc_own_addr(net), addr, peer_id, U16_MAX, | ||
| 492 | tipc_link_min_win(snd_l), tipc_link_max_win(snd_l), | ||
| 493 | n->capabilities, &n->bc_entry.inputq1, | ||
| 494 | &n->bc_entry.namedq, snd_l, &n->bc_entry.link)) { | ||
| 495 | pr_warn("Broadcast rcv link refresh failed, no memory\n"); | ||
| 496 | tipc_node_write_unlock_fast(n); | ||
| 497 | tipc_node_put(n); | ||
| 498 | n = NULL; | ||
| 499 | goto exit; | ||
| 500 | } | ||
| 491 | n->preliminary = false; | 501 | n->preliminary = false; |
| 492 | n->addr = addr; | 502 | n->addr = addr; |
| 493 | hlist_del_rcu(&n->hash); | 503 | hlist_del_rcu(&n->hash); |
| @@ -567,7 +577,16 @@ update: · 73 unmodified lines | |||
| 567 | n->signature = INVALID_NODE_SIG; | 577 | n->signature = INVALID_NODE_SIG; |
| 568 | n->active_links[0] = INVALID_BEARER_ID; | 578 | n->active_links[0] = INVALID_BEARER_ID; |
| 569 | n->active_links[1] = INVALID_BEARER_ID; | 579 | n->active_links[1] = INVALID_BEARER_ID; |
| 570 | n->bc_entry.link = NULL; | 580 | if (!preliminary && |
| 581 | !tipc_link_bc_create(net, tipc_own_addr(net), addr, peer_id, U16_MAX, | ||
| 582 | tipc_link_min_win(snd_l), tipc_link_max_win(snd_l), | ||
| 583 | n->capabilities, &n->bc_entry.inputq1, | ||
| 584 | &n->bc_entry.namedq, snd_l, &n->bc_entry.link)) { | ||
| 585 | pr_warn("Broadcast rcv link creation failed, no memory\n"); | ||
| 586 | kfree(n); | ||
| 587 | n = NULL; | ||
| 588 | goto exit; | ||
| 589 | } | ||
| 571 | tipc_node_get(n); | 590 | tipc_node_get(n); |
| 572 | timer_setup(&n->timer, tipc_node_timeout, 0); | 591 | timer_setup(&n->timer, tipc_node_timeout, 0); |
| 573 | /* Start a slow timer anyway, crypto needs it */ | 592 | /* Start a slow timer anyway, crypto needs it */ |
| @@ -1155,7 +1174,7 @@ void tipc_node_check_dest(struct net *net, u32 addr, · 581 unmodified lines | |||
| 1155 | bool *respond, bool *dupl_addr) | 1174 | bool *respond, bool *dupl_addr) |
| 1156 | { | 1175 | { |
| 1157 | struct tipc_node *n; | 1176 | struct tipc_node *n; |
| 1158 | struct tipc_link *l, *snd_l; | 1177 | struct tipc_link *l; |
| 1159 | struct tipc_link_entry *le; | 1178 | struct tipc_link_entry *le; |
| 1160 | bool addr_match = false; | 1179 | bool addr_match = false; |
| 1161 | bool sign_match = false; | 1180 | bool sign_match = false; |
| @@ -1175,22 +1194,6 @@ void tipc_node_check_dest(struct net *net, u32 addr, · 13 unmodified lines | |||
| 1175 | return; | 1194 | return; |
| 1176 | 1195 | ||
| 1177 | tipc_node_write_lock(n); | 1196 | tipc_node_write_lock(n); |
| 1178 | if (unlikely(!n->bc_entry.link)) { | ||
| 1179 | snd_l = tipc_bc_sndlink(net); | ||
| 1180 | if (!tipc_link_bc_create(net, tipc_own_addr(net), | ||
| 1181 | addr, peer_id, U16_MAX, | ||
| 1182 | tipc_link_min_win(snd_l), | ||
| 1183 | tipc_link_max_win(snd_l), | ||
| 1184 | n->capabilities, | ||
| 1185 | &n->bc_entry.inputq1, | ||
| 1186 | &n->bc_entry.namedq, snd_l, | ||
| 1187 | &n->bc_entry.link)) { | ||
| 1188 | pr_warn("Broadcast rcv link creation failed, no mem\n"); | ||
| 1189 | tipc_node_write_unlock_fast(n); | ||
| 1190 | tipc_node_put(n); | ||
| 1191 | return; | ||
| 1192 | } | ||
| 1193 | } | ||
| 1194 | 1197 | ||
| 1195 | le = &n->links[b->identity]; | 1198 | le = &n->links[b->identity]; |
| 1196 | 1199 | ||
| @@ -502,6 +502,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock, · 501 unmodified lines | |||
| 502 | sock_init_data(sock, sk); | 502 | sock_init_data(sock, sk); |
| 503 | tipc_set_sk_state(sk, TIPC_OPEN); | 503 | tipc_set_sk_state(sk, TIPC_OPEN); |
| 504 | if (tipc_sk_insert(tsk)) { | 504 | if (tipc_sk_insert(tsk)) { |
| 505 | sk_free(sk); | ||
| 505 | pr_warn("Socket create failed; port number exhausted\n"); | 506 | pr_warn("Socket create failed; port number exhausted\n"); |
| 506 | return -EINVAL; | 507 | return -EINVAL; |
| 507 | } | 508 | } |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | |||
| 4 | * Tests for sockmap/sockhash holding kTLS sockets. | 4 | * Tests for sockmap/sockhash holding kTLS sockets. |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #include <netinet/tcp.h> | ||
| 7 | #include "test_progs.h" | 8 | #include "test_progs.h" |
| 8 | 9 | ||
| 9 | #define MAX_TEST_NAME 80 | 10 | #define MAX_TEST_NAME 80 |
| @@ -92,9 +93,78 @@ close_srv: · 82 unmodified lines | |||
| 92 | close(srv); | 93 | close(srv); |
| 93 | } | 94 | } |
| 94 | 95 | ||
| 96 | static void test_sockmap_ktls_update_fails_when_sock_has_ulp(int family, int map) | ||
| 97 | { | ||
| 98 | struct sockaddr_storage addr = {}; | ||
| 99 | socklen_t len = sizeof(addr); | ||
| 100 | struct sockaddr_in6 *v6; | ||
| 101 | struct sockaddr_in *v4; | ||
| 102 | int err, s, zero = 0; | ||
| 103 | |||
| 104 | switch (family) { | ||
| 105 | case AF_INET: | ||
| 106 | v4 = (struct sockaddr_in *)&addr; | ||
| 107 | v4->sin_family = AF_INET; | ||
| 108 | break; | ||
| 109 | case AF_INET6: | ||
| 110 | v6 = (struct sockaddr_in6 *)&addr; | ||
| 111 | v6->sin6_family = AF_INET6; | ||
| 112 | break; | ||
| 113 | default: | ||
| 114 | PRINT_FAIL("unsupported socket family %d", family); | ||
| 115 | return; | ||
| 116 | } | ||
| 117 | |||
| 118 | s = socket(family, SOCK_STREAM, 0); | ||
| 119 | if (!ASSERT_GE(s, 0, "socket")) | ||
| 120 | return; | ||
| 121 | |||
| 122 | err = bind(s, (struct sockaddr *)&addr, len); | ||
| 123 | if (!ASSERT_OK(err, "bind")) | ||
| 124 | goto close; | ||
| 125 | |||
| 126 | err = getsockname(s, (struct sockaddr *)&addr, &len); | ||
| 127 | if (!ASSERT_OK(err, "getsockname")) | ||
| 128 | goto close; | ||
| 129 | |||
| 130 | err = connect(s, (struct sockaddr *)&addr, len); | ||
| 131 | if (!ASSERT_OK(err, "connect")) | ||
| 132 | goto close; | ||
| 133 | |||
| 134 | /* save sk->sk_prot and set it to tls_prots */ | ||
| 135 | err = setsockopt(s, IPPROTO_TCP, TCP_ULP, "tls", strlen("tls")); | ||
| 136 | if (!ASSERT_OK(err, "setsockopt(TCP_ULP)")) | ||
| 137 | goto close; | ||
| 138 | |||
| 139 | /* sockmap update should not affect saved sk_prot */ | ||
| 140 | err = bpf_map_update_elem(map, &zero, &s, BPF_ANY); | ||
| 141 | if (!ASSERT_ERR(err, "sockmap update elem")) | ||
| 142 | goto close; | ||
| 143 | |||
| 144 | /* call sk->sk_prot->setsockopt to dispatch to saved sk_prot */ | ||
| 145 | err = setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &zero, sizeof(zero)); | ||
| 146 | ASSERT_OK(err, "setsockopt(TCP_NODELAY)"); | ||
| 147 | |||
| 148 | close: | ||
| 149 | close(s); | ||
| 150 | } | ||
| 151 | |||
| 152 | static const char *fmt_test_name(const char *subtest_name, int family, | ||
| 153 | enum bpf_map_type map_type) | ||
| 154 | { | ||
| 155 | const char *map_type_str = BPF_MAP_TYPE_SOCKMAP ? "SOCKMAP" : "SOCKHASH"; | ||
| 156 | const char *family_str = AF_INET ? "IPv4" : "IPv6"; | ||
| 157 | static char test_name[MAX_TEST_NAME]; | ||
| 158 | |||
| 159 | snprintf(test_name, MAX_TEST_NAME, | ||
| 160 | "sockmap_ktls %s %s %s", | ||
| 161 | subtest_name, family_str, map_type_str); | ||
| 162 | |||
| 163 | return test_name; | ||
| 164 | } | ||
| 165 | |||
| 95 | static void run_tests(int family, enum bpf_map_type map_type) | 166 | static void run_tests(int family, enum bpf_map_type map_type) |
| 96 | { | 167 | { |
| 97 | char test_name[MAX_TEST_NAME]; | ||
| 98 | int map; | 168 | int map; |
| 99 | 169 | ||
| 100 | map = bpf_map_create(map_type, NULL, sizeof(int), sizeof(int), 1, NULL); | 170 | map = bpf_map_create(map_type, NULL, sizeof(int), sizeof(int), 1, NULL); |
| @@ -103,14 +173,10 @@ static void run_tests(int family, enum bpf_map_type map_type) · 2 unmodified lines | |||
| 103 | return; | 173 | return; |
| 104 | } | 174 | } |
| 105 | 175 | ||
| 106 | snprintf(test_name, MAX_TEST_NAME, | 176 | if (test__start_subtest(fmt_test_name("disconnect_after_delete", family, map_type))) |
| 107 | "sockmap_ktls disconnect_after_delete %s %s", | 177 | test_sockmap_ktls_disconnect_after_delete(family, map); |
| 108 | family == AF_INET ? "IPv4" : "IPv6", | 178 | if (test__start_subtest(fmt_test_name("update_fails_when_sock_has_ulp", family, map_type))) |
| 109 | map_type == BPF_MAP_TYPE_SOCKMAP ? "SOCKMAP" : "SOCKHASH"); | 179 | test_sockmap_ktls_update_fails_when_sock_has_ulp(family, map); |
| 110 | if (!test__start_subtest(test_name)) | ||
| 111 | return; | ||
| 112 | |||
| 113 | test_sockmap_ktls_disconnect_after_delete(family, map); | ||
| 114 | 180 | ||
| 115 | close(map); | 181 | close(map); |
| 116 | } | 182 | } |
| @@ -54,7 +54,7 @@ TEST_GEN_FILES += ipsec · 53 unmodified lines | |||
| 54 | TEST_GEN_FILES += ioam6_parser | 54 | TEST_GEN_FILES += ioam6_parser |
| 55 | TEST_GEN_FILES += gro | 55 | TEST_GEN_FILES += gro |
| 56 | TEST_GEN_PROGS = reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa | 56 | TEST_GEN_PROGS = reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa |
| 57 | TEST_GEN_PROGS += reuseport_dualstack reuseaddr_conflict tls | 57 | TEST_GEN_PROGS += reuseport_dualstack reuseaddr_conflict tls tun |
| 58 | TEST_GEN_FILES += toeplitz | 58 | TEST_GEN_FILES += toeplitz |
| 59 | TEST_GEN_FILES += cmsg_sender | 59 | TEST_GEN_FILES += cmsg_sender |
| 60 | TEST_GEN_FILES += stress_reuseport_listen | 60 | TEST_GEN_FILES += stress_reuseport_listen |
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | 2 | ||
| 3 | CLANG ?= clang | 3 | CLANG ?= clang |
| 4 | CCINCLUDE += -I../../bpf | 4 | CCINCLUDE += -I../../bpf |
| 5 | CCINCLUDE += -I../../../lib | 5 | CCINCLUDE += -I../../../../lib |
| 6 | CCINCLUDE += -I../../../../../usr/include/ | 6 | CCINCLUDE += -I../../../../../usr/include/ |
| 7 | 7 | ||
| 8 | TEST_CUSTOM_PROGS = $(OUTPUT)/bpf/nat6to4.o | 8 | TEST_CUSTOM_PROGS = $(OUTPUT)/bpf/nat6to4.o |
| @@ -61,6 +61,39 @@ chk_msk_nr() · 60 unmodified lines | |||
| 61 | __chk_nr "grep -c token:" $* | 61 | __chk_nr "grep -c token:" $* |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | wait_msk_nr() | ||
| 65 | { | ||
| 66 | local condition="grep -c token:" | ||
| 67 | local expected=$1 | ||
| 68 | local timeout=20 | ||
| 69 | local msg nr | ||
| 70 | local max=0 | ||
| 71 | local i=0 | ||
| 72 | |||
| 73 | shift 1 | ||
| 74 | msg=$* | ||
| 75 | |||
| 76 | while [ $i -lt $timeout ]; do | ||
| 77 | nr=$(ss -inmHMN $ns | $condition) | ||
| 78 | [ $nr == $expected ] && break; | ||
| 79 | [ $nr -gt $max ] && max=$nr | ||
| 80 | i=$((i + 1)) | ||
| 81 | sleep 1 | ||
| 82 | done | ||
| 83 | |||
| 84 | printf "%-50s" "$msg" | ||
| 85 | if [ $i -ge $timeout ]; then | ||
| 86 | echo "[ fail ] timeout while expecting $expected max $max last $nr" | ||
| 87 | ret=$test_cnt | ||
| 88 | elif [ $nr != $expected ]; then | ||
| 89 | echo "[ fail ] expected $expected found $nr" | ||
| 90 | ret=$test_cnt | ||
| 91 | else | ||
| 92 | echo "[ ok ]" | ||
| 93 | fi | ||
| 94 | test_cnt=$((test_cnt+1)) | ||
| 95 | } | ||
| 96 | |||
| 64 | chk_msk_fallback_nr() | 97 | chk_msk_fallback_nr() |
| 65 | { | 98 | { |
| 66 | __chk_nr "grep -c fallback" $* | 99 | __chk_nr "grep -c fallback" $* |
| @@ -146,7 +179,7 @@ ip -n $ns link set dev lo up · 79 unmodified lines | |||
| 146 | echo "a" | \ | 179 | echo "a" | \ |
| 147 | timeout ${timeout_test} \ | 180 | timeout ${timeout_test} \ |
| 148 | ip netns exec $ns \ | 181 | ip netns exec $ns \ |
| 149 | ./mptcp_connect -p 10000 -l -t ${timeout_poll} \ | 182 | ./mptcp_connect -p 10000 -l -t ${timeout_poll} -w 20 \ |
| 150 | 0.0.0.0 >/dev/null & | 183 | 0.0.0.0 >/dev/null & |
| 151 | wait_local_port_listen $ns 10000 | 184 | wait_local_port_listen $ns 10000 |
| 152 | chk_msk_nr 0 "no msk on netns creation" | 185 | chk_msk_nr 0 "no msk on netns creation" |
| @@ -155,7 +188,7 @@ chk_msk_listen 10000 · 2 unmodified lines | |||
| 155 | echo "b" | \ | 188 | echo "b" | \ |
| 156 | timeout ${timeout_test} \ | 189 | timeout ${timeout_test} \ |
| 157 | ip netns exec $ns \ | 190 | ip netns exec $ns \ |
| 158 | ./mptcp_connect -p 10000 -r 0 -t ${timeout_poll} \ | 191 | ./mptcp_connect -p 10000 -r 0 -t ${timeout_poll} -w 20 \ |
| 159 | 127.0.0.1 >/dev/null & | 192 | 127.0.0.1 >/dev/null & |
| 160 | wait_connected $ns 10000 | 193 | wait_connected $ns 10000 |
| 161 | chk_msk_nr 2 "after MPC handshake " | 194 | chk_msk_nr 2 "after MPC handshake " |
| @@ -167,13 +200,13 @@ flush_pids · 5 unmodified lines | |||
| 167 | echo "a" | \ | 200 | echo "a" | \ |
| 168 | timeout ${timeout_test} \ | 201 | timeout ${timeout_test} \ |
| 169 | ip netns exec $ns \ | 202 | ip netns exec $ns \ |
| 170 | ./mptcp_connect -p 10001 -l -s TCP -t ${timeout_poll} \ | 203 | ./mptcp_connect -p 10001 -l -s TCP -t ${timeout_poll} -w 20 \ |
| 171 | 0.0.0.0 >/dev/null & | 204 | 0.0.0.0 >/dev/null & |
| 172 | wait_local_port_listen $ns 10001 | 205 | wait_local_port_listen $ns 10001 |
| 173 | echo "b" | \ | 206 | echo "b" | \ |
| 174 | timeout ${timeout_test} \ | 207 | timeout ${timeout_test} \ |
| 175 | ip netns exec $ns \ | 208 | ip netns exec $ns \ |
| 176 | ./mptcp_connect -p 10001 -r 0 -t ${timeout_poll} \ | 209 | ./mptcp_connect -p 10001 -r 0 -t ${timeout_poll} -w 20 \ |
| 177 | 127.0.0.1 >/dev/null & | 210 | 127.0.0.1 >/dev/null & |
| 178 | wait_connected $ns 10001 | 211 | wait_connected $ns 10001 |
| 179 | chk_msk_fallback_nr 1 "check fallback" | 212 | chk_msk_fallback_nr 1 "check fallback" |
| @@ -184,7 +217,7 @@ for I in `seq 1 $NR_CLIENTS`; do · 4 unmodified lines | |||
| 184 | echo "a" | \ | 217 | echo "a" | \ |
| 185 | timeout ${timeout_test} \ | 218 | timeout ${timeout_test} \ |
| 186 | ip netns exec $ns \ | 219 | ip netns exec $ns \ |
| 187 | ./mptcp_connect -p $((I+10001)) -l -w 10 \ | 220 | ./mptcp_connect -p $((I+10001)) -l -w 20 \ |
| 188 | -t ${timeout_poll} 0.0.0.0 >/dev/null & | 221 | -t ${timeout_poll} 0.0.0.0 >/dev/null & |
| 189 | done | 222 | done |
| 190 | wait_local_port_listen $ns $((NR_CLIENTS + 10001)) | 223 | wait_local_port_listen $ns $((NR_CLIENTS + 10001)) |
| @@ -193,12 +226,11 @@ for I in `seq 1 $NR_CLIENTS`; do · 2 unmodified lines | |||
| 193 | echo "b" | \ | 226 | echo "b" | \ |
| 194 | timeout ${timeout_test} \ | 227 | timeout ${timeout_test} \ |
| 195 | ip netns exec $ns \ | 228 | ip netns exec $ns \ |
| 196 | ./mptcp_connect -p $((I+10001)) -w 10 \ | 229 | ./mptcp_connect -p $((I+10001)) -w 20 \ |
| 197 | -t ${timeout_poll} 127.0.0.1 >/dev/null & | 230 | -t ${timeout_poll} 127.0.0.1 >/dev/null & |
| 198 | done | 231 | done |
| 199 | sleep 1.5 | ||
| 200 | 232 | ||
| 201 | chk_msk_nr $((NR_CLIENTS*2)) "many msk socket present" | 233 | wait_msk_nr $((NR_CLIENTS*2)) "many msk socket present" |
| 202 | flush_pids | 234 | flush_pids |
| 203 | 235 | ||
| 204 | exit $ret | 236 | exit $ret |
| @@ -265,7 +265,7 @@ static void sock_test_tcpulp(int sock, int proto, unsigned int line) · 264 unmodified lines | |||
| 265 | static int sock_listen_mptcp(const char * const listenaddr, | 265 | static int sock_listen_mptcp(const char * const listenaddr, |
| 266 | const char * const port) | 266 | const char * const port) |
| 267 | { | 267 | { |
| 268 | int sock; | 268 | int sock = -1; |
| 269 | struct addrinfo hints = { | 269 | struct addrinfo hints = { |
| 270 | .ai_protocol = IPPROTO_TCP, | 270 | .ai_protocol = IPPROTO_TCP, |
| 271 | .ai_socktype = SOCK_STREAM, | 271 | .ai_socktype = SOCK_STREAM, |
| @@ -88,7 +88,7 @@ static void xgetaddrinfo(const char *node, const char *service, · 87 unmodified lines | |||
| 88 | static int sock_listen_mptcp(const char * const listenaddr, | 88 | static int sock_listen_mptcp(const char * const listenaddr, |
| 89 | const char * const port) | 89 | const char * const port) |
| 90 | { | 90 | { |
| 91 | int sock; | 91 | int sock = -1; |
| 92 | struct addrinfo hints = { | 92 | struct addrinfo hints = { |
| 93 | .ai_protocol = IPPROTO_TCP, | 93 | .ai_protocol = IPPROTO_TCP, |
| 94 | .ai_socktype = SOCK_STREAM, | 94 | .ai_socktype = SOCK_STREAM, |
| @@ -136,7 +136,7 @@ static void xgetaddrinfo(const char *node, const char *service, · 135 unmodified lines | |||
| 136 | static int sock_listen_mptcp(const char * const listenaddr, | 136 | static int sock_listen_mptcp(const char * const listenaddr, |
| 137 | const char * const port) | 137 | const char * const port) |
| 138 | { | 138 | { |
| 139 | int sock; | 139 | int sock = -1; |
| 140 | struct addrinfo hints = { | 140 | struct addrinfo hints = { |
| 141 | .ai_protocol = IPPROTO_TCP, | 141 | .ai_protocol = IPPROTO_TCP, |
| 142 | .ai_socktype = SOCK_STREAM, | 142 | .ai_socktype = SOCK_STREAM, |
| @@ -0,0 +1,162 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 3 | #define _GNU_SOURCE | ||
| 4 | |||
| 5 | #include <errno.h> | ||
| 6 | #include <fcntl.h> | ||
| 7 | #include <stdio.h> | ||
| 8 | #include <stdlib.h> | ||
| 9 | #include <string.h> | ||
| 10 | #include <unistd.h> | ||
| 11 | #include <linux/if.h> | ||
| 12 | #include <linux/if_tun.h> | ||
| 13 | #include <linux/netlink.h> | ||
| 14 | #include <linux/rtnetlink.h> | ||
| 15 | #include <sys/ioctl.h> | ||
| 16 | #include <sys/socket.h> | ||
| 17 | |||
| 18 | #include "../kselftest_harness.h" | ||
| 19 | |||
| 20 | static int tun_attach(int fd, char *dev) | ||
| 21 | { | ||
| 22 | struct ifreq ifr; | ||
| 23 | |||
| 24 | memset(&ifr, 0, sizeof(ifr)); | ||
| 25 | strcpy(ifr.ifr_name, dev); | ||
| 26 | ifr.ifr_flags = IFF_ATTACH_QUEUE; | ||
| 27 | |||
| 28 | return ioctl(fd, TUNSETQUEUE, (void *) &ifr); | ||
| 29 | } | ||
| 30 | |||
| 31 | static int tun_detach(int fd, char *dev) | ||
| 32 | { | ||
| 33 | struct ifreq ifr; | ||
| 34 | |||
| 35 | memset(&ifr, 0, sizeof(ifr)); | ||
| 36 | strcpy(ifr.ifr_name, dev); | ||
| 37 | ifr.ifr_flags = IFF_DETACH_QUEUE; | ||
| 38 | |||
| 39 | return ioctl(fd, TUNSETQUEUE, (void *) &ifr); | ||
| 40 | } | ||
| 41 | |||
| 42 | static int tun_alloc(char *dev) | ||
| 43 | { | ||
| 44 | struct ifreq ifr; | ||
| 45 | int fd, err; | ||
| 46 | |||
| 47 | fd = open("/dev/net/tun", O_RDWR); | ||
| 48 | if (fd < 0) { | ||
| 49 | fprintf(stderr, "can't open tun: %s\n", strerror(errno)); | ||
| 50 | return fd; | ||
| 51 | } | ||
| 52 | |||
| 53 | memset(&ifr, 0, sizeof(ifr)); | ||
| 54 | strcpy(ifr.ifr_name, dev); | ||
| 55 | ifr.ifr_flags = IFF_TAP | IFF_NAPI | IFF_MULTI_QUEUE; | ||
| 56 | |||
| 57 | err = ioctl(fd, TUNSETIFF, (void *) &ifr); | ||
| 58 | if (err < 0) { | ||
| 59 | fprintf(stderr, "can't TUNSETIFF: %s\n", strerror(errno)); | ||
| 60 | close(fd); | ||
| 61 | return err; | ||
| 62 | } | ||
| 63 | strcpy(dev, ifr.ifr_name); | ||
| 64 | return fd; | ||
| 65 | } | ||
| 66 | |||
| 67 | static int tun_delete(char *dev) | ||
| 68 | { | ||
| 69 | struct { | ||
| 70 | struct nlmsghdr nh; | ||
| 71 | struct ifinfomsg ifm; | ||
| 72 | unsigned char data[64]; | ||
| 73 | } req; | ||
| 74 | struct rtattr *rta; | ||
| 75 | int ret, rtnl; | ||
| 76 | |||
| 77 | rtnl = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); | ||
| 78 | if (rtnl < 0) { | ||
| 79 | fprintf(stderr, "can't open rtnl: %s\n", strerror(errno)); | ||
| 80 | return 1; | ||
| 81 | } | ||
| 82 | |||
| 83 | memset(&req, 0, sizeof(req)); | ||
| 84 | req.nh.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.ifm))); | ||
| 85 | req.nh.nlmsg_flags = NLM_F_REQUEST; | ||
| 86 | req.nh.nlmsg_type = RTM_DELLINK; | ||
| 87 | |||
| 88 | req.ifm.ifi_family = AF_UNSPEC; | ||
| 89 | |||
| 90 | rta = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.nh.nlmsg_len)); | ||
| 91 | rta->rta_type = IFLA_IFNAME; | ||
| 92 | rta->rta_len = RTA_LENGTH(IFNAMSIZ); | ||
| 93 | req.nh.nlmsg_len += rta->rta_len; | ||
| 94 | memcpy(RTA_DATA(rta), dev, IFNAMSIZ); | ||
| 95 | |||
| 96 | ret = send(rtnl, &req, req.nh.nlmsg_len, 0); | ||
| 97 | if (ret < 0) | ||
| 98 | fprintf(stderr, "can't send: %s\n", strerror(errno)); | ||
| 99 | ret = (unsigned int)ret != req.nh.nlmsg_len; | ||
| 100 | |||
| 101 | close(rtnl); | ||
| 102 | return ret; | ||
| 103 | } | ||
| 104 | |||
| 105 | FIXTURE(tun) | ||
| 106 | { | ||
| 107 | char ifname[IFNAMSIZ]; | ||
| 108 | int fd, fd2; | ||
| 109 | }; | ||
| 110 | |||
| 111 | FIXTURE_SETUP(tun) | ||
| 112 | { | ||
| 113 | memset(self->ifname, 0, sizeof(self->ifname)); | ||
| 114 | |||
| 115 | self->fd = tun_alloc(self->ifname); | ||
| 116 | ASSERT_GE(self->fd, 0); | ||
| 117 | |||
| 118 | self->fd2 = tun_alloc(self->ifname); | ||
| 119 | ASSERT_GE(self->fd2, 0); | ||
| 120 | } | ||
| 121 | |||
| 122 | FIXTURE_TEARDOWN(tun) | ||
| 123 | { | ||
| 124 | if (self->fd >= 0) | ||
| 125 | close(self->fd); | ||
| 126 | if (self->fd2 >= 0) | ||
| 127 | close(self->fd2); | ||
| 128 | } | ||
| 129 | |||
| 130 | TEST_F(tun, delete_detach_close) { | ||
| 131 | EXPECT_EQ(tun_delete(self->ifname), 0); | ||
| 132 | EXPECT_EQ(tun_detach(self->fd, self->ifname), -1); | ||
| 133 | EXPECT_EQ(errno, 22); | ||
| 134 | } | ||
| 135 | |||
| 136 | TEST_F(tun, detach_delete_close) { | ||
| 137 | EXPECT_EQ(tun_detach(self->fd, self->ifname), 0); | ||
| 138 | EXPECT_EQ(tun_delete(self->ifname), 0); | ||
| 139 | } | ||
| 140 | |||
| 141 | TEST_F(tun, detach_close_delete) { | ||
| 142 | EXPECT_EQ(tun_detach(self->fd, self->ifname), 0); | ||
| 143 | close(self->fd); | ||
| 144 | self->fd = -1; | ||
| 145 | EXPECT_EQ(tun_delete(self->ifname), 0); | ||
| 146 | } | ||
| 147 | |||
| 148 | TEST_F(tun, reattach_delete_close) { | ||
| 149 | EXPECT_EQ(tun_detach(self->fd, self->ifname), 0); | ||
| 150 | EXPECT_EQ(tun_attach(self->fd, self->ifname), 0); | ||
| 151 | EXPECT_EQ(tun_delete(self->ifname), 0); | ||
| 152 | } | ||
| 153 | |||
| 154 | TEST_F(tun, reattach_close_delete) { | ||
| 155 | EXPECT_EQ(tun_detach(self->fd, self->ifname), 0); | ||
| 156 | EXPECT_EQ(tun_attach(self->fd, self->ifname), 0); | ||
| 157 | close(self->fd); | ||
| 158 | self->fd = -1; | ||
| 159 | EXPECT_EQ(tun_delete(self->ifname), 0); | ||
| 160 | } | ||
| 161 | |||
| 162 | TEST_HARNESS_MAIN | ||
| @@ -120,7 +120,7 @@ run_all() { · 119 unmodified lines | |||
| 120 | run_udp "${ipv4_args}" | 120 | run_udp "${ipv4_args}" |
| 121 | 121 | ||
| 122 | echo "ipv6" | 122 | echo "ipv6" |
| 123 | run_tcp "${ipv4_args}" | 123 | run_tcp "${ipv6_args}" |
| 124 | run_udp "${ipv6_args}" | 124 | run_udp "${ipv6_args}" |
| 125 | } | 125 | } |
| 126 | 126 | ||
| @@ -609,5 +609,82 @@ · 608 unmodified lines | |||
| 609 | "teardown": [ | 609 | "teardown": [ |
| 610 | "$TC actions flush action gact" | 610 | "$TC actions flush action gact" |
| 611 | ] | 611 | ] |
| 612 | }, | ||
| 613 | { | ||
| 614 | "id": "7f52", | ||
| 615 | "name": "Try to flush action which is referenced by filter", | ||
| 616 | "category": [ | ||
| 617 | "actions", | ||
| 618 | "gact" | ||
| 619 | ], | ||
| 620 | "plugins": { | ||
| 621 | "requires": "nsPlugin" | ||
| 622 | }, | ||
| 623 | "setup": [ | ||
| 624 | [ | ||
| 625 | "$TC actions flush action gact", | ||
| 626 | 0, | ||
| 627 | 1, | ||
| 628 | 255 | ||
| 629 | ], | ||
| 630 | "$TC qdisc add dev $DEV1 ingress", | ||
| 631 | "$TC actions add action pass index 1", | ||
| 632 | "$TC filter add dev $DEV1 protocol all ingress prio 1 handle 0x1234 matchall action gact index 1" | ||
| 633 | ], | ||
| 634 | "cmdUnderTest": "$TC actions flush action gact", | ||
| 635 | "expExitCode": "1", | ||
| 636 | "verifyCmd": "$TC actions ls action gact", | ||
| 637 | "matchPattern": "total acts 1.*action order [0-9]*: gact action pass.*index 1 ref 2 bind 1", | ||
| 638 | "matchCount": "1", | ||
| 639 | "teardown": [ | ||
| 640 | "$TC qdisc del dev $DEV1 ingress", | ||
| 641 | [ | ||
| 642 | "sleep 1; $TC actions flush action gact", | ||
| 643 | 0, | ||
| 644 | 1 | ||
| 645 | ] | ||
| 646 | ] | ||
| 647 | }, | ||
| 648 | { | ||
| 649 | "id": "ae1e", | ||
| 650 | "name": "Try to flush actions when last one is referenced by filter", | ||
| 651 | "category": [ | ||
| 652 | "actions", | ||
| 653 | "gact" | ||
| 654 | ], | ||
| 655 | "plugins": { | ||
| 656 | "requires": "nsPlugin" | ||
| 657 | }, | ||
| 658 | "setup": [ | ||
| 659 | [ | ||
| 660 | "$TC actions flush action gact", | ||
| 661 | 0, | ||
| 662 | 1, | ||
| 663 | 255 | ||
| 664 | ], | ||
| 665 | "$TC qdisc add dev $DEV1 ingress", | ||
| 666 | [ | ||
| 667 | "$TC actions add action pass index 1", | ||
| 668 | 0, | ||
| 669 | 1, | ||
| 670 | 255 | ||
| 671 | ], | ||
| 672 | "$TC actions add action reclassify index 2", | ||
| 673 | "$TC actions add action drop index 3", | ||
| 674 | "$TC filter add dev $DEV1 protocol all ingress prio 1 handle 0x1234 matchall action gact index 3" | ||
| 675 | ], | ||
| 676 | "cmdUnderTest": "$TC actions flush action gact", | ||
| 677 | "expExitCode": "0", | ||
| 678 | "verifyCmd": "$TC actions ls action gact", | ||
| 679 | "matchPattern": "total acts 1.*action order [0-9]*: gact action drop.*index 3 ref 2 bind 1", | ||
| 680 | "matchCount": "1", | ||
| 681 | "teardown": [ | ||
| 682 | "$TC qdisc del dev $DEV1 ingress", | ||
| 683 | [ | ||
| 684 | "sleep 1; $TC actions flush action gact", | ||
| 685 | 0, | ||
| 686 | 1 | ||
| 687 | ] | ||
| 688 | ] | ||
| 612 | } | 689 | } |
| 613 | ] | 690 | ] |