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 | 14397 | F: sound/soc/codecs/tfa989x.c |
| 14398 | 14398 | |
| 14399 | 14399 | NXP-NCI NFC DRIVER |
| 14400 | −R: Charles Gorand <charles.gorand@effinnov.com> | |
| 14401 | 14400 | L: linux-nfc@lists.01.org (subscribers-only) |
| 14402 | −S: Supported | |
| 14401 | +S: Orphan | |
| 14403 | 14402 | F: Documentation/devicetree/bindings/net/nfc/nxp,nci.yaml |
| 14404 | 14403 | F: drivers/nfc/nxp-nci |
| 14405 | 14404 | |
| @@ -2228,7 +2228,8 @@ void bond_3ad_unbind_slave(struct slave *slave) · 2227 unmodified lines | ||
| 2228 | 2228 | temp_aggregator->num_of_ports--; |
| 2229 | 2229 | if (__agg_active_ports(temp_aggregator) == 0) { |
| 2230 | 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 | 2233 | if (select_new_active_agg) { |
| 2233 | 2234 | slave_info(bond->dev, slave->dev, "Removing an active aggregator\n"); |
| 2234 | 2235 | /* select new active aggregator */ |
| @@ -1302,12 +1302,12 @@ int bond_alb_initialize(struct bonding *bond, int rlb_enabled) · 1301 unmodified lines | ||
| 1302 | 1302 | return res; |
| 1303 | 1303 | |
| 1304 | 1304 | if (rlb_enabled) { |
| 1305 | − bond->alb_info.rlb_enabled = 1; | |
| 1306 | 1305 | res = rlb_initialize(bond); |
| 1307 | 1306 | if (res) { |
| 1308 | 1307 | tlb_deinitialize(bond); |
| 1309 | 1308 | return res; |
| 1310 | 1309 | } |
| 1310 | + bond->alb_info.rlb_enabled = 1; | |
| 1311 | 1311 | } else { |
| 1312 | 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 | 878 | if (duplex == DUPLEX_FULL) |
| 879 | 879 | reg |= DUPLX_MODE; |
| 880 | 880 | |
| 881 | + if (tx_pause) | |
| 882 | + reg |= TXFLOW_CNTL; | |
| 883 | + if (rx_pause) | |
| 884 | + reg |= RXFLOW_CNTL; | |
| 885 | + | |
| 881 | 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 | 300 | const char *label, *state; |
| 301 | 301 | int ret = -EINVAL; |
| 302 | 302 | |
| 303 | + of_node_get(hellcreek->dev->of_node); | |
| 303 | 304 | leds = of_find_node_by_name(hellcreek->dev->of_node, "leds"); |
| 304 | 305 | if (!leds) { |
| 305 | 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 | 1886 | static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index, |
| 1887 | 1887 | struct felix_stream_filter_counters *counters) |
| 1888 | 1888 | { |
| 1889 | + mutex_lock(&ocelot->stats_lock); | |
| 1890 | + | |
| 1889 | 1891 | ocelot_rmw(ocelot, SYS_STAT_CFG_STAT_VIEW(index), |
| 1890 | 1892 | SYS_STAT_CFG_STAT_VIEW_M, |
| 1891 | 1893 | SYS_STAT_CFG); |
| @@ -1900,6 +1902,8 @@ static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index, · 8 unmodified lines | ||
| 1900 | 1902 | SYS_STAT_CFG_STAT_VIEW(index) | |
| 1901 | 1903 | SYS_STAT_CFG_STAT_CLEAR_SHOT(0x10), |
| 1902 | 1904 | SYS_STAT_CFG); |
| 1905 | + | |
| 1906 | + mutex_unlock(&ocelot->stats_lock); | |
| 1903 | 1907 | } |
| 1904 | 1908 | |
| 1905 | 1909 | static int vsc9959_psfp_filter_add(struct ocelot *ocelot, int port, |
| @@ -52,7 +52,7 @@ · 51 unmodified lines | ||
| 52 | 52 | |
| 53 | 53 | #define CN93_SDP_EPF_RINFO_SRN(val) ((val) & 0xFF) |
| 54 | 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 | 57 | /* SDP Function select */ |
| 58 | 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 | 4415 | return 0; |
| 4416 | 4416 | |
| 4417 | 4417 | err_nexthop_neigh_init: |
| 4418 | + list_del(&nh->router_list_node); | |
| 4419 | + mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh); | |
| 4418 | 4420 | mlxsw_sp_nexthop_remove(mlxsw_sp, nh); |
| 4419 | 4421 | return err; |
| 4420 | 4422 | } |
| @@ -6740,6 +6742,7 @@ static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp, · 2319 unmodified lines | ||
| 6740 | 6742 | const struct fib6_info *rt) |
| 6741 | 6743 | { |
| 6742 | 6744 | struct net_device *dev = rt->fib6_nh->fib_nh_dev; |
| 6745 | + int err; | |
| 6743 | 6746 | |
| 6744 | 6747 | nh->nhgi = nh_grp->nhgi; |
| 6745 | 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 | 6758 | return 0; |
| 6756 | 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 | 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 | 396 | u32 mact_entry; |
| 397 | 397 | int res, err; |
| 398 | 398 | |
| 399 | + if (!sparx5_netdevice_check(dev)) | |
| 400 | + return -EOPNOTSUPP; | |
| 401 | + | |
| 399 | 402 | if (netif_is_bridge_master(v->obj.orig_dev)) { |
| 400 | 403 | sparx5_mact_learn(spx5, PGID_CPU, v->addr, v->vid); |
| 401 | 404 | return 0; |
| @@ -466,6 +469,9 @@ static int sparx5_handle_port_mdb_del(struct net_device *dev, · 64 unmodified lines | ||
| 466 | 469 | u32 mact_entry, res, pgid_entry[3]; |
| 467 | 470 | int err; |
| 468 | 471 | |
| 472 | + if (!sparx5_netdevice_check(dev)) | |
| 473 | + return -EOPNOTSUPP; | |
| 474 | + | |
| 469 | 475 | if (netif_is_bridge_master(v->obj.orig_dev)) { |
| 470 | 476 | sparx5_mact_forget(spx5, v->addr, v->vid); |
| 471 | 477 | return 0; |
| @@ -1515,14 +1515,14 @@ static void epic_remove_one(struct pci_dev *pdev) · 1514 unmodified lines | ||
| 1515 | 1515 | struct net_device *dev = pci_get_drvdata(pdev); |
| 1516 | 1516 | struct epic_private *ep = netdev_priv(dev); |
| 1517 | 1517 | |
| 1518 | + unregister_netdev(dev); | |
| 1518 | 1519 | dma_free_coherent(&pdev->dev, TX_TOTAL_SIZE, ep->tx_ring, |
| 1519 | 1520 | ep->tx_ring_dma); |
| 1520 | 1521 | dma_free_coherent(&pdev->dev, RX_TOTAL_SIZE, ep->rx_ring, |
| 1521 | 1522 | ep->rx_ring_dma); |
| 1522 | − unregister_netdev(dev); | |
| 1523 | 1523 | pci_iounmap(pdev, ep->ioaddr); |
| 1524 | − pci_release_regions(pdev); | |
| 1525 | 1524 | free_netdev(dev); |
| 1525 | + pci_release_regions(pdev); | |
| 1526 | 1526 | pci_disable_device(pdev); |
| 1527 | 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 | 88 | /* Reset PHY, otherwise MII_LPA will provide outdated information. |
| 89 | 89 | * This issue is reproducible only with some link partner PHYs |
| 90 | 90 | */ |
| 91 | − if (phydev->state == PHY_NOLINK && phydev->drv->soft_reset) | |
| 92 | − phydev->drv->soft_reset(phydev); | |
| 91 | + if (phydev->state == PHY_NOLINK) { | |
| 92 | + phy_init_hw(phydev); | |
| 93 | + phy_start_aneg(phydev); | |
| 94 | + } | |
| 93 | 95 | } |
| 94 | 96 | |
| 95 | 97 | static struct phy_driver asix_driver[] = { |
| @@ -229,9 +229,7 @@ static int dp83822_config_intr(struct phy_device *phydev) · 228 unmodified lines | ||
| 229 | 229 | if (misr_status < 0) |
| 230 | 230 | return misr_status; |
| 231 | 231 | |
| 232 | − misr_status |= (DP83822_RX_ERR_HF_INT_EN | | |
| 233 | − DP83822_FALSE_CARRIER_HF_INT_EN | | |
| 234 | − DP83822_LINK_STAT_INT_EN | | |
| 232 | + misr_status |= (DP83822_LINK_STAT_INT_EN | | |
| 235 | 233 | DP83822_ENERGY_DET_INT_EN | |
| 236 | 234 | DP83822_LINK_QUAL_INT_EN); |
| 237 | 235 | |
| @@ -31,6 +31,7 @@ · 30 unmodified lines | ||
| 31 | 31 | #include <linux/io.h> |
| 32 | 32 | #include <linux/uaccess.h> |
| 33 | 33 | #include <linux/atomic.h> |
| 34 | +#include <linux/suspend.h> | |
| 34 | 35 | #include <net/netlink.h> |
| 35 | 36 | #include <net/genetlink.h> |
| 36 | 37 | #include <net/sock.h> |
| @@ -976,6 +977,28 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat) · 939 unmodified lines | ||
| 976 | 977 | struct phy_driver *drv = phydev->drv; |
| 977 | 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 | 1002 | mutex_lock(&phydev->lock); |
| 980 | 1003 | ret = drv->handle_interrupt(phydev); |
| 981 | 1004 | mutex_unlock(&phydev->lock); |
| @@ -278,6 +278,15 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev) · 277 unmodified lines | ||
| 278 | 278 | if (phydev->mac_managed_pm) |
| 279 | 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 | 290 | /* We must stop the state machine manually, otherwise it stops out of |
| 282 | 291 | * control, possibly with the phydev->lock held. Upon resume, netdev |
| 283 | 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 | 324 | if (ret < 0) |
| 316 | 325 | return ret; |
| 317 | 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 | 341 | if (phydev->attached_dev && phydev->adjust_link) |
| 319 | 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 | 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 | 2520 | if (err < 0) |
| 2521 | 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 | 282 | static void tun_napi_disable(struct tun_file *tfile) |
| 277 | 283 | { |
| 278 | 284 | if (tfile->napi_enabled) |
| @@ -634,7 +640,8 @@ static void __tun_detach(struct tun_file *tfile, bool clean) · 355 unmodified lines | ||
| 634 | 640 | tun = rtnl_dereference(tfile->tun); |
| 635 | 641 | |
| 636 | 642 | if (tun && clean) { |
| 637 | − tun_napi_disable(tfile); | |
| 643 | + if (!tfile->detached) | |
| 644 | + tun_napi_disable(tfile); | |
| 638 | 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 | 660 | if (clean) { |
| 654 | 661 | RCU_INIT_POINTER(tfile->tun, NULL); |
| 655 | 662 | sock_put(&tfile->sk); |
| 656 | − } else | |
| 663 | + } else { | |
| 657 | 664 | tun_disable_queue(tun, tfile); |
| 665 | + tun_napi_disable(tfile); | |
| 666 | + } | |
| 658 | 667 | |
| 659 | 668 | synchronize_net(); |
| 660 | 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 | 736 | sock_put(&tfile->sk); |
| 728 | 737 | } |
| 729 | 738 | list_for_each_entry_safe(tfile, tmp, &tun->disabled, next) { |
| 739 | + tun_napi_del(tfile); | |
| 730 | 740 | tun_enable_queue(tfile); |
| 731 | 741 | tun_queue_purge(tfile); |
| 732 | 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 | 818 | if (tfile->detached) { |
| 809 | 819 | tun_enable_queue(tfile); |
| 820 | + tun_napi_enable(tfile); | |
| 810 | 821 | } else { |
| 811 | 822 | sock_hold(&tfile->sk); |
| 812 | 823 | tun_napi_init(tun, tfile, napi, napi_frags); |
| @@ -126,8 +126,7 @@ · 125 unmodified lines | ||
| 126 | 126 | AX_MEDIUM_RE) |
| 127 | 127 | |
| 128 | 128 | #define AX88772_MEDIUM_DEFAULT \ |
| 129 | − (AX_MEDIUM_FD | AX_MEDIUM_RFC | \ | |
| 130 | − AX_MEDIUM_TFC | AX_MEDIUM_PS | \ | |
| 129 | + (AX_MEDIUM_FD | AX_MEDIUM_PS | \ | |
| 131 | 130 | AX_MEDIUM_AC | AX_MEDIUM_RE) |
| 132 | 131 | |
| 133 | 132 | /* AX88772 & AX88178 RX_CTL values */ |
| @@ -431,6 +431,7 @@ void asix_adjust_link(struct net_device *netdev) · 430 unmodified lines | ||
| 431 | 431 | |
| 432 | 432 | asix_write_medium_mode(dev, mode, 0); |
| 433 | 433 | phy_print_status(phydev); |
| 434 | + usbnet_link_change(dev, phydev->link, 0); | |
| 434 | 435 | } |
| 435 | 436 | |
| 436 | 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 | 1472 | * are bundled into this buffer and where we can find an array of |
| 1473 | 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 | 1511 | if (skb->len < 4) |
| 1476 | 1512 | return 0; |
| 1477 | 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 | 1521 | /* Make sure that the bounds of the metadata array are inside the SKB |
| 1486 | 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 | 1525 | return 0; |
| 1490 | 1526 | pkt_hdr = (u32 *)(skb->data + hdr_off); |
| 1491 | 1527 | |
| 1492 | 1528 | /* Packets must not overlap the metadata array */ |
| 1493 | 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 | 1533 | u16 pkt_len; |
| 1497 | 1534 | |
| 1498 | 1535 | le32_to_cpus(pkt_hdr); |
| 1499 | 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 | 1545 | return 0; |
| 1503 | 1546 | |
| 1504 | 1547 | /* Check CRC or runt packet */ |
| 1505 | − if (((*pkt_hdr & (AX_RXHDR_CRC_ERR | AX_RXHDR_DROP_ERR)) == 0) && | |
| 1506 | − pkt_len >= 2 + ETH_HLEN) { | |
| 1507 | − bool last = (pkt_cnt == 0); | |
| 1508 | − | |
| 1509 | − if (last) { | |
| 1510 | − ax_skb = skb; | |
| 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); | |
| 1548 | + if ((*pkt_hdr & (AX_RXHDR_CRC_ERR | AX_RXHDR_DROP_ERR)) || | |
| 1549 | + pkt_len < 2 + ETH_HLEN) { | |
| 1550 | + dev->net->stats.rx_errors++; | |
| 1551 | + skb_pull(skb, pkt_len_plus_padd); | |
| 1552 | + continue; | |
| 1553 | + } | |
| 1522 | 1554 | |
| 1523 | − if (last) | |
| 1524 | − return 1; | |
| 1555 | + /* last packet */ | |
| 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 */ | |
| 1530 | − if (!skb_pull(skb, (pkt_len + 7) & 0xFFF8)) | |
| 1567 | + ax_skb = skb_clone(skb, GFP_ATOMIC); | |
| 1568 | + if (!ax_skb) | |
| 1531 | 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 | 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 | 2004 | cmd, reqtype, value, index, size); |
| 2005 | 2005 | |
| 2006 | 2006 | if (size) { |
| 2007 | − buf = kmalloc(size, GFP_KERNEL); | |
| 2007 | + buf = kmalloc(size, GFP_NOIO); | |
| 2008 | 2008 | if (!buf) |
| 2009 | 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 | 2036 | cmd, reqtype, value, index, size); |
| 2037 | 2037 | |
| 2038 | 2038 | if (data) { |
| 2039 | − buf = kmemdup(data, size, GFP_KERNEL); | |
| 2039 | + buf = kmemdup(data, size, GFP_NOIO); | |
| 2040 | 2040 | if (!buf) |
| 2041 | 2041 | goto out; |
| 2042 | 2042 | } else { |
| @@ -167,9 +167,9 @@ static int nfcmrvl_i2c_parse_dt(struct device_node *node, · 166 unmodified lines | ||
| 167 | 167 | pdata->irq_polarity = IRQF_TRIGGER_RISING; |
| 168 | 168 | |
| 169 | 169 | ret = irq_of_parse_and_map(node, 0); |
| 170 | − if (ret < 0) { | |
| 171 | − pr_err("Unable to get irq, error: %d\n", ret); | |
| 172 | − return ret; | |
| 170 | + if (!ret) { | |
| 171 | + pr_err("Unable to get irq\n"); | |
| 172 | + return -EINVAL; | |
| 173 | 173 | } |
| 174 | 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 | 117 | ret = irq_of_parse_and_map(node, 0); |
| 118 | − if (ret < 0) { | |
| 119 | − pr_err("Unable to get irq, error: %d\n", ret); | |
| 120 | − return ret; | |
| 118 | + if (!ret) { | |
| 119 | + pr_err("Unable to get irq\n"); | |
| 120 | + return -EINVAL; | |
| 121 | 121 | } |
| 122 | 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 | 122 | skb_put_data(*skb, &header, NXP_NCI_FW_HDR_LEN); |
| 123 | 123 | |
| 124 | 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 | 128 | nfc_err(&client->dev, |
| 127 | 129 | "Invalid frame length: %u (expected %zu)\n", |
| 128 | 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 | 165 | skb_put_data(*skb, (void *)&header, NCI_CTRL_HDR_SIZE); |
| 164 | 166 | |
| 167 | + if (!header.plen) | |
| 168 | + return 0; | |
| 169 | + | |
| 165 | 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 | 174 | nfc_err(&client->dev, |
| 168 | 175 | "Invalid frame payload length: %u (expected %u)\n", |
| 169 | 176 | r, header.plen); |
| @@ -1671,7 +1671,7 @@ enum netdev_priv_flags { · 1670 unmodified lines | ||
| 1671 | 1671 | IFF_FAILOVER_SLAVE = 1<<28, |
| 1672 | 1672 | IFF_L3MDEV_RX_HANDLER = 1<<29, |
| 1673 | 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 | 1675 | IFF_CHANGE_PROTO_DOWN = BIT_ULL(32), |
| 1676 | 1676 | }; |
| 1677 | 1677 | |
| @@ -572,6 +572,10 @@ struct macsec_ops; · 571 unmodified lines | ||
| 572 | 572 | * @mdix_ctrl: User setting of crossover |
| 573 | 573 | * @pma_extable: Cached value of PMA/PMD Extended Abilities Register |
| 574 | 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 | 579 | * @interface: enum phy_interface_t value |
| 576 | 580 | * @skb: Netlink message for cable diagnostics |
| 577 | 581 | * @nest: Netlink nest used for cable diagnostics |
| @@ -626,6 +630,8 @@ struct phy_device { · 48 unmodified lines | ||
| 626 | 630 | |
| 627 | 631 | /* Interrupts are enabled */ |
| 628 | 632 | unsigned interrupts:1; |
| 633 | + unsigned irq_suspended:1; | |
| 634 | + unsigned irq_rerun:1; | |
| 629 | 635 | |
| 630 | 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 | 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 | 1346 | * @pkt: pktinfo currently processed |
| 1342 | 1347 | * @basechain: base chain currently processed |
| 1343 | 1348 | * @chain: chain currently processed |
| 1344 | 1349 | * @rule: rule that was evaluated |
| 1345 | 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 | 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 | 1358 | const struct nft_pktinfo *pkt; |
| 1352 | 1359 | const struct nft_base_chain *basechain; |
| 1353 | 1360 | const struct nft_chain *chain; |
| 1354 | 1361 | const struct nft_rule_dp *rule; |
| 1355 | 1362 | const struct nft_verdict *verdict; |
| 1356 | − enum nft_trace_types type; | |
| 1357 | − bool packet_dumped; | |
| 1358 | − bool trace; | |
| 1359 | 1363 | }; |
| 1360 | 1364 | |
| 1361 | 1365 | void nft_trace_init(struct nft_traceinfo *info, const struct nft_pktinfo *pkt, |
| @@ -2,16 +2,17 @@ · 1 unmodified line | ||
| 2 | 2 | #ifndef _UAPI_MPTCP_H |
| 3 | 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 | 10 | #include <linux/const.h> |
| 6 | 11 | #include <linux/types.h> |
| 7 | 12 | #include <linux/in.h> /* for sockaddr_in */ |
| 8 | 13 | #include <linux/in6.h> /* for sockaddr_in6 */ |
| 9 | 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 | 16 | #define MPTCP_SUBFLOW_FLAG_MCAP_REM _BITUL(0) |
| 16 | 17 | #define MPTCP_SUBFLOW_FLAG_MCAP_LOC _BITUL(1) |
| 17 | 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 | 1012 | return okfn(net, sk, skb); |
| 1013 | 1013 | |
| 1014 | 1014 | ops = nf_hook_entries_get_hook_ops(e); |
| 1015 | − for (i = 0; i < e->num_hook_entries && | |
| 1016 | − ops[i]->priority <= NF_BR_PRI_BRNF; i++) | |
| 1017 | − ; | |
| 1015 | + for (i = 0; i < e->num_hook_entries; i++) { | |
| 1016 | + /* These hooks have already been called */ | |
| 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 | 1034 | nf_hook_state_init(&state, hook, NFPROTO_BRIDGE, indev, outdev, |
| 1020 | 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 | 410 | u32 mtu = dst_mtu(encap_dst) - headroom; |
| 411 | 411 | |
| 412 | 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 | 414 | return 0; |
| 415 | 415 | |
| 416 | 416 | skb_dst_update_pmtu_no_confirm(skb, mtu); |
| @@ -1964,7 +1964,10 @@ process: · 1963 unmodified lines | ||
| 1964 | 1964 | struct sock *nsk; |
| 1965 | 1965 | |
| 1966 | 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 | 1971 | &iph->saddr, &iph->daddr, |
| 1969 | 1972 | AF_INET, dif, sdif); |
| 1970 | 1973 | if (unlikely(drop_reason)) { |
| @@ -2016,6 +2019,7 @@ process: · 45 unmodified lines | ||
| 2016 | 2019 | } |
| 2017 | 2020 | goto discard_and_relse; |
| 2018 | 2021 | } |
| 2022 | + nf_reset_ct(skb); | |
| 2019 | 2023 | if (nsk == sk) { |
| 2020 | 2024 | reqsk_put(req); |
| 2021 | 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 | 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 | 1112 | neigh_parms_data_state_setall(idev->nd_parms); |
| 1117 | 1113 | |
| 1118 | 1114 | ifa->addr = *cfg->pfx; |
| @@ -5172,9 +5168,9 @@ next: · 4053 unmodified lines | ||
| 5172 | 5168 | fillargs->event = RTM_GETMULTICAST; |
| 5173 | 5169 | |
| 5174 | 5170 | /* multicast address */ |
| 5175 | − for (ifmca = rcu_dereference(idev->mc_list); | |
| 5171 | + for (ifmca = rtnl_dereference(idev->mc_list); | |
| 5176 | 5172 | ifmca; |
| 5177 | − ifmca = rcu_dereference(ifmca->next), ip_idx++) { | |
| 5173 | + ifmca = rtnl_dereference(ifmca->next), ip_idx++) { | |
| 5178 | 5174 | if (ip_idx < s_ip_idx) |
| 5179 | 5175 | continue; |
| 5180 | 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 | 4571 | f6i = ip6_route_info_create(&cfg, gfp_flags, NULL); |
| 4572 | − if (!IS_ERR(f6i)) | |
| 4572 | + if (!IS_ERR(f6i)) { | |
| 4573 | 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 | 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 | 407 | return rhashtable_init(&sdata->hmac_infos, &rht_params); |
| 408 | 408 | } |
| 409 | −EXPORT_SYMBOL(seg6_hmac_net_init); | |
| 410 | 409 | |
| 411 | 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 | 323 | kcalloc(cmax, sizeof(*kp), GFP_KERNEL_ACCOUNT | __GFP_NOWARN) : |
| 324 | 324 | NULL; |
| 325 | 325 | |
| 326 | − rcu_read_lock(); | |
| 327 | − | |
| 328 | 326 | ca = min(t->prl_count, cmax); |
| 329 | 327 | |
| 330 | 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 | 343 | for_each_prl_rcu(t->prl) { |
| 346 | 344 | if (c >= cmax) |
| 347 | 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 | 351 | if (kprl.addr != htonl(INADDR_ANY)) |
| 354 | 352 | break; |
| 355 | 353 | } |
| 356 | −out: | |
| 354 | + | |
| 357 | 355 | rcu_read_unlock(); |
| 358 | 356 | |
| 359 | 357 | len = sizeof(*kp) * c; |
| @@ -362,7 +360,7 @@ out: · 2 unmodified lines | ||
| 362 | 360 | ret = -EFAULT; |
| 363 | 361 | |
| 364 | 362 | kfree(kp); |
| 365 | − | |
| 363 | +out: | |
| 366 | 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 | 765 | opts->suboptions |= OPTION_MPTCP_RST; |
| 766 | 766 | opts->reset_transient = subflow->reset_transient; |
| 767 | 767 | opts->reset_reason = subflow->reset_reason; |
| 768 | + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPRSTTX); | |
| 768 | 769 | |
| 769 | 770 | return true; |
| 770 | 771 | } |
| @@ -788,6 +789,7 @@ static bool mptcp_established_options_fastclose(struct sock *sk, · 17 unmodified lines | ||
| 788 | 789 | opts->rcvr_key = msk->remote_key; |
| 789 | 790 | |
| 790 | 791 | pr_debug("FASTCLOSE key=%llu", opts->rcvr_key); |
| 792 | + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFASTCLOSETX); | |
| 791 | 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 | 811 | opts->fail_seq = subflow->map_seq; |
| 810 | 812 | |
| 811 | 813 | pr_debug("MP_FAIL fail_seq=%llu", opts->fail_seq); |
| 814 | + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFAILTX); | |
| 812 | 815 | |
| 813 | 816 | return true; |
| 814 | 817 | } |
| @@ -833,13 +836,11 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb, · 18 unmodified lines | ||
| 833 | 836 | mptcp_established_options_mp_fail(sk, &opt_size, remaining, opts)) { |
| 834 | 837 | *size += opt_size; |
| 835 | 838 | remaining -= opt_size; |
| 836 | − MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFASTCLOSETX); | |
| 837 | 839 | } |
| 838 | 840 | /* MP_RST can be used with MP_FASTCLOSE and MP_FAIL if there is room */ |
| 839 | 841 | if (mptcp_established_options_rst(sk, skb, &opt_size, remaining, opts)) { |
| 840 | 842 | *size += opt_size; |
| 841 | 843 | remaining -= opt_size; |
| 842 | − MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPRSTTX); | |
| 843 | 844 | } |
| 844 | 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 | 967 | goto reset; |
| 967 | 968 | subflow->mp_capable = 0; |
| 968 | 969 | pr_fallback(msk); |
| 969 | − __mptcp_do_fallback(msk); | |
| 970 | + mptcp_do_fallback(ssk); | |
| 970 | 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 | 300 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); |
| 301 | 301 | struct mptcp_sock *msk = mptcp_sk(subflow->conn); |
| 302 | − struct sock *s = (struct sock *)msk; | |
| 303 | 302 | |
| 304 | 303 | pr_debug("fail_seq=%llu", fail_seq); |
| 305 | 304 | |
| 306 | 305 | if (!READ_ONCE(msk->allow_infinite_fallback)) |
| 307 | 306 | return; |
| 308 | 307 | |
| 309 | − if (!READ_ONCE(subflow->mp_fail_response_expect)) { | |
| 308 | + if (!subflow->fail_tout) { | |
| 310 | 309 | pr_debug("send MP_FAIL response and infinite map"); |
| 311 | 310 | |
| 312 | 311 | subflow->send_mp_fail = 1; |
| 313 | − MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFAILTX); | |
| 314 | 312 | subflow->send_infinite_map = 1; |
| 315 | − } else if (!sock_flag(sk, SOCK_DEAD)) { | |
| 313 | + tcp_send_ack(sk); | |
| 314 | + } else { | |
| 316 | 315 | pr_debug("MP_FAIL response received"); |
| 317 | − | |
| 318 | − sk_stop_timer(s, &s->sk_timer); | |
| 316 | + WRITE_ONCE(subflow->fail_tout, 0); | |
| 319 | 317 | } |
| 320 | 318 | } |
| 321 | 319 | |
| @@ -500,7 +500,7 @@ static void mptcp_set_timeout(struct sock *sk) · 499 unmodified lines | ||
| 500 | 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 | 505 | return !((1 << inet_sk_state_load(ssk)) & |
| 506 | 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 | 1245 | MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_INFINITEMAPTX); |
| 1246 | 1246 | mptcp_subflow_ctx(ssk)->send_infinite_map = 0; |
| 1247 | 1247 | pr_fallback(msk); |
| 1248 | − __mptcp_do_fallback(msk); | |
| 1248 | + mptcp_do_fallback(ssk); | |
| 1249 | 1249 | } |
| 1250 | 1250 | |
| 1251 | 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 | 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 | 2178 | static void mptcp_timeout_timer(struct timer_list *t) |
| 2194 | 2179 | { |
| 2195 | 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 | 2331 | kfree_rcu(subflow, rcu); |
| 2347 | 2332 | } else { |
| 2348 | 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 | 2339 | __tcp_close(ssk, 0); |
| 2350 | 2340 | |
| 2351 | 2341 | /* close acquired an extra ref */ |
| @@ -2518,27 +2508,50 @@ reset_timer: · 166 unmodified lines | ||
| 2518 | 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 | 2532 | static void mptcp_mp_fail_no_response(struct mptcp_sock *msk) |
| 2522 | 2533 | { |
| 2523 | − struct mptcp_subflow_context *subflow; | |
| 2524 | − struct sock *ssk; | |
| 2534 | + struct sock *ssk = msk->first; | |
| 2525 | 2535 | bool slow; |
| 2526 | 2536 | |
| 2527 | − subflow = mp_fail_response_expect_subflow(msk); | |
| 2528 | − if (subflow) { | |
| 2529 | − pr_debug("MP_FAIL doesn't respond, reset the subflow"); | |
| 2537 | + if (!ssk) | |
| 2538 | + return; | |
| 2530 | 2539 | |
| 2531 | − ssk = mptcp_subflow_tcp_sock(subflow); | |
| 2532 | − slow = lock_sock_fast(ssk); | |
| 2533 | − mptcp_subflow_reset(ssk); | |
| 2534 | − unlock_sock_fast(ssk, slow); | |
| 2535 | − } | |
| 2540 | + pr_debug("MP_FAIL doesn't respond, reset the subflow"); | |
| 2541 | + | |
| 2542 | + slow = lock_sock_fast(ssk); | |
| 2543 | + mptcp_subflow_reset(ssk); | |
| 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 | 2550 | static void mptcp_worker(struct work_struct *work) |
| 2539 | 2551 | { |
| 2540 | 2552 | struct mptcp_sock *msk = container_of(work, struct mptcp_sock, work); |
| 2541 | 2553 | struct sock *sk = &msk->sk.icsk_inet.sk; |
| 2554 | + unsigned long fail_tout; | |
| 2542 | 2555 | int state; |
| 2543 | 2556 | |
| 2544 | 2557 | lock_sock(sk); |
| @@ -2575,7 +2588,9 @@ static void mptcp_worker(struct work_struct *work) · 30 unmodified lines | ||
| 2575 | 2588 | if (test_and_clear_bit(MPTCP_WORK_RTX, &msk->flags)) |
| 2576 | 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 | 2595 | unlock: |
| 2581 | 2596 | release_sock(sk); |
| @@ -2822,6 +2837,7 @@ static void __mptcp_destroy_sock(struct sock *sk) · 240 unmodified lines | ||
| 2822 | 2837 | static void mptcp_close(struct sock *sk, long timeout) |
| 2823 | 2838 | { |
| 2824 | 2839 | struct mptcp_subflow_context *subflow; |
| 2840 | + struct mptcp_sock *msk = mptcp_sk(sk); | |
| 2825 | 2841 | bool do_cancel_work = false; |
| 2826 | 2842 | |
| 2827 | 2843 | lock_sock(sk); |
| @@ -2840,10 +2856,16 @@ static void mptcp_close(struct sock *sk, long timeout) · 12 unmodified lines | ||
| 2840 | 2856 | cleanup: |
| 2841 | 2857 | /* orphan all the subflows */ |
| 2842 | 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 | 2860 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); |
| 2845 | 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 | 2869 | sock_orphan(ssk); |
| 2848 | 2870 | unlock_sock_fast(ssk, slow); |
| 2849 | 2871 | } |
| @@ -2852,13 +2874,13 @@ cleanup: · 2 unmodified lines | ||
| 2852 | 2874 | sock_hold(sk); |
| 2853 | 2875 | pr_debug("msk=%p state=%d", sk, sk->sk_state); |
| 2854 | 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 | 2879 | if (sk->sk_state == TCP_CLOSE) { |
| 2858 | 2880 | __mptcp_destroy_sock(sk); |
| 2859 | 2881 | do_cancel_work = true; |
| 2860 | 2882 | } else { |
| 2861 | − sk_reset_timer(sk, &sk->sk_timer, jiffies + TCP_TIMEWAIT_LEN); | |
| 2883 | + mptcp_reset_timeout(msk, 0); | |
| 2862 | 2884 | } |
| 2863 | 2885 | release_sock(sk); |
| 2864 | 2886 | if (do_cancel_work) |
| @@ -306,6 +306,7 @@ struct mptcp_sock { · 305 unmodified lines | ||
| 306 | 306 | |
| 307 | 307 | u32 setsockopt_seq; |
| 308 | 308 | char ca_name[TCP_CA_NAME_MAX]; |
| 309 | + struct mptcp_sock *dl_next; | |
| 309 | 310 | }; |
| 310 | 311 | |
| 311 | 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 | 469 | local_id_valid : 1, /* local_id is correctly initialized */ |
| 469 | 470 | valid_csum_seen : 1; /* at least one csum validated */ |
| 470 | 471 | enum mptcp_data_avail data_avail; |
| 471 | − bool mp_fail_response_expect; | |
| 472 | 472 | u32 remote_nonce; |
| 473 | 473 | u64 thmac; |
| 474 | 474 | u32 local_nonce; |
| @@ -482,6 +482,7 @@ struct mptcp_subflow_context { · 7 unmodified lines | ||
| 482 | 482 | u8 stale_count; |
| 483 | 483 | |
| 484 | 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 | 609 | struct mptcp_subflow_context *subflow); |
| 609 | 610 | void mptcp_subflow_send_ack(struct sock *ssk); |
| 610 | 611 | void mptcp_subflow_reset(struct sock *ssk); |
| 612 | +void mptcp_subflow_queue_clean(struct sock *ssk); | |
| 611 | 613 | void mptcp_sock_graft(struct sock *sk, struct socket *parent); |
| 612 | 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 | 665 | void mptcp_finish_connect(struct sock *sk); |
| 664 | 666 | void __mptcp_set_connected(struct sock *sk); |
| 667 | +void mptcp_reset_timeout(struct mptcp_sock *msk, unsigned long fail_tout); | |
| 665 | 668 | static inline bool mptcp_is_fully_established(struct sock *sk) |
| 666 | 669 | { |
| 667 | 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 | 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); | |
| 932 | − struct mptcp_sock *msk = mptcp_sk(subflow->conn); | |
| 934 | + struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); | |
| 935 | + struct sock *sk = subflow->conn; | |
| 936 | + struct mptcp_sock *msk; | |
| 933 | 937 | |
| 938 | + msk = mptcp_sk(sk); | |
| 934 | 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 | 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 | 843 | MAPPING_INVALID, |
| 844 | 844 | MAPPING_EMPTY, |
| 845 | 845 | MAPPING_DATA_FIN, |
| 846 | − MAPPING_DUMMY | |
| 846 | + MAPPING_DUMMY, | |
| 847 | + MAPPING_BAD_CSUM | |
| 847 | 848 | }; |
| 848 | 849 | |
| 849 | 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 | 959 | subflow->map_data_csum); |
| 959 | 960 | if (unlikely(csum)) { |
| 960 | 961 | MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DATACSUMERR); |
| 961 | − if (subflow->mp_join || subflow->valid_csum_seen) { | |
| 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; | |
| 962 | + return MAPPING_BAD_CSUM; | |
| 966 | 963 | } |
| 967 | 964 | |
| 968 | 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 | 972 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); |
| 976 | 973 | bool csum_reqd = READ_ONCE(msk->csum_enabled); |
| 977 | − struct sock *sk = (struct sock *)msk; | |
| 978 | 974 | struct mptcp_ext *mpext; |
| 979 | 975 | struct sk_buff *skb; |
| 980 | 976 | u16 data_len; |
| @@ -1016,9 +1012,6 @@ static enum mapping_status get_mapping_status(struct sock *ssk, · 35 unmodified lines | ||
| 1016 | 1012 | pr_debug("infinite mapping received"); |
| 1017 | 1013 | MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_INFINITEMAPRX); |
| 1018 | 1014 | subflow->map_data_len = 0; |
| 1019 | − if (!sock_flag(ssk, SOCK_DEAD)) | |
| 1020 | − sk_stop_timer(sk, &sk->sk_timer); | |
| 1021 | − | |
| 1022 | 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 | 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 | 1188 | static bool subflow_check_data_avail(struct sock *ssk) |
| 1169 | 1189 | { |
| 1170 | 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 | 1205 | status = get_mapping_status(ssk, msk); |
| 1186 | 1206 | trace_subflow_check_data_avail(status, skb_peek(&ssk->sk_receive_queue)); |
| 1187 | − if (unlikely(status == MAPPING_INVALID)) | |
| 1188 | − goto fallback; | |
| 1189 | − | |
| 1190 | − if (unlikely(status == MAPPING_DUMMY)) | |
| 1207 | + if (unlikely(status == MAPPING_INVALID || status == MAPPING_DUMMY || | |
| 1208 | + status == MAPPING_BAD_CSUM)) | |
| 1191 | 1209 | goto fallback; |
| 1192 | 1210 | |
| 1193 | 1211 | if (status != MAPPING_OK) |
| @@ -1229,22 +1247,17 @@ no_data: · 35 unmodified lines | ||
| 1229 | 1247 | fallback: |
| 1230 | 1248 | if (!__mptcp_check_fallback(msk)) { |
| 1231 | 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 | 1254 | if (!READ_ONCE(msk->allow_infinite_fallback)) { |
| 1234 | − ssk->sk_err = EBADMSG; | |
| 1235 | − tcp_set_state(ssk, TCP_CLOSE); | |
| 1236 | 1255 | subflow->reset_transient = 0; |
| 1237 | 1256 | subflow->reset_reason = MPTCP_RST_EMIDDLEBOX; |
| 1238 | − tcp_send_active_reset(ssk, GFP_ATOMIC); | |
| 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); | |
| 1257 | + goto reset; | |
| 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 | 1261 | return true; |
| 1249 | 1262 | } |
| 1250 | 1263 | |
| @@ -1252,16 +1265,20 @@ fallback: · 1 unmodified line | ||
| 1252 | 1265 | /* fatal protocol error, close the socket. |
| 1253 | 1266 | * subflow_error_report() will introduce the appropriate barriers |
| 1254 | 1267 | */ |
| 1255 | − ssk->sk_err = EBADMSG; | |
| 1256 | − tcp_set_state(ssk, TCP_CLOSE); | |
| 1257 | 1268 | subflow->reset_transient = 0; |
| 1258 | 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 | 1276 | tcp_send_active_reset(ssk, GFP_ATOMIC); |
| 1260 | 1277 | WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA); |
| 1261 | 1278 | return false; |
| 1262 | 1279 | } |
| 1263 | 1280 | |
| 1264 | − __mptcp_do_fallback(msk); | |
| 1281 | + mptcp_do_fallback(ssk); | |
| 1265 | 1282 | } |
| 1266 | 1283 | |
| 1267 | 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 | 1778 | static int subflow_ulp_init(struct sock *sk) |
| 1710 | 1779 | { |
| 1711 | 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 | 1803 | pdev = to_platform_device(dev->dev.parent); |
| 1804 | 1804 | if (pdev) { |
| 1805 | 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 | 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 | 25 | const struct nft_chain *chain, |
| 26 | 26 | enum nft_trace_types type) |
| 27 | 27 | { |
| 28 | − const struct nft_pktinfo *pkt = info->pkt; | |
| 29 | − | |
| 30 | − if (!info->trace || !pkt->skb->nf_trace) | |
| 28 | + if (!info->trace || !info->nf_trace) | |
| 31 | 29 | return; |
| 32 | 30 | |
| 33 | 31 | info->chain = chain; |
| @@ -42,11 +40,24 @@ static inline void nft_trace_packet(struct nft_traceinfo *info, · 8 unmodified lines | ||
| 42 | 40 | enum nft_trace_types type) |
| 43 | 41 | { |
| 44 | 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 | 46 | info->rule = rule; |
| 46 | 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 | 61 | static void nft_bitwise_fast_eval(const struct nft_expr *expr, |
| 51 | 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 | 96 | const struct nft_chain *chain, |
| 86 | 97 | const struct nft_regs *regs) |
| 87 | 98 | { |
| 99 | + const struct nft_pktinfo *pkt = info->pkt; | |
| 88 | 100 | enum nft_trace_types type; |
| 89 | 101 | |
| 90 | 102 | switch (regs->verdict.code) { |
| @@ -92,8 +104,13 @@ static noinline void __nft_trace_verdict(struct nft_traceinfo *info, · 1 unmodified line | ||
| 92 | 104 | case NFT_RETURN: |
| 93 | 105 | type = NFT_TRACETYPE_RETURN; |
| 94 | 106 | break; |
| 107 | + case NF_STOLEN: | |
| 108 | + type = NFT_TRACETYPE_RULE; | |
| 109 | + /* can't access skb->nf_trace; use copy */ | |
| 110 | + break; | |
| 95 | 111 | default: |
| 96 | 112 | type = NFT_TRACETYPE_RULE; |
| 113 | + info->nf_trace = pkt->skb->nf_trace; | |
| 97 | 114 | break; |
| 98 | 115 | } |
| 99 | 116 | |
| @@ -254,6 +271,7 @@ next_rule: · 154 unmodified lines | ||
| 254 | 271 | switch (regs.verdict.code) { |
| 255 | 272 | case NFT_BREAK: |
| 256 | 273 | regs.verdict.code = NFT_CONTINUE; |
| 274 | + nft_trace_copy_nftrace(&info); | |
| 257 | 275 | continue; |
| 258 | 276 | case NFT_CONTINUE: |
| 259 | 277 | nft_trace_packet(&info, chain, rule, |
| @@ -7,7 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <linux/module.h> |
| 8 | 8 | #include <linux/static_key.h> |
| 9 | 9 | #include <linux/hash.h> |
| 10 | −#include <linux/jhash.h> | |
| 10 | +#include <linux/siphash.h> | |
| 11 | 11 | #include <linux/if_vlan.h> |
| 12 | 12 | #include <linux/init.h> |
| 13 | 13 | #include <linux/skbuff.h> |
| @@ -25,22 +25,6 @@ · 11 unmodified lines | ||
| 25 | 25 | DEFINE_STATIC_KEY_FALSE(nft_trace_enabled); |
| 26 | 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 | 28 | static int trace_fill_header(struct sk_buff *nlskb, u16 type, |
| 45 | 29 | const struct sk_buff *skb, |
| 46 | 30 | int off, unsigned int len) |
| @@ -186,6 +170,7 @@ void nft_trace_notify(struct nft_traceinfo *info) · 139 unmodified lines | ||
| 186 | 170 | struct nlmsghdr *nlh; |
| 187 | 171 | struct sk_buff *skb; |
| 188 | 172 | unsigned int size; |
| 173 | + u32 mark = 0; | |
| 189 | 174 | u16 event; |
| 190 | 175 | |
| 191 | 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 | 214 | if (nla_put_be32(skb, NFTA_TRACE_TYPE, htonl(info->type))) |
| 230 | 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 | 218 | goto nla_put_failure; |
| 234 | 219 | |
| 235 | 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 | 234 | case NFT_TRACETYPE_RULE: |
| 250 | 235 | if (nft_verdict_dump(skb, NFTA_TRACE_VERDICT, info->verdict)) |
| 251 | 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 | 244 | break; |
| 253 | 245 | case NFT_TRACETYPE_POLICY: |
| 246 | + mark = pkt->skb->mark; | |
| 247 | + | |
| 254 | 248 | if (nla_put_be32(skb, NFTA_TRACE_POLICY, |
| 255 | 249 | htonl(info->basechain->policy))) |
| 256 | 250 | goto nla_put_failure; |
| 257 | 251 | break; |
| 258 | 252 | } |
| 259 | 253 | |
| 260 | − if (pkt->skb->mark && | |
| 261 | − nla_put_be32(skb, NFTA_TRACE_MARK, htonl(pkt->skb->mark))) | |
| 254 | + if (mark && nla_put_be32(skb, NFTA_TRACE_MARK, htonl(mark))) | |
| 262 | 255 | goto nla_put_failure; |
| 263 | 256 | |
| 264 | 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 | 276 | const struct nft_verdict *verdict, |
| 284 | 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 | 282 | info->basechain = nft_base_chain(chain); |
| 287 | 283 | info->trace = true; |
| 284 | + info->nf_trace = pkt->skb->nf_trace; | |
| 288 | 285 | info->packet_dumped = false; |
| 289 | 286 | info->pkt = pkt; |
| 290 | 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 | 143 | /* Another cpu may race to insert the element with the same key */ |
| 144 | 144 | if (prev) { |
| 145 | 145 | nft_set_elem_destroy(set, he, true); |
| 146 | + atomic_dec(&set->nelems); | |
| 146 | 147 | he = prev; |
| 147 | 148 | } |
| 148 | 149 | |
| @@ -152,6 +153,7 @@ out: · 3 unmodified lines | ||
| 152 | 153 | |
| 153 | 154 | err2: |
| 154 | 155 | nft_set_elem_destroy(set, he, true); |
| 156 | + atomic_dec(&set->nelems); | |
| 155 | 157 | err1: |
| 156 | 158 | return false; |
| 157 | 159 | } |
| @@ -31,89 +31,89 @@ static void rose_idletimer_expiry(struct timer_list *); · 30 unmodified lines | ||
| 31 | 31 | |
| 32 | 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 | 36 | sk->sk_timer.function = rose_heartbeat_expiry; |
| 37 | 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 | 42 | void rose_start_t1timer(struct sock *sk) |
| 43 | 43 | { |
| 44 | 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 | 48 | rose->timer.function = rose_timer_expiry; |
| 49 | 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 | 54 | void rose_start_t2timer(struct sock *sk) |
| 55 | 55 | { |
| 56 | 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 | 60 | rose->timer.function = rose_timer_expiry; |
| 61 | 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 | 66 | void rose_start_t3timer(struct sock *sk) |
| 67 | 67 | { |
| 68 | 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 | 72 | rose->timer.function = rose_timer_expiry; |
| 73 | 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 | 78 | void rose_start_hbtimer(struct sock *sk) |
| 79 | 79 | { |
| 80 | 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 | 84 | rose->timer.function = rose_timer_expiry; |
| 85 | 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 | 90 | void rose_start_idletimer(struct sock *sk) |
| 91 | 91 | { |
| 92 | 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 | 96 | if (rose->idle > 0) { |
| 97 | 97 | rose->idletimer.function = rose_idletimer_expiry; |
| 98 | 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 | 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 | 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 | 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 | 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 | 130 | (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) { |
| 131 | 131 | bh_unlock_sock(sk); |
| 132 | 132 | rose_destroy_socket(sk); |
| 133 | + sock_put(sk); | |
| 133 | 134 | return; |
| 134 | 135 | } |
| 135 | 136 | break; |
| @@ -152,6 +153,7 @@ static void rose_heartbeat_expiry(struct timer_list *t) · 16 unmodified lines | ||
| 152 | 153 | |
| 153 | 154 | rose_start_heartbeat(sk); |
| 154 | 155 | bh_unlock_sock(sk); |
| 156 | + sock_put(sk); | |
| 155 | 157 | } |
| 156 | 158 | |
| 157 | 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 | 183 | break; |
| 182 | 184 | } |
| 183 | 185 | bh_unlock_sock(sk); |
| 186 | + sock_put(sk); | |
| 184 | 187 | } |
| 185 | 188 | |
| 186 | 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 | 208 | sock_set_flag(sk, SOCK_DEAD); |
| 206 | 209 | } |
| 207 | 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 | 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 | 594 | struct nlattr *nest; |
| 594 | 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 | 605 | if (nla_put_string(skb, TCA_KIND, ops->kind)) |
| 605 | 606 | goto nla_put_failure; |
| 606 | 607 | |
| 608 | + ret = 0; | |
| 607 | 609 | mutex_lock(&idrinfo->lock); |
| 608 | 610 | idr_for_each_entry_ul(idr, p, tmp, id) { |
| 609 | 611 | if (IS_ERR(p)) |
| 610 | 612 | continue; |
| 611 | 613 | ret = tcf_idr_release_unsafe(p); |
| 612 | − if (ret == ACT_P_DELETED) { | |
| 614 | + if (ret == ACT_P_DELETED) | |
| 613 | 615 | module_put(ops->owner); |
| 614 | − n_i++; | |
| 615 | − } else if (ret < 0) { | |
| 616 | − mutex_unlock(&idrinfo->lock); | |
| 617 | − goto nla_put_failure; | |
| 618 | − } | |
| 616 | + else if (ret < 0) | |
| 617 | + break; | |
| 618 | + n_i++; | |
| 619 | 619 | } |
| 620 | 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 | 628 | ret = nla_put_u32(skb, TCA_FCNT, n_i); |
| 623 | 629 | if (ret) |
| @@ -638,7 +644,7 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb, · 14 unmodified lines | ||
| 638 | 644 | struct tcf_idrinfo *idrinfo = tn->idrinfo; |
| 639 | 645 | |
| 640 | 646 | if (type == RTM_DELACTION) { |
| 641 | − return tcf_del_walker(idrinfo, skb, ops); | |
| 647 | + return tcf_del_walker(idrinfo, skb, ops, extack); | |
| 642 | 648 | } else if (type == RTM_GETACTION) { |
| 643 | 649 | return tcf_dump_walker(idrinfo, skb, cb); |
| 644 | 650 | } else { |
| @@ -2149,10 +2149,13 @@ SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len, · 2148 unmodified lines | ||
| 2149 | 2149 | int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags, |
| 2150 | 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 | 2157 | struct socket *sock; |
| 2153 | 2158 | struct iovec iov; |
| 2154 | − struct msghdr msg; | |
| 2155 | − struct sockaddr_storage address; | |
| 2156 | 2159 | int err, err2; |
| 2157 | 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 | 2166 | if (!sock) |
| 2164 | 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 | 2169 | if (sock->file->f_flags & O_NONBLOCK) |
| 2175 | 2170 | flags |= MSG_DONTWAIT; |
| 2176 | 2171 | err = sock_recvmsg(sock, &msg, flags); |
| @@ -2375,6 +2370,7 @@ int __copy_msghdr_from_user(struct msghdr *kmsg, · 198 unmodified lines | ||
| 2375 | 2370 | return -EFAULT; |
| 2376 | 2371 | |
| 2377 | 2372 | kmsg->msg_control_is_user = true; |
| 2373 | + kmsg->msg_get_inq = 0; | |
| 2378 | 2374 | kmsg->msg_control_user = msg.msg_control; |
| 2379 | 2375 | kmsg->msg_controllen = msg.msg_controllen; |
| 2380 | 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 | 472 | bool preliminary) |
| 473 | 473 | { |
| 474 | 474 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
| 475 | + struct tipc_link *l, *snd_l = tipc_bc_sndlink(net); | |
| 475 | 476 | struct tipc_node *n, *temp_node; |
| 476 | − struct tipc_link *l; | |
| 477 | 477 | unsigned long intv; |
| 478 | 478 | int bearer_id; |
| 479 | 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 | 488 | goto exit; |
| 489 | 489 | /* A preliminary node becomes "real" now, refresh its data */ |
| 490 | 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 | 501 | n->preliminary = false; |
| 492 | 502 | n->addr = addr; |
| 493 | 503 | hlist_del_rcu(&n->hash); |
| @@ -567,7 +577,16 @@ update: · 73 unmodified lines | ||
| 567 | 577 | n->signature = INVALID_NODE_SIG; |
| 568 | 578 | n->active_links[0] = INVALID_BEARER_ID; |
| 569 | 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 | 590 | tipc_node_get(n); |
| 572 | 591 | timer_setup(&n->timer, tipc_node_timeout, 0); |
| 573 | 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 | 1174 | bool *respond, bool *dupl_addr) |
| 1156 | 1175 | { |
| 1157 | 1176 | struct tipc_node *n; |
| 1158 | − struct tipc_link *l, *snd_l; | |
| 1177 | + struct tipc_link *l; | |
| 1159 | 1178 | struct tipc_link_entry *le; |
| 1160 | 1179 | bool addr_match = false; |
| 1161 | 1180 | bool sign_match = false; |
| @@ -1175,22 +1194,6 @@ void tipc_node_check_dest(struct net *net, u32 addr, · 13 unmodified lines | ||
| 1175 | 1194 | return; |
| 1176 | 1195 | |
| 1177 | 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 | 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 | 502 | sock_init_data(sock, sk); |
| 503 | 503 | tipc_set_sk_state(sk, TIPC_OPEN); |
| 504 | 504 | if (tipc_sk_insert(tsk)) { |
| 505 | + sk_free(sk); | |
| 505 | 506 | pr_warn("Socket create failed; port number exhausted\n"); |
| 506 | 507 | return -EINVAL; |
| 507 | 508 | } |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | * Tests for sockmap/sockhash holding kTLS sockets. |
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | +#include <netinet/tcp.h> | |
| 7 | 8 | #include "test_progs.h" |
| 8 | 9 | |
| 9 | 10 | #define MAX_TEST_NAME 80 |
| @@ -92,9 +93,78 @@ close_srv: · 82 unmodified lines | ||
| 92 | 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 | 166 | static void run_tests(int family, enum bpf_map_type map_type) |
| 96 | 167 | { |
| 97 | − char test_name[MAX_TEST_NAME]; | |
| 98 | 168 | int map; |
| 99 | 169 | |
| 100 | 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 | 173 | return; |
| 104 | 174 | } |
| 105 | 175 | |
| 106 | − snprintf(test_name, MAX_TEST_NAME, | |
| 107 | − "sockmap_ktls disconnect_after_delete %s %s", | |
| 108 | − family == AF_INET ? "IPv4" : "IPv6", | |
| 109 | − map_type == BPF_MAP_TYPE_SOCKMAP ? "SOCKMAP" : "SOCKHASH"); | |
| 110 | − if (!test__start_subtest(test_name)) | |
| 111 | − return; | |
| 112 | − | |
| 113 | − test_sockmap_ktls_disconnect_after_delete(family, map); | |
| 176 | + if (test__start_subtest(fmt_test_name("disconnect_after_delete", family, map_type))) | |
| 177 | + test_sockmap_ktls_disconnect_after_delete(family, map); | |
| 178 | + if (test__start_subtest(fmt_test_name("update_fails_when_sock_has_ulp", family, map_type))) | |
| 179 | + test_sockmap_ktls_update_fails_when_sock_has_ulp(family, map); | |
| 114 | 180 | |
| 115 | 181 | close(map); |
| 116 | 182 | } |
| @@ -54,7 +54,7 @@ TEST_GEN_FILES += ipsec · 53 unmodified lines | ||
| 54 | 54 | TEST_GEN_FILES += ioam6_parser |
| 55 | 55 | TEST_GEN_FILES += gro |
| 56 | 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 | 58 | TEST_GEN_FILES += toeplitz |
| 59 | 59 | TEST_GEN_FILES += cmsg_sender |
| 60 | 60 | TEST_GEN_FILES += stress_reuseport_listen |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | CLANG ?= clang |
| 4 | 4 | CCINCLUDE += -I../../bpf |
| 5 | −CCINCLUDE += -I../../../lib | |
| 5 | +CCINCLUDE += -I../../../../lib | |
| 6 | 6 | CCINCLUDE += -I../../../../../usr/include/ |
| 7 | 7 | |
| 8 | 8 | TEST_CUSTOM_PROGS = $(OUTPUT)/bpf/nat6to4.o |
| @@ -61,6 +61,39 @@ chk_msk_nr() · 60 unmodified lines | ||
| 61 | 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 | 97 | chk_msk_fallback_nr() |
| 65 | 98 | { |
| 66 | 99 | __chk_nr "grep -c fallback" $* |
| @@ -146,7 +179,7 @@ ip -n $ns link set dev lo up · 79 unmodified lines | ||
| 146 | 179 | echo "a" | \ |
| 147 | 180 | timeout ${timeout_test} \ |
| 148 | 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 | 183 | 0.0.0.0 >/dev/null & |
| 151 | 184 | wait_local_port_listen $ns 10000 |
| 152 | 185 | chk_msk_nr 0 "no msk on netns creation" |
| @@ -155,7 +188,7 @@ chk_msk_listen 10000 · 2 unmodified lines | ||
| 155 | 188 | echo "b" | \ |
| 156 | 189 | timeout ${timeout_test} \ |
| 157 | 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 | 192 | 127.0.0.1 >/dev/null & |
| 160 | 193 | wait_connected $ns 10000 |
| 161 | 194 | chk_msk_nr 2 "after MPC handshake " |
| @@ -167,13 +200,13 @@ flush_pids · 5 unmodified lines | ||
| 167 | 200 | echo "a" | \ |
| 168 | 201 | timeout ${timeout_test} \ |
| 169 | 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 | 204 | 0.0.0.0 >/dev/null & |
| 172 | 205 | wait_local_port_listen $ns 10001 |
| 173 | 206 | echo "b" | \ |
| 174 | 207 | timeout ${timeout_test} \ |
| 175 | 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 | 210 | 127.0.0.1 >/dev/null & |
| 178 | 211 | wait_connected $ns 10001 |
| 179 | 212 | chk_msk_fallback_nr 1 "check fallback" |
| @@ -184,7 +217,7 @@ for I in `seq 1 $NR_CLIENTS`; do · 4 unmodified lines | ||
| 184 | 217 | echo "a" | \ |
| 185 | 218 | timeout ${timeout_test} \ |
| 186 | 219 | ip netns exec $ns \ |
| 187 | − ./mptcp_connect -p $((I+10001)) -l -w 10 \ | |
| 220 | + ./mptcp_connect -p $((I+10001)) -l -w 20 \ | |
| 188 | 221 | -t ${timeout_poll} 0.0.0.0 >/dev/null & |
| 189 | 222 | done |
| 190 | 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 | 226 | echo "b" | \ |
| 194 | 227 | timeout ${timeout_test} \ |
| 195 | 228 | ip netns exec $ns \ |
| 196 | − ./mptcp_connect -p $((I+10001)) -w 10 \ | |
| 229 | + ./mptcp_connect -p $((I+10001)) -w 20 \ | |
| 197 | 230 | -t ${timeout_poll} 127.0.0.1 >/dev/null & |
| 198 | 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 | 234 | flush_pids |
| 203 | 235 | |
| 204 | 236 | exit $ret |
| @@ -265,7 +265,7 @@ static void sock_test_tcpulp(int sock, int proto, unsigned int line) · 264 unmodified lines | ||
| 265 | 265 | static int sock_listen_mptcp(const char * const listenaddr, |
| 266 | 266 | const char * const port) |
| 267 | 267 | { |
| 268 | − int sock; | |
| 268 | + int sock = -1; | |
| 269 | 269 | struct addrinfo hints = { |
| 270 | 270 | .ai_protocol = IPPROTO_TCP, |
| 271 | 271 | .ai_socktype = SOCK_STREAM, |
| @@ -88,7 +88,7 @@ static void xgetaddrinfo(const char *node, const char *service, · 87 unmodified lines | ||
| 88 | 88 | static int sock_listen_mptcp(const char * const listenaddr, |
| 89 | 89 | const char * const port) |
| 90 | 90 | { |
| 91 | − int sock; | |
| 91 | + int sock = -1; | |
| 92 | 92 | struct addrinfo hints = { |
| 93 | 93 | .ai_protocol = IPPROTO_TCP, |
| 94 | 94 | .ai_socktype = SOCK_STREAM, |
| @@ -136,7 +136,7 @@ static void xgetaddrinfo(const char *node, const char *service, · 135 unmodified lines | ||
| 136 | 136 | static int sock_listen_mptcp(const char * const listenaddr, |
| 137 | 137 | const char * const port) |
| 138 | 138 | { |
| 139 | − int sock; | |
| 139 | + int sock = -1; | |
| 140 | 140 | struct addrinfo hints = { |
| 141 | 141 | .ai_protocol = IPPROTO_TCP, |
| 142 | 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 | 120 | run_udp "${ipv4_args}" |
| 121 | 121 | |
| 122 | 122 | echo "ipv6" |
| 123 | − run_tcp "${ipv4_args}" | |
| 123 | + run_tcp "${ipv6_args}" | |
| 124 | 124 | run_udp "${ipv6_args}" |
| 125 | 125 | } |
| 126 | 126 | |
| @@ -609,5 +609,82 @@ · 608 unmodified lines | ||
| 609 | 609 | "teardown": [ |
| 610 | 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 | ] |