Networking fixes for 6.4-rc2, including fixes from netfilter
Current release - regressions: - mtk_eth_soc: fix NULL pointer dereference Previous releases - regressions: - core: - skb_partial_csum_set() fix against transport header magic value - fix load-tearing on sk->sk_stamp in sock_recv_cmsgs(). - annotate sk->sk_err write from do_recvmmsg() - add vlan_get_protocol_and_depth() helper - netlink: annotate accesses to nlk->cb_running - netfilter: always release netdev hooks from notifier Previous releases - always broken: - core: deal with most data-races in sk_wait_event() - netfilter: fix possible bug_on with enable_hooks=1 - eth: bonding: fix send_peer_notif overflow - eth: xpcs: fix incorrect number of interfaces - eth: ipvlan: fix out-of-bounds caused by unclear skb->cb - eth: stmmac: Initialize MAC_ONEUS_TIC_COUNTER register Signed-off-by: Paolo Abeni <pabeni@redhat.com> -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEEg1AjqC77wbdLX2LbKSR5jcyPE6QFAmRcxawSHHBhYmVuaUBy ZWRoYXQuY29tAAoJECkkeY3MjxOkv6wQAJgfOBlDAkZNKHzwtMuFiLxECeEMWY9h wJCyiq0qXnz9p5ZqjdmTmA8B+jUp9VkpgN5Z3lid5hXDfzDrvXL1KGZW4pc4ooz9 GUzrp0EUzO5UsyrlZRS9vJ9mbCGN5M1ZWtWH93g8OzGJPRnLs0Q/Tr4IFTBVKzVb GmJPy/ZYWYDjnvx3BgewRDuYeH3Rt9lsIt4Pxq/E+D8W3ypvVM0m3GvrO5eEzMeu EfeilAdmJGJUufeoGguKt0hheqILS3kNCjQO25XS2Lq1OqetnR/wqTwXaaVxL2du Eb2ca7wKkihDpl2l8bQ3ss6vqM0HEpZ63Y2PJaNBS8ASdLsMq4n2L6j2JMfT8hWY RG3nJS7F2UFLyYmCJjNL1/I+Z9XeMyFKnHORzHK1dAkMlhd+8NauKWAxdjlxMbxX p1msyTl54bG0g6FrU/zAirCWNAAZYCPdZG/XvA/2Jj9mdy64OlGlv/QdJvfjcx+C L6nkwZfwXU7QUwKeeTfP8abte2SLrXIxkJrnNEAntPnFOSmd16+/yvQ8JVlbWTMd JugJrSAIxjOglIr/1fsnUuV+Ab+JDYQv/wkoyzvtcY2tjhTAHzgmTwwSfeYiCTJE rEbjyVvVgMcLTUIk/R9QC5/k6nX/7/KRDHxPOMBX4boOsuA0ARVjzt8uKRvv/7cS dRV98RwvCKvD =MoPD -----END PGP SIGNATURE----- Merge tag 'net-6.4-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net Pull networking fixes from Paolo Abeni: "Including fixes from netfilter. Current release - regressions: - mtk_eth_soc: fix NULL pointer dereference Previous releases - regressions: - core: - skb_partial_csum_set() fix against transport header magic value - fix load-tearing on sk->sk_stamp in sock_recv_cmsgs(). - annotate sk->sk_err write from do_recvmmsg() - add vlan_get_protocol_and_depth() helper - netlink: annotate accesses to nlk->cb_running - netfilter: always release netdev hooks from notifier Previous releases - always broken: - core: deal with most data-races in sk_wait_event() - netfilter: fix possible bug_on with enable_hooks=1 - eth: bonding: fix send_peer_notif overflow - eth: xpcs: fix incorrect number of interfaces - eth: ipvlan: fix out-of-bounds caused by unclear skb->cb - eth: stmmac: Initialize MAC_ONEUS_TIC_COUNTER register" * tag 'net-6.4-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (31 commits) af_unix: Fix data races around sk->sk_shutdown. af_unix: Fix a data race of sk->sk_receive_queue->qlen. net: datagram: fix data-races in datagram_poll() net: mscc: ocelot: fix stat counter register values ipvlan:Fix out-of-bounds caused by unclear skb->cb docs: networking: fix x25-iface.rst heading & index order gve: Remove the code of clearing PBA bit tcp: add annotations around sk->sk_shutdown accesses net: add vlan_get_protocol_and_depth() helper net: pcs: xpcs: fix incorrect number of interfaces net: deal with most data-races in sk_wait_event() net: annotate sk->sk_err write from do_recvmmsg() netlink: annotate accesses to nlk->cb_running kselftest: bonding: add num_grat_arp test selftests: forwarding: lib: add netns support for tc rule handle stats get Documentation: bonding: fix the doc of peer_notif_delay bonding: fix send_peer_notif overflow net: ethernet: mtk_eth_soc: fix NULL pointer dereference selftests: nft_flowtable.sh: check ingress/egress chain too selftests: nft_flowtable.sh: monitor result file sizes ...
This commit is contained in:
commit
6e27831b91
@ -776,10 +776,11 @@ peer_notif_delay
|
||||
Specify the delay, in milliseconds, between each peer
|
||||
notification (gratuitous ARP and unsolicited IPv6 Neighbor
|
||||
Advertisement) when they are issued after a failover event.
|
||||
This delay should be a multiple of the link monitor interval
|
||||
(arp_interval or miimon, whichever is active). The default
|
||||
value is 0 which means to match the value of the link monitor
|
||||
interval.
|
||||
This delay should be a multiple of the MII link monitor interval
|
||||
(miimon).
|
||||
|
||||
The valid range is 0 - 300000. The default value is 0, which means
|
||||
to match the value of the MII link monitor interval.
|
||||
|
||||
prio
|
||||
Slave priority. A higher number means higher priority.
|
||||
|
@ -116,8 +116,8 @@ Contents:
|
||||
udplite
|
||||
vrf
|
||||
vxlan
|
||||
x25-iface
|
||||
x25
|
||||
x25-iface
|
||||
xfrm_device
|
||||
xfrm_proc
|
||||
xfrm_sync
|
||||
|
@ -1,8 +1,7 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
============================-
|
||||
X.25 Device Driver Interface
|
||||
============================-
|
||||
============================
|
||||
|
||||
Version 1.1
|
||||
|
||||
|
@ -84,6 +84,11 @@ nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
/* Limit the max delay range to 300s */
|
||||
static struct netlink_range_validation delay_range = {
|
||||
.max = 300000,
|
||||
};
|
||||
|
||||
static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
|
||||
[IFLA_BOND_MODE] = { .type = NLA_U8 },
|
||||
[IFLA_BOND_ACTIVE_SLAVE] = { .type = NLA_U32 },
|
||||
@ -114,7 +119,7 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
|
||||
[IFLA_BOND_AD_ACTOR_SYSTEM] = { .type = NLA_BINARY,
|
||||
.len = ETH_ALEN },
|
||||
[IFLA_BOND_TLB_DYNAMIC_LB] = { .type = NLA_U8 },
|
||||
[IFLA_BOND_PEER_NOTIF_DELAY] = { .type = NLA_U32 },
|
||||
[IFLA_BOND_PEER_NOTIF_DELAY] = NLA_POLICY_FULL_RANGE(NLA_U32, &delay_range),
|
||||
[IFLA_BOND_MISSED_MAX] = { .type = NLA_U8 },
|
||||
[IFLA_BOND_NS_IP6_TARGET] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
@ -169,6 +169,12 @@ static const struct bond_opt_value bond_num_peer_notif_tbl[] = {
|
||||
{ NULL, -1, 0}
|
||||
};
|
||||
|
||||
static const struct bond_opt_value bond_peer_notif_delay_tbl[] = {
|
||||
{ "off", 0, 0},
|
||||
{ "maxval", 300000, BOND_VALFLAG_MAX},
|
||||
{ NULL, -1, 0}
|
||||
};
|
||||
|
||||
static const struct bond_opt_value bond_primary_reselect_tbl[] = {
|
||||
{ "always", BOND_PRI_RESELECT_ALWAYS, BOND_VALFLAG_DEFAULT},
|
||||
{ "better", BOND_PRI_RESELECT_BETTER, 0},
|
||||
@ -488,7 +494,7 @@ static const struct bond_option bond_opts[BOND_OPT_LAST] = {
|
||||
.id = BOND_OPT_PEER_NOTIF_DELAY,
|
||||
.name = "peer_notif_delay",
|
||||
.desc = "Delay between each peer notification on failover event, in milliseconds",
|
||||
.values = bond_intmax_tbl,
|
||||
.values = bond_peer_notif_delay_tbl,
|
||||
.set = bond_option_peer_notif_delay_set
|
||||
}
|
||||
};
|
||||
|
@ -294,19 +294,6 @@ static int gve_napi_poll_dqo(struct napi_struct *napi, int budget)
|
||||
bool reschedule = false;
|
||||
int work_done = 0;
|
||||
|
||||
/* Clear PCI MSI-X Pending Bit Array (PBA)
|
||||
*
|
||||
* This bit is set if an interrupt event occurs while the vector is
|
||||
* masked. If this bit is set and we reenable the interrupt, it will
|
||||
* fire again. Since we're just about to poll the queue state, we don't
|
||||
* need it to fire again.
|
||||
*
|
||||
* Under high softirq load, it's possible that the interrupt condition
|
||||
* is triggered twice before we got the chance to process it.
|
||||
*/
|
||||
gve_write_irq_doorbell_dqo(priv, block,
|
||||
GVE_ITR_NO_UPDATE_DQO | GVE_ITR_CLEAR_PBA_BIT_DQO);
|
||||
|
||||
if (block->tx)
|
||||
reschedule |= gve_tx_poll_dqo(block, /*do_clean=*/true);
|
||||
|
||||
|
@ -654,7 +654,7 @@ __mtk_wed_detach(struct mtk_wed_device *dev)
|
||||
BIT(hw->index), BIT(hw->index));
|
||||
}
|
||||
|
||||
if (!hw_list[!hw->index]->wed_dev &&
|
||||
if ((!hw_list[!hw->index] || !hw_list[!hw->index]->wed_dev) &&
|
||||
hw->eth->dma_dev != hw->eth->dev)
|
||||
mtk_eth_set_dma_device(hw->eth, hw->eth->dev);
|
||||
|
||||
|
@ -307,15 +307,15 @@ static const u32 vsc7514_sys_regmap[] = {
|
||||
REG(SYS_COUNT_DROP_YELLOW_PRIO_4, 0x000218),
|
||||
REG(SYS_COUNT_DROP_YELLOW_PRIO_5, 0x00021c),
|
||||
REG(SYS_COUNT_DROP_YELLOW_PRIO_6, 0x000220),
|
||||
REG(SYS_COUNT_DROP_YELLOW_PRIO_7, 0x000214),
|
||||
REG(SYS_COUNT_DROP_GREEN_PRIO_0, 0x000218),
|
||||
REG(SYS_COUNT_DROP_GREEN_PRIO_1, 0x00021c),
|
||||
REG(SYS_COUNT_DROP_GREEN_PRIO_2, 0x000220),
|
||||
REG(SYS_COUNT_DROP_GREEN_PRIO_3, 0x000224),
|
||||
REG(SYS_COUNT_DROP_GREEN_PRIO_4, 0x000228),
|
||||
REG(SYS_COUNT_DROP_GREEN_PRIO_5, 0x00022c),
|
||||
REG(SYS_COUNT_DROP_GREEN_PRIO_6, 0x000230),
|
||||
REG(SYS_COUNT_DROP_GREEN_PRIO_7, 0x000234),
|
||||
REG(SYS_COUNT_DROP_YELLOW_PRIO_7, 0x000224),
|
||||
REG(SYS_COUNT_DROP_GREEN_PRIO_0, 0x000228),
|
||||
REG(SYS_COUNT_DROP_GREEN_PRIO_1, 0x00022c),
|
||||
REG(SYS_COUNT_DROP_GREEN_PRIO_2, 0x000230),
|
||||
REG(SYS_COUNT_DROP_GREEN_PRIO_3, 0x000234),
|
||||
REG(SYS_COUNT_DROP_GREEN_PRIO_4, 0x000238),
|
||||
REG(SYS_COUNT_DROP_GREEN_PRIO_5, 0x00023c),
|
||||
REG(SYS_COUNT_DROP_GREEN_PRIO_6, 0x000240),
|
||||
REG(SYS_COUNT_DROP_GREEN_PRIO_7, 0x000244),
|
||||
REG(SYS_RESET_CFG, 0x000508),
|
||||
REG(SYS_CMID, 0x00050c),
|
||||
REG(SYS_VLAN_ETYPE_CFG, 0x000510),
|
||||
|
@ -181,6 +181,7 @@ enum power_event {
|
||||
#define GMAC4_LPI_CTRL_STATUS 0xd0
|
||||
#define GMAC4_LPI_TIMER_CTRL 0xd4
|
||||
#define GMAC4_LPI_ENTRY_TIMER 0xd8
|
||||
#define GMAC4_MAC_ONEUS_TIC_COUNTER 0xdc
|
||||
|
||||
/* LPI control and status defines */
|
||||
#define GMAC4_LPI_CTRL_STATUS_LPITCSE BIT(21) /* LPI Tx Clock Stop Enable */
|
||||
|
@ -25,6 +25,7 @@ static void dwmac4_core_init(struct mac_device_info *hw,
|
||||
struct stmmac_priv *priv = netdev_priv(dev);
|
||||
void __iomem *ioaddr = hw->pcsr;
|
||||
u32 value = readl(ioaddr + GMAC_CONFIG);
|
||||
u32 clk_rate;
|
||||
|
||||
value |= GMAC_CORE_INIT;
|
||||
|
||||
@ -47,6 +48,10 @@ static void dwmac4_core_init(struct mac_device_info *hw,
|
||||
|
||||
writel(value, ioaddr + GMAC_CONFIG);
|
||||
|
||||
/* Configure LPI 1us counter to number of CSR clock ticks in 1us - 1 */
|
||||
clk_rate = clk_get_rate(priv->plat->stmmac_clk);
|
||||
writel((clk_rate / 1000000) - 1, ioaddr + GMAC4_MAC_ONEUS_TIC_COUNTER);
|
||||
|
||||
/* Enable GMAC interrupts */
|
||||
value = GMAC_INT_DEFAULT_ENABLE;
|
||||
|
||||
|
@ -436,6 +436,9 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb)
|
||||
goto err;
|
||||
}
|
||||
skb_dst_set(skb, &rt->dst);
|
||||
|
||||
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
|
||||
|
||||
err = ip_local_out(net, skb->sk, skb);
|
||||
if (unlikely(net_xmit_eval(err)))
|
||||
dev->stats.tx_errors++;
|
||||
@ -474,6 +477,9 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb)
|
||||
goto err;
|
||||
}
|
||||
skb_dst_set(skb, dst);
|
||||
|
||||
memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
|
||||
|
||||
err = ip6_local_out(net, skb->sk, skb);
|
||||
if (unlikely(net_xmit_eval(err)))
|
||||
dev->stats.tx_errors++;
|
||||
|
@ -67,6 +67,7 @@ static int mvusb_mdio_probe(struct usb_interface *interface,
|
||||
struct device *dev = &interface->dev;
|
||||
struct mvusb_mdio *mvusb;
|
||||
struct mii_bus *mdio;
|
||||
int ret;
|
||||
|
||||
mdio = devm_mdiobus_alloc_size(dev, sizeof(*mvusb));
|
||||
if (!mdio)
|
||||
@ -87,7 +88,15 @@ static int mvusb_mdio_probe(struct usb_interface *interface,
|
||||
mdio->write = mvusb_mdio_write;
|
||||
|
||||
usb_set_intfdata(interface, mvusb);
|
||||
return of_mdiobus_register(mdio, dev->of_node);
|
||||
ret = of_mdiobus_register(mdio, dev->of_node);
|
||||
if (ret)
|
||||
goto put_dev;
|
||||
|
||||
return 0;
|
||||
|
||||
put_dev:
|
||||
usb_put_dev(mvusb->udev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mvusb_mdio_disconnect(struct usb_interface *interface)
|
||||
|
@ -1203,7 +1203,7 @@ static const struct xpcs_compat synopsys_xpcs_compat[DW_XPCS_INTERFACE_MAX] = {
|
||||
[DW_XPCS_2500BASEX] = {
|
||||
.supported = xpcs_2500basex_features,
|
||||
.interface = xpcs_2500basex_interfaces,
|
||||
.num_interfaces = ARRAY_SIZE(xpcs_2500basex_features),
|
||||
.num_interfaces = ARRAY_SIZE(xpcs_2500basex_interfaces),
|
||||
.an_mode = DW_2500BASEX,
|
||||
},
|
||||
};
|
||||
|
@ -40,6 +40,11 @@ static inline int bcm_phy_write_exp_sel(struct phy_device *phydev,
|
||||
return bcm_phy_write_exp(phydev, reg | MII_BCM54XX_EXP_SEL_ER, val);
|
||||
}
|
||||
|
||||
static inline int bcm_phy_read_exp_sel(struct phy_device *phydev, u16 reg)
|
||||
{
|
||||
return bcm_phy_read_exp(phydev, reg | MII_BCM54XX_EXP_SEL_ER);
|
||||
}
|
||||
|
||||
int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val);
|
||||
int bcm54xx_auxctl_read(struct phy_device *phydev, u16 regnum);
|
||||
|
||||
|
@ -486,7 +486,7 @@ static int bcm7xxx_16nm_ephy_afe_config(struct phy_device *phydev)
|
||||
bcm_phy_write_misc(phydev, 0x0038, 0x0002, 0xede0);
|
||||
|
||||
/* Read CORE_EXPA9 */
|
||||
tmp = bcm_phy_read_exp(phydev, 0x00a9);
|
||||
tmp = bcm_phy_read_exp_sel(phydev, 0x00a9);
|
||||
/* CORE_EXPA9[6:1] is rcalcode[5:0] */
|
||||
rcalcode = (tmp & 0x7e) / 2;
|
||||
/* Correct RCAL code + 1 is -1% rprogr, LP: +16 */
|
||||
|
@ -742,7 +742,7 @@ static ssize_t tap_get_user(struct tap_queue *q, void *msg_control,
|
||||
|
||||
/* Move network header to the right position for VLAN tagged packets */
|
||||
if (eth_type_vlan(skb->protocol) &&
|
||||
__vlan_get_protocol(skb, skb->protocol, &depth) != 0)
|
||||
vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
|
||||
skb_set_network_header(skb, depth);
|
||||
|
||||
/* copy skb_ubuf_info for callback when skb has no error */
|
||||
@ -1197,7 +1197,7 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp)
|
||||
|
||||
/* Move network header to the right position for VLAN tagged packets */
|
||||
if (eth_type_vlan(skb->protocol) &&
|
||||
__vlan_get_protocol(skb, skb->protocol, &depth) != 0)
|
||||
vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
|
||||
skb_set_network_header(skb, depth);
|
||||
|
||||
rcu_read_lock();
|
||||
|
@ -236,8 +236,9 @@ void dim_park_tired(struct dim *dim);
|
||||
*
|
||||
* Calculate the delta between two samples (in data rates).
|
||||
* Takes into consideration counter wrap-around.
|
||||
* Returned boolean indicates whether curr_stats are reliable.
|
||||
*/
|
||||
void dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
|
||||
bool dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
|
||||
struct dim_stats *curr_stats);
|
||||
|
||||
/**
|
||||
|
@ -637,6 +637,23 @@ static inline __be16 vlan_get_protocol(const struct sk_buff *skb)
|
||||
return __vlan_get_protocol(skb, skb->protocol, NULL);
|
||||
}
|
||||
|
||||
/* This version of __vlan_get_protocol() also pulls mac header in skb->head */
|
||||
static inline __be16 vlan_get_protocol_and_depth(struct sk_buff *skb,
|
||||
__be16 type, int *depth)
|
||||
{
|
||||
int maclen;
|
||||
|
||||
type = __vlan_get_protocol(skb, type, &maclen);
|
||||
|
||||
if (type) {
|
||||
if (!pskb_may_pull(skb, maclen))
|
||||
type = 0;
|
||||
else if (depth)
|
||||
*depth = maclen;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/* A getter for the SKB protocol field which will handle VLAN tags consistently
|
||||
* whether VLAN acceleration is enabled or not.
|
||||
*/
|
||||
|
@ -233,7 +233,7 @@ struct bonding {
|
||||
*/
|
||||
spinlock_t mode_lock;
|
||||
spinlock_t stats_lock;
|
||||
u8 send_peer_notif;
|
||||
u32 send_peer_notif;
|
||||
u8 igmp_retrans;
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct proc_dir_entry *proc_entry;
|
||||
|
@ -2718,7 +2718,7 @@ static inline void sock_recv_cmsgs(struct msghdr *msg, struct sock *sk,
|
||||
__sock_recv_cmsgs(msg, sk, skb);
|
||||
else if (unlikely(sock_flag(sk, SOCK_TIMESTAMP)))
|
||||
sock_write_timestamp(sk, skb->tstamp);
|
||||
else if (unlikely(sk->sk_stamp == SK_DEFAULT_STAMP))
|
||||
else if (unlikely(sock_read_timestamp(sk) == SK_DEFAULT_STAMP))
|
||||
sock_write_timestamp(sk, 0);
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ void dim_park_tired(struct dim *dim)
|
||||
}
|
||||
EXPORT_SYMBOL(dim_park_tired);
|
||||
|
||||
void dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
|
||||
bool dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
|
||||
struct dim_stats *curr_stats)
|
||||
{
|
||||
/* u32 holds up to 71 minutes, should be enough */
|
||||
@ -66,7 +66,7 @@ void dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
|
||||
start->comp_ctr);
|
||||
|
||||
if (!delta_us)
|
||||
return;
|
||||
return false;
|
||||
|
||||
curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us);
|
||||
curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us);
|
||||
@ -79,5 +79,6 @@ void dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
|
||||
else
|
||||
curr_stats->cpe_ratio = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(dim_calc_stats);
|
||||
|
@ -227,7 +227,8 @@ void net_dim(struct dim *dim, struct dim_sample end_sample)
|
||||
dim->start_sample.event_ctr);
|
||||
if (nevents < DIM_NEVENTS)
|
||||
break;
|
||||
dim_calc_stats(&dim->start_sample, &end_sample, &curr_stats);
|
||||
if (!dim_calc_stats(&dim->start_sample, &end_sample, &curr_stats))
|
||||
break;
|
||||
if (net_dim_decision(&curr_stats, dim)) {
|
||||
dim->state = DIM_APPLY_NEW_PROFILE;
|
||||
schedule_work(&dim->work);
|
||||
|
@ -88,7 +88,8 @@ void rdma_dim(struct dim *dim, u64 completions)
|
||||
nevents = curr_sample->event_ctr - dim->start_sample.event_ctr;
|
||||
if (nevents < DIM_NEVENTS)
|
||||
break;
|
||||
dim_calc_stats(&dim->start_sample, curr_sample, &curr_stats);
|
||||
if (!dim_calc_stats(&dim->start_sample, curr_sample, &curr_stats))
|
||||
break;
|
||||
if (rdma_dim_decision(&curr_stats, dim)) {
|
||||
dim->state = DIM_APPLY_NEW_PROFILE;
|
||||
schedule_work(&dim->work);
|
||||
|
@ -42,7 +42,7 @@ int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb
|
||||
eth_type_vlan(skb->protocol)) {
|
||||
int depth;
|
||||
|
||||
if (!__vlan_get_protocol(skb, skb->protocol, &depth))
|
||||
if (!vlan_get_protocol_and_depth(skb, skb->protocol, &depth))
|
||||
goto drop;
|
||||
|
||||
skb_set_network_header(skb, depth);
|
||||
|
@ -807,18 +807,21 @@ __poll_t datagram_poll(struct file *file, struct socket *sock,
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
__poll_t mask;
|
||||
u8 shutdown;
|
||||
|
||||
sock_poll_wait(file, sock, wait);
|
||||
mask = 0;
|
||||
|
||||
/* exceptional events? */
|
||||
if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue))
|
||||
if (READ_ONCE(sk->sk_err) ||
|
||||
!skb_queue_empty_lockless(&sk->sk_error_queue))
|
||||
mask |= EPOLLERR |
|
||||
(sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
|
||||
|
||||
if (sk->sk_shutdown & RCV_SHUTDOWN)
|
||||
shutdown = READ_ONCE(sk->sk_shutdown);
|
||||
if (shutdown & RCV_SHUTDOWN)
|
||||
mask |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM;
|
||||
if (sk->sk_shutdown == SHUTDOWN_MASK)
|
||||
if (shutdown == SHUTDOWN_MASK)
|
||||
mask |= EPOLLHUP;
|
||||
|
||||
/* readable? */
|
||||
@ -827,10 +830,12 @@ __poll_t datagram_poll(struct file *file, struct socket *sock,
|
||||
|
||||
/* Connection-based need to check for termination and startup */
|
||||
if (connection_based(sk)) {
|
||||
if (sk->sk_state == TCP_CLOSE)
|
||||
int state = READ_ONCE(sk->sk_state);
|
||||
|
||||
if (state == TCP_CLOSE)
|
||||
mask |= EPOLLHUP;
|
||||
/* connection hasn't started yet? */
|
||||
if (sk->sk_state == TCP_SYN_SENT)
|
||||
if (state == TCP_SYN_SENT)
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
@ -3335,7 +3335,7 @@ __be16 skb_network_protocol(struct sk_buff *skb, int *depth)
|
||||
type = eth->h_proto;
|
||||
}
|
||||
|
||||
return __vlan_get_protocol(skb, type, depth);
|
||||
return vlan_get_protocol_and_depth(skb, type, depth);
|
||||
}
|
||||
|
||||
/* openvswitch calls this on rx path, so we need a different check.
|
||||
|
@ -5298,7 +5298,7 @@ bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off)
|
||||
u32 csum_end = (u32)start + (u32)off + sizeof(__sum16);
|
||||
u32 csum_start = skb_headroom(skb) + (u32)start;
|
||||
|
||||
if (unlikely(csum_start > U16_MAX || csum_end > skb_headlen(skb))) {
|
||||
if (unlikely(csum_start >= U16_MAX || csum_end > skb_headlen(skb))) {
|
||||
net_warn_ratelimited("bad partial csum: csum=%u/%u headroom=%u headlen=%u\n",
|
||||
start, off, skb_headroom(skb), skb_headlen(skb));
|
||||
return false;
|
||||
@ -5306,7 +5306,7 @@ bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off)
|
||||
skb->ip_summed = CHECKSUM_PARTIAL;
|
||||
skb->csum_start = csum_start;
|
||||
skb->csum_offset = off;
|
||||
skb_set_transport_header(skb, start);
|
||||
skb->transport_header = csum_start;
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(skb_partial_csum_set);
|
||||
|
@ -73,8 +73,8 @@ int sk_stream_wait_connect(struct sock *sk, long *timeo_p)
|
||||
add_wait_queue(sk_sleep(sk), &wait);
|
||||
sk->sk_write_pending++;
|
||||
done = sk_wait_event(sk, timeo_p,
|
||||
!sk->sk_err &&
|
||||
!((1 << sk->sk_state) &
|
||||
!READ_ONCE(sk->sk_err) &&
|
||||
!((1 << READ_ONCE(sk->sk_state)) &
|
||||
~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)), &wait);
|
||||
remove_wait_queue(sk_sleep(sk), &wait);
|
||||
sk->sk_write_pending--;
|
||||
@ -87,9 +87,9 @@ EXPORT_SYMBOL(sk_stream_wait_connect);
|
||||
* sk_stream_closing - Return 1 if we still have things to send in our buffers.
|
||||
* @sk: socket to verify
|
||||
*/
|
||||
static inline int sk_stream_closing(struct sock *sk)
|
||||
static int sk_stream_closing(const struct sock *sk)
|
||||
{
|
||||
return (1 << sk->sk_state) &
|
||||
return (1 << READ_ONCE(sk->sk_state)) &
|
||||
(TCPF_FIN_WAIT1 | TCPF_CLOSING | TCPF_LAST_ACK);
|
||||
}
|
||||
|
||||
@ -142,8 +142,8 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p)
|
||||
|
||||
set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
|
||||
sk->sk_write_pending++;
|
||||
sk_wait_event(sk, ¤t_timeo, sk->sk_err ||
|
||||
(sk->sk_shutdown & SEND_SHUTDOWN) ||
|
||||
sk_wait_event(sk, ¤t_timeo, READ_ONCE(sk->sk_err) ||
|
||||
(READ_ONCE(sk->sk_shutdown) & SEND_SHUTDOWN) ||
|
||||
(sk_stream_memory_free(sk) &&
|
||||
!vm_wait), &wait);
|
||||
sk->sk_write_pending--;
|
||||
|
@ -894,7 +894,7 @@ int inet_shutdown(struct socket *sock, int how)
|
||||
EPOLLHUP, even on eg. unconnected UDP sockets -- RR */
|
||||
fallthrough;
|
||||
default:
|
||||
sk->sk_shutdown |= how;
|
||||
WRITE_ONCE(sk->sk_shutdown, sk->sk_shutdown | how);
|
||||
if (sk->sk_prot->shutdown)
|
||||
sk->sk_prot->shutdown(sk, how);
|
||||
break;
|
||||
|
@ -498,6 +498,7 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
|
||||
__poll_t mask;
|
||||
struct sock *sk = sock->sk;
|
||||
const struct tcp_sock *tp = tcp_sk(sk);
|
||||
u8 shutdown;
|
||||
int state;
|
||||
|
||||
sock_poll_wait(file, sock, wait);
|
||||
@ -540,9 +541,10 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
|
||||
* NOTE. Check for TCP_CLOSE is added. The goal is to prevent
|
||||
* blocking on fresh not-connected or disconnected socket. --ANK
|
||||
*/
|
||||
if (sk->sk_shutdown == SHUTDOWN_MASK || state == TCP_CLOSE)
|
||||
shutdown = READ_ONCE(sk->sk_shutdown);
|
||||
if (shutdown == SHUTDOWN_MASK || state == TCP_CLOSE)
|
||||
mask |= EPOLLHUP;
|
||||
if (sk->sk_shutdown & RCV_SHUTDOWN)
|
||||
if (shutdown & RCV_SHUTDOWN)
|
||||
mask |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
|
||||
|
||||
/* Connected or passive Fast Open socket? */
|
||||
@ -559,7 +561,7 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
|
||||
if (tcp_stream_is_readable(sk, target))
|
||||
mask |= EPOLLIN | EPOLLRDNORM;
|
||||
|
||||
if (!(sk->sk_shutdown & SEND_SHUTDOWN)) {
|
||||
if (!(shutdown & SEND_SHUTDOWN)) {
|
||||
if (__sk_stream_is_writeable(sk, 1)) {
|
||||
mask |= EPOLLOUT | EPOLLWRNORM;
|
||||
} else { /* send SIGIO later */
|
||||
@ -2867,7 +2869,7 @@ void __tcp_close(struct sock *sk, long timeout)
|
||||
int data_was_unread = 0;
|
||||
int state;
|
||||
|
||||
sk->sk_shutdown = SHUTDOWN_MASK;
|
||||
WRITE_ONCE(sk->sk_shutdown, SHUTDOWN_MASK);
|
||||
|
||||
if (sk->sk_state == TCP_LISTEN) {
|
||||
tcp_set_state(sk, TCP_CLOSE);
|
||||
@ -3119,7 +3121,7 @@ int tcp_disconnect(struct sock *sk, int flags)
|
||||
|
||||
inet_bhash2_reset_saddr(sk);
|
||||
|
||||
sk->sk_shutdown = 0;
|
||||
WRITE_ONCE(sk->sk_shutdown, 0);
|
||||
sock_reset_flag(sk, SOCK_DONE);
|
||||
tp->srtt_us = 0;
|
||||
tp->mdev_us = jiffies_to_usecs(TCP_TIMEOUT_INIT);
|
||||
@ -4649,7 +4651,7 @@ void tcp_done(struct sock *sk)
|
||||
if (req)
|
||||
reqsk_fastopen_remove(sk, req, false);
|
||||
|
||||
sk->sk_shutdown = SHUTDOWN_MASK;
|
||||
WRITE_ONCE(sk->sk_shutdown, SHUTDOWN_MASK);
|
||||
|
||||
if (!sock_flag(sk, SOCK_DEAD))
|
||||
sk->sk_state_change(sk);
|
||||
|
@ -168,7 +168,7 @@ static int tcp_msg_wait_data(struct sock *sk, struct sk_psock *psock,
|
||||
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
|
||||
ret = sk_wait_event(sk, &timeo,
|
||||
!list_empty(&psock->ingress_msg) ||
|
||||
!skb_queue_empty(&sk->sk_receive_queue), &wait);
|
||||
!skb_queue_empty_lockless(&sk->sk_receive_queue), &wait);
|
||||
sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
|
||||
remove_wait_queue(sk_sleep(sk), &wait);
|
||||
return ret;
|
||||
|
@ -4362,7 +4362,7 @@ void tcp_fin(struct sock *sk)
|
||||
|
||||
inet_csk_schedule_ack(sk);
|
||||
|
||||
sk->sk_shutdown |= RCV_SHUTDOWN;
|
||||
WRITE_ONCE(sk->sk_shutdown, sk->sk_shutdown | RCV_SHUTDOWN);
|
||||
sock_set_flag(sk, SOCK_DONE);
|
||||
|
||||
switch (sk->sk_state) {
|
||||
@ -6599,7 +6599,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
|
||||
break;
|
||||
|
||||
tcp_set_state(sk, TCP_FIN_WAIT2);
|
||||
sk->sk_shutdown |= SEND_SHUTDOWN;
|
||||
WRITE_ONCE(sk->sk_shutdown, sk->sk_shutdown | SEND_SHUTDOWN);
|
||||
|
||||
sk_dst_confirm(sk);
|
||||
|
||||
|
@ -583,7 +583,8 @@ static int llc_ui_wait_for_disc(struct sock *sk, long timeout)
|
||||
|
||||
add_wait_queue(sk_sleep(sk), &wait);
|
||||
while (1) {
|
||||
if (sk_wait_event(sk, &timeout, sk->sk_state == TCP_CLOSE, &wait))
|
||||
if (sk_wait_event(sk, &timeout,
|
||||
READ_ONCE(sk->sk_state) == TCP_CLOSE, &wait))
|
||||
break;
|
||||
rc = -ERESTARTSYS;
|
||||
if (signal_pending(current))
|
||||
@ -603,7 +604,8 @@ static bool llc_ui_wait_for_conn(struct sock *sk, long timeout)
|
||||
|
||||
add_wait_queue(sk_sleep(sk), &wait);
|
||||
while (1) {
|
||||
if (sk_wait_event(sk, &timeout, sk->sk_state != TCP_SYN_SENT, &wait))
|
||||
if (sk_wait_event(sk, &timeout,
|
||||
READ_ONCE(sk->sk_state) != TCP_SYN_SENT, &wait))
|
||||
break;
|
||||
if (signal_pending(current) || !timeout)
|
||||
break;
|
||||
@ -622,7 +624,7 @@ static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout)
|
||||
while (1) {
|
||||
rc = 0;
|
||||
if (sk_wait_event(sk, &timeout,
|
||||
(sk->sk_shutdown & RCV_SHUTDOWN) ||
|
||||
(READ_ONCE(sk->sk_shutdown) & RCV_SHUTDOWN) ||
|
||||
(!llc_data_accept_state(llc->state) &&
|
||||
!llc->remote_busy_flag &&
|
||||
!llc->p_flag), &wait))
|
||||
|
@ -711,9 +711,11 @@ void nf_conntrack_destroy(struct nf_conntrack *nfct)
|
||||
|
||||
rcu_read_lock();
|
||||
ct_hook = rcu_dereference(nf_ct_hook);
|
||||
BUG_ON(ct_hook == NULL);
|
||||
ct_hook->destroy(nfct);
|
||||
if (ct_hook)
|
||||
ct_hook->destroy(nfct);
|
||||
rcu_read_unlock();
|
||||
|
||||
WARN_ON(!ct_hook);
|
||||
}
|
||||
EXPORT_SYMBOL(nf_conntrack_destroy);
|
||||
|
||||
|
@ -1218,11 +1218,12 @@ static int __init nf_conntrack_standalone_init(void)
|
||||
nf_conntrack_htable_size_user = nf_conntrack_htable_size;
|
||||
#endif
|
||||
|
||||
nf_conntrack_init_end();
|
||||
|
||||
ret = register_pernet_subsys(&nf_conntrack_net_ops);
|
||||
if (ret < 0)
|
||||
goto out_pernet;
|
||||
|
||||
nf_conntrack_init_end();
|
||||
return 0;
|
||||
|
||||
out_pernet:
|
||||
|
@ -344,6 +344,12 @@ static void nft_netdev_event(unsigned long event, struct net_device *dev,
|
||||
return;
|
||||
}
|
||||
|
||||
/* UNREGISTER events are also happening on netns exit.
|
||||
*
|
||||
* Although nf_tables core releases all tables/chains, only this event
|
||||
* handler provides guarantee that hook->ops.dev is still accessible,
|
||||
* so we cannot skip exiting net namespaces.
|
||||
*/
|
||||
__nft_release_basechain(ctx);
|
||||
}
|
||||
|
||||
@ -362,9 +368,6 @@ static int nf_tables_netdev_event(struct notifier_block *this,
|
||||
event != NETDEV_CHANGENAME)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
if (!check_net(ctx.net))
|
||||
return NOTIFY_DONE;
|
||||
|
||||
nft_net = nft_pernet(ctx.net);
|
||||
mutex_lock(&nft_net->commit_mutex);
|
||||
list_for_each_entry(table, &nft_net->tables, list) {
|
||||
|
@ -1990,7 +1990,7 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
|
||||
|
||||
skb_free_datagram(sk, skb);
|
||||
|
||||
if (nlk->cb_running &&
|
||||
if (READ_ONCE(nlk->cb_running) &&
|
||||
atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2) {
|
||||
ret = netlink_dump(sk);
|
||||
if (ret) {
|
||||
@ -2302,7 +2302,7 @@ static int netlink_dump(struct sock *sk)
|
||||
if (cb->done)
|
||||
cb->done(cb);
|
||||
|
||||
nlk->cb_running = false;
|
||||
WRITE_ONCE(nlk->cb_running, false);
|
||||
module = cb->module;
|
||||
skb = cb->skb;
|
||||
mutex_unlock(nlk->cb_mutex);
|
||||
@ -2365,7 +2365,7 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
|
||||
goto error_put;
|
||||
}
|
||||
|
||||
nlk->cb_running = true;
|
||||
WRITE_ONCE(nlk->cb_running, true);
|
||||
nlk->dump_done_errno = INT_MAX;
|
||||
|
||||
mutex_unlock(nlk->cb_mutex);
|
||||
@ -2703,7 +2703,7 @@ static int netlink_native_seq_show(struct seq_file *seq, void *v)
|
||||
nlk->groups ? (u32)nlk->groups[0] : 0,
|
||||
sk_rmem_alloc_get(s),
|
||||
sk_wmem_alloc_get(s),
|
||||
nlk->cb_running,
|
||||
READ_ONCE(nlk->cb_running),
|
||||
refcount_read(&s->sk_refcnt),
|
||||
atomic_read(&s->sk_drops),
|
||||
sock_i_ino(s)
|
||||
|
@ -1934,10 +1934,8 @@ static void packet_parse_headers(struct sk_buff *skb, struct socket *sock)
|
||||
/* Move network header to the right position for VLAN tagged packets */
|
||||
if (likely(skb->dev->type == ARPHRD_ETHER) &&
|
||||
eth_type_vlan(skb->protocol) &&
|
||||
__vlan_get_protocol(skb, skb->protocol, &depth) != 0) {
|
||||
if (pskb_may_pull(skb, depth))
|
||||
skb_set_network_header(skb, depth);
|
||||
}
|
||||
vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
|
||||
skb_set_network_header(skb, depth);
|
||||
|
||||
skb_probe_transport_header(skb);
|
||||
}
|
||||
|
@ -67,8 +67,8 @@ static void smc_close_stream_wait(struct smc_sock *smc, long timeout)
|
||||
|
||||
rc = sk_wait_event(sk, &timeout,
|
||||
!smc_tx_prepared_sends(&smc->conn) ||
|
||||
sk->sk_err == ECONNABORTED ||
|
||||
sk->sk_err == ECONNRESET ||
|
||||
READ_ONCE(sk->sk_err) == ECONNABORTED ||
|
||||
READ_ONCE(sk->sk_err) == ECONNRESET ||
|
||||
smc->conn.killed,
|
||||
&wait);
|
||||
if (rc)
|
||||
|
@ -267,9 +267,9 @@ int smc_rx_wait(struct smc_sock *smc, long *timeo,
|
||||
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
|
||||
add_wait_queue(sk_sleep(sk), &wait);
|
||||
rc = sk_wait_event(sk, timeo,
|
||||
sk->sk_err ||
|
||||
READ_ONCE(sk->sk_err) ||
|
||||
cflags->peer_conn_abort ||
|
||||
sk->sk_shutdown & RCV_SHUTDOWN ||
|
||||
READ_ONCE(sk->sk_shutdown) & RCV_SHUTDOWN ||
|
||||
conn->killed ||
|
||||
fcrit(conn),
|
||||
&wait);
|
||||
|
@ -113,8 +113,8 @@ static int smc_tx_wait(struct smc_sock *smc, int flags)
|
||||
break; /* at least 1 byte of free & no urgent data */
|
||||
set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
|
||||
sk_wait_event(sk, &timeo,
|
||||
sk->sk_err ||
|
||||
(sk->sk_shutdown & SEND_SHUTDOWN) ||
|
||||
READ_ONCE(sk->sk_err) ||
|
||||
(READ_ONCE(sk->sk_shutdown) & SEND_SHUTDOWN) ||
|
||||
smc_cdc_rxed_any_close(conn) ||
|
||||
(atomic_read(&conn->sndbuf_space) &&
|
||||
!conn->urg_tx_pend),
|
||||
|
@ -2911,7 +2911,7 @@ static int do_recvmmsg(int fd, struct mmsghdr __user *mmsg,
|
||||
* error to return on the next call or if the
|
||||
* app asks about it using getsockopt(SO_ERROR).
|
||||
*/
|
||||
sock->sk->sk_err = -err;
|
||||
WRITE_ONCE(sock->sk->sk_err, -err);
|
||||
}
|
||||
out_put:
|
||||
fput_light(sock->file, fput_needed);
|
||||
|
@ -314,9 +314,9 @@ static void tsk_rej_rx_queue(struct sock *sk, int error)
|
||||
tipc_sk_respond(sk, skb, error);
|
||||
}
|
||||
|
||||
static bool tipc_sk_connected(struct sock *sk)
|
||||
static bool tipc_sk_connected(const struct sock *sk)
|
||||
{
|
||||
return sk->sk_state == TIPC_ESTABLISHED;
|
||||
return READ_ONCE(sk->sk_state) == TIPC_ESTABLISHED;
|
||||
}
|
||||
|
||||
/* tipc_sk_type_connectionless - check if the socket is datagram socket
|
||||
|
@ -111,7 +111,8 @@ int wait_on_pending_writer(struct sock *sk, long *timeo)
|
||||
break;
|
||||
}
|
||||
|
||||
if (sk_wait_event(sk, timeo, !sk->sk_write_pending, &wait))
|
||||
if (sk_wait_event(sk, timeo,
|
||||
!READ_ONCE(sk->sk_write_pending), &wait))
|
||||
break;
|
||||
}
|
||||
remove_wait_queue(sk_sleep(sk), &wait);
|
||||
|
@ -603,7 +603,7 @@ static void unix_release_sock(struct sock *sk, int embrion)
|
||||
/* Clear state */
|
||||
unix_state_lock(sk);
|
||||
sock_orphan(sk);
|
||||
sk->sk_shutdown = SHUTDOWN_MASK;
|
||||
WRITE_ONCE(sk->sk_shutdown, SHUTDOWN_MASK);
|
||||
path = u->path;
|
||||
u->path.dentry = NULL;
|
||||
u->path.mnt = NULL;
|
||||
@ -628,7 +628,7 @@ static void unix_release_sock(struct sock *sk, int embrion)
|
||||
if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) {
|
||||
unix_state_lock(skpair);
|
||||
/* No more writes */
|
||||
skpair->sk_shutdown = SHUTDOWN_MASK;
|
||||
WRITE_ONCE(skpair->sk_shutdown, SHUTDOWN_MASK);
|
||||
if (!skb_queue_empty(&sk->sk_receive_queue) || embrion)
|
||||
WRITE_ONCE(skpair->sk_err, ECONNRESET);
|
||||
unix_state_unlock(skpair);
|
||||
@ -1442,7 +1442,7 @@ static long unix_wait_for_peer(struct sock *other, long timeo)
|
||||
|
||||
sched = !sock_flag(other, SOCK_DEAD) &&
|
||||
!(other->sk_shutdown & RCV_SHUTDOWN) &&
|
||||
unix_recvq_full(other);
|
||||
unix_recvq_full_lockless(other);
|
||||
|
||||
unix_state_unlock(other);
|
||||
|
||||
@ -3008,7 +3008,7 @@ static int unix_shutdown(struct socket *sock, int mode)
|
||||
++mode;
|
||||
|
||||
unix_state_lock(sk);
|
||||
sk->sk_shutdown |= mode;
|
||||
WRITE_ONCE(sk->sk_shutdown, sk->sk_shutdown | mode);
|
||||
other = unix_peer(sk);
|
||||
if (other)
|
||||
sock_hold(other);
|
||||
@ -3028,7 +3028,7 @@ static int unix_shutdown(struct socket *sock, int mode)
|
||||
if (mode&SEND_SHUTDOWN)
|
||||
peer_mode |= RCV_SHUTDOWN;
|
||||
unix_state_lock(other);
|
||||
other->sk_shutdown |= peer_mode;
|
||||
WRITE_ONCE(other->sk_shutdown, other->sk_shutdown | peer_mode);
|
||||
unix_state_unlock(other);
|
||||
other->sk_state_change(other);
|
||||
if (peer_mode == SHUTDOWN_MASK)
|
||||
@ -3160,16 +3160,18 @@ static __poll_t unix_poll(struct file *file, struct socket *sock, poll_table *wa
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
__poll_t mask;
|
||||
u8 shutdown;
|
||||
|
||||
sock_poll_wait(file, sock, wait);
|
||||
mask = 0;
|
||||
shutdown = READ_ONCE(sk->sk_shutdown);
|
||||
|
||||
/* exceptional events? */
|
||||
if (READ_ONCE(sk->sk_err))
|
||||
mask |= EPOLLERR;
|
||||
if (sk->sk_shutdown == SHUTDOWN_MASK)
|
||||
if (shutdown == SHUTDOWN_MASK)
|
||||
mask |= EPOLLHUP;
|
||||
if (sk->sk_shutdown & RCV_SHUTDOWN)
|
||||
if (shutdown & RCV_SHUTDOWN)
|
||||
mask |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM;
|
||||
|
||||
/* readable? */
|
||||
@ -3203,9 +3205,11 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock,
|
||||
struct sock *sk = sock->sk, *other;
|
||||
unsigned int writable;
|
||||
__poll_t mask;
|
||||
u8 shutdown;
|
||||
|
||||
sock_poll_wait(file, sock, wait);
|
||||
mask = 0;
|
||||
shutdown = READ_ONCE(sk->sk_shutdown);
|
||||
|
||||
/* exceptional events? */
|
||||
if (READ_ONCE(sk->sk_err) ||
|
||||
@ -3213,9 +3217,9 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock,
|
||||
mask |= EPOLLERR |
|
||||
(sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
|
||||
|
||||
if (sk->sk_shutdown & RCV_SHUTDOWN)
|
||||
if (shutdown & RCV_SHUTDOWN)
|
||||
mask |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM;
|
||||
if (sk->sk_shutdown == SHUTDOWN_MASK)
|
||||
if (shutdown == SHUTDOWN_MASK)
|
||||
mask |= EPOLLHUP;
|
||||
|
||||
/* readable? */
|
||||
|
@ -6,6 +6,7 @@
|
||||
ALL_TESTS="
|
||||
prio
|
||||
arp_validate
|
||||
num_grat_arp
|
||||
"
|
||||
|
||||
REQUIRE_MZ=no
|
||||
@ -255,6 +256,55 @@ arp_validate()
|
||||
arp_validate_ns "active-backup"
|
||||
}
|
||||
|
||||
garp_test()
|
||||
{
|
||||
local param="$1"
|
||||
local active_slave exp_num real_num i
|
||||
RET=0
|
||||
|
||||
# create bond
|
||||
bond_reset "${param}"
|
||||
|
||||
bond_check_connection
|
||||
[ $RET -ne 0 ] && log_test "num_grat_arp" "$retmsg"
|
||||
|
||||
|
||||
# Add tc rules to count GARP number
|
||||
for i in $(seq 0 2); do
|
||||
tc -n ${g_ns} filter add dev s$i ingress protocol arp pref 1 handle 101 \
|
||||
flower skip_hw arp_op request arp_sip ${s_ip4} arp_tip ${s_ip4} action pass
|
||||
done
|
||||
|
||||
# Do failover
|
||||
active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave")
|
||||
ip -n ${s_ns} link set ${active_slave} down
|
||||
|
||||
exp_num=$(echo "${param}" | cut -f6 -d ' ')
|
||||
sleep $((exp_num + 2))
|
||||
|
||||
active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave")
|
||||
|
||||
# check result
|
||||
real_num=$(tc_rule_handle_stats_get "dev s${active_slave#eth} ingress" 101 ".packets" "-n ${g_ns}")
|
||||
if [ "${real_num}" -ne "${exp_num}" ]; then
|
||||
echo "$real_num garp packets sent on active slave ${active_slave}"
|
||||
RET=1
|
||||
fi
|
||||
|
||||
for i in $(seq 0 2); do
|
||||
tc -n ${g_ns} filter del dev s$i ingress
|
||||
done
|
||||
}
|
||||
|
||||
num_grat_arp()
|
||||
{
|
||||
local val
|
||||
for val in 10 20 30 50; do
|
||||
garp_test "mode active-backup miimon 100 num_grat_arp $val peer_notify_delay 1000"
|
||||
log_test "num_grat_arp" "active-backup miimon num_grat_arp $val"
|
||||
done
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
setup_prepare
|
||||
|
@ -61,6 +61,8 @@ server_create()
|
||||
ip -n ${g_ns} link set s${i} up
|
||||
ip -n ${g_ns} link set s${i} master br0
|
||||
ip -n ${s_ns} link set eth${i} master bond0
|
||||
|
||||
tc -n ${g_ns} qdisc add dev s${i} clsact
|
||||
done
|
||||
|
||||
ip -n ${s_ns} link set bond0 up
|
||||
|
@ -791,8 +791,9 @@ tc_rule_handle_stats_get()
|
||||
local id=$1; shift
|
||||
local handle=$1; shift
|
||||
local selector=${1:-.packets}; shift
|
||||
local netns=${1:-""}; shift
|
||||
|
||||
tc -j -s filter show $id \
|
||||
tc $netns -j -s filter show $id \
|
||||
| jq ".[] | select(.options.handle == $handle) | \
|
||||
.options.actions[0].stats$selector"
|
||||
}
|
||||
|
@ -188,6 +188,26 @@ if [ $? -ne 0 ]; then
|
||||
exit $ksft_skip
|
||||
fi
|
||||
|
||||
ip netns exec $ns2 nft -f - <<EOF
|
||||
table inet filter {
|
||||
counter ip4dscp0 { }
|
||||
counter ip4dscp3 { }
|
||||
|
||||
chain input {
|
||||
type filter hook input priority 0; policy accept;
|
||||
meta l4proto tcp goto {
|
||||
ip dscp cs3 counter name ip4dscp3 accept
|
||||
ip dscp 0 counter name ip4dscp0 accept
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "SKIP: Could not load nft ruleset"
|
||||
exit $ksft_skip
|
||||
fi
|
||||
|
||||
# test basic connectivity
|
||||
if ! ip netns exec $ns1 ping -c 1 -q 10.0.2.99 > /dev/null; then
|
||||
echo "ERROR: $ns1 cannot reach ns2" 1>&2
|
||||
@ -255,6 +275,60 @@ check_counters()
|
||||
fi
|
||||
}
|
||||
|
||||
check_dscp()
|
||||
{
|
||||
local what=$1
|
||||
local ok=1
|
||||
|
||||
local counter=$(ip netns exec $ns2 nft reset counter inet filter ip4dscp3 | grep packets)
|
||||
|
||||
local pc4=${counter%*bytes*}
|
||||
local pc4=${pc4#*packets}
|
||||
|
||||
local counter=$(ip netns exec $ns2 nft reset counter inet filter ip4dscp0 | grep packets)
|
||||
local pc4z=${counter%*bytes*}
|
||||
local pc4z=${pc4z#*packets}
|
||||
|
||||
case "$what" in
|
||||
"dscp_none")
|
||||
if [ $pc4 -gt 0 ] || [ $pc4z -eq 0 ]; then
|
||||
echo "FAIL: dscp counters do not match, expected dscp3 == 0, dscp0 > 0, but got $pc4,$pc4z" 1>&2
|
||||
ret=1
|
||||
ok=0
|
||||
fi
|
||||
;;
|
||||
"dscp_fwd")
|
||||
if [ $pc4 -eq 0 ] || [ $pc4z -eq 0 ]; then
|
||||
echo "FAIL: dscp counters do not match, expected dscp3 and dscp0 > 0 but got $pc4,$pc4z" 1>&2
|
||||
ret=1
|
||||
ok=0
|
||||
fi
|
||||
;;
|
||||
"dscp_ingress")
|
||||
if [ $pc4 -eq 0 ] || [ $pc4z -gt 0 ]; then
|
||||
echo "FAIL: dscp counters do not match, expected dscp3 > 0, dscp0 == 0 but got $pc4,$pc4z" 1>&2
|
||||
ret=1
|
||||
ok=0
|
||||
fi
|
||||
;;
|
||||
"dscp_egress")
|
||||
if [ $pc4 -eq 0 ] || [ $pc4z -gt 0 ]; then
|
||||
echo "FAIL: dscp counters do not match, expected dscp3 > 0, dscp0 == 0 but got $pc4,$pc4z" 1>&2
|
||||
ret=1
|
||||
ok=0
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "FAIL: Unknown DSCP check" 1>&2
|
||||
ret=1
|
||||
ok=0
|
||||
esac
|
||||
|
||||
if [ $ok -eq 1 ] ;then
|
||||
echo "PASS: $what: dscp packet counters match"
|
||||
fi
|
||||
}
|
||||
|
||||
check_transfer()
|
||||
{
|
||||
in=$1
|
||||
@ -286,17 +360,26 @@ test_tcp_forwarding_ip()
|
||||
ip netns exec $nsa nc -w 4 "$dstip" "$dstport" < "$nsin" > "$ns1out" &
|
||||
cpid=$!
|
||||
|
||||
sleep 3
|
||||
sleep 1
|
||||
|
||||
if ps -p $lpid > /dev/null;then
|
||||
prev="$(ls -l $ns1out $ns2out)"
|
||||
sleep 1
|
||||
|
||||
while [[ "$prev" != "$(ls -l $ns1out $ns2out)" ]]; do
|
||||
sleep 1;
|
||||
prev="$(ls -l $ns1out $ns2out)"
|
||||
done
|
||||
|
||||
if test -d /proc/"$lpid"/; then
|
||||
kill $lpid
|
||||
fi
|
||||
|
||||
if ps -p $cpid > /dev/null;then
|
||||
if test -d /proc/"$cpid"/; then
|
||||
kill $cpid
|
||||
fi
|
||||
|
||||
wait
|
||||
wait $lpid
|
||||
wait $cpid
|
||||
|
||||
if ! check_transfer "$nsin" "$ns2out" "ns1 -> ns2"; then
|
||||
lret=1
|
||||
@ -316,6 +399,51 @@ test_tcp_forwarding()
|
||||
return $?
|
||||
}
|
||||
|
||||
test_tcp_forwarding_set_dscp()
|
||||
{
|
||||
check_dscp "dscp_none"
|
||||
|
||||
ip netns exec $nsr1 nft -f - <<EOF
|
||||
table netdev dscpmangle {
|
||||
chain setdscp0 {
|
||||
type filter hook ingress device "veth0" priority 0; policy accept
|
||||
ip dscp set cs3
|
||||
}
|
||||
}
|
||||
EOF
|
||||
if [ $? -eq 0 ]; then
|
||||
test_tcp_forwarding_ip "$1" "$2" 10.0.2.99 12345
|
||||
check_dscp "dscp_ingress"
|
||||
|
||||
ip netns exec $nsr1 nft delete table netdev dscpmangle
|
||||
else
|
||||
echo "SKIP: Could not load netdev:ingress for veth0"
|
||||
fi
|
||||
|
||||
ip netns exec $nsr1 nft -f - <<EOF
|
||||
table netdev dscpmangle {
|
||||
chain setdscp0 {
|
||||
type filter hook egress device "veth1" priority 0; policy accept
|
||||
ip dscp set cs3
|
||||
}
|
||||
}
|
||||
EOF
|
||||
if [ $? -eq 0 ]; then
|
||||
test_tcp_forwarding_ip "$1" "$2" 10.0.2.99 12345
|
||||
check_dscp "dscp_egress"
|
||||
|
||||
ip netns exec $nsr1 nft flush table netdev dscpmangle
|
||||
else
|
||||
echo "SKIP: Could not load netdev:egress for veth1"
|
||||
fi
|
||||
|
||||
# partial. If flowtable really works, then both dscp-is-0 and dscp-is-cs3
|
||||
# counters should have seen packets (before and after ft offload kicks in).
|
||||
ip netns exec $nsr1 nft -a insert rule inet filter forward ip dscp set cs3
|
||||
test_tcp_forwarding_ip "$1" "$2" 10.0.2.99 12345
|
||||
check_dscp "dscp_fwd"
|
||||
}
|
||||
|
||||
test_tcp_forwarding_nat()
|
||||
{
|
||||
local lret
|
||||
@ -385,6 +513,11 @@ table ip nat {
|
||||
}
|
||||
EOF
|
||||
|
||||
if ! test_tcp_forwarding_set_dscp $ns1 $ns2 0 ""; then
|
||||
echo "FAIL: flow offload for ns1/ns2 with dscp update" 1>&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! test_tcp_forwarding_nat $ns1 $ns2 0 ""; then
|
||||
echo "FAIL: flow offload for ns1/ns2 with NAT" 1>&2
|
||||
ip netns exec $nsr1 nft list ruleset
|
||||
@ -489,8 +622,8 @@ ip -net $nsr1 addr add 10.0.1.1/24 dev veth0
|
||||
ip -net $nsr1 addr add dead:1::1/64 dev veth0
|
||||
ip -net $nsr1 link set up dev veth0
|
||||
|
||||
KEY_SHA="0x"$(ps -xaf | sha1sum | cut -d " " -f 1)
|
||||
KEY_AES="0x"$(ps -xaf | md5sum | cut -d " " -f 1)
|
||||
KEY_SHA="0x"$(ps -af | sha1sum | cut -d " " -f 1)
|
||||
KEY_AES="0x"$(ps -af | md5sum | cut -d " " -f 1)
|
||||
SPI1=$RANDOM
|
||||
SPI2=$RANDOM
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user