Networking fixes for 6.4-rc8, including fixes from ipsec, bpf,
mptcp and netfilter. Current release - regressions: - netfilter: add NFT_TRANS_PREPARE_ERROR to deal with bound set/chain - eth: mlx5e: - fix scheduling of IPsec ASO query while in atomic - free IRQ rmap and notifier on kernel shutdown Current release - new code bugs: - phy: manual remove LEDs to ensure correct ordering Previous releases - regressions: - mptcp: fix possible divide by zero in recvmsg() - dsa: revert "net: phy: dp83867: perform soft reset and retain established link" Previous releases - always broken: - sched: netem: acquire qdisc lock in netem_change() - bpf: - fix verifier id tracking of scalars on spill - fix NULL dereference on exceptions - accept function names that contain dots - netfilter: disallow element updates of bound anonymous sets - mptcp: ensure listener is unhashed before updating the sk status - xfrm: - add missed call to delete offloaded policies - fix inbound ipv4/udp/esp packets to UDPv6 dualstack sockets - selftests: fixes for FIPS mode - dsa: mt7530: fix multiple CPU ports, BPDU and LLDP handling - eth: sfc: use budget for TX completions Misc: - wifi: iwlwifi: add support for SO-F device with PCI id 0x7AF0 Signed-off-by: Paolo Abeni <pabeni@redhat.com> -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEEg1AjqC77wbdLX2LbKSR5jcyPE6QFAmSUZO0SHHBhYmVuaUBy ZWRoYXQuY29tAAoJECkkeY3MjxOkBjAP/RfTUYdlPqz9jSvz0HmQt2Er39HyVb9I pzEpJSQGfO+eyIrlxmleu8cAaW5HdvyfMcBgr04uh+Jf06s+VJrD95IO9zDHHKoC 86itYNKMS3fSt1ivzg49i5uq66MhjtAcfIOB9HMOAQ2Jd+DYlzyWOOHw28ZAxsBZ Q6TU97YEMuU4FdLkoKob1aVswC5cPxNx2IH9NagfbtijaYZqeN9ZX9EI5yMUyH8f 5gboqOhXUQK0MQLM5TFySHeoayyQ+tRBz24nF0/6lWiRr+xzMTEKdkFpRza7Mxzj S8NxN3C+zOf96gic6kYOXmM6y0sOlbwC9JoeWTp8Tuh6DEYi6xLC2XkiYJ51idZg PElgRpkM1ddqvvFWFgZlNik5z0vbGnJH7pt0VuOSNntxE60cdQwvWEOr09vvPcS5 0nMVD0uc8pds2h4hit+sdLltcVnOgoNUYr1/sI6oydofa1BrLnhFPF7z/gUs9foD NuCchiaBF11yBGKufcNBNEB4w35g3Kcu6TGhHb168OJi+UnSnwlI0Ccw7iO10pkv RjefhR60+wZC6+leo57nZeYqaLQJuALY0QYFsyeM+T0MGSYkbH24CmbNdSmO4MRr +VX2CwIqeIds4Hx31o0Feu+FaJqXw46/2nrSDxel/hlCJnGSMXZTw+b/4pFEHLP+ l71ijZpJqV1S =GH2b -----END PGP SIGNATURE----- Merge tag 'net-6.4-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net Pull networking fixes from Paolo Abeni: "Including fixes from ipsec, bpf, mptcp and netfilter. Current release - regressions: - netfilter: add NFT_TRANS_PREPARE_ERROR to deal with bound set/chain - eth: mlx5e: - fix scheduling of IPsec ASO query while in atomic - free IRQ rmap and notifier on kernel shutdown Current release - new code bugs: - phy: manual remove LEDs to ensure correct ordering Previous releases - regressions: - mptcp: fix possible divide by zero in recvmsg() - dsa: revert "net: phy: dp83867: perform soft reset and retain established link" Previous releases - always broken: - sched: netem: acquire qdisc lock in netem_change() - bpf: - fix verifier id tracking of scalars on spill - fix NULL dereference on exceptions - accept function names that contain dots - netfilter: disallow element updates of bound anonymous sets - mptcp: ensure listener is unhashed before updating the sk status - xfrm: - add missed call to delete offloaded policies - fix inbound ipv4/udp/esp packets to UDPv6 dualstack sockets - selftests: fixes for FIPS mode - dsa: mt7530: fix multiple CPU ports, BPDU and LLDP handling - eth: sfc: use budget for TX completions Misc: - wifi: iwlwifi: add support for SO-F device with PCI id 0x7AF0" * tag 'net-6.4-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (74 commits) revert "net: align SO_RCVMARK required privileges with SO_MARK" net: wwan: iosm: Convert single instance struct member to flexible array sch_netem: acquire qdisc lock in netem_change() selftests: forwarding: Fix race condition in mirror installation wifi: mac80211: report all unusable beacon frames mptcp: ensure listener is unhashed before updating the sk status mptcp: drop legacy code around RX EOF mptcp: consolidate fallback and non fallback state machine mptcp: fix possible list corruption on passive MPJ mptcp: fix possible divide by zero in recvmsg() mptcp: handle correctly disconnect() failures bpf: Force kprobe multi expected_attach_type for kprobe_multi link bpf/btf: Accept function names that contain dots Revert "net: phy: dp83867: perform soft reset and retain established link" net: mdio: fix the wrong parameters netfilter: nf_tables: Fix for deleting base chains with payload netfilter: nfnetlink_osf: fix module autoload netfilter: nf_tables: drop module reference after updating chain netfilter: nf_tables: disallow timeout for anonymous sets netfilter: nf_tables: disallow updates of anonymous sets ...
This commit is contained in:
commit
8a28a0b6f1
10
MAINTAINERS
10
MAINTAINERS
|
@ -9972,8 +9972,9 @@ M: Miquel Raynal <miquel.raynal@bootlin.com>
|
|||
L: linux-wpan@vger.kernel.org
|
||||
S: Maintained
|
||||
W: https://linux-wpan.org/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sschmidt/wpan.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sschmidt/wpan-next.git
|
||||
Q: https://patchwork.kernel.org/project/linux-wpan/list/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/wpan/wpan.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/wpan/wpan-next.git
|
||||
F: Documentation/networking/ieee802154.rst
|
||||
F: drivers/net/ieee802154/
|
||||
F: include/linux/ieee802154.h
|
||||
|
@ -13269,10 +13270,11 @@ F: drivers/memory/mtk-smi.c
|
|||
F: include/soc/mediatek/smi.h
|
||||
|
||||
MEDIATEK SWITCH DRIVER
|
||||
M: Sean Wang <sean.wang@mediatek.com>
|
||||
M: Arınç ÜNAL <arinc.unal@arinc9.com>
|
||||
M: Daniel Golle <daniel@makrotopia.org>
|
||||
M: Landen Chao <Landen.Chao@mediatek.com>
|
||||
M: DENG Qingfang <dqfext@gmail.com>
|
||||
M: Daniel Golle <daniel@makrotopia.org>
|
||||
M: Sean Wang <sean.wang@mediatek.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/dsa/mt7530-mdio.c
|
||||
|
|
|
@ -2570,7 +2570,7 @@ out_image:
|
|||
}
|
||||
|
||||
if (bpf_jit_enable > 1)
|
||||
bpf_jit_dump(prog->len, proglen, pass + 1, image);
|
||||
bpf_jit_dump(prog->len, proglen, pass + 1, rw_image);
|
||||
|
||||
if (image) {
|
||||
if (!prog->is_func || extra_pass) {
|
||||
|
|
|
@ -399,6 +399,20 @@ static void mt7530_pll_setup(struct mt7530_priv *priv)
|
|||
core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN);
|
||||
}
|
||||
|
||||
/* If port 6 is available as a CPU port, always prefer that as the default,
|
||||
* otherwise don't care.
|
||||
*/
|
||||
static struct dsa_port *
|
||||
mt753x_preferred_default_local_cpu_port(struct dsa_switch *ds)
|
||||
{
|
||||
struct dsa_port *cpu_dp = dsa_to_port(ds, 6);
|
||||
|
||||
if (dsa_port_is_cpu(cpu_dp))
|
||||
return cpu_dp;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Setup port 6 interface mode and TRGMII TX circuit */
|
||||
static int
|
||||
mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
|
||||
|
@ -985,6 +999,18 @@ unlock_exit:
|
|||
mutex_unlock(&priv->reg_mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
mt753x_trap_frames(struct mt7530_priv *priv)
|
||||
{
|
||||
/* Trap BPDUs to the CPU port(s) */
|
||||
mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK,
|
||||
MT753X_BPDU_CPU_ONLY);
|
||||
|
||||
/* Trap LLDP frames with :0E MAC DA to the CPU port(s) */
|
||||
mt7530_rmw(priv, MT753X_RGAC2, MT753X_R0E_PORT_FW_MASK,
|
||||
MT753X_R0E_PORT_FW(MT753X_BPDU_CPU_ONLY));
|
||||
}
|
||||
|
||||
static int
|
||||
mt753x_cpu_port_enable(struct dsa_switch *ds, int port)
|
||||
{
|
||||
|
@ -1007,9 +1033,16 @@ mt753x_cpu_port_enable(struct dsa_switch *ds, int port)
|
|||
UNU_FFP(BIT(port)));
|
||||
|
||||
/* Set CPU port number */
|
||||
if (priv->id == ID_MT7621)
|
||||
if (priv->id == ID_MT7530 || priv->id == ID_MT7621)
|
||||
mt7530_rmw(priv, MT7530_MFC, CPU_MASK, CPU_EN | CPU_PORT(port));
|
||||
|
||||
/* Add the CPU port to the CPU port bitmap for MT7531 and the switch on
|
||||
* the MT7988 SoC. Trapped frames will be forwarded to the CPU port that
|
||||
* is affine to the inbound user port.
|
||||
*/
|
||||
if (priv->id == ID_MT7531 || priv->id == ID_MT7988)
|
||||
mt7530_set(priv, MT7531_CFC, MT7531_CPU_PMAP(BIT(port)));
|
||||
|
||||
/* CPU port gets connected to all user ports of
|
||||
* the switch.
|
||||
*/
|
||||
|
@ -2255,6 +2288,8 @@ mt7530_setup(struct dsa_switch *ds)
|
|||
|
||||
priv->p6_interface = PHY_INTERFACE_MODE_NA;
|
||||
|
||||
mt753x_trap_frames(priv);
|
||||
|
||||
/* Enable and reset MIB counters */
|
||||
mt7530_mib_reset(ds);
|
||||
|
||||
|
@ -2352,17 +2387,9 @@ static int
|
|||
mt7531_setup_common(struct dsa_switch *ds)
|
||||
{
|
||||
struct mt7530_priv *priv = ds->priv;
|
||||
struct dsa_port *cpu_dp;
|
||||
int ret, i;
|
||||
|
||||
/* BPDU to CPU port */
|
||||
dsa_switch_for_each_cpu_port(cpu_dp, ds) {
|
||||
mt7530_rmw(priv, MT7531_CFC, MT7531_CPU_PMAP_MASK,
|
||||
BIT(cpu_dp->index));
|
||||
break;
|
||||
}
|
||||
mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK,
|
||||
MT753X_BPDU_CPU_ONLY);
|
||||
mt753x_trap_frames(priv);
|
||||
|
||||
/* Enable and reset MIB counters */
|
||||
mt7530_mib_reset(ds);
|
||||
|
@ -3085,6 +3112,7 @@ static int mt7988_setup(struct dsa_switch *ds)
|
|||
const struct dsa_switch_ops mt7530_switch_ops = {
|
||||
.get_tag_protocol = mtk_get_tag_protocol,
|
||||
.setup = mt753x_setup,
|
||||
.preferred_default_local_cpu_port = mt753x_preferred_default_local_cpu_port,
|
||||
.get_strings = mt7530_get_strings,
|
||||
.get_ethtool_stats = mt7530_get_ethtool_stats,
|
||||
.get_sset_count = mt7530_get_sset_count,
|
||||
|
|
|
@ -54,6 +54,7 @@ enum mt753x_id {
|
|||
#define MT7531_MIRROR_PORT_GET(x) (((x) >> 16) & MIRROR_MASK)
|
||||
#define MT7531_MIRROR_PORT_SET(x) (((x) & MIRROR_MASK) << 16)
|
||||
#define MT7531_CPU_PMAP_MASK GENMASK(7, 0)
|
||||
#define MT7531_CPU_PMAP(x) FIELD_PREP(MT7531_CPU_PMAP_MASK, x)
|
||||
|
||||
#define MT753X_MIRROR_REG(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
|
||||
MT7531_CFC : MT7530_MFC)
|
||||
|
@ -66,6 +67,11 @@ enum mt753x_id {
|
|||
#define MT753X_BPC 0x24
|
||||
#define MT753X_BPDU_PORT_FW_MASK GENMASK(2, 0)
|
||||
|
||||
/* Register for :03 and :0E MAC DA frame control */
|
||||
#define MT753X_RGAC2 0x2c
|
||||
#define MT753X_R0E_PORT_FW_MASK GENMASK(18, 16)
|
||||
#define MT753X_R0E_PORT_FW(x) FIELD_PREP(MT753X_R0E_PORT_FW_MASK, x)
|
||||
|
||||
enum mt753x_bpdu_port_fw {
|
||||
MT753X_BPDU_FOLLOW_MFC,
|
||||
MT753X_BPDU_CPU_EXCLUDE = 4,
|
||||
|
|
|
@ -1135,8 +1135,8 @@ static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter,
|
|||
eth_hdr_len = ntohs(skb->protocol) == ETH_P_8021Q ?
|
||||
VLAN_ETH_HLEN : ETH_HLEN;
|
||||
if (skb->len <= 60 &&
|
||||
(lancer_chip(adapter) || skb_vlan_tag_present(skb)) &&
|
||||
is_ipv4_pkt(skb)) {
|
||||
(lancer_chip(adapter) || BE3_chip(adapter) ||
|
||||
skb_vlan_tag_present(skb)) && is_ipv4_pkt(skb)) {
|
||||
ip = (struct iphdr *)ip_hdr(skb);
|
||||
pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len));
|
||||
}
|
||||
|
|
|
@ -54,6 +54,9 @@ static int phy_mode(enum dpmac_eth_if eth_if, phy_interface_t *if_mode)
|
|||
case DPMAC_ETH_IF_XFI:
|
||||
*if_mode = PHY_INTERFACE_MODE_10GBASER;
|
||||
break;
|
||||
case DPMAC_ETH_IF_CAUI:
|
||||
*if_mode = PHY_INTERFACE_MODE_25GBASER;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -79,6 +82,8 @@ static enum dpmac_eth_if dpmac_eth_if_mode(phy_interface_t if_mode)
|
|||
return DPMAC_ETH_IF_XFI;
|
||||
case PHY_INTERFACE_MODE_1000BASEX:
|
||||
return DPMAC_ETH_IF_1000BASEX;
|
||||
case PHY_INTERFACE_MODE_25GBASER:
|
||||
return DPMAC_ETH_IF_CAUI;
|
||||
default:
|
||||
return DPMAC_ETH_IF_MII;
|
||||
}
|
||||
|
@ -418,7 +423,7 @@ int dpaa2_mac_connect(struct dpaa2_mac *mac)
|
|||
|
||||
mac->phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE |
|
||||
MAC_10FD | MAC_100FD | MAC_1000FD | MAC_2500FD | MAC_5000FD |
|
||||
MAC_10000FD;
|
||||
MAC_10000FD | MAC_25000FD;
|
||||
|
||||
dpaa2_mac_set_supported_interfaces(mac);
|
||||
|
||||
|
|
|
@ -732,7 +732,8 @@ static void mlx5e_rx_compute_wqe_bulk_params(struct mlx5e_params *params,
|
|||
static int mlx5e_build_rq_frags_info(struct mlx5_core_dev *mdev,
|
||||
struct mlx5e_params *params,
|
||||
struct mlx5e_xsk_param *xsk,
|
||||
struct mlx5e_rq_frags_info *info)
|
||||
struct mlx5e_rq_frags_info *info,
|
||||
u32 *xdp_frag_size)
|
||||
{
|
||||
u32 byte_count = MLX5E_SW2HW_MTU(params, params->sw_mtu);
|
||||
int frag_size_max = DEFAULT_FRAG_SIZE;
|
||||
|
@ -845,6 +846,8 @@ out:
|
|||
|
||||
info->log_num_frags = order_base_2(info->num_frags);
|
||||
|
||||
*xdp_frag_size = info->num_frags > 1 && params->xdp_prog ? PAGE_SIZE : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -989,7 +992,8 @@ int mlx5e_build_rq_param(struct mlx5_core_dev *mdev,
|
|||
}
|
||||
default: /* MLX5_WQ_TYPE_CYCLIC */
|
||||
MLX5_SET(wq, wq, log_wq_sz, params->log_rq_mtu_frames);
|
||||
err = mlx5e_build_rq_frags_info(mdev, params, xsk, ¶m->frags_info);
|
||||
err = mlx5e_build_rq_frags_info(mdev, params, xsk, ¶m->frags_info,
|
||||
¶m->xdp_frag_size);
|
||||
if (err)
|
||||
return err;
|
||||
ndsegs = param->frags_info.num_frags;
|
||||
|
|
|
@ -24,6 +24,7 @@ struct mlx5e_rq_param {
|
|||
u32 rqc[MLX5_ST_SZ_DW(rqc)];
|
||||
struct mlx5_wq_param wq;
|
||||
struct mlx5e_rq_frags_info frags_info;
|
||||
u32 xdp_frag_size;
|
||||
};
|
||||
|
||||
struct mlx5e_sq_param {
|
||||
|
|
|
@ -2021,6 +2021,8 @@ void
|
|||
mlx5_tc_ct_delete_flow(struct mlx5_tc_ct_priv *priv,
|
||||
struct mlx5_flow_attr *attr)
|
||||
{
|
||||
if (!attr->ct_attr.ft) /* no ct action, return */
|
||||
return;
|
||||
if (!attr->ct_attr.nf_ft) /* means only ct clear action, and not ct_clear,ct() */
|
||||
return;
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ static int mlx5e_init_xsk_rq(struct mlx5e_channel *c,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
return xdp_rxq_info_reg(&rq->xdp_rxq, rq->netdev, rq_xdp_ix, 0);
|
||||
return xdp_rxq_info_reg(&rq->xdp_rxq, rq->netdev, rq_xdp_ix, c->napi.napi_id);
|
||||
}
|
||||
|
||||
static int mlx5e_open_xsk_rq(struct mlx5e_channel *c, struct mlx5e_params *params,
|
||||
|
|
|
@ -61,16 +61,19 @@ static void mlx5e_ipsec_handle_tx_limit(struct work_struct *_work)
|
|||
struct mlx5e_ipsec_sa_entry *sa_entry = dwork->sa_entry;
|
||||
struct xfrm_state *x = sa_entry->x;
|
||||
|
||||
spin_lock(&x->lock);
|
||||
if (sa_entry->attrs.drop)
|
||||
return;
|
||||
|
||||
spin_lock_bh(&x->lock);
|
||||
xfrm_state_check_expire(x);
|
||||
if (x->km.state == XFRM_STATE_EXPIRED) {
|
||||
sa_entry->attrs.drop = true;
|
||||
mlx5e_accel_ipsec_fs_modify(sa_entry);
|
||||
}
|
||||
spin_unlock(&x->lock);
|
||||
spin_unlock_bh(&x->lock);
|
||||
|
||||
if (sa_entry->attrs.drop)
|
||||
mlx5e_accel_ipsec_fs_modify(sa_entry);
|
||||
return;
|
||||
}
|
||||
spin_unlock_bh(&x->lock);
|
||||
|
||||
queue_delayed_work(sa_entry->ipsec->wq, &dwork->dwork,
|
||||
MLX5_IPSEC_RESCHED);
|
||||
|
@ -1040,11 +1043,17 @@ err_fs:
|
|||
return err;
|
||||
}
|
||||
|
||||
static void mlx5e_xfrm_free_policy(struct xfrm_policy *x)
|
||||
static void mlx5e_xfrm_del_policy(struct xfrm_policy *x)
|
||||
{
|
||||
struct mlx5e_ipsec_pol_entry *pol_entry = to_ipsec_pol_entry(x);
|
||||
|
||||
mlx5e_accel_ipsec_fs_del_pol(pol_entry);
|
||||
}
|
||||
|
||||
static void mlx5e_xfrm_free_policy(struct xfrm_policy *x)
|
||||
{
|
||||
struct mlx5e_ipsec_pol_entry *pol_entry = to_ipsec_pol_entry(x);
|
||||
|
||||
kfree(pol_entry);
|
||||
}
|
||||
|
||||
|
@ -1065,6 +1074,7 @@ static const struct xfrmdev_ops mlx5e_ipsec_packet_xfrmdev_ops = {
|
|||
|
||||
.xdo_dev_state_update_curlft = mlx5e_xfrm_update_curlft,
|
||||
.xdo_dev_policy_add = mlx5e_xfrm_add_policy,
|
||||
.xdo_dev_policy_delete = mlx5e_xfrm_del_policy,
|
||||
.xdo_dev_policy_free = mlx5e_xfrm_free_policy,
|
||||
};
|
||||
|
||||
|
|
|
@ -305,7 +305,17 @@ static void mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry,
|
|||
}
|
||||
|
||||
mlx5e_ipsec_build_accel_xfrm_attrs(sa_entry, &attrs);
|
||||
|
||||
/* It is safe to execute the modify below unlocked since the only flows
|
||||
* that could affect this HW object, are create, destroy and this work.
|
||||
*
|
||||
* Creation flow can't co-exist with this modify work, the destruction
|
||||
* flow would cancel this work, and this work is a single entity that
|
||||
* can't conflict with it self.
|
||||
*/
|
||||
spin_unlock_bh(&sa_entry->x->lock);
|
||||
mlx5_accel_esp_modify_xfrm(sa_entry, &attrs);
|
||||
spin_lock_bh(&sa_entry->x->lock);
|
||||
|
||||
data.data_offset_condition_operand =
|
||||
MLX5_IPSEC_ASO_REMOVE_FLOW_PKT_CNT_OFFSET;
|
||||
|
@ -431,7 +441,7 @@ static void mlx5e_ipsec_handle_event(struct work_struct *_work)
|
|||
aso = sa_entry->ipsec->aso;
|
||||
attrs = &sa_entry->attrs;
|
||||
|
||||
spin_lock(&sa_entry->x->lock);
|
||||
spin_lock_bh(&sa_entry->x->lock);
|
||||
ret = mlx5e_ipsec_aso_query(sa_entry, NULL);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
@ -447,7 +457,7 @@ static void mlx5e_ipsec_handle_event(struct work_struct *_work)
|
|||
mlx5e_ipsec_handle_limits(sa_entry);
|
||||
|
||||
unlock:
|
||||
spin_unlock(&sa_entry->x->lock);
|
||||
spin_unlock_bh(&sa_entry->x->lock);
|
||||
kfree(work);
|
||||
}
|
||||
|
||||
|
@ -596,7 +606,8 @@ int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry,
|
|||
do {
|
||||
ret = mlx5_aso_poll_cq(aso->aso, false);
|
||||
if (ret)
|
||||
usleep_range(2, 10);
|
||||
/* We are in atomic context */
|
||||
udelay(10);
|
||||
} while (ret && time_is_after_jiffies(expires));
|
||||
spin_unlock_bh(&aso->lock);
|
||||
return ret;
|
||||
|
|
|
@ -641,7 +641,7 @@ static void mlx5e_free_mpwqe_rq_drop_page(struct mlx5e_rq *rq)
|
|||
}
|
||||
|
||||
static int mlx5e_init_rxq_rq(struct mlx5e_channel *c, struct mlx5e_params *params,
|
||||
struct mlx5e_rq *rq)
|
||||
u32 xdp_frag_size, struct mlx5e_rq *rq)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = c->mdev;
|
||||
int err;
|
||||
|
@ -665,7 +665,8 @@ static int mlx5e_init_rxq_rq(struct mlx5e_channel *c, struct mlx5e_params *param
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
return xdp_rxq_info_reg(&rq->xdp_rxq, rq->netdev, rq->ix, c->napi.napi_id);
|
||||
return __xdp_rxq_info_reg(&rq->xdp_rxq, rq->netdev, rq->ix, c->napi.napi_id,
|
||||
xdp_frag_size);
|
||||
}
|
||||
|
||||
static int mlx5_rq_shampo_alloc(struct mlx5_core_dev *mdev,
|
||||
|
@ -2240,7 +2241,7 @@ static int mlx5e_open_rxq_rq(struct mlx5e_channel *c, struct mlx5e_params *param
|
|||
{
|
||||
int err;
|
||||
|
||||
err = mlx5e_init_rxq_rq(c, params, &c->rq);
|
||||
err = mlx5e_init_rxq_rq(c, params, rq_params->xdp_frag_size, &c->rq);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
|
|
@ -1439,6 +1439,7 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
|
|||
mlx5e_hairpin_flow_del(priv, flow);
|
||||
|
||||
free_flow_post_acts(flow);
|
||||
mlx5_tc_ct_delete_flow(get_ct_priv(flow->priv), attr);
|
||||
|
||||
kvfree(attr->parse_attr);
|
||||
kfree(flow->attr);
|
||||
|
|
|
@ -511,10 +511,11 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev,
|
|||
struct mlx5_flow_rule *dst;
|
||||
void *in_flow_context, *vlan;
|
||||
void *in_match_value;
|
||||
int reformat_id = 0;
|
||||
unsigned int inlen;
|
||||
int dst_cnt_size;
|
||||
u32 *in, action;
|
||||
void *in_dests;
|
||||
u32 *in;
|
||||
int err;
|
||||
|
||||
if (mlx5_set_extended_dest(dev, fte, &extended_dest))
|
||||
|
@ -553,22 +554,42 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev,
|
|||
|
||||
MLX5_SET(flow_context, in_flow_context, extended_destination,
|
||||
extended_dest);
|
||||
if (extended_dest) {
|
||||
u32 action;
|
||||
|
||||
action = fte->action.action &
|
||||
~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
|
||||
MLX5_SET(flow_context, in_flow_context, action, action);
|
||||
} else {
|
||||
MLX5_SET(flow_context, in_flow_context, action,
|
||||
fte->action.action);
|
||||
if (fte->action.pkt_reformat)
|
||||
MLX5_SET(flow_context, in_flow_context, packet_reformat_id,
|
||||
fte->action.pkt_reformat->id);
|
||||
action = fte->action.action;
|
||||
if (extended_dest)
|
||||
action &= ~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
|
||||
|
||||
MLX5_SET(flow_context, in_flow_context, action, action);
|
||||
|
||||
if (!extended_dest && fte->action.pkt_reformat) {
|
||||
struct mlx5_pkt_reformat *pkt_reformat = fte->action.pkt_reformat;
|
||||
|
||||
if (pkt_reformat->owner == MLX5_FLOW_RESOURCE_OWNER_SW) {
|
||||
reformat_id = mlx5_fs_dr_action_get_pkt_reformat_id(pkt_reformat);
|
||||
if (reformat_id < 0) {
|
||||
mlx5_core_err(dev,
|
||||
"Unsupported SW-owned pkt_reformat type (%d) in FW-owned table\n",
|
||||
pkt_reformat->reformat_type);
|
||||
err = reformat_id;
|
||||
goto err_out;
|
||||
}
|
||||
} else {
|
||||
reformat_id = fte->action.pkt_reformat->id;
|
||||
}
|
||||
}
|
||||
if (fte->action.modify_hdr)
|
||||
|
||||
MLX5_SET(flow_context, in_flow_context, packet_reformat_id, (u32)reformat_id);
|
||||
|
||||
if (fte->action.modify_hdr) {
|
||||
if (fte->action.modify_hdr->owner == MLX5_FLOW_RESOURCE_OWNER_SW) {
|
||||
mlx5_core_err(dev, "Can't use SW-owned modify_hdr in FW-owned table\n");
|
||||
err = -EOPNOTSUPP;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
MLX5_SET(flow_context, in_flow_context, modify_header_id,
|
||||
fte->action.modify_hdr->id);
|
||||
}
|
||||
|
||||
MLX5_SET(flow_context, in_flow_context, encrypt_decrypt_type,
|
||||
fte->action.crypto.type);
|
||||
|
@ -885,6 +906,8 @@ static int mlx5_cmd_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns,
|
|||
|
||||
pkt_reformat->id = MLX5_GET(alloc_packet_reformat_context_out,
|
||||
out, packet_reformat_id);
|
||||
pkt_reformat->owner = MLX5_FLOW_RESOURCE_OWNER_FW;
|
||||
|
||||
kfree(in);
|
||||
return err;
|
||||
}
|
||||
|
@ -969,6 +992,7 @@ static int mlx5_cmd_modify_header_alloc(struct mlx5_flow_root_namespace *ns,
|
|||
err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
|
||||
|
||||
modify_hdr->id = MLX5_GET(alloc_modify_header_context_out, out, modify_header_id);
|
||||
modify_hdr->owner = MLX5_FLOW_RESOURCE_OWNER_FW;
|
||||
kfree(in);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -54,8 +54,14 @@ struct mlx5_flow_definer {
|
|||
u32 id;
|
||||
};
|
||||
|
||||
enum mlx5_flow_resource_owner {
|
||||
MLX5_FLOW_RESOURCE_OWNER_FW,
|
||||
MLX5_FLOW_RESOURCE_OWNER_SW,
|
||||
};
|
||||
|
||||
struct mlx5_modify_hdr {
|
||||
enum mlx5_flow_namespace_type ns_type;
|
||||
enum mlx5_flow_resource_owner owner;
|
||||
union {
|
||||
struct mlx5_fs_dr_action action;
|
||||
u32 id;
|
||||
|
@ -65,6 +71,7 @@ struct mlx5_modify_hdr {
|
|||
struct mlx5_pkt_reformat {
|
||||
enum mlx5_flow_namespace_type ns_type;
|
||||
int reformat_type; /* from mlx5_ifc */
|
||||
enum mlx5_flow_resource_owner owner;
|
||||
union {
|
||||
struct mlx5_fs_dr_action action;
|
||||
u32 id;
|
||||
|
|
|
@ -126,14 +126,22 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void irq_release(struct mlx5_irq *irq)
|
||||
/* mlx5_system_free_irq - Free an IRQ
|
||||
* @irq: IRQ to free
|
||||
*
|
||||
* Free the IRQ and other resources such as rmap from the system.
|
||||
* BUT doesn't free or remove reference from mlx5.
|
||||
* This function is very important for the shutdown flow, where we need to
|
||||
* cleanup system resoruces but keep mlx5 objects alive,
|
||||
* see mlx5_irq_table_free_irqs().
|
||||
*/
|
||||
static void mlx5_system_free_irq(struct mlx5_irq *irq)
|
||||
{
|
||||
struct mlx5_irq_pool *pool = irq->pool;
|
||||
#ifdef CONFIG_RFS_ACCEL
|
||||
struct cpu_rmap *rmap;
|
||||
#endif
|
||||
|
||||
xa_erase(&pool->irqs, irq->pool_index);
|
||||
/* free_irq requires that affinity_hint and rmap will be cleared before
|
||||
* calling it. To satisfy this requirement, we call
|
||||
* irq_cpu_rmap_remove() to remove the notifier
|
||||
|
@ -145,10 +153,18 @@ static void irq_release(struct mlx5_irq *irq)
|
|||
irq_cpu_rmap_remove(rmap, irq->map.virq);
|
||||
#endif
|
||||
|
||||
free_cpumask_var(irq->mask);
|
||||
free_irq(irq->map.virq, &irq->nh);
|
||||
if (irq->map.index && pci_msix_can_alloc_dyn(pool->dev->pdev))
|
||||
pci_msix_free_irq(pool->dev->pdev, irq->map);
|
||||
}
|
||||
|
||||
static void irq_release(struct mlx5_irq *irq)
|
||||
{
|
||||
struct mlx5_irq_pool *pool = irq->pool;
|
||||
|
||||
xa_erase(&pool->irqs, irq->pool_index);
|
||||
mlx5_system_free_irq(irq);
|
||||
free_cpumask_var(irq->mask);
|
||||
kfree(irq);
|
||||
}
|
||||
|
||||
|
@ -565,15 +581,21 @@ void mlx5_irqs_release_vectors(struct mlx5_irq **irqs, int nirqs)
|
|||
int mlx5_irqs_request_vectors(struct mlx5_core_dev *dev, u16 *cpus, int nirqs,
|
||||
struct mlx5_irq **irqs, struct cpu_rmap **rmap)
|
||||
{
|
||||
struct mlx5_irq_table *table = mlx5_irq_table_get(dev);
|
||||
struct mlx5_irq_pool *pool = table->pcif_pool;
|
||||
struct irq_affinity_desc af_desc;
|
||||
struct mlx5_irq *irq;
|
||||
int offset = 1;
|
||||
int i;
|
||||
|
||||
if (!pool->xa_num_irqs.max)
|
||||
offset = 0;
|
||||
|
||||
af_desc.is_managed = false;
|
||||
for (i = 0; i < nirqs; i++) {
|
||||
cpumask_clear(&af_desc.mask);
|
||||
cpumask_set_cpu(cpus[i], &af_desc.mask);
|
||||
irq = mlx5_irq_request(dev, i + 1, &af_desc, rmap);
|
||||
irq = mlx5_irq_request(dev, i + offset, &af_desc, rmap);
|
||||
if (IS_ERR(irq))
|
||||
break;
|
||||
irqs[i] = irq;
|
||||
|
@ -699,7 +721,8 @@ static void mlx5_irq_pool_free_irqs(struct mlx5_irq_pool *pool)
|
|||
unsigned long index;
|
||||
|
||||
xa_for_each(&pool->irqs, index, irq)
|
||||
free_irq(irq->map.virq, &irq->nh);
|
||||
mlx5_system_free_irq(irq);
|
||||
|
||||
}
|
||||
|
||||
static void mlx5_irq_pools_free_irqs(struct mlx5_irq_table *table)
|
||||
|
|
|
@ -1421,9 +1421,13 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn,
|
|||
}
|
||||
case DR_ACTION_TYP_TNL_L3_TO_L2:
|
||||
{
|
||||
u8 hw_actions[DR_ACTION_CACHE_LINE_SIZE] = {};
|
||||
u8 *hw_actions;
|
||||
int ret;
|
||||
|
||||
hw_actions = kzalloc(DR_ACTION_CACHE_LINE_SIZE, GFP_KERNEL);
|
||||
if (!hw_actions)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = mlx5dr_ste_set_action_decap_l3_list(dmn->ste_ctx,
|
||||
data, data_sz,
|
||||
hw_actions,
|
||||
|
@ -1431,6 +1435,7 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn,
|
|||
&action->rewrite->num_of_actions);
|
||||
if (ret) {
|
||||
mlx5dr_dbg(dmn, "Failed creating decap l3 action list\n");
|
||||
kfree(hw_actions);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1440,6 +1445,7 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn,
|
|||
ret = mlx5dr_ste_alloc_modify_hdr(action);
|
||||
if (ret) {
|
||||
mlx5dr_dbg(dmn, "Failed preparing reformat data\n");
|
||||
kfree(hw_actions);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
|
@ -2129,6 +2135,11 @@ mlx5dr_action_create_aso(struct mlx5dr_domain *dmn, u32 obj_id,
|
|||
return action;
|
||||
}
|
||||
|
||||
u32 mlx5dr_action_get_pkt_reformat_id(struct mlx5dr_action *action)
|
||||
{
|
||||
return action->reformat->id;
|
||||
}
|
||||
|
||||
int mlx5dr_action_destroy(struct mlx5dr_action *action)
|
||||
{
|
||||
if (WARN_ON_ONCE(refcount_read(&action->refcount) > 1))
|
||||
|
|
|
@ -331,8 +331,16 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
|
|||
}
|
||||
|
||||
if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT) {
|
||||
bool is_decap = fte->action.pkt_reformat->reformat_type ==
|
||||
MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2;
|
||||
bool is_decap;
|
||||
|
||||
if (fte->action.pkt_reformat->owner == MLX5_FLOW_RESOURCE_OWNER_FW) {
|
||||
err = -EINVAL;
|
||||
mlx5dr_err(domain, "FW-owned reformat can't be used in SW rule\n");
|
||||
goto free_actions;
|
||||
}
|
||||
|
||||
is_decap = fte->action.pkt_reformat->reformat_type ==
|
||||
MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2;
|
||||
|
||||
if (is_decap)
|
||||
actions[num_actions++] =
|
||||
|
@ -661,6 +669,7 @@ static int mlx5_cmd_dr_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
pkt_reformat->owner = MLX5_FLOW_RESOURCE_OWNER_SW;
|
||||
pkt_reformat->action.dr_action = action;
|
||||
|
||||
return 0;
|
||||
|
@ -691,6 +700,7 @@ static int mlx5_cmd_dr_modify_header_alloc(struct mlx5_flow_root_namespace *ns,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
modify_hdr->owner = MLX5_FLOW_RESOURCE_OWNER_SW;
|
||||
modify_hdr->action.dr_action = action;
|
||||
|
||||
return 0;
|
||||
|
@ -816,6 +826,19 @@ static u32 mlx5_cmd_dr_get_capabilities(struct mlx5_flow_root_namespace *ns,
|
|||
return steering_caps;
|
||||
}
|
||||
|
||||
int mlx5_fs_dr_action_get_pkt_reformat_id(struct mlx5_pkt_reformat *pkt_reformat)
|
||||
{
|
||||
switch (pkt_reformat->reformat_type) {
|
||||
case MLX5_REFORMAT_TYPE_L2_TO_VXLAN:
|
||||
case MLX5_REFORMAT_TYPE_L2_TO_NVGRE:
|
||||
case MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL:
|
||||
case MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL:
|
||||
case MLX5_REFORMAT_TYPE_INSERT_HDR:
|
||||
return mlx5dr_action_get_pkt_reformat_id(pkt_reformat->action.dr_action);
|
||||
}
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
bool mlx5_fs_dr_is_supported(struct mlx5_core_dev *dev)
|
||||
{
|
||||
return mlx5dr_is_supported(dev);
|
||||
|
|
|
@ -38,6 +38,8 @@ struct mlx5_fs_dr_table {
|
|||
|
||||
bool mlx5_fs_dr_is_supported(struct mlx5_core_dev *dev);
|
||||
|
||||
int mlx5_fs_dr_action_get_pkt_reformat_id(struct mlx5_pkt_reformat *pkt_reformat);
|
||||
|
||||
const struct mlx5_flow_cmds *mlx5_fs_cmd_get_dr_cmds(void);
|
||||
|
||||
#else
|
||||
|
@ -47,6 +49,11 @@ static inline const struct mlx5_flow_cmds *mlx5_fs_cmd_get_dr_cmds(void)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static inline u32 mlx5_fs_dr_action_get_pkt_reformat_id(struct mlx5_pkt_reformat *pkt_reformat)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool mlx5_fs_dr_is_supported(struct mlx5_core_dev *dev)
|
||||
{
|
||||
return false;
|
||||
|
|
|
@ -150,6 +150,8 @@ mlx5dr_action_create_dest_match_range(struct mlx5dr_domain *dmn,
|
|||
|
||||
int mlx5dr_action_destroy(struct mlx5dr_action *action);
|
||||
|
||||
u32 mlx5dr_action_get_pkt_reformat_id(struct mlx5dr_action *action);
|
||||
|
||||
int mlx5dr_definer_get(struct mlx5dr_domain *dmn, u16 format_id,
|
||||
u8 *dw_selectors, u8 *byte_selectors,
|
||||
u8 *match_mask, u32 *definer_id);
|
||||
|
|
|
@ -582,8 +582,7 @@ qcaspi_spi_thread(void *data)
|
|||
while (!kthread_should_stop()) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
if ((qca->intr_req == qca->intr_svc) &&
|
||||
(qca->txr.skb[qca->txr.head] == NULL) &&
|
||||
(qca->sync == QCASPI_SYNC_READY))
|
||||
!qca->txr.skb[qca->txr.head])
|
||||
schedule();
|
||||
|
||||
set_current_state(TASK_RUNNING);
|
||||
|
|
|
@ -2950,7 +2950,7 @@ static u32 efx_ef10_extract_event_ts(efx_qword_t *event)
|
|||
return tstamp;
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
|
||||
{
|
||||
struct efx_nic *efx = channel->efx;
|
||||
|
@ -2958,13 +2958,14 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
|
|||
unsigned int tx_ev_desc_ptr;
|
||||
unsigned int tx_ev_q_label;
|
||||
unsigned int tx_ev_type;
|
||||
int work_done;
|
||||
u64 ts_part;
|
||||
|
||||
if (unlikely(READ_ONCE(efx->reset_pending)))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
if (unlikely(EFX_QWORD_FIELD(*event, ESF_DZ_TX_DROP_EVENT)))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
/* Get the transmit queue */
|
||||
tx_ev_q_label = EFX_QWORD_FIELD(*event, ESF_DZ_TX_QLABEL);
|
||||
|
@ -2973,8 +2974,7 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
|
|||
if (!tx_queue->timestamping) {
|
||||
/* Transmit completion */
|
||||
tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, ESF_DZ_TX_DESCR_INDX);
|
||||
efx_xmit_done(tx_queue, tx_ev_desc_ptr & tx_queue->ptr_mask);
|
||||
return;
|
||||
return efx_xmit_done(tx_queue, tx_ev_desc_ptr & tx_queue->ptr_mask);
|
||||
}
|
||||
|
||||
/* Transmit timestamps are only available for 8XXX series. They result
|
||||
|
@ -3000,6 +3000,7 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
|
|||
* fields in the event.
|
||||
*/
|
||||
tx_ev_type = EFX_QWORD_FIELD(*event, ESF_EZ_TX_SOFT1);
|
||||
work_done = 0;
|
||||
|
||||
switch (tx_ev_type) {
|
||||
case TX_TIMESTAMP_EVENT_TX_EV_COMPLETION:
|
||||
|
@ -3016,6 +3017,7 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
|
|||
tx_queue->completed_timestamp_major = ts_part;
|
||||
|
||||
efx_xmit_done_single(tx_queue);
|
||||
work_done = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -3026,6 +3028,8 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
|
|||
EFX_QWORD_VAL(*event));
|
||||
break;
|
||||
}
|
||||
|
||||
return work_done;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -3081,13 +3085,16 @@ static void efx_ef10_handle_driver_generated_event(struct efx_channel *channel,
|
|||
}
|
||||
}
|
||||
|
||||
#define EFX_NAPI_MAX_TX 512
|
||||
|
||||
static int efx_ef10_ev_process(struct efx_channel *channel, int quota)
|
||||
{
|
||||
struct efx_nic *efx = channel->efx;
|
||||
efx_qword_t event, *p_event;
|
||||
unsigned int read_ptr;
|
||||
int ev_code;
|
||||
int spent_tx = 0;
|
||||
int spent = 0;
|
||||
int ev_code;
|
||||
|
||||
if (quota <= 0)
|
||||
return spent;
|
||||
|
@ -3126,7 +3133,11 @@ static int efx_ef10_ev_process(struct efx_channel *channel, int quota)
|
|||
}
|
||||
break;
|
||||
case ESE_DZ_EV_CODE_TX_EV:
|
||||
efx_ef10_handle_tx_event(channel, &event);
|
||||
spent_tx += efx_ef10_handle_tx_event(channel, &event);
|
||||
if (spent_tx >= EFX_NAPI_MAX_TX) {
|
||||
spent = quota;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case ESE_DZ_EV_CODE_DRIVER_EV:
|
||||
efx_ef10_handle_driver_event(channel, &event);
|
||||
|
|
|
@ -253,6 +253,8 @@ static void ef100_ev_read_ack(struct efx_channel *channel)
|
|||
efx_reg(channel->efx, ER_GZ_EVQ_INT_PRIME));
|
||||
}
|
||||
|
||||
#define EFX_NAPI_MAX_TX 512
|
||||
|
||||
static int ef100_ev_process(struct efx_channel *channel, int quota)
|
||||
{
|
||||
struct efx_nic *efx = channel->efx;
|
||||
|
@ -260,6 +262,7 @@ static int ef100_ev_process(struct efx_channel *channel, int quota)
|
|||
bool evq_phase, old_evq_phase;
|
||||
unsigned int read_ptr;
|
||||
efx_qword_t *p_event;
|
||||
int spent_tx = 0;
|
||||
int spent = 0;
|
||||
bool ev_phase;
|
||||
int ev_type;
|
||||
|
@ -295,7 +298,9 @@ static int ef100_ev_process(struct efx_channel *channel, int quota)
|
|||
efx_mcdi_process_event(channel, p_event);
|
||||
break;
|
||||
case ESE_GZ_EF100_EV_TX_COMPLETION:
|
||||
ef100_ev_tx(channel, p_event);
|
||||
spent_tx += ef100_ev_tx(channel, p_event);
|
||||
if (spent_tx >= EFX_NAPI_MAX_TX)
|
||||
spent = quota;
|
||||
break;
|
||||
case ESE_GZ_EF100_EV_DRIVER:
|
||||
netif_info(efx, drv, efx->net_dev,
|
||||
|
|
|
@ -346,7 +346,7 @@ void ef100_tx_write(struct efx_tx_queue *tx_queue)
|
|||
ef100_tx_push_buffers(tx_queue);
|
||||
}
|
||||
|
||||
void ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event)
|
||||
int ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event)
|
||||
{
|
||||
unsigned int tx_done =
|
||||
EFX_QWORD_FIELD(*p_event, ESF_GZ_EV_TXCMPL_NUM_DESC);
|
||||
|
@ -357,7 +357,7 @@ void ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event)
|
|||
unsigned int tx_index = (tx_queue->read_count + tx_done - 1) &
|
||||
tx_queue->ptr_mask;
|
||||
|
||||
efx_xmit_done(tx_queue, tx_index);
|
||||
return efx_xmit_done(tx_queue, tx_index);
|
||||
}
|
||||
|
||||
/* Add a socket buffer to a TX queue
|
||||
|
|
|
@ -20,7 +20,7 @@ void ef100_tx_init(struct efx_tx_queue *tx_queue);
|
|||
void ef100_tx_write(struct efx_tx_queue *tx_queue);
|
||||
unsigned int ef100_tx_max_skb_descs(struct efx_nic *efx);
|
||||
|
||||
void ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event);
|
||||
int ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event);
|
||||
|
||||
netdev_tx_t ef100_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
|
||||
int __ef100_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb,
|
||||
|
|
|
@ -249,7 +249,7 @@ void efx_xmit_done_check_empty(struct efx_tx_queue *tx_queue)
|
|||
}
|
||||
}
|
||||
|
||||
void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
|
||||
int efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
|
||||
{
|
||||
unsigned int fill_level, pkts_compl = 0, bytes_compl = 0;
|
||||
unsigned int efv_pkts_compl = 0;
|
||||
|
@ -279,6 +279,8 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
|
|||
}
|
||||
|
||||
efx_xmit_done_check_empty(tx_queue);
|
||||
|
||||
return pkts_compl + efv_pkts_compl;
|
||||
}
|
||||
|
||||
/* Remove buffers put into a tx_queue for the current packet.
|
||||
|
|
|
@ -28,7 +28,7 @@ static inline bool efx_tx_buffer_in_use(struct efx_tx_buffer *buffer)
|
|||
}
|
||||
|
||||
void efx_xmit_done_check_empty(struct efx_tx_queue *tx_queue);
|
||||
void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
|
||||
int efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
|
||||
|
||||
void efx_enqueue_unwind(struct efx_tx_queue *tx_queue,
|
||||
unsigned int insert_count);
|
||||
|
|
|
@ -1348,3 +1348,5 @@ module_spi_driver(adf7242_driver);
|
|||
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
|
||||
MODULE_DESCRIPTION("ADF7242 IEEE802.15.4 Transceiver Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
MODULE_FIRMWARE(FIRMWARE);
|
||||
|
|
|
@ -685,7 +685,7 @@ static int hwsim_del_edge_nl(struct sk_buff *msg, struct genl_info *info)
|
|||
static int hwsim_set_edge_lqi(struct sk_buff *msg, struct genl_info *info)
|
||||
{
|
||||
struct nlattr *edge_attrs[MAC802154_HWSIM_EDGE_ATTR_MAX + 1];
|
||||
struct hwsim_edge_info *einfo;
|
||||
struct hwsim_edge_info *einfo, *einfo_old;
|
||||
struct hwsim_phy *phy_v0;
|
||||
struct hwsim_edge *e;
|
||||
u32 v0, v1;
|
||||
|
@ -723,8 +723,10 @@ static int hwsim_set_edge_lqi(struct sk_buff *msg, struct genl_info *info)
|
|||
list_for_each_entry_rcu(e, &phy_v0->edges, list) {
|
||||
if (e->endpoint->idx == v1) {
|
||||
einfo->lqi = lqi;
|
||||
rcu_assign_pointer(e->info, einfo);
|
||||
einfo_old = rcu_replace_pointer(e->info, einfo,
|
||||
lockdep_is_held(&hwsim_phys_lock));
|
||||
rcu_read_unlock();
|
||||
kfree_rcu(einfo_old, rcu);
|
||||
mutex_unlock(&hwsim_phys_lock);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -936,7 +936,7 @@ static int dp83867_phy_reset(struct phy_device *phydev)
|
|||
{
|
||||
int err;
|
||||
|
||||
err = phy_write(phydev, DP83867_CTRL, DP83867_SW_RESTART);
|
||||
err = phy_write(phydev, DP83867_CTRL, DP83867_SW_RESET);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
|
|
@ -1287,7 +1287,7 @@ EXPORT_SYMBOL_GPL(mdiobus_modify_changed);
|
|||
* @mask: bit mask of bits to clear
|
||||
* @set: bit mask of bits to set
|
||||
*/
|
||||
int mdiobus_c45_modify_changed(struct mii_bus *bus, int devad, int addr,
|
||||
int mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, int devad,
|
||||
u32 regnum, u16 mask, u16 set)
|
||||
{
|
||||
int err;
|
||||
|
|
|
@ -3021,6 +3021,15 @@ static int phy_led_blink_set(struct led_classdev *led_cdev,
|
|||
return err;
|
||||
}
|
||||
|
||||
static void phy_leds_unregister(struct phy_device *phydev)
|
||||
{
|
||||
struct phy_led *phyled;
|
||||
|
||||
list_for_each_entry(phyled, &phydev->leds, list) {
|
||||
led_classdev_unregister(&phyled->led_cdev);
|
||||
}
|
||||
}
|
||||
|
||||
static int of_phy_led(struct phy_device *phydev,
|
||||
struct device_node *led)
|
||||
{
|
||||
|
@ -3054,7 +3063,7 @@ static int of_phy_led(struct phy_device *phydev,
|
|||
init_data.fwnode = of_fwnode_handle(led);
|
||||
init_data.devname_mandatory = true;
|
||||
|
||||
err = devm_led_classdev_register_ext(dev, cdev, &init_data);
|
||||
err = led_classdev_register_ext(dev, cdev, &init_data);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -3083,6 +3092,7 @@ static int of_phy_leds(struct phy_device *phydev)
|
|||
err = of_phy_led(phydev, led);
|
||||
if (err) {
|
||||
of_node_put(led);
|
||||
phy_leds_unregister(phydev);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
@ -3305,6 +3315,9 @@ static int phy_remove(struct device *dev)
|
|||
|
||||
cancel_delayed_work_sync(&phydev->state_queue);
|
||||
|
||||
if (IS_ENABLED(CONFIG_PHYLIB_LEDS))
|
||||
phy_leds_unregister(phydev);
|
||||
|
||||
phydev->state = PHY_DOWN;
|
||||
|
||||
sfp_bus_del_upstream(phydev->sfp_bus);
|
||||
|
|
|
@ -548,6 +548,8 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
|
|||
IWL_DEV_INFO(0x54F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
|
||||
IWL_DEV_INFO(0x7A70, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
|
||||
IWL_DEV_INFO(0x7A70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
|
||||
IWL_DEV_INFO(0x7AF0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
|
||||
IWL_DEV_INFO(0x7AF0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
|
||||
|
||||
IWL_DEV_INFO(0x271C, 0x0214, iwl9260_2ac_cfg, iwl9260_1_name),
|
||||
IWL_DEV_INFO(0x7E40, 0x1691, iwl_cfg_ma_a0_gf4_a0, iwl_ax411_killer_1690s_name),
|
||||
|
|
|
@ -626,14 +626,12 @@ static void mux_dl_adb_decode(struct iosm_mux *ipc_mux,
|
|||
if (adth->signature != cpu_to_le32(IOSM_AGGR_MUX_SIG_ADTH))
|
||||
goto adb_decode_err;
|
||||
|
||||
if (le16_to_cpu(adth->table_length) < (sizeof(struct mux_adth) -
|
||||
sizeof(struct mux_adth_dg)))
|
||||
if (le16_to_cpu(adth->table_length) < sizeof(struct mux_adth))
|
||||
goto adb_decode_err;
|
||||
|
||||
/* Calculate the number of datagrams. */
|
||||
nr_of_dg = (le16_to_cpu(adth->table_length) -
|
||||
sizeof(struct mux_adth) +
|
||||
sizeof(struct mux_adth_dg)) /
|
||||
sizeof(struct mux_adth)) /
|
||||
sizeof(struct mux_adth_dg);
|
||||
|
||||
/* Is the datagram table empty ? */
|
||||
|
@ -649,7 +647,7 @@ static void mux_dl_adb_decode(struct iosm_mux *ipc_mux,
|
|||
}
|
||||
|
||||
/* New aggregated datagram table. */
|
||||
dg = &adth->dg;
|
||||
dg = adth->dg;
|
||||
if (mux_dl_process_dg(ipc_mux, adbh, dg, skb, if_id,
|
||||
nr_of_dg) < 0)
|
||||
goto adb_decode_err;
|
||||
|
@ -849,7 +847,7 @@ static void ipc_mux_ul_encode_adth(struct iosm_mux *ipc_mux,
|
|||
adth->if_id = i;
|
||||
adth->table_length = cpu_to_le16(adth_dg_size);
|
||||
adth_dg_size -= offsetof(struct mux_adth, dg);
|
||||
memcpy(&adth->dg, ul_adb->dg[i], adth_dg_size);
|
||||
memcpy(adth->dg, ul_adb->dg[i], adth_dg_size);
|
||||
ul_adb->if_cnt++;
|
||||
}
|
||||
|
||||
|
@ -1426,14 +1424,13 @@ static int ipc_mux_get_payload_from_adb(struct iosm_mux *ipc_mux,
|
|||
|
||||
if (adth->signature == cpu_to_le32(IOSM_AGGR_MUX_SIG_ADTH)) {
|
||||
nr_of_dg = (le16_to_cpu(adth->table_length) -
|
||||
sizeof(struct mux_adth) +
|
||||
sizeof(struct mux_adth_dg)) /
|
||||
sizeof(struct mux_adth)) /
|
||||
sizeof(struct mux_adth_dg);
|
||||
|
||||
if (nr_of_dg <= 0)
|
||||
return payload_size;
|
||||
|
||||
dg = &adth->dg;
|
||||
dg = adth->dg;
|
||||
|
||||
for (i = 0; i < nr_of_dg; i++, dg++) {
|
||||
if (le32_to_cpu(dg->datagram_index) <
|
||||
|
|
|
@ -161,7 +161,7 @@ struct mux_adth {
|
|||
u8 opt_ipv4v6;
|
||||
__le32 next_table_index;
|
||||
__le32 reserved2;
|
||||
struct mux_adth_dg dg;
|
||||
struct mux_adth_dg dg[];
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -762,3 +762,6 @@ EXPORT_SYMBOL(fdp_nci_remove);
|
|||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("NFC NCI driver for Intel Fields Peak NFC controller");
|
||||
MODULE_AUTHOR("Robert Dolca <robert.dolca@intel.com>");
|
||||
|
||||
MODULE_FIRMWARE(FDP_OTP_PATCH_NAME);
|
||||
MODULE_FIRMWARE(FDP_RAM_PATCH_NAME);
|
||||
|
|
|
@ -958,6 +958,14 @@ struct dsa_switch_ops {
|
|||
struct phy_device *phy);
|
||||
void (*port_disable)(struct dsa_switch *ds, int port);
|
||||
|
||||
/*
|
||||
* Compatibility between device trees defining multiple CPU ports and
|
||||
* drivers which are not OK to use by default the numerically smallest
|
||||
* CPU port of a switch for its local ports. This can return NULL,
|
||||
* meaning "don't know/don't care".
|
||||
*/
|
||||
struct dsa_port *(*preferred_default_local_cpu_port)(struct dsa_switch *ds);
|
||||
|
||||
/*
|
||||
* Port's MAC EEE settings
|
||||
*/
|
||||
|
|
|
@ -472,7 +472,8 @@ struct nft_set_ops {
|
|||
int (*init)(const struct nft_set *set,
|
||||
const struct nft_set_desc *desc,
|
||||
const struct nlattr * const nla[]);
|
||||
void (*destroy)(const struct nft_set *set);
|
||||
void (*destroy)(const struct nft_ctx *ctx,
|
||||
const struct nft_set *set);
|
||||
void (*gc_init)(const struct nft_set *set);
|
||||
|
||||
unsigned int elemsize;
|
||||
|
@ -809,6 +810,8 @@ int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set,
|
|||
struct nft_expr *expr_array[]);
|
||||
void nft_set_elem_destroy(const struct nft_set *set, void *elem,
|
||||
bool destroy_expr);
|
||||
void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
|
||||
const struct nft_set *set, void *elem);
|
||||
|
||||
/**
|
||||
* struct nft_set_gc_batch_head - nf_tables set garbage collection batch
|
||||
|
@ -901,6 +904,7 @@ struct nft_expr_type {
|
|||
|
||||
enum nft_trans_phase {
|
||||
NFT_TRANS_PREPARE,
|
||||
NFT_TRANS_PREPARE_ERROR,
|
||||
NFT_TRANS_ABORT,
|
||||
NFT_TRANS_COMMIT,
|
||||
NFT_TRANS_RELEASE
|
||||
|
@ -1009,7 +1013,10 @@ static inline struct nft_userdata *nft_userdata(const struct nft_rule *rule)
|
|||
return (void *)&rule->data[rule->dlen];
|
||||
}
|
||||
|
||||
void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule);
|
||||
void nft_rule_expr_activate(const struct nft_ctx *ctx, struct nft_rule *rule);
|
||||
void nft_rule_expr_deactivate(const struct nft_ctx *ctx, struct nft_rule *rule,
|
||||
enum nft_trans_phase phase);
|
||||
void nf_tables_rule_destroy(const struct nft_ctx *ctx, struct nft_rule *rule);
|
||||
|
||||
static inline void nft_set_elem_update_expr(const struct nft_set_ext *ext,
|
||||
struct nft_regs *regs,
|
||||
|
@ -1104,6 +1111,8 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
|
|||
const struct nft_set_iter *iter,
|
||||
struct nft_set_elem *elem);
|
||||
int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set);
|
||||
int nf_tables_bind_chain(const struct nft_ctx *ctx, struct nft_chain *chain);
|
||||
void nf_tables_unbind_chain(const struct nft_ctx *ctx, struct nft_chain *chain);
|
||||
|
||||
enum nft_chain_types {
|
||||
NFT_CHAIN_T_DEFAULT = 0,
|
||||
|
@ -1140,11 +1149,17 @@ int nft_chain_validate_dependency(const struct nft_chain *chain,
|
|||
int nft_chain_validate_hooks(const struct nft_chain *chain,
|
||||
unsigned int hook_flags);
|
||||
|
||||
static inline bool nft_chain_binding(const struct nft_chain *chain)
|
||||
{
|
||||
return chain->flags & NFT_CHAIN_BINDING;
|
||||
}
|
||||
|
||||
static inline bool nft_chain_is_bound(struct nft_chain *chain)
|
||||
{
|
||||
return (chain->flags & NFT_CHAIN_BINDING) && chain->bound;
|
||||
}
|
||||
|
||||
int nft_chain_add(struct nft_table *table, struct nft_chain *chain);
|
||||
void nft_chain_del(struct nft_chain *chain);
|
||||
void nf_tables_chain_destroy(struct nft_ctx *ctx);
|
||||
|
||||
|
@ -1558,6 +1573,7 @@ static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
|
|||
* struct nft_trans - nf_tables object update in transaction
|
||||
*
|
||||
* @list: used internally
|
||||
* @binding_list: list of objects with possible bindings
|
||||
* @msg_type: message type
|
||||
* @put_net: ctx->net needs to be put
|
||||
* @ctx: transaction context
|
||||
|
@ -1565,6 +1581,7 @@ static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
|
|||
*/
|
||||
struct nft_trans {
|
||||
struct list_head list;
|
||||
struct list_head binding_list;
|
||||
int msg_type;
|
||||
bool put_net;
|
||||
struct nft_ctx ctx;
|
||||
|
@ -1575,6 +1592,7 @@ struct nft_trans_rule {
|
|||
struct nft_rule *rule;
|
||||
struct nft_flow_rule *flow;
|
||||
u32 rule_id;
|
||||
bool bound;
|
||||
};
|
||||
|
||||
#define nft_trans_rule(trans) \
|
||||
|
@ -1583,6 +1601,8 @@ struct nft_trans_rule {
|
|||
(((struct nft_trans_rule *)trans->data)->flow)
|
||||
#define nft_trans_rule_id(trans) \
|
||||
(((struct nft_trans_rule *)trans->data)->rule_id)
|
||||
#define nft_trans_rule_bound(trans) \
|
||||
(((struct nft_trans_rule *)trans->data)->bound)
|
||||
|
||||
struct nft_trans_set {
|
||||
struct nft_set *set;
|
||||
|
@ -1607,15 +1627,19 @@ struct nft_trans_set {
|
|||
(((struct nft_trans_set *)trans->data)->gc_int)
|
||||
|
||||
struct nft_trans_chain {
|
||||
struct nft_chain *chain;
|
||||
bool update;
|
||||
char *name;
|
||||
struct nft_stats __percpu *stats;
|
||||
u8 policy;
|
||||
bool bound;
|
||||
u32 chain_id;
|
||||
struct nft_base_chain *basechain;
|
||||
struct list_head hook_list;
|
||||
};
|
||||
|
||||
#define nft_trans_chain(trans) \
|
||||
(((struct nft_trans_chain *)trans->data)->chain)
|
||||
#define nft_trans_chain_update(trans) \
|
||||
(((struct nft_trans_chain *)trans->data)->update)
|
||||
#define nft_trans_chain_name(trans) \
|
||||
|
@ -1624,6 +1648,8 @@ struct nft_trans_chain {
|
|||
(((struct nft_trans_chain *)trans->data)->stats)
|
||||
#define nft_trans_chain_policy(trans) \
|
||||
(((struct nft_trans_chain *)trans->data)->policy)
|
||||
#define nft_trans_chain_bound(trans) \
|
||||
(((struct nft_trans_chain *)trans->data)->bound)
|
||||
#define nft_trans_chain_id(trans) \
|
||||
(((struct nft_trans_chain *)trans->data)->chain_id)
|
||||
#define nft_trans_basechain(trans) \
|
||||
|
@ -1700,6 +1726,7 @@ static inline int nft_request_module(struct net *net, const char *fmt, ...) { re
|
|||
struct nftables_pernet {
|
||||
struct list_head tables;
|
||||
struct list_head commit_list;
|
||||
struct list_head binding_list;
|
||||
struct list_head module_list;
|
||||
struct list_head notify_list;
|
||||
struct mutex commit_mutex;
|
||||
|
|
|
@ -1054,6 +1054,7 @@ struct xfrm_offload {
|
|||
struct sec_path {
|
||||
int len;
|
||||
int olen;
|
||||
int verified_cnt;
|
||||
|
||||
struct xfrm_state *xvec[XFRM_MAX_DEPTH];
|
||||
struct xfrm_offload ovec[XFRM_MAX_OFFLOAD_DEPTH];
|
||||
|
|
|
@ -744,13 +744,12 @@ static bool btf_name_offset_valid(const struct btf *btf, u32 offset)
|
|||
return offset < btf->hdr.str_len;
|
||||
}
|
||||
|
||||
static bool __btf_name_char_ok(char c, bool first, bool dot_ok)
|
||||
static bool __btf_name_char_ok(char c, bool first)
|
||||
{
|
||||
if ((first ? !isalpha(c) :
|
||||
!isalnum(c)) &&
|
||||
c != '_' &&
|
||||
((c == '.' && !dot_ok) ||
|
||||
c != '.'))
|
||||
c != '.')
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -767,20 +766,20 @@ static const char *btf_str_by_offset(const struct btf *btf, u32 offset)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static bool __btf_name_valid(const struct btf *btf, u32 offset, bool dot_ok)
|
||||
static bool __btf_name_valid(const struct btf *btf, u32 offset)
|
||||
{
|
||||
/* offset must be valid */
|
||||
const char *src = btf_str_by_offset(btf, offset);
|
||||
const char *src_limit;
|
||||
|
||||
if (!__btf_name_char_ok(*src, true, dot_ok))
|
||||
if (!__btf_name_char_ok(*src, true))
|
||||
return false;
|
||||
|
||||
/* set a limit on identifier length */
|
||||
src_limit = src + KSYM_NAME_LEN;
|
||||
src++;
|
||||
while (*src && src < src_limit) {
|
||||
if (!__btf_name_char_ok(*src, false, dot_ok))
|
||||
if (!__btf_name_char_ok(*src, false))
|
||||
return false;
|
||||
src++;
|
||||
}
|
||||
|
@ -788,17 +787,14 @@ static bool __btf_name_valid(const struct btf *btf, u32 offset, bool dot_ok)
|
|||
return !*src;
|
||||
}
|
||||
|
||||
/* Only C-style identifier is permitted. This can be relaxed if
|
||||
* necessary.
|
||||
*/
|
||||
static bool btf_name_valid_identifier(const struct btf *btf, u32 offset)
|
||||
{
|
||||
return __btf_name_valid(btf, offset, false);
|
||||
return __btf_name_valid(btf, offset);
|
||||
}
|
||||
|
||||
static bool btf_name_valid_section(const struct btf *btf, u32 offset)
|
||||
{
|
||||
return __btf_name_valid(btf, offset, true);
|
||||
return __btf_name_valid(btf, offset);
|
||||
}
|
||||
|
||||
static const char *__btf_name_by_offset(const struct btf *btf, u32 offset)
|
||||
|
@ -4422,7 +4418,7 @@ static s32 btf_var_check_meta(struct btf_verifier_env *env,
|
|||
}
|
||||
|
||||
if (!t->name_off ||
|
||||
!__btf_name_valid(env->btf, t->name_off, true)) {
|
||||
!__btf_name_valid(env->btf, t->name_off)) {
|
||||
btf_verifier_log_type(env, t, "Invalid name");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -3440,6 +3440,11 @@ static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
|
|||
return prog->enforce_expected_attach_type &&
|
||||
prog->expected_attach_type != attach_type ?
|
||||
-EINVAL : 0;
|
||||
case BPF_PROG_TYPE_KPROBE:
|
||||
if (prog->expected_attach_type == BPF_TRACE_KPROBE_MULTI &&
|
||||
attach_type != BPF_TRACE_KPROBE_MULTI)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3868,6 +3868,9 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
|
|||
return err;
|
||||
}
|
||||
save_register_state(state, spi, reg, size);
|
||||
/* Break the relation on a narrowing spill. */
|
||||
if (fls64(reg->umax_value) > BITS_PER_BYTE * size)
|
||||
state->stack[spi].spilled_ptr.id = 0;
|
||||
} else if (!reg && !(off % BPF_REG_SIZE) && is_bpf_st_mem(insn) &&
|
||||
insn->imm != 0 && env->bpf_capable) {
|
||||
struct bpf_reg_state fake_reg = {};
|
||||
|
@ -17214,9 +17217,10 @@ static int jit_subprogs(struct bpf_verifier_env *env)
|
|||
}
|
||||
|
||||
/* finally lock prog and jit images for all functions and
|
||||
* populate kallsysm
|
||||
* populate kallsysm. Begin at the first subprogram, since
|
||||
* bpf_prog_load will add the kallsyms for the main program.
|
||||
*/
|
||||
for (i = 0; i < env->subprog_cnt; i++) {
|
||||
for (i = 1; i < env->subprog_cnt; i++) {
|
||||
bpf_prog_lock_ro(func[i]);
|
||||
bpf_prog_kallsyms_add(func[i]);
|
||||
}
|
||||
|
@ -17242,6 +17246,8 @@ static int jit_subprogs(struct bpf_verifier_env *env)
|
|||
prog->jited = 1;
|
||||
prog->bpf_func = func[0]->bpf_func;
|
||||
prog->jited_len = func[0]->jited_len;
|
||||
prog->aux->extable = func[0]->aux->extable;
|
||||
prog->aux->num_exentries = func[0]->aux->num_exentries;
|
||||
prog->aux->func = func;
|
||||
prog->aux->func_cnt = env->subprog_cnt;
|
||||
bpf_prog_jit_attempt_done(prog);
|
||||
|
|
|
@ -1362,12 +1362,6 @@ set_sndbuf:
|
|||
__sock_set_mark(sk, val);
|
||||
break;
|
||||
case SO_RCVMARK:
|
||||
if (!sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) &&
|
||||
!sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) {
|
||||
ret = -EPERM;
|
||||
break;
|
||||
}
|
||||
|
||||
sock_valbool_flag(sk, SOCK_RCVMARK, valbool);
|
||||
break;
|
||||
|
||||
|
|
|
@ -403,6 +403,24 @@ static int dsa_tree_setup_default_cpu(struct dsa_switch_tree *dst)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct dsa_port *
|
||||
dsa_switch_preferred_default_local_cpu_port(struct dsa_switch *ds)
|
||||
{
|
||||
struct dsa_port *cpu_dp;
|
||||
|
||||
if (!ds->ops->preferred_default_local_cpu_port)
|
||||
return NULL;
|
||||
|
||||
cpu_dp = ds->ops->preferred_default_local_cpu_port(ds);
|
||||
if (!cpu_dp)
|
||||
return NULL;
|
||||
|
||||
if (WARN_ON(!dsa_port_is_cpu(cpu_dp) || cpu_dp->ds != ds))
|
||||
return NULL;
|
||||
|
||||
return cpu_dp;
|
||||
}
|
||||
|
||||
/* Perform initial assignment of CPU ports to user ports and DSA links in the
|
||||
* fabric, giving preference to CPU ports local to each switch. Default to
|
||||
* using the first CPU port in the switch tree if the port does not have a CPU
|
||||
|
@ -410,12 +428,16 @@ static int dsa_tree_setup_default_cpu(struct dsa_switch_tree *dst)
|
|||
*/
|
||||
static int dsa_tree_setup_cpu_ports(struct dsa_switch_tree *dst)
|
||||
{
|
||||
struct dsa_port *cpu_dp, *dp;
|
||||
struct dsa_port *preferred_cpu_dp, *cpu_dp, *dp;
|
||||
|
||||
list_for_each_entry(cpu_dp, &dst->ports, list) {
|
||||
if (!dsa_port_is_cpu(cpu_dp))
|
||||
continue;
|
||||
|
||||
preferred_cpu_dp = dsa_switch_preferred_default_local_cpu_port(cpu_dp->ds);
|
||||
if (preferred_cpu_dp && preferred_cpu_dp != cpu_dp)
|
||||
continue;
|
||||
|
||||
/* Prefer a local CPU port */
|
||||
dsa_switch_for_each_port(dp, cpu_dp->ds) {
|
||||
/* Prefer the first local CPU port found */
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#define MAXNAME 32
|
||||
#define WPAN_PHY_ENTRY __array(char, wpan_phy_name, MAXNAME)
|
||||
#define WPAN_PHY_ASSIGN strlcpy(__entry->wpan_phy_name, \
|
||||
#define WPAN_PHY_ASSIGN strscpy(__entry->wpan_phy_name, \
|
||||
wpan_phy_name(wpan_phy), \
|
||||
MAXNAME)
|
||||
#define WPAN_PHY_PR_FMT "%s"
|
||||
|
|
|
@ -340,6 +340,9 @@ static int esp_xmit(struct xfrm_state *x, struct sk_buff *skb, netdev_features_
|
|||
|
||||
secpath_reset(skb);
|
||||
|
||||
if (skb_needs_linearize(skb, skb->dev->features) &&
|
||||
__skb_linearize(skb))
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -164,6 +164,7 @@ drop:
|
|||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm4_udp_encap_rcv);
|
||||
|
||||
int xfrm4_rcv(struct sk_buff *skb)
|
||||
{
|
||||
|
|
|
@ -374,6 +374,9 @@ static int esp6_xmit(struct xfrm_state *x, struct sk_buff *skb, netdev_features
|
|||
|
||||
secpath_reset(skb);
|
||||
|
||||
if (skb_needs_linearize(skb, skb->dev->features) &&
|
||||
__skb_linearize(skb))
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -86,6 +86,9 @@ int xfrm6_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
|
|||
__be32 *udpdata32;
|
||||
__u16 encap_type = up->encap_type;
|
||||
|
||||
if (skb->protocol == htons(ETH_P_IP))
|
||||
return xfrm4_udp_encap_rcv(sk, skb);
|
||||
|
||||
/* if this is not encapsulated socket, then just return now */
|
||||
if (!encap_type)
|
||||
return 1;
|
||||
|
|
|
@ -2110,7 +2110,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
|||
/* either the frame has been decrypted or will be dropped */
|
||||
status->flag |= RX_FLAG_DECRYPTED;
|
||||
|
||||
if (unlikely(ieee80211_is_beacon(fc) && result == RX_DROP_UNUSABLE &&
|
||||
if (unlikely(ieee80211_is_beacon(fc) && (result & RX_DROP_UNUSABLE) &&
|
||||
rx->sdata->dev))
|
||||
cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev,
|
||||
skb->data, skb->len);
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#define MAXNAME 32
|
||||
#define LOCAL_ENTRY __array(char, wpan_phy_name, MAXNAME)
|
||||
#define LOCAL_ASSIGN strlcpy(__entry->wpan_phy_name, \
|
||||
#define LOCAL_ASSIGN strscpy(__entry->wpan_phy_name, \
|
||||
wpan_phy_name(local->hw.phy), MAXNAME)
|
||||
#define LOCAL_PR_FMT "%s"
|
||||
#define LOCAL_PR_ARG __entry->wpan_phy_name
|
||||
|
|
|
@ -1047,6 +1047,7 @@ static int mptcp_pm_nl_create_listen_socket(struct sock *sk,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
inet_sk_state_store(newsk, TCP_LISTEN);
|
||||
err = kernel_listen(ssock, backlog);
|
||||
if (err)
|
||||
return err;
|
||||
|
|
|
@ -44,7 +44,7 @@ enum {
|
|||
static struct percpu_counter mptcp_sockets_allocated ____cacheline_aligned_in_smp;
|
||||
|
||||
static void __mptcp_destroy_sock(struct sock *sk);
|
||||
static void __mptcp_check_send_data_fin(struct sock *sk);
|
||||
static void mptcp_check_send_data_fin(struct sock *sk);
|
||||
|
||||
DEFINE_PER_CPU(struct mptcp_delegated_action, mptcp_delegated_actions);
|
||||
static struct net_device mptcp_napi_dev;
|
||||
|
@ -424,8 +424,7 @@ static bool mptcp_pending_data_fin_ack(struct sock *sk)
|
|||
{
|
||||
struct mptcp_sock *msk = mptcp_sk(sk);
|
||||
|
||||
return !__mptcp_check_fallback(msk) &&
|
||||
((1 << sk->sk_state) &
|
||||
return ((1 << sk->sk_state) &
|
||||
(TCPF_FIN_WAIT1 | TCPF_CLOSING | TCPF_LAST_ACK)) &&
|
||||
msk->write_seq == READ_ONCE(msk->snd_una);
|
||||
}
|
||||
|
@ -583,9 +582,6 @@ static bool mptcp_check_data_fin(struct sock *sk)
|
|||
u64 rcv_data_fin_seq;
|
||||
bool ret = false;
|
||||
|
||||
if (__mptcp_check_fallback(msk))
|
||||
return ret;
|
||||
|
||||
/* Need to ack a DATA_FIN received from a peer while this side
|
||||
* of the connection is in ESTABLISHED, FIN_WAIT1, or FIN_WAIT2.
|
||||
* msk->rcv_data_fin was set when parsing the incoming options
|
||||
|
@ -623,7 +619,8 @@ static bool mptcp_check_data_fin(struct sock *sk)
|
|||
}
|
||||
|
||||
ret = true;
|
||||
mptcp_send_ack(msk);
|
||||
if (!__mptcp_check_fallback(msk))
|
||||
mptcp_send_ack(msk);
|
||||
mptcp_close_wake_up(sk);
|
||||
}
|
||||
return ret;
|
||||
|
@ -850,12 +847,12 @@ static bool __mptcp_finish_join(struct mptcp_sock *msk, struct sock *ssk)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void __mptcp_flush_join_list(struct sock *sk)
|
||||
static void __mptcp_flush_join_list(struct sock *sk, struct list_head *join_list)
|
||||
{
|
||||
struct mptcp_subflow_context *tmp, *subflow;
|
||||
struct mptcp_sock *msk = mptcp_sk(sk);
|
||||
|
||||
list_for_each_entry_safe(subflow, tmp, &msk->join_list, node) {
|
||||
list_for_each_entry_safe(subflow, tmp, join_list, node) {
|
||||
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
|
||||
bool slow = lock_sock_fast(ssk);
|
||||
|
||||
|
@ -897,49 +894,6 @@ bool mptcp_schedule_work(struct sock *sk)
|
|||
return false;
|
||||
}
|
||||
|
||||
void mptcp_subflow_eof(struct sock *sk)
|
||||
{
|
||||
if (!test_and_set_bit(MPTCP_WORK_EOF, &mptcp_sk(sk)->flags))
|
||||
mptcp_schedule_work(sk);
|
||||
}
|
||||
|
||||
static void mptcp_check_for_eof(struct mptcp_sock *msk)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow;
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
int receivers = 0;
|
||||
|
||||
mptcp_for_each_subflow(msk, subflow)
|
||||
receivers += !subflow->rx_eof;
|
||||
if (receivers)
|
||||
return;
|
||||
|
||||
if (!(sk->sk_shutdown & RCV_SHUTDOWN)) {
|
||||
/* hopefully temporary hack: propagate shutdown status
|
||||
* to msk, when all subflows agree on it
|
||||
*/
|
||||
WRITE_ONCE(sk->sk_shutdown, sk->sk_shutdown | RCV_SHUTDOWN);
|
||||
|
||||
smp_mb__before_atomic(); /* SHUTDOWN must be visible first */
|
||||
sk->sk_data_ready(sk);
|
||||
}
|
||||
|
||||
switch (sk->sk_state) {
|
||||
case TCP_ESTABLISHED:
|
||||
inet_sk_state_store(sk, TCP_CLOSE_WAIT);
|
||||
break;
|
||||
case TCP_FIN_WAIT1:
|
||||
inet_sk_state_store(sk, TCP_CLOSING);
|
||||
break;
|
||||
case TCP_FIN_WAIT2:
|
||||
inet_sk_state_store(sk, TCP_CLOSE);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
mptcp_close_wake_up(sk);
|
||||
}
|
||||
|
||||
static struct sock *mptcp_subflow_recv_lookup(const struct mptcp_sock *msk)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow;
|
||||
|
@ -1609,7 +1563,7 @@ out:
|
|||
if (!mptcp_timer_pending(sk))
|
||||
mptcp_reset_timer(sk);
|
||||
if (do_check_data_fin)
|
||||
__mptcp_check_send_data_fin(sk);
|
||||
mptcp_check_send_data_fin(sk);
|
||||
}
|
||||
|
||||
static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk, bool first)
|
||||
|
@ -1727,7 +1681,13 @@ static int mptcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
|
|||
if (ret && ret != -EINPROGRESS && ret != -ERESTARTSYS && ret != -EINTR)
|
||||
*copied_syn = 0;
|
||||
} else if (ret && ret != -EINPROGRESS) {
|
||||
mptcp_disconnect(sk, 0);
|
||||
/* The disconnect() op called by tcp_sendmsg_fastopen()/
|
||||
* __inet_stream_connect() can fail, due to looking check,
|
||||
* see mptcp_disconnect().
|
||||
* Attempt it again outside the problematic scope.
|
||||
*/
|
||||
if (!mptcp_disconnect(sk, 0))
|
||||
sk->sk_socket->state = SS_UNCONNECTED;
|
||||
}
|
||||
inet_sk(sk)->defer_connect = 0;
|
||||
|
||||
|
@ -2158,9 +2118,6 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
|
|||
break;
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(MPTCP_WORK_EOF, &msk->flags))
|
||||
mptcp_check_for_eof(msk);
|
||||
|
||||
if (sk->sk_shutdown & RCV_SHUTDOWN) {
|
||||
/* race breaker: the shutdown could be after the
|
||||
* previous receive queue check
|
||||
|
@ -2389,7 +2346,10 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
|
|||
|
||||
need_push = (flags & MPTCP_CF_PUSH) && __mptcp_retransmit_pending_data(sk);
|
||||
if (!dispose_it) {
|
||||
tcp_disconnect(ssk, 0);
|
||||
/* The MPTCP code never wait on the subflow sockets, TCP-level
|
||||
* disconnect should never fail
|
||||
*/
|
||||
WARN_ON_ONCE(tcp_disconnect(ssk, 0));
|
||||
msk->subflow->state = SS_UNCONNECTED;
|
||||
mptcp_subflow_ctx_reset(subflow);
|
||||
release_sock(ssk);
|
||||
|
@ -2408,13 +2368,6 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
|
|||
kfree_rcu(subflow, rcu);
|
||||
} else {
|
||||
/* otherwise tcp will dispose of the ssk and subflow ctx */
|
||||
if (ssk->sk_state == TCP_LISTEN) {
|
||||
tcp_set_state(ssk, TCP_CLOSE);
|
||||
mptcp_subflow_queue_clean(sk, ssk);
|
||||
inet_csk_listen_stop(ssk);
|
||||
mptcp_event_pm_listener(ssk, MPTCP_EVENT_LISTENER_CLOSED);
|
||||
}
|
||||
|
||||
__tcp_close(ssk, 0);
|
||||
|
||||
/* close acquired an extra ref */
|
||||
|
@ -2671,16 +2624,12 @@ static void mptcp_worker(struct work_struct *work)
|
|||
if (unlikely((1 << state) & (TCPF_CLOSE | TCPF_LISTEN)))
|
||||
goto unlock;
|
||||
|
||||
mptcp_check_data_fin_ack(sk);
|
||||
|
||||
mptcp_check_fastclose(msk);
|
||||
|
||||
mptcp_pm_nl_work(msk);
|
||||
|
||||
if (test_and_clear_bit(MPTCP_WORK_EOF, &msk->flags))
|
||||
mptcp_check_for_eof(msk);
|
||||
|
||||
__mptcp_check_send_data_fin(sk);
|
||||
mptcp_check_send_data_fin(sk);
|
||||
mptcp_check_data_fin_ack(sk);
|
||||
mptcp_check_data_fin(sk);
|
||||
|
||||
if (test_and_clear_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags))
|
||||
|
@ -2812,13 +2761,19 @@ void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how)
|
|||
break;
|
||||
fallthrough;
|
||||
case TCP_SYN_SENT:
|
||||
tcp_disconnect(ssk, O_NONBLOCK);
|
||||
WARN_ON_ONCE(tcp_disconnect(ssk, O_NONBLOCK));
|
||||
break;
|
||||
default:
|
||||
if (__mptcp_check_fallback(mptcp_sk(sk))) {
|
||||
pr_debug("Fallback");
|
||||
ssk->sk_shutdown |= how;
|
||||
tcp_shutdown(ssk, how);
|
||||
|
||||
/* simulate the data_fin ack reception to let the state
|
||||
* machine move forward
|
||||
*/
|
||||
WRITE_ONCE(mptcp_sk(sk)->snd_una, mptcp_sk(sk)->snd_nxt);
|
||||
mptcp_schedule_work(sk);
|
||||
} else {
|
||||
pr_debug("Sending DATA_FIN on subflow %p", ssk);
|
||||
tcp_send_ack(ssk);
|
||||
|
@ -2858,7 +2813,7 @@ static int mptcp_close_state(struct sock *sk)
|
|||
return next & TCP_ACTION_FIN;
|
||||
}
|
||||
|
||||
static void __mptcp_check_send_data_fin(struct sock *sk)
|
||||
static void mptcp_check_send_data_fin(struct sock *sk)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow;
|
||||
struct mptcp_sock *msk = mptcp_sk(sk);
|
||||
|
@ -2876,19 +2831,6 @@ static void __mptcp_check_send_data_fin(struct sock *sk)
|
|||
|
||||
WRITE_ONCE(msk->snd_nxt, msk->write_seq);
|
||||
|
||||
/* fallback socket will not get data_fin/ack, can move to the next
|
||||
* state now
|
||||
*/
|
||||
if (__mptcp_check_fallback(msk)) {
|
||||
WRITE_ONCE(msk->snd_una, msk->write_seq);
|
||||
if ((1 << sk->sk_state) & (TCPF_CLOSING | TCPF_LAST_ACK)) {
|
||||
inet_sk_state_store(sk, TCP_CLOSE);
|
||||
mptcp_close_wake_up(sk);
|
||||
} else if (sk->sk_state == TCP_FIN_WAIT1) {
|
||||
inet_sk_state_store(sk, TCP_FIN_WAIT2);
|
||||
}
|
||||
}
|
||||
|
||||
mptcp_for_each_subflow(msk, subflow) {
|
||||
struct sock *tcp_sk = mptcp_subflow_tcp_sock(subflow);
|
||||
|
||||
|
@ -2908,7 +2850,7 @@ static void __mptcp_wr_shutdown(struct sock *sk)
|
|||
WRITE_ONCE(msk->write_seq, msk->write_seq + 1);
|
||||
WRITE_ONCE(msk->snd_data_fin_enable, 1);
|
||||
|
||||
__mptcp_check_send_data_fin(sk);
|
||||
mptcp_check_send_data_fin(sk);
|
||||
}
|
||||
|
||||
static void __mptcp_destroy_sock(struct sock *sk)
|
||||
|
@ -2953,10 +2895,24 @@ static __poll_t mptcp_check_readable(struct mptcp_sock *msk)
|
|||
return EPOLLIN | EPOLLRDNORM;
|
||||
}
|
||||
|
||||
static void mptcp_listen_inuse_dec(struct sock *sk)
|
||||
static void mptcp_check_listen_stop(struct sock *sk)
|
||||
{
|
||||
if (inet_sk_state_load(sk) == TCP_LISTEN)
|
||||
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
|
||||
struct sock *ssk;
|
||||
|
||||
if (inet_sk_state_load(sk) != TCP_LISTEN)
|
||||
return;
|
||||
|
||||
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
|
||||
ssk = mptcp_sk(sk)->first;
|
||||
if (WARN_ON_ONCE(!ssk || inet_sk_state_load(ssk) != TCP_LISTEN))
|
||||
return;
|
||||
|
||||
lock_sock_nested(ssk, SINGLE_DEPTH_NESTING);
|
||||
mptcp_subflow_queue_clean(sk, ssk);
|
||||
inet_csk_listen_stop(ssk);
|
||||
mptcp_event_pm_listener(ssk, MPTCP_EVENT_LISTENER_CLOSED);
|
||||
tcp_set_state(ssk, TCP_CLOSE);
|
||||
release_sock(ssk);
|
||||
}
|
||||
|
||||
bool __mptcp_close(struct sock *sk, long timeout)
|
||||
|
@ -2969,7 +2925,7 @@ bool __mptcp_close(struct sock *sk, long timeout)
|
|||
WRITE_ONCE(sk->sk_shutdown, SHUTDOWN_MASK);
|
||||
|
||||
if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) {
|
||||
mptcp_listen_inuse_dec(sk);
|
||||
mptcp_check_listen_stop(sk);
|
||||
inet_sk_state_store(sk, TCP_CLOSE);
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -3073,15 +3029,20 @@ static int mptcp_disconnect(struct sock *sk, int flags)
|
|||
{
|
||||
struct mptcp_sock *msk = mptcp_sk(sk);
|
||||
|
||||
/* Deny disconnect if other threads are blocked in sk_wait_event()
|
||||
* or inet_wait_for_connect().
|
||||
*/
|
||||
if (sk->sk_wait_pending)
|
||||
return -EBUSY;
|
||||
|
||||
/* We are on the fastopen error path. We can't call straight into the
|
||||
* subflows cleanup code due to lock nesting (we are already under
|
||||
* msk->firstsocket lock). Do nothing and leave the cleanup to the
|
||||
* caller.
|
||||
* msk->firstsocket lock).
|
||||
*/
|
||||
if (msk->fastopening)
|
||||
return 0;
|
||||
return -EBUSY;
|
||||
|
||||
mptcp_listen_inuse_dec(sk);
|
||||
mptcp_check_listen_stop(sk);
|
||||
inet_sk_state_store(sk, TCP_CLOSE);
|
||||
|
||||
mptcp_stop_timer(sk);
|
||||
|
@ -3140,6 +3101,7 @@ struct sock *mptcp_sk_clone_init(const struct sock *sk,
|
|||
inet_sk(nsk)->pinet6 = mptcp_inet6_sk(nsk);
|
||||
#endif
|
||||
|
||||
nsk->sk_wait_pending = 0;
|
||||
__mptcp_init_sock(nsk);
|
||||
|
||||
msk = mptcp_sk(nsk);
|
||||
|
@ -3327,9 +3289,14 @@ static void mptcp_release_cb(struct sock *sk)
|
|||
for (;;) {
|
||||
unsigned long flags = (msk->cb_flags & MPTCP_FLAGS_PROCESS_CTX_NEED) |
|
||||
msk->push_pending;
|
||||
struct list_head join_list;
|
||||
|
||||
if (!flags)
|
||||
break;
|
||||
|
||||
INIT_LIST_HEAD(&join_list);
|
||||
list_splice_init(&msk->join_list, &join_list);
|
||||
|
||||
/* the following actions acquire the subflow socket lock
|
||||
*
|
||||
* 1) can't be invoked in atomic scope
|
||||
|
@ -3340,8 +3307,9 @@ static void mptcp_release_cb(struct sock *sk)
|
|||
msk->push_pending = 0;
|
||||
msk->cb_flags &= ~flags;
|
||||
spin_unlock_bh(&sk->sk_lock.slock);
|
||||
|
||||
if (flags & BIT(MPTCP_FLUSH_JOIN_LIST))
|
||||
__mptcp_flush_join_list(sk);
|
||||
__mptcp_flush_join_list(sk, &join_list);
|
||||
if (flags & BIT(MPTCP_PUSH_PENDING))
|
||||
__mptcp_push_pending(sk, 0);
|
||||
if (flags & BIT(MPTCP_RETRANSMIT))
|
||||
|
|
|
@ -113,7 +113,6 @@
|
|||
/* MPTCP socket atomic flags */
|
||||
#define MPTCP_NOSPACE 1
|
||||
#define MPTCP_WORK_RTX 2
|
||||
#define MPTCP_WORK_EOF 3
|
||||
#define MPTCP_FALLBACK_DONE 4
|
||||
#define MPTCP_WORK_CLOSE_SUBFLOW 5
|
||||
|
||||
|
@ -476,14 +475,13 @@ struct mptcp_subflow_context {
|
|||
send_mp_fail : 1,
|
||||
send_fastclose : 1,
|
||||
send_infinite_map : 1,
|
||||
rx_eof : 1,
|
||||
remote_key_valid : 1, /* received the peer key from */
|
||||
disposable : 1, /* ctx can be free at ulp release time */
|
||||
stale : 1, /* unable to snd/rcv data, do not use for xmit */
|
||||
local_id_valid : 1, /* local_id is correctly initialized */
|
||||
valid_csum_seen : 1, /* at least one csum validated */
|
||||
is_mptfo : 1, /* subflow is doing TFO */
|
||||
__unused : 8;
|
||||
__unused : 9;
|
||||
enum mptcp_data_avail data_avail;
|
||||
u32 remote_nonce;
|
||||
u64 thmac;
|
||||
|
@ -720,7 +718,6 @@ static inline u64 mptcp_expand_seq(u64 old_seq, u64 cur_seq, bool use_64bit)
|
|||
void __mptcp_check_push(struct sock *sk, struct sock *ssk);
|
||||
void __mptcp_data_acked(struct sock *sk);
|
||||
void __mptcp_error_report(struct sock *sk);
|
||||
void mptcp_subflow_eof(struct sock *sk);
|
||||
bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq, bool use_64bit);
|
||||
static inline bool mptcp_data_fin_enabled(const struct mptcp_sock *msk)
|
||||
{
|
||||
|
|
|
@ -1749,14 +1749,16 @@ static void subflow_state_change(struct sock *sk)
|
|||
{
|
||||
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
||||
struct sock *parent = subflow->conn;
|
||||
struct mptcp_sock *msk;
|
||||
|
||||
__subflow_state_change(sk);
|
||||
|
||||
msk = mptcp_sk(parent);
|
||||
if (subflow_simultaneous_connect(sk)) {
|
||||
mptcp_propagate_sndbuf(parent, sk);
|
||||
mptcp_do_fallback(sk);
|
||||
mptcp_rcv_space_init(mptcp_sk(parent), sk);
|
||||
pr_fallback(mptcp_sk(parent));
|
||||
mptcp_rcv_space_init(msk, sk);
|
||||
pr_fallback(msk);
|
||||
subflow->conn_finished = 1;
|
||||
mptcp_set_connected(parent);
|
||||
}
|
||||
|
@ -1772,11 +1774,12 @@ static void subflow_state_change(struct sock *sk)
|
|||
|
||||
subflow_sched_work_if_closed(mptcp_sk(parent), sk);
|
||||
|
||||
if (__mptcp_check_fallback(mptcp_sk(parent)) &&
|
||||
!subflow->rx_eof && subflow_is_done(sk)) {
|
||||
subflow->rx_eof = 1;
|
||||
mptcp_subflow_eof(parent);
|
||||
}
|
||||
/* when the fallback subflow closes the rx side, trigger a 'dummy'
|
||||
* ingress data fin, so that the msk state will follow along
|
||||
*/
|
||||
if (__mptcp_check_fallback(msk) && subflow_is_done(sk) && msk->first == sk &&
|
||||
mptcp_update_rcv_data_fin(msk, READ_ONCE(msk->ack_seq), true))
|
||||
mptcp_schedule_work(parent);
|
||||
}
|
||||
|
||||
void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_ssk)
|
||||
|
|
|
@ -1207,6 +1207,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|||
skb->transport_header = skb->network_header;
|
||||
|
||||
skb_set_inner_ipproto(skb, next_protocol);
|
||||
skb_set_inner_mac_header(skb, skb_inner_network_offset(skb));
|
||||
|
||||
if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) {
|
||||
bool check = false;
|
||||
|
@ -1349,6 +1350,7 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|||
skb->transport_header = skb->network_header;
|
||||
|
||||
skb_set_inner_ipproto(skb, next_protocol);
|
||||
skb_set_inner_mac_header(skb, skb_inner_network_offset(skb));
|
||||
|
||||
if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) {
|
||||
bool check = false;
|
||||
|
|
|
@ -151,6 +151,7 @@ static struct nft_trans *nft_trans_alloc_gfp(const struct nft_ctx *ctx,
|
|||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD(&trans->list);
|
||||
INIT_LIST_HEAD(&trans->binding_list);
|
||||
trans->msg_type = msg_type;
|
||||
trans->ctx = *ctx;
|
||||
|
||||
|
@ -163,13 +164,20 @@ static struct nft_trans *nft_trans_alloc(const struct nft_ctx *ctx,
|
|||
return nft_trans_alloc_gfp(ctx, msg_type, size, GFP_KERNEL);
|
||||
}
|
||||
|
||||
static void nft_trans_destroy(struct nft_trans *trans)
|
||||
static void nft_trans_list_del(struct nft_trans *trans)
|
||||
{
|
||||
list_del(&trans->list);
|
||||
list_del(&trans->binding_list);
|
||||
}
|
||||
|
||||
static void nft_trans_destroy(struct nft_trans *trans)
|
||||
{
|
||||
nft_trans_list_del(trans);
|
||||
kfree(trans);
|
||||
}
|
||||
|
||||
static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set)
|
||||
static void __nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set,
|
||||
bool bind)
|
||||
{
|
||||
struct nftables_pernet *nft_net;
|
||||
struct net *net = ctx->net;
|
||||
|
@ -183,16 +191,80 @@ static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set)
|
|||
switch (trans->msg_type) {
|
||||
case NFT_MSG_NEWSET:
|
||||
if (nft_trans_set(trans) == set)
|
||||
nft_trans_set_bound(trans) = true;
|
||||
nft_trans_set_bound(trans) = bind;
|
||||
break;
|
||||
case NFT_MSG_NEWSETELEM:
|
||||
if (nft_trans_elem_set(trans) == set)
|
||||
nft_trans_elem_set_bound(trans) = true;
|
||||
nft_trans_elem_set_bound(trans) = bind;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set)
|
||||
{
|
||||
return __nft_set_trans_bind(ctx, set, true);
|
||||
}
|
||||
|
||||
static void nft_set_trans_unbind(const struct nft_ctx *ctx, struct nft_set *set)
|
||||
{
|
||||
return __nft_set_trans_bind(ctx, set, false);
|
||||
}
|
||||
|
||||
static void __nft_chain_trans_bind(const struct nft_ctx *ctx,
|
||||
struct nft_chain *chain, bool bind)
|
||||
{
|
||||
struct nftables_pernet *nft_net;
|
||||
struct net *net = ctx->net;
|
||||
struct nft_trans *trans;
|
||||
|
||||
if (!nft_chain_binding(chain))
|
||||
return;
|
||||
|
||||
nft_net = nft_pernet(net);
|
||||
list_for_each_entry_reverse(trans, &nft_net->commit_list, list) {
|
||||
switch (trans->msg_type) {
|
||||
case NFT_MSG_NEWCHAIN:
|
||||
if (nft_trans_chain(trans) == chain)
|
||||
nft_trans_chain_bound(trans) = bind;
|
||||
break;
|
||||
case NFT_MSG_NEWRULE:
|
||||
if (trans->ctx.chain == chain)
|
||||
nft_trans_rule_bound(trans) = bind;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void nft_chain_trans_bind(const struct nft_ctx *ctx,
|
||||
struct nft_chain *chain)
|
||||
{
|
||||
__nft_chain_trans_bind(ctx, chain, true);
|
||||
}
|
||||
|
||||
int nf_tables_bind_chain(const struct nft_ctx *ctx, struct nft_chain *chain)
|
||||
{
|
||||
if (!nft_chain_binding(chain))
|
||||
return 0;
|
||||
|
||||
if (nft_chain_binding(ctx->chain))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (chain->bound)
|
||||
return -EBUSY;
|
||||
|
||||
chain->bound = true;
|
||||
chain->use++;
|
||||
nft_chain_trans_bind(ctx, chain);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nf_tables_unbind_chain(const struct nft_ctx *ctx, struct nft_chain *chain)
|
||||
{
|
||||
__nft_chain_trans_bind(ctx, chain, false);
|
||||
}
|
||||
|
||||
static int nft_netdev_register_hooks(struct net *net,
|
||||
struct list_head *hook_list)
|
||||
{
|
||||
|
@ -292,6 +364,19 @@ static void nft_trans_commit_list_add_tail(struct net *net, struct nft_trans *tr
|
|||
{
|
||||
struct nftables_pernet *nft_net = nft_pernet(net);
|
||||
|
||||
switch (trans->msg_type) {
|
||||
case NFT_MSG_NEWSET:
|
||||
if (!nft_trans_set_update(trans) &&
|
||||
nft_set_is_anonymous(nft_trans_set(trans)))
|
||||
list_add_tail(&trans->binding_list, &nft_net->binding_list);
|
||||
break;
|
||||
case NFT_MSG_NEWCHAIN:
|
||||
if (!nft_trans_chain_update(trans) &&
|
||||
nft_chain_binding(nft_trans_chain(trans)))
|
||||
list_add_tail(&trans->binding_list, &nft_net->binding_list);
|
||||
break;
|
||||
}
|
||||
|
||||
list_add_tail(&trans->list, &nft_net->commit_list);
|
||||
}
|
||||
|
||||
|
@ -338,8 +423,9 @@ static struct nft_trans *nft_trans_chain_add(struct nft_ctx *ctx, int msg_type)
|
|||
ntohl(nla_get_be32(ctx->nla[NFTA_CHAIN_ID]));
|
||||
}
|
||||
}
|
||||
|
||||
nft_trans_chain(trans) = ctx->chain;
|
||||
nft_trans_commit_list_add_tail(ctx->net, trans);
|
||||
|
||||
return trans;
|
||||
}
|
||||
|
||||
|
@ -357,8 +443,7 @@ static int nft_delchain(struct nft_ctx *ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void nft_rule_expr_activate(const struct nft_ctx *ctx,
|
||||
struct nft_rule *rule)
|
||||
void nft_rule_expr_activate(const struct nft_ctx *ctx, struct nft_rule *rule)
|
||||
{
|
||||
struct nft_expr *expr;
|
||||
|
||||
|
@ -371,9 +456,8 @@ static void nft_rule_expr_activate(const struct nft_ctx *ctx,
|
|||
}
|
||||
}
|
||||
|
||||
static void nft_rule_expr_deactivate(const struct nft_ctx *ctx,
|
||||
struct nft_rule *rule,
|
||||
enum nft_trans_phase phase)
|
||||
void nft_rule_expr_deactivate(const struct nft_ctx *ctx, struct nft_rule *rule,
|
||||
enum nft_trans_phase phase)
|
||||
{
|
||||
struct nft_expr *expr;
|
||||
|
||||
|
@ -495,6 +579,58 @@ static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type,
|
|||
return __nft_trans_set_add(ctx, msg_type, set, NULL);
|
||||
}
|
||||
|
||||
static void nft_setelem_data_deactivate(const struct net *net,
|
||||
const struct nft_set *set,
|
||||
struct nft_set_elem *elem);
|
||||
|
||||
static int nft_mapelem_deactivate(const struct nft_ctx *ctx,
|
||||
struct nft_set *set,
|
||||
const struct nft_set_iter *iter,
|
||||
struct nft_set_elem *elem)
|
||||
{
|
||||
nft_setelem_data_deactivate(ctx->net, set, elem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nft_set_elem_catchall {
|
||||
struct list_head list;
|
||||
struct rcu_head rcu;
|
||||
void *elem;
|
||||
};
|
||||
|
||||
static void nft_map_catchall_deactivate(const struct nft_ctx *ctx,
|
||||
struct nft_set *set)
|
||||
{
|
||||
u8 genmask = nft_genmask_next(ctx->net);
|
||||
struct nft_set_elem_catchall *catchall;
|
||||
struct nft_set_elem elem;
|
||||
struct nft_set_ext *ext;
|
||||
|
||||
list_for_each_entry(catchall, &set->catchall_list, list) {
|
||||
ext = nft_set_elem_ext(set, catchall->elem);
|
||||
if (!nft_set_elem_active(ext, genmask))
|
||||
continue;
|
||||
|
||||
elem.priv = catchall->elem;
|
||||
nft_setelem_data_deactivate(ctx->net, set, &elem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void nft_map_deactivate(const struct nft_ctx *ctx, struct nft_set *set)
|
||||
{
|
||||
struct nft_set_iter iter = {
|
||||
.genmask = nft_genmask_next(ctx->net),
|
||||
.fn = nft_mapelem_deactivate,
|
||||
};
|
||||
|
||||
set->ops->walk(ctx, set, &iter);
|
||||
WARN_ON_ONCE(iter.err);
|
||||
|
||||
nft_map_catchall_deactivate(ctx, set);
|
||||
}
|
||||
|
||||
static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set)
|
||||
{
|
||||
int err;
|
||||
|
@ -503,6 +639,9 @@ static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set)
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
|
||||
nft_map_deactivate(ctx, set);
|
||||
|
||||
nft_deactivate_next(ctx->net, set);
|
||||
ctx->table->use--;
|
||||
|
||||
|
@ -2226,7 +2365,7 @@ static int nft_basechain_init(struct nft_base_chain *basechain, u8 family,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int nft_chain_add(struct nft_table *table, struct nft_chain *chain)
|
||||
int nft_chain_add(struct nft_table *table, struct nft_chain *chain)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -2528,6 +2667,8 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
|
|||
nft_trans_basechain(trans) = basechain;
|
||||
INIT_LIST_HEAD(&nft_trans_chain_hooks(trans));
|
||||
list_splice(&hook.list, &nft_trans_chain_hooks(trans));
|
||||
if (nla[NFTA_CHAIN_HOOK])
|
||||
module_put(hook.type->owner);
|
||||
|
||||
nft_trans_commit_list_add_tail(ctx->net, trans);
|
||||
|
||||
|
@ -2670,21 +2811,18 @@ static int nf_tables_newchain(struct sk_buff *skb, const struct nfnl_info *info,
|
|||
return nf_tables_addchain(&ctx, family, genmask, policy, flags, extack);
|
||||
}
|
||||
|
||||
static int nft_delchain_hook(struct nft_ctx *ctx, struct nft_chain *chain,
|
||||
static int nft_delchain_hook(struct nft_ctx *ctx,
|
||||
struct nft_base_chain *basechain,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
const struct nft_chain *chain = &basechain->chain;
|
||||
const struct nlattr * const *nla = ctx->nla;
|
||||
struct nft_chain_hook chain_hook = {};
|
||||
struct nft_base_chain *basechain;
|
||||
struct nft_hook *this, *hook;
|
||||
LIST_HEAD(chain_del_list);
|
||||
struct nft_trans *trans;
|
||||
int err;
|
||||
|
||||
if (!nft_is_base_chain(chain))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
basechain = nft_base_chain(chain);
|
||||
err = nft_chain_parse_hook(ctx->net, basechain, nla, &chain_hook,
|
||||
ctx->family, chain->flags, extack);
|
||||
if (err < 0)
|
||||
|
@ -2769,7 +2907,12 @@ static int nf_tables_delchain(struct sk_buff *skb, const struct nfnl_info *info,
|
|||
if (chain->flags & NFT_CHAIN_HW_OFFLOAD)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return nft_delchain_hook(&ctx, chain, extack);
|
||||
if (nft_is_base_chain(chain)) {
|
||||
struct nft_base_chain *basechain = nft_base_chain(chain);
|
||||
|
||||
if (nft_base_chain_netdev(table->family, basechain->ops.hooknum))
|
||||
return nft_delchain_hook(&ctx, basechain, extack);
|
||||
}
|
||||
}
|
||||
|
||||
if (info->nlh->nlmsg_flags & NLM_F_NONREC &&
|
||||
|
@ -3490,8 +3633,7 @@ err_fill_rule_info:
|
|||
return err;
|
||||
}
|
||||
|
||||
static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
|
||||
struct nft_rule *rule)
|
||||
void nf_tables_rule_destroy(const struct nft_ctx *ctx, struct nft_rule *rule)
|
||||
{
|
||||
struct nft_expr *expr, *next;
|
||||
|
||||
|
@ -3508,7 +3650,7 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
|
|||
kfree(rule);
|
||||
}
|
||||
|
||||
void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule)
|
||||
static void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule)
|
||||
{
|
||||
nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_RELEASE);
|
||||
nf_tables_rule_destroy(ctx, rule);
|
||||
|
@ -3596,12 +3738,6 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct nft_set_elem_catchall {
|
||||
struct list_head list;
|
||||
struct rcu_head rcu;
|
||||
void *elem;
|
||||
};
|
||||
|
||||
int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set)
|
||||
{
|
||||
u8 genmask = nft_genmask_next(ctx->net);
|
||||
|
@ -3844,7 +3980,7 @@ err_destroy_flow_rule:
|
|||
if (flow)
|
||||
nft_flow_rule_destroy(flow);
|
||||
err_release_rule:
|
||||
nft_rule_expr_deactivate(&ctx, rule, NFT_TRANS_PREPARE);
|
||||
nft_rule_expr_deactivate(&ctx, rule, NFT_TRANS_PREPARE_ERROR);
|
||||
nf_tables_rule_destroy(&ctx, rule);
|
||||
err_release_expr:
|
||||
for (i = 0; i < n; i++) {
|
||||
|
@ -4777,6 +4913,9 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
|
|||
if (!(flags & NFT_SET_TIMEOUT))
|
||||
return -EINVAL;
|
||||
|
||||
if (flags & NFT_SET_ANONYMOUS)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
err = nf_msecs_to_jiffies64(nla[NFTA_SET_TIMEOUT], &desc.timeout);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -4785,6 +4924,10 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
|
|||
if (nla[NFTA_SET_GC_INTERVAL] != NULL) {
|
||||
if (!(flags & NFT_SET_TIMEOUT))
|
||||
return -EINVAL;
|
||||
|
||||
if (flags & NFT_SET_ANONYMOUS)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
desc.gc_int = ntohl(nla_get_be32(nla[NFTA_SET_GC_INTERVAL]));
|
||||
}
|
||||
|
||||
|
@ -4831,6 +4974,9 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
|
|||
if (info->nlh->nlmsg_flags & NLM_F_REPLACE)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (nft_set_is_anonymous(set))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
err = nft_set_expr_alloc(&ctx, set, nla, exprs, &num_exprs, flags);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
@ -4934,7 +5080,7 @@ err_set_expr_alloc:
|
|||
for (i = 0; i < set->num_exprs; i++)
|
||||
nft_expr_destroy(&ctx, set->exprs[i]);
|
||||
err_set_destroy:
|
||||
ops->destroy(set);
|
||||
ops->destroy(&ctx, set);
|
||||
err_set_init:
|
||||
kfree(set->name);
|
||||
err_set_name:
|
||||
|
@ -4949,7 +5095,7 @@ static void nft_set_catchall_destroy(const struct nft_ctx *ctx,
|
|||
|
||||
list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
|
||||
list_del_rcu(&catchall->list);
|
||||
nft_set_elem_destroy(set, catchall->elem, true);
|
||||
nf_tables_set_elem_destroy(ctx, set, catchall->elem);
|
||||
kfree_rcu(catchall, rcu);
|
||||
}
|
||||
}
|
||||
|
@ -4964,7 +5110,7 @@ static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
|
|||
for (i = 0; i < set->num_exprs; i++)
|
||||
nft_expr_destroy(ctx, set->exprs[i]);
|
||||
|
||||
set->ops->destroy(set);
|
||||
set->ops->destroy(ctx, set);
|
||||
nft_set_catchall_destroy(ctx, set);
|
||||
kfree(set->name);
|
||||
kvfree(set);
|
||||
|
@ -5129,10 +5275,60 @@ static void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
|
|||
}
|
||||
}
|
||||
|
||||
static void nft_setelem_data_activate(const struct net *net,
|
||||
const struct nft_set *set,
|
||||
struct nft_set_elem *elem);
|
||||
|
||||
static int nft_mapelem_activate(const struct nft_ctx *ctx,
|
||||
struct nft_set *set,
|
||||
const struct nft_set_iter *iter,
|
||||
struct nft_set_elem *elem)
|
||||
{
|
||||
nft_setelem_data_activate(ctx->net, set, elem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nft_map_catchall_activate(const struct nft_ctx *ctx,
|
||||
struct nft_set *set)
|
||||
{
|
||||
u8 genmask = nft_genmask_next(ctx->net);
|
||||
struct nft_set_elem_catchall *catchall;
|
||||
struct nft_set_elem elem;
|
||||
struct nft_set_ext *ext;
|
||||
|
||||
list_for_each_entry(catchall, &set->catchall_list, list) {
|
||||
ext = nft_set_elem_ext(set, catchall->elem);
|
||||
if (!nft_set_elem_active(ext, genmask))
|
||||
continue;
|
||||
|
||||
elem.priv = catchall->elem;
|
||||
nft_setelem_data_activate(ctx->net, set, &elem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void nft_map_activate(const struct nft_ctx *ctx, struct nft_set *set)
|
||||
{
|
||||
struct nft_set_iter iter = {
|
||||
.genmask = nft_genmask_next(ctx->net),
|
||||
.fn = nft_mapelem_activate,
|
||||
};
|
||||
|
||||
set->ops->walk(ctx, set, &iter);
|
||||
WARN_ON_ONCE(iter.err);
|
||||
|
||||
nft_map_catchall_activate(ctx, set);
|
||||
}
|
||||
|
||||
void nf_tables_activate_set(const struct nft_ctx *ctx, struct nft_set *set)
|
||||
{
|
||||
if (nft_set_is_anonymous(set))
|
||||
if (nft_set_is_anonymous(set)) {
|
||||
if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
|
||||
nft_map_activate(ctx, set);
|
||||
|
||||
nft_clear(ctx->net, set);
|
||||
}
|
||||
|
||||
set->use++;
|
||||
}
|
||||
|
@ -5143,14 +5339,28 @@ void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set,
|
|||
enum nft_trans_phase phase)
|
||||
{
|
||||
switch (phase) {
|
||||
case NFT_TRANS_PREPARE:
|
||||
case NFT_TRANS_PREPARE_ERROR:
|
||||
nft_set_trans_unbind(ctx, set);
|
||||
if (nft_set_is_anonymous(set))
|
||||
nft_deactivate_next(ctx->net, set);
|
||||
|
||||
set->use--;
|
||||
break;
|
||||
case NFT_TRANS_PREPARE:
|
||||
if (nft_set_is_anonymous(set)) {
|
||||
if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
|
||||
nft_map_deactivate(ctx, set);
|
||||
|
||||
nft_deactivate_next(ctx->net, set);
|
||||
}
|
||||
set->use--;
|
||||
return;
|
||||
case NFT_TRANS_ABORT:
|
||||
case NFT_TRANS_RELEASE:
|
||||
if (nft_set_is_anonymous(set) &&
|
||||
set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
|
||||
nft_map_deactivate(ctx, set);
|
||||
|
||||
set->use--;
|
||||
fallthrough;
|
||||
default:
|
||||
|
@ -5903,6 +6113,7 @@ static void nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
|
|||
__nft_set_elem_expr_destroy(ctx, expr);
|
||||
}
|
||||
|
||||
/* Drop references and destroy. Called from gc, dynset and abort path. */
|
||||
void nft_set_elem_destroy(const struct nft_set *set, void *elem,
|
||||
bool destroy_expr)
|
||||
{
|
||||
|
@ -5924,11 +6135,11 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(nft_set_elem_destroy);
|
||||
|
||||
/* Only called from commit path, nft_setelem_data_deactivate() already deals
|
||||
* with the refcounting from the preparation phase.
|
||||
/* Destroy element. References have been already dropped in the preparation
|
||||
* path via nft_setelem_data_deactivate().
|
||||
*/
|
||||
static void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
|
||||
const struct nft_set *set, void *elem)
|
||||
void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
|
||||
const struct nft_set *set, void *elem)
|
||||
{
|
||||
struct nft_set_ext *ext = nft_set_elem_ext(set, elem);
|
||||
|
||||
|
@ -6491,19 +6702,19 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
|
|||
if (flags)
|
||||
*nft_set_ext_flags(ext) = flags;
|
||||
|
||||
if (obj) {
|
||||
*nft_set_ext_obj(ext) = obj;
|
||||
obj->use++;
|
||||
}
|
||||
if (ulen > 0) {
|
||||
if (nft_set_ext_check(&tmpl, NFT_SET_EXT_USERDATA, ulen) < 0) {
|
||||
err = -EINVAL;
|
||||
goto err_elem_userdata;
|
||||
goto err_elem_free;
|
||||
}
|
||||
udata = nft_set_ext_userdata(ext);
|
||||
udata->len = ulen - 1;
|
||||
nla_memcpy(&udata->data, nla[NFTA_SET_ELEM_USERDATA], ulen);
|
||||
}
|
||||
if (obj) {
|
||||
*nft_set_ext_obj(ext) = obj;
|
||||
obj->use++;
|
||||
}
|
||||
err = nft_set_elem_expr_setup(ctx, &tmpl, ext, expr_array, num_exprs);
|
||||
if (err < 0)
|
||||
goto err_elem_free;
|
||||
|
@ -6558,10 +6769,7 @@ err_set_full:
|
|||
err_element_clash:
|
||||
kfree(trans);
|
||||
err_elem_free:
|
||||
if (obj)
|
||||
obj->use--;
|
||||
err_elem_userdata:
|
||||
nf_tables_set_elem_destroy(ctx, set, elem.priv);
|
||||
nft_set_elem_destroy(set, elem.priv, true);
|
||||
err_parse_data:
|
||||
if (nla[NFTA_SET_ELEM_DATA] != NULL)
|
||||
nft_data_release(&elem.data.val, desc.type);
|
||||
|
@ -6605,7 +6813,8 @@ static int nf_tables_newsetelem(struct sk_buff *skb,
|
|||
if (IS_ERR(set))
|
||||
return PTR_ERR(set);
|
||||
|
||||
if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
|
||||
if (!list_empty(&set->bindings) &&
|
||||
(set->flags & (NFT_SET_CONSTANT | NFT_SET_ANONYMOUS)))
|
||||
return -EBUSY;
|
||||
|
||||
nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
|
||||
|
@ -6638,7 +6847,6 @@ static int nf_tables_newsetelem(struct sk_buff *skb,
|
|||
void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
|
||||
{
|
||||
struct nft_chain *chain;
|
||||
struct nft_rule *rule;
|
||||
|
||||
if (type == NFT_DATA_VERDICT) {
|
||||
switch (data->verdict.code) {
|
||||
|
@ -6646,15 +6854,6 @@ void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
|
|||
case NFT_GOTO:
|
||||
chain = data->verdict.chain;
|
||||
chain->use++;
|
||||
|
||||
if (!nft_chain_is_bound(chain))
|
||||
break;
|
||||
|
||||
chain->table->use++;
|
||||
list_for_each_entry(rule, &chain->rules, list)
|
||||
chain->use++;
|
||||
|
||||
nft_chain_add(chain->table, chain);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -6889,7 +7088,9 @@ static int nf_tables_delsetelem(struct sk_buff *skb,
|
|||
set = nft_set_lookup(table, nla[NFTA_SET_ELEM_LIST_SET], genmask);
|
||||
if (IS_ERR(set))
|
||||
return PTR_ERR(set);
|
||||
if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
|
||||
|
||||
if (!list_empty(&set->bindings) &&
|
||||
(set->flags & (NFT_SET_CONSTANT | NFT_SET_ANONYMOUS)))
|
||||
return -EBUSY;
|
||||
|
||||
nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
|
||||
|
@ -7671,6 +7872,7 @@ void nf_tables_deactivate_flowtable(const struct nft_ctx *ctx,
|
|||
enum nft_trans_phase phase)
|
||||
{
|
||||
switch (phase) {
|
||||
case NFT_TRANS_PREPARE_ERROR:
|
||||
case NFT_TRANS_PREPARE:
|
||||
case NFT_TRANS_ABORT:
|
||||
case NFT_TRANS_RELEASE:
|
||||
|
@ -8943,7 +9145,7 @@ static void nf_tables_trans_destroy_work(struct work_struct *w)
|
|||
synchronize_rcu();
|
||||
|
||||
list_for_each_entry_safe(trans, next, &head, list) {
|
||||
list_del(&trans->list);
|
||||
nft_trans_list_del(trans);
|
||||
nft_commit_release(trans);
|
||||
}
|
||||
}
|
||||
|
@ -9308,6 +9510,27 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
list_for_each_entry(trans, &nft_net->binding_list, binding_list) {
|
||||
switch (trans->msg_type) {
|
||||
case NFT_MSG_NEWSET:
|
||||
if (!nft_trans_set_update(trans) &&
|
||||
nft_set_is_anonymous(nft_trans_set(trans)) &&
|
||||
!nft_trans_set_bound(trans)) {
|
||||
pr_warn_once("nftables ruleset with unbound set\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case NFT_MSG_NEWCHAIN:
|
||||
if (!nft_trans_chain_update(trans) &&
|
||||
nft_chain_binding(nft_trans_chain(trans)) &&
|
||||
!nft_trans_chain_bound(trans)) {
|
||||
pr_warn_once("nftables ruleset with unbound chain\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* 0. Validate ruleset, otherwise roll back for error reporting. */
|
||||
if (nf_tables_validate(net) < 0)
|
||||
return -EAGAIN;
|
||||
|
@ -9677,7 +9900,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
|
|||
kfree(nft_trans_chain_name(trans));
|
||||
nft_trans_destroy(trans);
|
||||
} else {
|
||||
if (nft_chain_is_bound(trans->ctx.chain)) {
|
||||
if (nft_trans_chain_bound(trans)) {
|
||||
nft_trans_destroy(trans);
|
||||
break;
|
||||
}
|
||||
|
@ -9700,6 +9923,10 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
|
|||
nft_trans_destroy(trans);
|
||||
break;
|
||||
case NFT_MSG_NEWRULE:
|
||||
if (nft_trans_rule_bound(trans)) {
|
||||
nft_trans_destroy(trans);
|
||||
break;
|
||||
}
|
||||
trans->ctx.chain->use--;
|
||||
list_del_rcu(&nft_trans_rule(trans)->list);
|
||||
nft_rule_expr_deactivate(&trans->ctx,
|
||||
|
@ -9734,6 +9961,9 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
|
|||
case NFT_MSG_DESTROYSET:
|
||||
trans->ctx.table->use++;
|
||||
nft_clear(trans->ctx.net, nft_trans_set(trans));
|
||||
if (nft_trans_set(trans)->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
|
||||
nft_map_activate(&trans->ctx, nft_trans_set(trans));
|
||||
|
||||
nft_trans_destroy(trans);
|
||||
break;
|
||||
case NFT_MSG_NEWSETELEM:
|
||||
|
@ -9814,7 +10044,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
|
|||
|
||||
list_for_each_entry_safe_reverse(trans, next,
|
||||
&nft_net->commit_list, list) {
|
||||
list_del(&trans->list);
|
||||
nft_trans_list_del(trans);
|
||||
nf_tables_abort_release(trans);
|
||||
}
|
||||
|
||||
|
@ -10263,22 +10493,12 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
|
|||
static void nft_verdict_uninit(const struct nft_data *data)
|
||||
{
|
||||
struct nft_chain *chain;
|
||||
struct nft_rule *rule;
|
||||
|
||||
switch (data->verdict.code) {
|
||||
case NFT_JUMP:
|
||||
case NFT_GOTO:
|
||||
chain = data->verdict.chain;
|
||||
chain->use--;
|
||||
|
||||
if (!nft_chain_is_bound(chain))
|
||||
break;
|
||||
|
||||
chain->table->use--;
|
||||
list_for_each_entry(rule, &chain->rules, list)
|
||||
chain->use--;
|
||||
|
||||
nft_chain_del(chain);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -10513,6 +10733,9 @@ static void __nft_release_table(struct net *net, struct nft_table *table)
|
|||
list_for_each_entry_safe(set, ns, &table->sets, list) {
|
||||
list_del(&set->list);
|
||||
table->use--;
|
||||
if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
|
||||
nft_map_deactivate(&ctx, set);
|
||||
|
||||
nft_set_destroy(&ctx, set);
|
||||
}
|
||||
list_for_each_entry_safe(obj, ne, &table->objects, list) {
|
||||
|
@ -10597,6 +10820,7 @@ static int __net_init nf_tables_init_net(struct net *net)
|
|||
|
||||
INIT_LIST_HEAD(&nft_net->tables);
|
||||
INIT_LIST_HEAD(&nft_net->commit_list);
|
||||
INIT_LIST_HEAD(&nft_net->binding_list);
|
||||
INIT_LIST_HEAD(&nft_net->module_list);
|
||||
INIT_LIST_HEAD(&nft_net->notify_list);
|
||||
mutex_init(&nft_net->commit_mutex);
|
||||
|
|
|
@ -439,3 +439,4 @@ module_init(nfnl_osf_init);
|
|||
module_exit(nfnl_osf_fini);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_OSF);
|
||||
|
|
|
@ -76,11 +76,9 @@ static int nft_immediate_init(const struct nft_ctx *ctx,
|
|||
switch (priv->data.verdict.code) {
|
||||
case NFT_JUMP:
|
||||
case NFT_GOTO:
|
||||
if (nft_chain_is_bound(chain)) {
|
||||
err = -EBUSY;
|
||||
goto err1;
|
||||
}
|
||||
chain->bound = true;
|
||||
err = nf_tables_bind_chain(ctx, chain);
|
||||
if (err < 0)
|
||||
return err;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -98,6 +96,31 @@ static void nft_immediate_activate(const struct nft_ctx *ctx,
|
|||
const struct nft_expr *expr)
|
||||
{
|
||||
const struct nft_immediate_expr *priv = nft_expr_priv(expr);
|
||||
const struct nft_data *data = &priv->data;
|
||||
struct nft_ctx chain_ctx;
|
||||
struct nft_chain *chain;
|
||||
struct nft_rule *rule;
|
||||
|
||||
if (priv->dreg == NFT_REG_VERDICT) {
|
||||
switch (data->verdict.code) {
|
||||
case NFT_JUMP:
|
||||
case NFT_GOTO:
|
||||
chain = data->verdict.chain;
|
||||
if (!nft_chain_binding(chain))
|
||||
break;
|
||||
|
||||
chain_ctx = *ctx;
|
||||
chain_ctx.chain = chain;
|
||||
|
||||
list_for_each_entry(rule, &chain->rules, list)
|
||||
nft_rule_expr_activate(&chain_ctx, rule);
|
||||
|
||||
nft_clear(ctx->net, chain);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nft_data_hold(&priv->data, nft_dreg_to_type(priv->dreg));
|
||||
}
|
||||
|
@ -107,6 +130,43 @@ static void nft_immediate_deactivate(const struct nft_ctx *ctx,
|
|||
enum nft_trans_phase phase)
|
||||
{
|
||||
const struct nft_immediate_expr *priv = nft_expr_priv(expr);
|
||||
const struct nft_data *data = &priv->data;
|
||||
struct nft_ctx chain_ctx;
|
||||
struct nft_chain *chain;
|
||||
struct nft_rule *rule;
|
||||
|
||||
if (priv->dreg == NFT_REG_VERDICT) {
|
||||
switch (data->verdict.code) {
|
||||
case NFT_JUMP:
|
||||
case NFT_GOTO:
|
||||
chain = data->verdict.chain;
|
||||
if (!nft_chain_binding(chain))
|
||||
break;
|
||||
|
||||
chain_ctx = *ctx;
|
||||
chain_ctx.chain = chain;
|
||||
|
||||
list_for_each_entry(rule, &chain->rules, list)
|
||||
nft_rule_expr_deactivate(&chain_ctx, rule, phase);
|
||||
|
||||
switch (phase) {
|
||||
case NFT_TRANS_PREPARE_ERROR:
|
||||
nf_tables_unbind_chain(ctx, chain);
|
||||
fallthrough;
|
||||
case NFT_TRANS_PREPARE:
|
||||
nft_deactivate_next(ctx->net, chain);
|
||||
break;
|
||||
default:
|
||||
nft_chain_del(chain);
|
||||
chain->bound = false;
|
||||
chain->table->use--;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (phase == NFT_TRANS_COMMIT)
|
||||
return;
|
||||
|
@ -131,15 +191,27 @@ static void nft_immediate_destroy(const struct nft_ctx *ctx,
|
|||
case NFT_GOTO:
|
||||
chain = data->verdict.chain;
|
||||
|
||||
if (!nft_chain_is_bound(chain))
|
||||
if (!nft_chain_binding(chain))
|
||||
break;
|
||||
|
||||
/* Rule construction failed, but chain is already bound:
|
||||
* let the transaction records release this chain and its rules.
|
||||
*/
|
||||
if (chain->bound) {
|
||||
chain->use--;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Rule has been deleted, release chain and its rules. */
|
||||
chain_ctx = *ctx;
|
||||
chain_ctx.chain = chain;
|
||||
|
||||
list_for_each_entry_safe(rule, n, &chain->rules, list)
|
||||
nf_tables_rule_release(&chain_ctx, rule);
|
||||
|
||||
chain->use--;
|
||||
list_for_each_entry_safe(rule, n, &chain->rules, list) {
|
||||
chain->use--;
|
||||
list_del(&rule->list);
|
||||
nf_tables_rule_destroy(&chain_ctx, rule);
|
||||
}
|
||||
nf_tables_chain_destroy(&chain_ctx);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -271,13 +271,14 @@ static int nft_bitmap_init(const struct nft_set *set,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void nft_bitmap_destroy(const struct nft_set *set)
|
||||
static void nft_bitmap_destroy(const struct nft_ctx *ctx,
|
||||
const struct nft_set *set)
|
||||
{
|
||||
struct nft_bitmap *priv = nft_set_priv(set);
|
||||
struct nft_bitmap_elem *be, *n;
|
||||
|
||||
list_for_each_entry_safe(be, n, &priv->list, head)
|
||||
nft_set_elem_destroy(set, be, true);
|
||||
nf_tables_set_elem_destroy(ctx, set, be);
|
||||
}
|
||||
|
||||
static bool nft_bitmap_estimate(const struct nft_set_desc *desc, u32 features,
|
||||
|
|
|
@ -400,19 +400,31 @@ static int nft_rhash_init(const struct nft_set *set,
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct nft_rhash_ctx {
|
||||
const struct nft_ctx ctx;
|
||||
const struct nft_set *set;
|
||||
};
|
||||
|
||||
static void nft_rhash_elem_destroy(void *ptr, void *arg)
|
||||
{
|
||||
nft_set_elem_destroy(arg, ptr, true);
|
||||
struct nft_rhash_ctx *rhash_ctx = arg;
|
||||
|
||||
nf_tables_set_elem_destroy(&rhash_ctx->ctx, rhash_ctx->set, ptr);
|
||||
}
|
||||
|
||||
static void nft_rhash_destroy(const struct nft_set *set)
|
||||
static void nft_rhash_destroy(const struct nft_ctx *ctx,
|
||||
const struct nft_set *set)
|
||||
{
|
||||
struct nft_rhash *priv = nft_set_priv(set);
|
||||
struct nft_rhash_ctx rhash_ctx = {
|
||||
.ctx = *ctx,
|
||||
.set = set,
|
||||
};
|
||||
|
||||
cancel_delayed_work_sync(&priv->gc_work);
|
||||
rcu_barrier();
|
||||
rhashtable_free_and_destroy(&priv->ht, nft_rhash_elem_destroy,
|
||||
(void *)set);
|
||||
(void *)&rhash_ctx);
|
||||
}
|
||||
|
||||
/* Number of buckets is stored in u32, so cap our result to 1U<<31 */
|
||||
|
@ -643,7 +655,8 @@ static int nft_hash_init(const struct nft_set *set,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void nft_hash_destroy(const struct nft_set *set)
|
||||
static void nft_hash_destroy(const struct nft_ctx *ctx,
|
||||
const struct nft_set *set)
|
||||
{
|
||||
struct nft_hash *priv = nft_set_priv(set);
|
||||
struct nft_hash_elem *he;
|
||||
|
@ -653,7 +666,7 @@ static void nft_hash_destroy(const struct nft_set *set)
|
|||
for (i = 0; i < priv->buckets; i++) {
|
||||
hlist_for_each_entry_safe(he, next, &priv->table[i], node) {
|
||||
hlist_del_rcu(&he->node);
|
||||
nft_set_elem_destroy(set, he, true);
|
||||
nf_tables_set_elem_destroy(ctx, set, he);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1974,12 +1974,16 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
|
|||
struct nft_set_iter *iter)
|
||||
{
|
||||
struct nft_pipapo *priv = nft_set_priv(set);
|
||||
struct net *net = read_pnet(&set->net);
|
||||
struct nft_pipapo_match *m;
|
||||
struct nft_pipapo_field *f;
|
||||
int i, r;
|
||||
|
||||
rcu_read_lock();
|
||||
m = rcu_dereference(priv->match);
|
||||
if (iter->genmask == nft_genmask_cur(net))
|
||||
m = rcu_dereference(priv->match);
|
||||
else
|
||||
m = priv->clone;
|
||||
|
||||
if (unlikely(!m))
|
||||
goto out;
|
||||
|
@ -2148,10 +2152,12 @@ out_scratch:
|
|||
|
||||
/**
|
||||
* nft_set_pipapo_match_destroy() - Destroy elements from key mapping array
|
||||
* @ctx: context
|
||||
* @set: nftables API set representation
|
||||
* @m: matching data pointing to key mapping array
|
||||
*/
|
||||
static void nft_set_pipapo_match_destroy(const struct nft_set *set,
|
||||
static void nft_set_pipapo_match_destroy(const struct nft_ctx *ctx,
|
||||
const struct nft_set *set,
|
||||
struct nft_pipapo_match *m)
|
||||
{
|
||||
struct nft_pipapo_field *f;
|
||||
|
@ -2168,15 +2174,17 @@ static void nft_set_pipapo_match_destroy(const struct nft_set *set,
|
|||
|
||||
e = f->mt[r].e;
|
||||
|
||||
nft_set_elem_destroy(set, e, true);
|
||||
nf_tables_set_elem_destroy(ctx, set, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nft_pipapo_destroy() - Free private data for set and all committed elements
|
||||
* @ctx: context
|
||||
* @set: nftables API set representation
|
||||
*/
|
||||
static void nft_pipapo_destroy(const struct nft_set *set)
|
||||
static void nft_pipapo_destroy(const struct nft_ctx *ctx,
|
||||
const struct nft_set *set)
|
||||
{
|
||||
struct nft_pipapo *priv = nft_set_priv(set);
|
||||
struct nft_pipapo_match *m;
|
||||
|
@ -2186,7 +2194,7 @@ static void nft_pipapo_destroy(const struct nft_set *set)
|
|||
if (m) {
|
||||
rcu_barrier();
|
||||
|
||||
nft_set_pipapo_match_destroy(set, m);
|
||||
nft_set_pipapo_match_destroy(ctx, set, m);
|
||||
|
||||
#ifdef NFT_PIPAPO_ALIGN
|
||||
free_percpu(m->scratch_aligned);
|
||||
|
@ -2203,7 +2211,7 @@ static void nft_pipapo_destroy(const struct nft_set *set)
|
|||
m = priv->clone;
|
||||
|
||||
if (priv->dirty)
|
||||
nft_set_pipapo_match_destroy(set, m);
|
||||
nft_set_pipapo_match_destroy(ctx, set, m);
|
||||
|
||||
#ifdef NFT_PIPAPO_ALIGN
|
||||
free_percpu(priv->clone->scratch_aligned);
|
||||
|
|
|
@ -664,7 +664,8 @@ static int nft_rbtree_init(const struct nft_set *set,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void nft_rbtree_destroy(const struct nft_set *set)
|
||||
static void nft_rbtree_destroy(const struct nft_ctx *ctx,
|
||||
const struct nft_set *set)
|
||||
{
|
||||
struct nft_rbtree *priv = nft_set_priv(set);
|
||||
struct nft_rbtree_elem *rbe;
|
||||
|
@ -675,7 +676,7 @@ static void nft_rbtree_destroy(const struct nft_set *set)
|
|||
while ((node = priv->root.rb_node) != NULL) {
|
||||
rb_erase(node, &priv->root);
|
||||
rbe = rb_entry(node, struct nft_rbtree_elem, node);
|
||||
nft_set_elem_destroy(set, rbe, true);
|
||||
nf_tables_set_elem_destroy(ctx, set, rbe);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,4 +71,3 @@ MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
|
|||
MODULE_DESCRIPTION("Passive OS fingerprint matching.");
|
||||
MODULE_ALIAS("ipt_osf");
|
||||
MODULE_ALIAS("ip6t_osf");
|
||||
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_OSF);
|
||||
|
|
|
@ -966,6 +966,7 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
sch_tree_lock(sch);
|
||||
/* backup q->clg and q->loss_model */
|
||||
old_clg = q->clg;
|
||||
old_loss_model = q->loss_model;
|
||||
|
@ -974,7 +975,7 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
|
|||
ret = get_loss_clg(q, tb[TCA_NETEM_LOSS]);
|
||||
if (ret) {
|
||||
q->loss_model = old_loss_model;
|
||||
return ret;
|
||||
goto unlock;
|
||||
}
|
||||
} else {
|
||||
q->loss_model = CLG_RANDOM;
|
||||
|
@ -1041,6 +1042,8 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
|
|||
/* capping jitter to the range acceptable by tabledist() */
|
||||
q->jitter = min_t(s64, abs(q->jitter), INT_MAX);
|
||||
|
||||
unlock:
|
||||
sch_tree_unlock(sch);
|
||||
return ret;
|
||||
|
||||
get_table_failure:
|
||||
|
@ -1050,7 +1053,8 @@ get_table_failure:
|
|||
*/
|
||||
q->clg = old_clg;
|
||||
q->loss_model = old_loss_model;
|
||||
return ret;
|
||||
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
static int netem_init(struct Qdisc *sch, struct nlattr *opt,
|
||||
|
|
|
@ -131,6 +131,7 @@ struct sec_path *secpath_set(struct sk_buff *skb)
|
|||
memset(sp->ovec, 0, sizeof(sp->ovec));
|
||||
sp->olen = 0;
|
||||
sp->len = 0;
|
||||
sp->verified_cnt = 0;
|
||||
|
||||
return sp;
|
||||
}
|
||||
|
@ -330,11 +331,10 @@ xfrm_inner_mode_encap_remove(struct xfrm_state *x,
|
|||
{
|
||||
switch (x->props.mode) {
|
||||
case XFRM_MODE_BEET:
|
||||
switch (XFRM_MODE_SKB_CB(skb)->protocol) {
|
||||
case IPPROTO_IPIP:
|
||||
case IPPROTO_BEETPH:
|
||||
switch (x->sel.family) {
|
||||
case AF_INET:
|
||||
return xfrm4_remove_beet_encap(x, skb);
|
||||
case IPPROTO_IPV6:
|
||||
case AF_INET6:
|
||||
return xfrm6_remove_beet_encap(x, skb);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -310,6 +310,52 @@ static void xfrmi_scrub_packet(struct sk_buff *skb, bool xnet)
|
|||
skb->mark = 0;
|
||||
}
|
||||
|
||||
static int xfrmi_input(struct sk_buff *skb, int nexthdr, __be32 spi,
|
||||
int encap_type, unsigned short family)
|
||||
{
|
||||
struct sec_path *sp;
|
||||
|
||||
sp = skb_sec_path(skb);
|
||||
if (sp && (sp->len || sp->olen) &&
|
||||
!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family))
|
||||
goto discard;
|
||||
|
||||
XFRM_SPI_SKB_CB(skb)->family = family;
|
||||
if (family == AF_INET) {
|
||||
XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
|
||||
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
|
||||
} else {
|
||||
XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
|
||||
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
|
||||
}
|
||||
|
||||
return xfrm_input(skb, nexthdr, spi, encap_type);
|
||||
discard:
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xfrmi4_rcv(struct sk_buff *skb)
|
||||
{
|
||||
return xfrmi_input(skb, ip_hdr(skb)->protocol, 0, 0, AF_INET);
|
||||
}
|
||||
|
||||
static int xfrmi6_rcv(struct sk_buff *skb)
|
||||
{
|
||||
return xfrmi_input(skb, skb_network_header(skb)[IP6CB(skb)->nhoff],
|
||||
0, 0, AF_INET6);
|
||||
}
|
||||
|
||||
static int xfrmi4_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
|
||||
{
|
||||
return xfrmi_input(skb, nexthdr, spi, encap_type, AF_INET);
|
||||
}
|
||||
|
||||
static int xfrmi6_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
|
||||
{
|
||||
return xfrmi_input(skb, nexthdr, spi, encap_type, AF_INET6);
|
||||
}
|
||||
|
||||
static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
|
||||
{
|
||||
const struct xfrm_mode *inner_mode;
|
||||
|
@ -945,8 +991,8 @@ static struct pernet_operations xfrmi_net_ops = {
|
|||
};
|
||||
|
||||
static struct xfrm6_protocol xfrmi_esp6_protocol __read_mostly = {
|
||||
.handler = xfrm6_rcv,
|
||||
.input_handler = xfrm_input,
|
||||
.handler = xfrmi6_rcv,
|
||||
.input_handler = xfrmi6_input,
|
||||
.cb_handler = xfrmi_rcv_cb,
|
||||
.err_handler = xfrmi6_err,
|
||||
.priority = 10,
|
||||
|
@ -996,8 +1042,8 @@ static struct xfrm6_tunnel xfrmi_ip6ip_handler __read_mostly = {
|
|||
#endif
|
||||
|
||||
static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = {
|
||||
.handler = xfrm4_rcv,
|
||||
.input_handler = xfrm_input,
|
||||
.handler = xfrmi4_rcv,
|
||||
.input_handler = xfrmi4_input,
|
||||
.cb_handler = xfrmi_rcv_cb,
|
||||
.err_handler = xfrmi4_err,
|
||||
.priority = 10,
|
||||
|
|
|
@ -1831,6 +1831,7 @@ again:
|
|||
|
||||
__xfrm_policy_unlink(pol, dir);
|
||||
spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
|
||||
xfrm_dev_policy_delete(pol);
|
||||
cnt++;
|
||||
xfrm_audit_policy_delete(pol, 1, task_valid);
|
||||
xfrm_policy_kill(pol);
|
||||
|
@ -1869,6 +1870,7 @@ again:
|
|||
|
||||
__xfrm_policy_unlink(pol, dir);
|
||||
spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
|
||||
xfrm_dev_policy_delete(pol);
|
||||
cnt++;
|
||||
xfrm_audit_policy_delete(pol, 1, task_valid);
|
||||
xfrm_policy_kill(pol);
|
||||
|
@ -3349,6 +3351,13 @@ xfrm_policy_ok(const struct xfrm_tmpl *tmpl, const struct sec_path *sp, int star
|
|||
if (xfrm_state_ok(tmpl, sp->xvec[idx], family, if_id))
|
||||
return ++idx;
|
||||
if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT) {
|
||||
if (idx < sp->verified_cnt) {
|
||||
/* Secpath entry previously verified, consider optional and
|
||||
* continue searching
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
if (start == -1)
|
||||
start = -2-idx;
|
||||
break;
|
||||
|
@ -3723,6 +3732,9 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
|
|||
* Order is _important_. Later we will implement
|
||||
* some barriers, but at the moment barriers
|
||||
* are implied between each two transformations.
|
||||
* Upon success, marks secpath entries as having been
|
||||
* verified to allow them to be skipped in future policy
|
||||
* checks (e.g. nested tunnels).
|
||||
*/
|
||||
for (i = xfrm_nr-1, k = 0; i >= 0; i--) {
|
||||
k = xfrm_policy_ok(tpp[i], sp, k, family, if_id);
|
||||
|
@ -3741,6 +3753,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
|
|||
}
|
||||
|
||||
xfrm_pols_put(pols, npols);
|
||||
sp->verified_cnt = k;
|
||||
|
||||
return 1;
|
||||
}
|
||||
XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLBLOCK);
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <test_progs.h>
|
||||
#include "test_subprogs_extable.skel.h"
|
||||
|
||||
void test_subprogs_extable(void)
|
||||
{
|
||||
const int read_sz = 456;
|
||||
struct test_subprogs_extable *skel;
|
||||
int err;
|
||||
|
||||
skel = test_subprogs_extable__open_and_load();
|
||||
if (!ASSERT_OK_PTR(skel, "skel_open_and_load"))
|
||||
return;
|
||||
|
||||
err = test_subprogs_extable__attach(skel);
|
||||
if (!ASSERT_OK(err, "skel_attach"))
|
||||
goto cleanup;
|
||||
|
||||
/* trigger tracepoint */
|
||||
ASSERT_OK(trigger_module_test_read(read_sz), "trigger_read");
|
||||
|
||||
ASSERT_NEQ(skel->bss->triggered, 0, "verify at least one program ran");
|
||||
|
||||
test_subprogs_extable__detach(skel);
|
||||
|
||||
cleanup:
|
||||
test_subprogs_extable__destroy(skel);
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include "vmlinux.h"
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__uint(max_entries, 8);
|
||||
__type(key, __u32);
|
||||
__type(value, __u64);
|
||||
} test_array SEC(".maps");
|
||||
|
||||
unsigned int triggered;
|
||||
|
||||
static __u64 test_cb(struct bpf_map *map, __u32 *key, __u64 *val, void *data)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
SEC("fexit/bpf_testmod_return_ptr")
|
||||
int BPF_PROG(handle_fexit_ret_subprogs, int arg, struct file *ret)
|
||||
{
|
||||
*(volatile long *)ret;
|
||||
*(volatile int *)&ret->f_mode;
|
||||
bpf_for_each_map_elem(&test_array, test_cb, NULL, 0);
|
||||
triggered++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("fexit/bpf_testmod_return_ptr")
|
||||
int BPF_PROG(handle_fexit_ret_subprogs2, int arg, struct file *ret)
|
||||
{
|
||||
*(volatile long *)ret;
|
||||
*(volatile int *)&ret->f_mode;
|
||||
bpf_for_each_map_elem(&test_array, test_cb, NULL, 0);
|
||||
triggered++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("fexit/bpf_testmod_return_ptr")
|
||||
int BPF_PROG(handle_fexit_ret_subprogs3, int arg, struct file *ret)
|
||||
{
|
||||
*(volatile long *)ret;
|
||||
*(volatile int *)&ret->f_mode;
|
||||
bpf_for_each_map_elem(&test_array, test_cb, NULL, 0);
|
||||
triggered++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
|
@ -371,4 +371,83 @@ __naked void and_then_at_fp_8(void)
|
|||
" ::: __clobber_all);
|
||||
}
|
||||
|
||||
SEC("xdp")
|
||||
__description("32-bit spill of 64-bit reg should clear ID")
|
||||
__failure __msg("math between ctx pointer and 4294967295 is not allowed")
|
||||
__naked void spill_32bit_of_64bit_fail(void)
|
||||
{
|
||||
asm volatile (" \
|
||||
r6 = r1; \
|
||||
/* Roll one bit to force the verifier to track both branches. */\
|
||||
call %[bpf_get_prandom_u32]; \
|
||||
r0 &= 0x8; \
|
||||
/* Put a large number into r1. */ \
|
||||
r1 = 0xffffffff; \
|
||||
r1 <<= 32; \
|
||||
r1 += r0; \
|
||||
/* Assign an ID to r1. */ \
|
||||
r2 = r1; \
|
||||
/* 32-bit spill r1 to stack - should clear the ID! */\
|
||||
*(u32*)(r10 - 8) = r1; \
|
||||
/* 32-bit fill r2 from stack. */ \
|
||||
r2 = *(u32*)(r10 - 8); \
|
||||
/* Compare r2 with another register to trigger find_equal_scalars.\
|
||||
* Having one random bit is important here, otherwise the verifier cuts\
|
||||
* the corners. If the ID was mistakenly preserved on spill, this would\
|
||||
* cause the verifier to think that r1 is also equal to zero in one of\
|
||||
* the branches, and equal to eight on the other branch.\
|
||||
*/ \
|
||||
r3 = 0; \
|
||||
if r2 != r3 goto l0_%=; \
|
||||
l0_%=: r1 >>= 32; \
|
||||
/* At this point, if the verifier thinks that r1 is 0, an out-of-bounds\
|
||||
* read will happen, because it actually contains 0xffffffff.\
|
||||
*/ \
|
||||
r6 += r1; \
|
||||
r0 = *(u32*)(r6 + 0); \
|
||||
exit; \
|
||||
" :
|
||||
: __imm(bpf_get_prandom_u32)
|
||||
: __clobber_all);
|
||||
}
|
||||
|
||||
SEC("xdp")
|
||||
__description("16-bit spill of 32-bit reg should clear ID")
|
||||
__failure __msg("dereference of modified ctx ptr R6 off=65535 disallowed")
|
||||
__naked void spill_16bit_of_32bit_fail(void)
|
||||
{
|
||||
asm volatile (" \
|
||||
r6 = r1; \
|
||||
/* Roll one bit to force the verifier to track both branches. */\
|
||||
call %[bpf_get_prandom_u32]; \
|
||||
r0 &= 0x8; \
|
||||
/* Put a large number into r1. */ \
|
||||
w1 = 0xffff0000; \
|
||||
r1 += r0; \
|
||||
/* Assign an ID to r1. */ \
|
||||
r2 = r1; \
|
||||
/* 16-bit spill r1 to stack - should clear the ID! */\
|
||||
*(u16*)(r10 - 8) = r1; \
|
||||
/* 16-bit fill r2 from stack. */ \
|
||||
r2 = *(u16*)(r10 - 8); \
|
||||
/* Compare r2 with another register to trigger find_equal_scalars.\
|
||||
* Having one random bit is important here, otherwise the verifier cuts\
|
||||
* the corners. If the ID was mistakenly preserved on spill, this would\
|
||||
* cause the verifier to think that r1 is also equal to zero in one of\
|
||||
* the branches, and equal to eight on the other branch.\
|
||||
*/ \
|
||||
r3 = 0; \
|
||||
if r2 != r3 goto l0_%=; \
|
||||
l0_%=: r1 >>= 16; \
|
||||
/* At this point, if the verifier thinks that r1 is 0, an out-of-bounds\
|
||||
* read will happen, because it actually contains 0xffff.\
|
||||
*/ \
|
||||
r6 += r1; \
|
||||
r0 = *(u32*)(r6 + 0); \
|
||||
exit; \
|
||||
" :
|
||||
: __imm(bpf_get_prandom_u32)
|
||||
: __clobber_all);
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
|
|
@ -249,7 +249,7 @@
|
|||
|
||||
/**
|
||||
* FIXTURE_SETUP() - Prepares the setup function for the fixture.
|
||||
* *_metadata* is included so that EXPECT_* and ASSERT_* work correctly.
|
||||
* *_metadata* is included so that EXPECT_*, ASSERT_* etc. work correctly.
|
||||
*
|
||||
* @fixture_name: fixture name
|
||||
*
|
||||
|
@ -275,7 +275,7 @@
|
|||
|
||||
/**
|
||||
* FIXTURE_TEARDOWN()
|
||||
* *_metadata* is included so that EXPECT_* and ASSERT_* work correctly.
|
||||
* *_metadata* is included so that EXPECT_*, ASSERT_* etc. work correctly.
|
||||
*
|
||||
* @fixture_name: fixture name
|
||||
*
|
||||
|
@ -388,7 +388,7 @@
|
|||
if (setjmp(_metadata->env) == 0) { \
|
||||
fixture_name##_setup(_metadata, &self, variant->data); \
|
||||
/* Let setup failure terminate early. */ \
|
||||
if (!_metadata->passed) \
|
||||
if (!_metadata->passed || _metadata->skip) \
|
||||
return; \
|
||||
_metadata->setup_completed = true; \
|
||||
fixture_name##_##test_name(_metadata, &self, variant->data); \
|
||||
|
|
|
@ -92,6 +92,13 @@ NSC_CMD="ip netns exec ${NSC}"
|
|||
|
||||
which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping)
|
||||
|
||||
# Check if FIPS mode is enabled
|
||||
if [ -f /proc/sys/crypto/fips_enabled ]; then
|
||||
fips_enabled=`cat /proc/sys/crypto/fips_enabled`
|
||||
else
|
||||
fips_enabled=0
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
# utilities
|
||||
|
||||
|
@ -1216,7 +1223,7 @@ ipv4_tcp_novrf()
|
|||
run_cmd nettest -d ${NSA_DEV} -r ${a}
|
||||
log_test_addr ${a} $? 1 "No server, device client, local conn"
|
||||
|
||||
ipv4_tcp_md5_novrf
|
||||
[ "$fips_enabled" = "1" ] || ipv4_tcp_md5_novrf
|
||||
}
|
||||
|
||||
ipv4_tcp_vrf()
|
||||
|
@ -1270,9 +1277,11 @@ ipv4_tcp_vrf()
|
|||
log_test_addr ${a} $? 1 "Global server, local connection"
|
||||
|
||||
# run MD5 tests
|
||||
setup_vrf_dup
|
||||
ipv4_tcp_md5
|
||||
cleanup_vrf_dup
|
||||
if [ "$fips_enabled" = "0" ]; then
|
||||
setup_vrf_dup
|
||||
ipv4_tcp_md5
|
||||
cleanup_vrf_dup
|
||||
fi
|
||||
|
||||
#
|
||||
# enable VRF global server
|
||||
|
@ -2772,7 +2781,7 @@ ipv6_tcp_novrf()
|
|||
log_test_addr ${a} $? 1 "No server, device client, local conn"
|
||||
done
|
||||
|
||||
ipv6_tcp_md5_novrf
|
||||
[ "$fips_enabled" = "1" ] || ipv6_tcp_md5_novrf
|
||||
}
|
||||
|
||||
ipv6_tcp_vrf()
|
||||
|
@ -2842,9 +2851,11 @@ ipv6_tcp_vrf()
|
|||
log_test_addr ${a} $? 1 "Global server, local connection"
|
||||
|
||||
# run MD5 tests
|
||||
setup_vrf_dup
|
||||
ipv6_tcp_md5
|
||||
cleanup_vrf_dup
|
||||
if [ "$fips_enabled" = "0" ]; then
|
||||
setup_vrf_dup
|
||||
ipv6_tcp_md5
|
||||
cleanup_vrf_dup
|
||||
fi
|
||||
|
||||
#
|
||||
# enable VRF global server
|
||||
|
|
|
@ -93,12 +93,16 @@ cleanup()
|
|||
|
||||
test_gretap()
|
||||
{
|
||||
ip neigh replace 192.0.2.130 lladdr $(mac_get $h3) \
|
||||
nud permanent dev br2
|
||||
full_test_span_gre_dir gt4 ingress 8 0 "mirror to gretap"
|
||||
full_test_span_gre_dir gt4 egress 0 8 "mirror to gretap"
|
||||
}
|
||||
|
||||
test_ip6gretap()
|
||||
{
|
||||
ip neigh replace 2001:db8:2::2 lladdr $(mac_get $h3) \
|
||||
nud permanent dev br2
|
||||
full_test_span_gre_dir gt6 ingress 8 0 "mirror to ip6gretap"
|
||||
full_test_span_gre_dir gt6 egress 0 8 "mirror to ip6gretap"
|
||||
}
|
||||
|
|
|
@ -90,12 +90,16 @@ cleanup()
|
|||
|
||||
test_gretap()
|
||||
{
|
||||
ip neigh replace 192.0.2.130 lladdr $(mac_get $h3) \
|
||||
nud permanent dev br1
|
||||
full_test_span_gre_dir gt4 ingress 8 0 "mirror to gretap"
|
||||
full_test_span_gre_dir gt4 egress 0 8 "mirror to gretap"
|
||||
}
|
||||
|
||||
test_ip6gretap()
|
||||
{
|
||||
ip neigh replace 2001:db8:2::2 lladdr $(mac_get $h3) \
|
||||
nud permanent dev br1
|
||||
full_test_span_gre_dir gt6 ingress 8 0 "mirror to ip6gretap"
|
||||
full_test_span_gre_dir gt6 egress 0 8 "mirror to ip6gretap"
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#define TLS_PAYLOAD_MAX_LEN 16384
|
||||
#define SOL_TLS 282
|
||||
|
||||
static int fips_enabled;
|
||||
|
||||
struct tls_crypto_info_keys {
|
||||
union {
|
||||
struct tls12_crypto_info_aes_gcm_128 aes128;
|
||||
|
@ -235,7 +237,7 @@ FIXTURE_VARIANT(tls)
|
|||
{
|
||||
uint16_t tls_version;
|
||||
uint16_t cipher_type;
|
||||
bool nopad;
|
||||
bool nopad, fips_non_compliant;
|
||||
};
|
||||
|
||||
FIXTURE_VARIANT_ADD(tls, 12_aes_gcm)
|
||||
|
@ -254,24 +256,28 @@ FIXTURE_VARIANT_ADD(tls, 12_chacha)
|
|||
{
|
||||
.tls_version = TLS_1_2_VERSION,
|
||||
.cipher_type = TLS_CIPHER_CHACHA20_POLY1305,
|
||||
.fips_non_compliant = true,
|
||||
};
|
||||
|
||||
FIXTURE_VARIANT_ADD(tls, 13_chacha)
|
||||
{
|
||||
.tls_version = TLS_1_3_VERSION,
|
||||
.cipher_type = TLS_CIPHER_CHACHA20_POLY1305,
|
||||
.fips_non_compliant = true,
|
||||
};
|
||||
|
||||
FIXTURE_VARIANT_ADD(tls, 13_sm4_gcm)
|
||||
{
|
||||
.tls_version = TLS_1_3_VERSION,
|
||||
.cipher_type = TLS_CIPHER_SM4_GCM,
|
||||
.fips_non_compliant = true,
|
||||
};
|
||||
|
||||
FIXTURE_VARIANT_ADD(tls, 13_sm4_ccm)
|
||||
{
|
||||
.tls_version = TLS_1_3_VERSION,
|
||||
.cipher_type = TLS_CIPHER_SM4_CCM,
|
||||
.fips_non_compliant = true,
|
||||
};
|
||||
|
||||
FIXTURE_VARIANT_ADD(tls, 12_aes_ccm)
|
||||
|
@ -311,6 +317,9 @@ FIXTURE_SETUP(tls)
|
|||
int one = 1;
|
||||
int ret;
|
||||
|
||||
if (fips_enabled && variant->fips_non_compliant)
|
||||
SKIP(return, "Unsupported cipher in FIPS mode");
|
||||
|
||||
tls_crypto_info_init(variant->tls_version, variant->cipher_type,
|
||||
&tls12);
|
||||
|
||||
|
@ -1865,4 +1874,17 @@ TEST(prequeue) {
|
|||
close(cfd);
|
||||
}
|
||||
|
||||
static void __attribute__((constructor)) fips_check(void) {
|
||||
int res;
|
||||
FILE *f;
|
||||
|
||||
f = fopen("/proc/sys/crypto/fips_enabled", "r");
|
||||
if (f) {
|
||||
res = fscanf(f, "%d", &fips_enabled);
|
||||
if (res != 1)
|
||||
ksft_print_msg("ERROR: Couldn't read /proc/sys/crypto/fips_enabled\n");
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_HARNESS_MAIN
|
||||
|
|
|
@ -264,60 +264,60 @@ setup_xfrm()
|
|||
ip -netns host1 xfrm state add src ${HOST1_4} dst ${HOST2_4} \
|
||||
proto esp spi ${SPI_1} reqid 0 mode tunnel \
|
||||
replay-window 4 replay-oseq 0x4 \
|
||||
auth-trunc 'hmac(md5)' ${AUTH_1} 96 \
|
||||
enc 'cbc(des3_ede)' ${ENC_1} \
|
||||
auth-trunc 'hmac(sha1)' ${AUTH_1} 96 \
|
||||
enc 'cbc(aes)' ${ENC_1} \
|
||||
sel src ${h1_4} dst ${h2_4} ${devarg}
|
||||
|
||||
ip -netns host2 xfrm state add src ${HOST1_4} dst ${HOST2_4} \
|
||||
proto esp spi ${SPI_1} reqid 0 mode tunnel \
|
||||
replay-window 4 replay-oseq 0x4 \
|
||||
auth-trunc 'hmac(md5)' ${AUTH_1} 96 \
|
||||
enc 'cbc(des3_ede)' ${ENC_1} \
|
||||
auth-trunc 'hmac(sha1)' ${AUTH_1} 96 \
|
||||
enc 'cbc(aes)' ${ENC_1} \
|
||||
sel src ${h1_4} dst ${h2_4}
|
||||
|
||||
|
||||
ip -netns host1 xfrm state add src ${HOST2_4} dst ${HOST1_4} \
|
||||
proto esp spi ${SPI_2} reqid 0 mode tunnel \
|
||||
replay-window 4 replay-oseq 0x4 \
|
||||
auth-trunc 'hmac(md5)' ${AUTH_2} 96 \
|
||||
enc 'cbc(des3_ede)' ${ENC_2} \
|
||||
auth-trunc 'hmac(sha1)' ${AUTH_2} 96 \
|
||||
enc 'cbc(aes)' ${ENC_2} \
|
||||
sel src ${h2_4} dst ${h1_4} ${devarg}
|
||||
|
||||
ip -netns host2 xfrm state add src ${HOST2_4} dst ${HOST1_4} \
|
||||
proto esp spi ${SPI_2} reqid 0 mode tunnel \
|
||||
replay-window 4 replay-oseq 0x4 \
|
||||
auth-trunc 'hmac(md5)' ${AUTH_2} 96 \
|
||||
enc 'cbc(des3_ede)' ${ENC_2} \
|
||||
auth-trunc 'hmac(sha1)' ${AUTH_2} 96 \
|
||||
enc 'cbc(aes)' ${ENC_2} \
|
||||
sel src ${h2_4} dst ${h1_4}
|
||||
|
||||
|
||||
ip -6 -netns host1 xfrm state add src ${HOST1_6} dst ${HOST2_6} \
|
||||
proto esp spi ${SPI_1} reqid 0 mode tunnel \
|
||||
replay-window 4 replay-oseq 0x4 \
|
||||
auth-trunc 'hmac(md5)' ${AUTH_1} 96 \
|
||||
enc 'cbc(des3_ede)' ${ENC_1} \
|
||||
auth-trunc 'hmac(sha1)' ${AUTH_1} 96 \
|
||||
enc 'cbc(aes)' ${ENC_1} \
|
||||
sel src ${h1_6} dst ${h2_6} ${devarg}
|
||||
|
||||
ip -6 -netns host2 xfrm state add src ${HOST1_6} dst ${HOST2_6} \
|
||||
proto esp spi ${SPI_1} reqid 0 mode tunnel \
|
||||
replay-window 4 replay-oseq 0x4 \
|
||||
auth-trunc 'hmac(md5)' ${AUTH_1} 96 \
|
||||
enc 'cbc(des3_ede)' ${ENC_1} \
|
||||
auth-trunc 'hmac(sha1)' ${AUTH_1} 96 \
|
||||
enc 'cbc(aes)' ${ENC_1} \
|
||||
sel src ${h1_6} dst ${h2_6}
|
||||
|
||||
|
||||
ip -6 -netns host1 xfrm state add src ${HOST2_6} dst ${HOST1_6} \
|
||||
proto esp spi ${SPI_2} reqid 0 mode tunnel \
|
||||
replay-window 4 replay-oseq 0x4 \
|
||||
auth-trunc 'hmac(md5)' ${AUTH_2} 96 \
|
||||
enc 'cbc(des3_ede)' ${ENC_2} \
|
||||
auth-trunc 'hmac(sha1)' ${AUTH_2} 96 \
|
||||
enc 'cbc(aes)' ${ENC_2} \
|
||||
sel src ${h2_6} dst ${h1_6} ${devarg}
|
||||
|
||||
ip -6 -netns host2 xfrm state add src ${HOST2_6} dst ${HOST1_6} \
|
||||
proto esp spi ${SPI_2} reqid 0 mode tunnel \
|
||||
replay-window 4 replay-oseq 0x4 \
|
||||
auth-trunc 'hmac(md5)' ${AUTH_2} 96 \
|
||||
enc 'cbc(des3_ede)' ${ENC_2} \
|
||||
auth-trunc 'hmac(sha1)' ${AUTH_2} 96 \
|
||||
enc 'cbc(aes)' ${ENC_2} \
|
||||
sel src ${h2_6} dst ${h1_6}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue