mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-27 12:57:53 +00:00
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
78 changed files with 1178 additions and 351 deletions
10
MAINTAINERS
10
MAINTAINERS
|
@ -9972,8 +9972,9 @@ M: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||||
L: linux-wpan@vger.kernel.org
|
L: linux-wpan@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
W: https://linux-wpan.org/
|
W: https://linux-wpan.org/
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sschmidt/wpan.git
|
Q: https://patchwork.kernel.org/project/linux-wpan/list/
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sschmidt/wpan-next.git
|
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: Documentation/networking/ieee802154.rst
|
||||||
F: drivers/net/ieee802154/
|
F: drivers/net/ieee802154/
|
||||||
F: include/linux/ieee802154.h
|
F: include/linux/ieee802154.h
|
||||||
|
@ -13269,10 +13270,11 @@ F: drivers/memory/mtk-smi.c
|
||||||
F: include/soc/mediatek/smi.h
|
F: include/soc/mediatek/smi.h
|
||||||
|
|
||||||
MEDIATEK SWITCH DRIVER
|
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: Landen Chao <Landen.Chao@mediatek.com>
|
||||||
M: DENG Qingfang <dqfext@gmail.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
|
L: netdev@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/net/dsa/mt7530-mdio.c
|
F: drivers/net/dsa/mt7530-mdio.c
|
||||||
|
|
|
@ -2570,7 +2570,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bpf_jit_enable > 1)
|
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 (image) {
|
||||||
if (!prog->is_func || extra_pass) {
|
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);
|
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 */
|
/* Setup port 6 interface mode and TRGMII TX circuit */
|
||||||
static int
|
static int
|
||||||
mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
|
mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
|
||||||
|
@ -985,6 +999,18 @@ static void mt7530_setup_port5(struct dsa_switch *ds, phy_interface_t interface)
|
||||||
mutex_unlock(&priv->reg_mutex);
|
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
|
static int
|
||||||
mt753x_cpu_port_enable(struct dsa_switch *ds, int port)
|
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)));
|
UNU_FFP(BIT(port)));
|
||||||
|
|
||||||
/* Set CPU port number */
|
/* 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));
|
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
|
/* CPU port gets connected to all user ports of
|
||||||
* the switch.
|
* the switch.
|
||||||
*/
|
*/
|
||||||
|
@ -2255,6 +2288,8 @@ mt7530_setup(struct dsa_switch *ds)
|
||||||
|
|
||||||
priv->p6_interface = PHY_INTERFACE_MODE_NA;
|
priv->p6_interface = PHY_INTERFACE_MODE_NA;
|
||||||
|
|
||||||
|
mt753x_trap_frames(priv);
|
||||||
|
|
||||||
/* Enable and reset MIB counters */
|
/* Enable and reset MIB counters */
|
||||||
mt7530_mib_reset(ds);
|
mt7530_mib_reset(ds);
|
||||||
|
|
||||||
|
@ -2352,17 +2387,9 @@ static int
|
||||||
mt7531_setup_common(struct dsa_switch *ds)
|
mt7531_setup_common(struct dsa_switch *ds)
|
||||||
{
|
{
|
||||||
struct mt7530_priv *priv = ds->priv;
|
struct mt7530_priv *priv = ds->priv;
|
||||||
struct dsa_port *cpu_dp;
|
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
/* BPDU to CPU port */
|
mt753x_trap_frames(priv);
|
||||||
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);
|
|
||||||
|
|
||||||
/* Enable and reset MIB counters */
|
/* Enable and reset MIB counters */
|
||||||
mt7530_mib_reset(ds);
|
mt7530_mib_reset(ds);
|
||||||
|
@ -3085,6 +3112,7 @@ static int mt7988_setup(struct dsa_switch *ds)
|
||||||
const struct dsa_switch_ops mt7530_switch_ops = {
|
const struct dsa_switch_ops mt7530_switch_ops = {
|
||||||
.get_tag_protocol = mtk_get_tag_protocol,
|
.get_tag_protocol = mtk_get_tag_protocol,
|
||||||
.setup = mt753x_setup,
|
.setup = mt753x_setup,
|
||||||
|
.preferred_default_local_cpu_port = mt753x_preferred_default_local_cpu_port,
|
||||||
.get_strings = mt7530_get_strings,
|
.get_strings = mt7530_get_strings,
|
||||||
.get_ethtool_stats = mt7530_get_ethtool_stats,
|
.get_ethtool_stats = mt7530_get_ethtool_stats,
|
||||||
.get_sset_count = mt7530_get_sset_count,
|
.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_GET(x) (((x) >> 16) & MIRROR_MASK)
|
||||||
#define MT7531_MIRROR_PORT_SET(x) (((x) & MIRROR_MASK) << 16)
|
#define MT7531_MIRROR_PORT_SET(x) (((x) & MIRROR_MASK) << 16)
|
||||||
#define MT7531_CPU_PMAP_MASK GENMASK(7, 0)
|
#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)) ? \
|
#define MT753X_MIRROR_REG(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
|
||||||
MT7531_CFC : MT7530_MFC)
|
MT7531_CFC : MT7530_MFC)
|
||||||
|
@ -66,6 +67,11 @@ enum mt753x_id {
|
||||||
#define MT753X_BPC 0x24
|
#define MT753X_BPC 0x24
|
||||||
#define MT753X_BPDU_PORT_FW_MASK GENMASK(2, 0)
|
#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 {
|
enum mt753x_bpdu_port_fw {
|
||||||
MT753X_BPDU_FOLLOW_MFC,
|
MT753X_BPDU_FOLLOW_MFC,
|
||||||
MT753X_BPDU_CPU_EXCLUDE = 4,
|
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 ?
|
eth_hdr_len = ntohs(skb->protocol) == ETH_P_8021Q ?
|
||||||
VLAN_ETH_HLEN : ETH_HLEN;
|
VLAN_ETH_HLEN : ETH_HLEN;
|
||||||
if (skb->len <= 60 &&
|
if (skb->len <= 60 &&
|
||||||
(lancer_chip(adapter) || skb_vlan_tag_present(skb)) &&
|
(lancer_chip(adapter) || BE3_chip(adapter) ||
|
||||||
is_ipv4_pkt(skb)) {
|
skb_vlan_tag_present(skb)) && is_ipv4_pkt(skb)) {
|
||||||
ip = (struct iphdr *)ip_hdr(skb);
|
ip = (struct iphdr *)ip_hdr(skb);
|
||||||
pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len));
|
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:
|
case DPMAC_ETH_IF_XFI:
|
||||||
*if_mode = PHY_INTERFACE_MODE_10GBASER;
|
*if_mode = PHY_INTERFACE_MODE_10GBASER;
|
||||||
break;
|
break;
|
||||||
|
case DPMAC_ETH_IF_CAUI:
|
||||||
|
*if_mode = PHY_INTERFACE_MODE_25GBASER;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
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;
|
return DPMAC_ETH_IF_XFI;
|
||||||
case PHY_INTERFACE_MODE_1000BASEX:
|
case PHY_INTERFACE_MODE_1000BASEX:
|
||||||
return DPMAC_ETH_IF_1000BASEX;
|
return DPMAC_ETH_IF_1000BASEX;
|
||||||
|
case PHY_INTERFACE_MODE_25GBASER:
|
||||||
|
return DPMAC_ETH_IF_CAUI;
|
||||||
default:
|
default:
|
||||||
return DPMAC_ETH_IF_MII;
|
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->phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE |
|
||||||
MAC_10FD | MAC_100FD | MAC_1000FD | MAC_2500FD | MAC_5000FD |
|
MAC_10FD | MAC_100FD | MAC_1000FD | MAC_2500FD | MAC_5000FD |
|
||||||
MAC_10000FD;
|
MAC_10000FD | MAC_25000FD;
|
||||||
|
|
||||||
dpaa2_mac_set_supported_interfaces(mac);
|
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,
|
static int mlx5e_build_rq_frags_info(struct mlx5_core_dev *mdev,
|
||||||
struct mlx5e_params *params,
|
struct mlx5e_params *params,
|
||||||
struct mlx5e_xsk_param *xsk,
|
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);
|
u32 byte_count = MLX5E_SW2HW_MTU(params, params->sw_mtu);
|
||||||
int frag_size_max = DEFAULT_FRAG_SIZE;
|
int frag_size_max = DEFAULT_FRAG_SIZE;
|
||||||
|
@ -845,6 +846,8 @@ static int mlx5e_build_rq_frags_info(struct mlx5_core_dev *mdev,
|
||||||
|
|
||||||
info->log_num_frags = order_base_2(info->num_frags);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -989,7 +992,8 @@ int mlx5e_build_rq_param(struct mlx5_core_dev *mdev,
|
||||||
}
|
}
|
||||||
default: /* MLX5_WQ_TYPE_CYCLIC */
|
default: /* MLX5_WQ_TYPE_CYCLIC */
|
||||||
MLX5_SET(wq, wq, log_wq_sz, params->log_rq_mtu_frames);
|
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)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
ndsegs = param->frags_info.num_frags;
|
ndsegs = param->frags_info.num_frags;
|
||||||
|
|
|
@ -24,6 +24,7 @@ struct mlx5e_rq_param {
|
||||||
u32 rqc[MLX5_ST_SZ_DW(rqc)];
|
u32 rqc[MLX5_ST_SZ_DW(rqc)];
|
||||||
struct mlx5_wq_param wq;
|
struct mlx5_wq_param wq;
|
||||||
struct mlx5e_rq_frags_info frags_info;
|
struct mlx5e_rq_frags_info frags_info;
|
||||||
|
u32 xdp_frag_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mlx5e_sq_param {
|
struct mlx5e_sq_param {
|
||||||
|
|
|
@ -2021,6 +2021,8 @@ void
|
||||||
mlx5_tc_ct_delete_flow(struct mlx5_tc_ct_priv *priv,
|
mlx5_tc_ct_delete_flow(struct mlx5_tc_ct_priv *priv,
|
||||||
struct mlx5_flow_attr *attr)
|
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() */
|
if (!attr->ct_attr.nf_ft) /* means only ct clear action, and not ct_clear,ct() */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ static int mlx5e_init_xsk_rq(struct mlx5e_channel *c,
|
||||||
if (err)
|
if (err)
|
||||||
return 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,
|
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 mlx5e_ipsec_sa_entry *sa_entry = dwork->sa_entry;
|
||||||
struct xfrm_state *x = sa_entry->x;
|
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);
|
xfrm_state_check_expire(x);
|
||||||
if (x->km.state == XFRM_STATE_EXPIRED) {
|
if (x->km.state == XFRM_STATE_EXPIRED) {
|
||||||
sa_entry->attrs.drop = true;
|
sa_entry->attrs.drop = true;
|
||||||
mlx5e_accel_ipsec_fs_modify(sa_entry);
|
spin_unlock_bh(&x->lock);
|
||||||
}
|
|
||||||
spin_unlock(&x->lock);
|
|
||||||
|
|
||||||
if (sa_entry->attrs.drop)
|
mlx5e_accel_ipsec_fs_modify(sa_entry);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
spin_unlock_bh(&x->lock);
|
||||||
|
|
||||||
queue_delayed_work(sa_entry->ipsec->wq, &dwork->dwork,
|
queue_delayed_work(sa_entry->ipsec->wq, &dwork->dwork,
|
||||||
MLX5_IPSEC_RESCHED);
|
MLX5_IPSEC_RESCHED);
|
||||||
|
@ -1040,11 +1043,17 @@ static int mlx5e_xfrm_add_policy(struct xfrm_policy *x,
|
||||||
return err;
|
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);
|
struct mlx5e_ipsec_pol_entry *pol_entry = to_ipsec_pol_entry(x);
|
||||||
|
|
||||||
mlx5e_accel_ipsec_fs_del_pol(pol_entry);
|
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);
|
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_state_update_curlft = mlx5e_xfrm_update_curlft,
|
||||||
.xdo_dev_policy_add = mlx5e_xfrm_add_policy,
|
.xdo_dev_policy_add = mlx5e_xfrm_add_policy,
|
||||||
|
.xdo_dev_policy_delete = mlx5e_xfrm_del_policy,
|
||||||
.xdo_dev_policy_free = mlx5e_xfrm_free_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);
|
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);
|
mlx5_accel_esp_modify_xfrm(sa_entry, &attrs);
|
||||||
|
spin_lock_bh(&sa_entry->x->lock);
|
||||||
|
|
||||||
data.data_offset_condition_operand =
|
data.data_offset_condition_operand =
|
||||||
MLX5_IPSEC_ASO_REMOVE_FLOW_PKT_CNT_OFFSET;
|
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;
|
aso = sa_entry->ipsec->aso;
|
||||||
attrs = &sa_entry->attrs;
|
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);
|
ret = mlx5e_ipsec_aso_query(sa_entry, NULL);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
@ -447,7 +457,7 @@ static void mlx5e_ipsec_handle_event(struct work_struct *_work)
|
||||||
mlx5e_ipsec_handle_limits(sa_entry);
|
mlx5e_ipsec_handle_limits(sa_entry);
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
spin_unlock(&sa_entry->x->lock);
|
spin_unlock_bh(&sa_entry->x->lock);
|
||||||
kfree(work);
|
kfree(work);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,7 +606,8 @@ int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry,
|
||||||
do {
|
do {
|
||||||
ret = mlx5_aso_poll_cq(aso->aso, false);
|
ret = mlx5_aso_poll_cq(aso->aso, false);
|
||||||
if (ret)
|
if (ret)
|
||||||
usleep_range(2, 10);
|
/* We are in atomic context */
|
||||||
|
udelay(10);
|
||||||
} while (ret && time_is_after_jiffies(expires));
|
} while (ret && time_is_after_jiffies(expires));
|
||||||
spin_unlock_bh(&aso->lock);
|
spin_unlock_bh(&aso->lock);
|
||||||
return ret;
|
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,
|
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;
|
struct mlx5_core_dev *mdev = c->mdev;
|
||||||
int err;
|
int err;
|
||||||
|
@ -665,7 +665,8 @@ static int mlx5e_init_rxq_rq(struct mlx5e_channel *c, struct mlx5e_params *param
|
||||||
if (err)
|
if (err)
|
||||||
return 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,
|
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;
|
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)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
|
|
@ -1439,6 +1439,7 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
|
||||||
mlx5e_hairpin_flow_del(priv, flow);
|
mlx5e_hairpin_flow_del(priv, flow);
|
||||||
|
|
||||||
free_flow_post_acts(flow);
|
free_flow_post_acts(flow);
|
||||||
|
mlx5_tc_ct_delete_flow(get_ct_priv(flow->priv), attr);
|
||||||
|
|
||||||
kvfree(attr->parse_attr);
|
kvfree(attr->parse_attr);
|
||||||
kfree(flow->attr);
|
kfree(flow->attr);
|
||||||
|
|
|
@ -511,10 +511,11 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev,
|
||||||
struct mlx5_flow_rule *dst;
|
struct mlx5_flow_rule *dst;
|
||||||
void *in_flow_context, *vlan;
|
void *in_flow_context, *vlan;
|
||||||
void *in_match_value;
|
void *in_match_value;
|
||||||
|
int reformat_id = 0;
|
||||||
unsigned int inlen;
|
unsigned int inlen;
|
||||||
int dst_cnt_size;
|
int dst_cnt_size;
|
||||||
|
u32 *in, action;
|
||||||
void *in_dests;
|
void *in_dests;
|
||||||
u32 *in;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (mlx5_set_extended_dest(dev, fte, &extended_dest))
|
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,
|
MLX5_SET(flow_context, in_flow_context, extended_destination,
|
||||||
extended_dest);
|
extended_dest);
|
||||||
if (extended_dest) {
|
|
||||||
u32 action;
|
|
||||||
|
|
||||||
action = fte->action.action &
|
action = fte->action.action;
|
||||||
~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
|
if (extended_dest)
|
||||||
MLX5_SET(flow_context, in_flow_context, action, action);
|
action &= ~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
|
||||||
} else {
|
|
||||||
MLX5_SET(flow_context, in_flow_context, action,
|
MLX5_SET(flow_context, in_flow_context, action, action);
|
||||||
fte->action.action);
|
|
||||||
if (fte->action.pkt_reformat)
|
if (!extended_dest && fte->action.pkt_reformat) {
|
||||||
MLX5_SET(flow_context, in_flow_context, packet_reformat_id,
|
struct mlx5_pkt_reformat *pkt_reformat = fte->action.pkt_reformat;
|
||||||
fte->action.pkt_reformat->id);
|
|
||||||
|
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,
|
MLX5_SET(flow_context, in_flow_context, modify_header_id,
|
||||||
fte->action.modify_hdr->id);
|
fte->action.modify_hdr->id);
|
||||||
|
}
|
||||||
|
|
||||||
MLX5_SET(flow_context, in_flow_context, encrypt_decrypt_type,
|
MLX5_SET(flow_context, in_flow_context, encrypt_decrypt_type,
|
||||||
fte->action.crypto.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,
|
pkt_reformat->id = MLX5_GET(alloc_packet_reformat_context_out,
|
||||||
out, packet_reformat_id);
|
out, packet_reformat_id);
|
||||||
|
pkt_reformat->owner = MLX5_FLOW_RESOURCE_OWNER_FW;
|
||||||
|
|
||||||
kfree(in);
|
kfree(in);
|
||||||
return err;
|
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));
|
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->id = MLX5_GET(alloc_modify_header_context_out, out, modify_header_id);
|
||||||
|
modify_hdr->owner = MLX5_FLOW_RESOURCE_OWNER_FW;
|
||||||
kfree(in);
|
kfree(in);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,8 +54,14 @@ struct mlx5_flow_definer {
|
||||||
u32 id;
|
u32 id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum mlx5_flow_resource_owner {
|
||||||
|
MLX5_FLOW_RESOURCE_OWNER_FW,
|
||||||
|
MLX5_FLOW_RESOURCE_OWNER_SW,
|
||||||
|
};
|
||||||
|
|
||||||
struct mlx5_modify_hdr {
|
struct mlx5_modify_hdr {
|
||||||
enum mlx5_flow_namespace_type ns_type;
|
enum mlx5_flow_namespace_type ns_type;
|
||||||
|
enum mlx5_flow_resource_owner owner;
|
||||||
union {
|
union {
|
||||||
struct mlx5_fs_dr_action action;
|
struct mlx5_fs_dr_action action;
|
||||||
u32 id;
|
u32 id;
|
||||||
|
@ -65,6 +71,7 @@ struct mlx5_modify_hdr {
|
||||||
struct mlx5_pkt_reformat {
|
struct mlx5_pkt_reformat {
|
||||||
enum mlx5_flow_namespace_type ns_type;
|
enum mlx5_flow_namespace_type ns_type;
|
||||||
int reformat_type; /* from mlx5_ifc */
|
int reformat_type; /* from mlx5_ifc */
|
||||||
|
enum mlx5_flow_resource_owner owner;
|
||||||
union {
|
union {
|
||||||
struct mlx5_fs_dr_action action;
|
struct mlx5_fs_dr_action action;
|
||||||
u32 id;
|
u32 id;
|
||||||
|
|
|
@ -126,14 +126,22 @@ int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int function_id,
|
||||||
return ret;
|
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;
|
struct mlx5_irq_pool *pool = irq->pool;
|
||||||
#ifdef CONFIG_RFS_ACCEL
|
#ifdef CONFIG_RFS_ACCEL
|
||||||
struct cpu_rmap *rmap;
|
struct cpu_rmap *rmap;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
xa_erase(&pool->irqs, irq->pool_index);
|
|
||||||
/* free_irq requires that affinity_hint and rmap will be cleared before
|
/* free_irq requires that affinity_hint and rmap will be cleared before
|
||||||
* calling it. To satisfy this requirement, we call
|
* calling it. To satisfy this requirement, we call
|
||||||
* irq_cpu_rmap_remove() to remove the notifier
|
* 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);
|
irq_cpu_rmap_remove(rmap, irq->map.virq);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
free_cpumask_var(irq->mask);
|
|
||||||
free_irq(irq->map.virq, &irq->nh);
|
free_irq(irq->map.virq, &irq->nh);
|
||||||
if (irq->map.index && pci_msix_can_alloc_dyn(pool->dev->pdev))
|
if (irq->map.index && pci_msix_can_alloc_dyn(pool->dev->pdev))
|
||||||
pci_msix_free_irq(pool->dev->pdev, irq->map);
|
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);
|
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,
|
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 **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 irq_affinity_desc af_desc;
|
||||||
struct mlx5_irq *irq;
|
struct mlx5_irq *irq;
|
||||||
|
int offset = 1;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (!pool->xa_num_irqs.max)
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
af_desc.is_managed = false;
|
af_desc.is_managed = false;
|
||||||
for (i = 0; i < nirqs; i++) {
|
for (i = 0; i < nirqs; i++) {
|
||||||
cpumask_clear(&af_desc.mask);
|
cpumask_clear(&af_desc.mask);
|
||||||
cpumask_set_cpu(cpus[i], &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))
|
if (IS_ERR(irq))
|
||||||
break;
|
break;
|
||||||
irqs[i] = irq;
|
irqs[i] = irq;
|
||||||
|
@ -699,7 +721,8 @@ static void mlx5_irq_pool_free_irqs(struct mlx5_irq_pool *pool)
|
||||||
unsigned long index;
|
unsigned long index;
|
||||||
|
|
||||||
xa_for_each(&pool->irqs, index, irq)
|
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)
|
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:
|
case DR_ACTION_TYP_TNL_L3_TO_L2:
|
||||||
{
|
{
|
||||||
u8 hw_actions[DR_ACTION_CACHE_LINE_SIZE] = {};
|
u8 *hw_actions;
|
||||||
int ret;
|
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,
|
ret = mlx5dr_ste_set_action_decap_l3_list(dmn->ste_ctx,
|
||||||
data, data_sz,
|
data, data_sz,
|
||||||
hw_actions,
|
hw_actions,
|
||||||
|
@ -1431,6 +1435,7 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn,
|
||||||
&action->rewrite->num_of_actions);
|
&action->rewrite->num_of_actions);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mlx5dr_dbg(dmn, "Failed creating decap l3 action list\n");
|
mlx5dr_dbg(dmn, "Failed creating decap l3 action list\n");
|
||||||
|
kfree(hw_actions);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1440,6 +1445,7 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn,
|
||||||
ret = mlx5dr_ste_alloc_modify_hdr(action);
|
ret = mlx5dr_ste_alloc_modify_hdr(action);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mlx5dr_dbg(dmn, "Failed preparing reformat data\n");
|
mlx5dr_dbg(dmn, "Failed preparing reformat data\n");
|
||||||
|
kfree(hw_actions);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2129,6 +2135,11 @@ mlx5dr_action_create_aso(struct mlx5dr_domain *dmn, u32 obj_id,
|
||||||
return action;
|
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)
|
int mlx5dr_action_destroy(struct mlx5dr_action *action)
|
||||||
{
|
{
|
||||||
if (WARN_ON_ONCE(refcount_read(&action->refcount) > 1))
|
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) {
|
if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT) {
|
||||||
bool is_decap = fte->action.pkt_reformat->reformat_type ==
|
bool is_decap;
|
||||||
MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2;
|
|
||||||
|
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)
|
if (is_decap)
|
||||||
actions[num_actions++] =
|
actions[num_actions++] =
|
||||||
|
@ -661,6 +669,7 @@ static int mlx5_cmd_dr_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pkt_reformat->owner = MLX5_FLOW_RESOURCE_OWNER_SW;
|
||||||
pkt_reformat->action.dr_action = action;
|
pkt_reformat->action.dr_action = action;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -691,6 +700,7 @@ static int mlx5_cmd_dr_modify_header_alloc(struct mlx5_flow_root_namespace *ns,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
modify_hdr->owner = MLX5_FLOW_RESOURCE_OWNER_SW;
|
||||||
modify_hdr->action.dr_action = action;
|
modify_hdr->action.dr_action = action;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -816,6 +826,19 @@ static u32 mlx5_cmd_dr_get_capabilities(struct mlx5_flow_root_namespace *ns,
|
||||||
return steering_caps;
|
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)
|
bool mlx5_fs_dr_is_supported(struct mlx5_core_dev *dev)
|
||||||
{
|
{
|
||||||
return mlx5dr_is_supported(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);
|
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);
|
const struct mlx5_flow_cmds *mlx5_fs_cmd_get_dr_cmds(void);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -47,6 +49,11 @@ static inline const struct mlx5_flow_cmds *mlx5_fs_cmd_get_dr_cmds(void)
|
||||||
return NULL;
|
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)
|
static inline bool mlx5_fs_dr_is_supported(struct mlx5_core_dev *dev)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -150,6 +150,8 @@ mlx5dr_action_create_dest_match_range(struct mlx5dr_domain *dmn,
|
||||||
|
|
||||||
int mlx5dr_action_destroy(struct mlx5dr_action *action);
|
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,
|
int mlx5dr_definer_get(struct mlx5dr_domain *dmn, u16 format_id,
|
||||||
u8 *dw_selectors, u8 *byte_selectors,
|
u8 *dw_selectors, u8 *byte_selectors,
|
||||||
u8 *match_mask, u32 *definer_id);
|
u8 *match_mask, u32 *definer_id);
|
||||||
|
|
|
@ -582,8 +582,7 @@ qcaspi_spi_thread(void *data)
|
||||||
while (!kthread_should_stop()) {
|
while (!kthread_should_stop()) {
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
if ((qca->intr_req == qca->intr_svc) &&
|
if ((qca->intr_req == qca->intr_svc) &&
|
||||||
(qca->txr.skb[qca->txr.head] == NULL) &&
|
!qca->txr.skb[qca->txr.head])
|
||||||
(qca->sync == QCASPI_SYNC_READY))
|
|
||||||
schedule();
|
schedule();
|
||||||
|
|
||||||
set_current_state(TASK_RUNNING);
|
set_current_state(TASK_RUNNING);
|
||||||
|
|
|
@ -2950,7 +2950,7 @@ static u32 efx_ef10_extract_event_ts(efx_qword_t *event)
|
||||||
return tstamp;
|
return tstamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
|
efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
|
||||||
{
|
{
|
||||||
struct efx_nic *efx = channel->efx;
|
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_desc_ptr;
|
||||||
unsigned int tx_ev_q_label;
|
unsigned int tx_ev_q_label;
|
||||||
unsigned int tx_ev_type;
|
unsigned int tx_ev_type;
|
||||||
|
int work_done;
|
||||||
u64 ts_part;
|
u64 ts_part;
|
||||||
|
|
||||||
if (unlikely(READ_ONCE(efx->reset_pending)))
|
if (unlikely(READ_ONCE(efx->reset_pending)))
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
if (unlikely(EFX_QWORD_FIELD(*event, ESF_DZ_TX_DROP_EVENT)))
|
if (unlikely(EFX_QWORD_FIELD(*event, ESF_DZ_TX_DROP_EVENT)))
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
/* Get the transmit queue */
|
/* Get the transmit queue */
|
||||||
tx_ev_q_label = EFX_QWORD_FIELD(*event, ESF_DZ_TX_QLABEL);
|
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) {
|
if (!tx_queue->timestamping) {
|
||||||
/* Transmit completion */
|
/* Transmit completion */
|
||||||
tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, ESF_DZ_TX_DESCR_INDX);
|
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 efx_xmit_done(tx_queue, tx_ev_desc_ptr & tx_queue->ptr_mask);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Transmit timestamps are only available for 8XXX series. They result
|
/* 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.
|
* fields in the event.
|
||||||
*/
|
*/
|
||||||
tx_ev_type = EFX_QWORD_FIELD(*event, ESF_EZ_TX_SOFT1);
|
tx_ev_type = EFX_QWORD_FIELD(*event, ESF_EZ_TX_SOFT1);
|
||||||
|
work_done = 0;
|
||||||
|
|
||||||
switch (tx_ev_type) {
|
switch (tx_ev_type) {
|
||||||
case TX_TIMESTAMP_EVENT_TX_EV_COMPLETION:
|
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;
|
tx_queue->completed_timestamp_major = ts_part;
|
||||||
|
|
||||||
efx_xmit_done_single(tx_queue);
|
efx_xmit_done_single(tx_queue);
|
||||||
|
work_done = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -3026,6 +3028,8 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
|
||||||
EFX_QWORD_VAL(*event));
|
EFX_QWORD_VAL(*event));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return work_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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)
|
static int efx_ef10_ev_process(struct efx_channel *channel, int quota)
|
||||||
{
|
{
|
||||||
struct efx_nic *efx = channel->efx;
|
struct efx_nic *efx = channel->efx;
|
||||||
efx_qword_t event, *p_event;
|
efx_qword_t event, *p_event;
|
||||||
unsigned int read_ptr;
|
unsigned int read_ptr;
|
||||||
int ev_code;
|
int spent_tx = 0;
|
||||||
int spent = 0;
|
int spent = 0;
|
||||||
|
int ev_code;
|
||||||
|
|
||||||
if (quota <= 0)
|
if (quota <= 0)
|
||||||
return spent;
|
return spent;
|
||||||
|
@ -3126,7 +3133,11 @@ static int efx_ef10_ev_process(struct efx_channel *channel, int quota)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ESE_DZ_EV_CODE_TX_EV:
|
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;
|
break;
|
||||||
case ESE_DZ_EV_CODE_DRIVER_EV:
|
case ESE_DZ_EV_CODE_DRIVER_EV:
|
||||||
efx_ef10_handle_driver_event(channel, &event);
|
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));
|
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)
|
static int ef100_ev_process(struct efx_channel *channel, int quota)
|
||||||
{
|
{
|
||||||
struct efx_nic *efx = channel->efx;
|
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;
|
bool evq_phase, old_evq_phase;
|
||||||
unsigned int read_ptr;
|
unsigned int read_ptr;
|
||||||
efx_qword_t *p_event;
|
efx_qword_t *p_event;
|
||||||
|
int spent_tx = 0;
|
||||||
int spent = 0;
|
int spent = 0;
|
||||||
bool ev_phase;
|
bool ev_phase;
|
||||||
int ev_type;
|
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);
|
efx_mcdi_process_event(channel, p_event);
|
||||||
break;
|
break;
|
||||||
case ESE_GZ_EF100_EV_TX_COMPLETION:
|
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;
|
break;
|
||||||
case ESE_GZ_EF100_EV_DRIVER:
|
case ESE_GZ_EF100_EV_DRIVER:
|
||||||
netif_info(efx, drv, efx->net_dev,
|
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);
|
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 =
|
unsigned int tx_done =
|
||||||
EFX_QWORD_FIELD(*p_event, ESF_GZ_EV_TXCMPL_NUM_DESC);
|
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) &
|
unsigned int tx_index = (tx_queue->read_count + tx_done - 1) &
|
||||||
tx_queue->ptr_mask;
|
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
|
/* 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);
|
void ef100_tx_write(struct efx_tx_queue *tx_queue);
|
||||||
unsigned int ef100_tx_max_skb_descs(struct efx_nic *efx);
|
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);
|
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,
|
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 fill_level, pkts_compl = 0, bytes_compl = 0;
|
||||||
unsigned int efv_pkts_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);
|
efx_xmit_done_check_empty(tx_queue);
|
||||||
|
|
||||||
|
return pkts_compl + efv_pkts_compl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove buffers put into a tx_queue for the current packet.
|
/* 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_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,
|
void efx_enqueue_unwind(struct efx_tx_queue *tx_queue,
|
||||||
unsigned int insert_count);
|
unsigned int insert_count);
|
||||||
|
|
|
@ -1348,3 +1348,5 @@ module_spi_driver(adf7242_driver);
|
||||||
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
|
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
|
||||||
MODULE_DESCRIPTION("ADF7242 IEEE802.15.4 Transceiver Driver");
|
MODULE_DESCRIPTION("ADF7242 IEEE802.15.4 Transceiver Driver");
|
||||||
MODULE_LICENSE("GPL");
|
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)
|
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 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_phy *phy_v0;
|
||||||
struct hwsim_edge *e;
|
struct hwsim_edge *e;
|
||||||
u32 v0, v1;
|
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) {
|
list_for_each_entry_rcu(e, &phy_v0->edges, list) {
|
||||||
if (e->endpoint->idx == v1) {
|
if (e->endpoint->idx == v1) {
|
||||||
einfo->lqi = lqi;
|
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();
|
rcu_read_unlock();
|
||||||
|
kfree_rcu(einfo_old, rcu);
|
||||||
mutex_unlock(&hwsim_phys_lock);
|
mutex_unlock(&hwsim_phys_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -936,7 +936,7 @@ static int dp83867_phy_reset(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = phy_write(phydev, DP83867_CTRL, DP83867_SW_RESTART);
|
err = phy_write(phydev, DP83867_CTRL, DP83867_SW_RESET);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
|
|
@ -1287,7 +1287,7 @@ EXPORT_SYMBOL_GPL(mdiobus_modify_changed);
|
||||||
* @mask: bit mask of bits to clear
|
* @mask: bit mask of bits to clear
|
||||||
* @set: bit mask of bits to set
|
* @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)
|
u32 regnum, u16 mask, u16 set)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
|
@ -3021,6 +3021,15 @@ static int phy_led_blink_set(struct led_classdev *led_cdev,
|
||||||
return err;
|
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,
|
static int of_phy_led(struct phy_device *phydev,
|
||||||
struct device_node *led)
|
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.fwnode = of_fwnode_handle(led);
|
||||||
init_data.devname_mandatory = true;
|
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)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -3083,6 +3092,7 @@ static int of_phy_leds(struct phy_device *phydev)
|
||||||
err = of_phy_led(phydev, led);
|
err = of_phy_led(phydev, led);
|
||||||
if (err) {
|
if (err) {
|
||||||
of_node_put(led);
|
of_node_put(led);
|
||||||
|
phy_leds_unregister(phydev);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3305,6 +3315,9 @@ static int phy_remove(struct device *dev)
|
||||||
|
|
||||||
cancel_delayed_work_sync(&phydev->state_queue);
|
cancel_delayed_work_sync(&phydev->state_queue);
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_PHYLIB_LEDS))
|
||||||
|
phy_leds_unregister(phydev);
|
||||||
|
|
||||||
phydev->state = PHY_DOWN;
|
phydev->state = PHY_DOWN;
|
||||||
|
|
||||||
sfp_bus_del_upstream(phydev->sfp_bus);
|
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(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, 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(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(0x271C, 0x0214, iwl9260_2ac_cfg, iwl9260_1_name),
|
||||||
IWL_DEV_INFO(0x7E40, 0x1691, iwl_cfg_ma_a0_gf4_a0, iwl_ax411_killer_1690s_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))
|
if (adth->signature != cpu_to_le32(IOSM_AGGR_MUX_SIG_ADTH))
|
||||||
goto adb_decode_err;
|
goto adb_decode_err;
|
||||||
|
|
||||||
if (le16_to_cpu(adth->table_length) < (sizeof(struct mux_adth) -
|
if (le16_to_cpu(adth->table_length) < sizeof(struct mux_adth))
|
||||||
sizeof(struct mux_adth_dg)))
|
|
||||||
goto adb_decode_err;
|
goto adb_decode_err;
|
||||||
|
|
||||||
/* Calculate the number of datagrams. */
|
/* Calculate the number of datagrams. */
|
||||||
nr_of_dg = (le16_to_cpu(adth->table_length) -
|
nr_of_dg = (le16_to_cpu(adth->table_length) -
|
||||||
sizeof(struct mux_adth) +
|
sizeof(struct mux_adth)) /
|
||||||
sizeof(struct mux_adth_dg)) /
|
|
||||||
sizeof(struct mux_adth_dg);
|
sizeof(struct mux_adth_dg);
|
||||||
|
|
||||||
/* Is the datagram table empty ? */
|
/* Is the datagram table empty ? */
|
||||||
|
@ -649,7 +647,7 @@ static void mux_dl_adb_decode(struct iosm_mux *ipc_mux,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* New aggregated datagram table. */
|
/* New aggregated datagram table. */
|
||||||
dg = &adth->dg;
|
dg = adth->dg;
|
||||||
if (mux_dl_process_dg(ipc_mux, adbh, dg, skb, if_id,
|
if (mux_dl_process_dg(ipc_mux, adbh, dg, skb, if_id,
|
||||||
nr_of_dg) < 0)
|
nr_of_dg) < 0)
|
||||||
goto adb_decode_err;
|
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->if_id = i;
|
||||||
adth->table_length = cpu_to_le16(adth_dg_size);
|
adth->table_length = cpu_to_le16(adth_dg_size);
|
||||||
adth_dg_size -= offsetof(struct mux_adth, dg);
|
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++;
|
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)) {
|
if (adth->signature == cpu_to_le32(IOSM_AGGR_MUX_SIG_ADTH)) {
|
||||||
nr_of_dg = (le16_to_cpu(adth->table_length) -
|
nr_of_dg = (le16_to_cpu(adth->table_length) -
|
||||||
sizeof(struct mux_adth) +
|
sizeof(struct mux_adth)) /
|
||||||
sizeof(struct mux_adth_dg)) /
|
|
||||||
sizeof(struct mux_adth_dg);
|
sizeof(struct mux_adth_dg);
|
||||||
|
|
||||||
if (nr_of_dg <= 0)
|
if (nr_of_dg <= 0)
|
||||||
return payload_size;
|
return payload_size;
|
||||||
|
|
||||||
dg = &adth->dg;
|
dg = adth->dg;
|
||||||
|
|
||||||
for (i = 0; i < nr_of_dg; i++, dg++) {
|
for (i = 0; i < nr_of_dg; i++, dg++) {
|
||||||
if (le32_to_cpu(dg->datagram_index) <
|
if (le32_to_cpu(dg->datagram_index) <
|
||||||
|
|
|
@ -161,7 +161,7 @@ struct mux_adth {
|
||||||
u8 opt_ipv4v6;
|
u8 opt_ipv4v6;
|
||||||
__le32 next_table_index;
|
__le32 next_table_index;
|
||||||
__le32 reserved2;
|
__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_LICENSE("GPL");
|
||||||
MODULE_DESCRIPTION("NFC NCI driver for Intel Fields Peak NFC controller");
|
MODULE_DESCRIPTION("NFC NCI driver for Intel Fields Peak NFC controller");
|
||||||
MODULE_AUTHOR("Robert Dolca <robert.dolca@intel.com>");
|
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);
|
struct phy_device *phy);
|
||||||
void (*port_disable)(struct dsa_switch *ds, int port);
|
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
|
* Port's MAC EEE settings
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -472,7 +472,8 @@ struct nft_set_ops {
|
||||||
int (*init)(const struct nft_set *set,
|
int (*init)(const struct nft_set *set,
|
||||||
const struct nft_set_desc *desc,
|
const struct nft_set_desc *desc,
|
||||||
const struct nlattr * const nla[]);
|
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);
|
void (*gc_init)(const struct nft_set *set);
|
||||||
|
|
||||||
unsigned int elemsize;
|
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[]);
|
struct nft_expr *expr_array[]);
|
||||||
void nft_set_elem_destroy(const struct nft_set *set, void *elem,
|
void nft_set_elem_destroy(const struct nft_set *set, void *elem,
|
||||||
bool destroy_expr);
|
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
|
* struct nft_set_gc_batch_head - nf_tables set garbage collection batch
|
||||||
|
@ -901,6 +904,7 @@ struct nft_expr_type {
|
||||||
|
|
||||||
enum nft_trans_phase {
|
enum nft_trans_phase {
|
||||||
NFT_TRANS_PREPARE,
|
NFT_TRANS_PREPARE,
|
||||||
|
NFT_TRANS_PREPARE_ERROR,
|
||||||
NFT_TRANS_ABORT,
|
NFT_TRANS_ABORT,
|
||||||
NFT_TRANS_COMMIT,
|
NFT_TRANS_COMMIT,
|
||||||
NFT_TRANS_RELEASE
|
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];
|
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,
|
static inline void nft_set_elem_update_expr(const struct nft_set_ext *ext,
|
||||||
struct nft_regs *regs,
|
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,
|
const struct nft_set_iter *iter,
|
||||||
struct nft_set_elem *elem);
|
struct nft_set_elem *elem);
|
||||||
int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set);
|
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 {
|
enum nft_chain_types {
|
||||||
NFT_CHAIN_T_DEFAULT = 0,
|
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,
|
int nft_chain_validate_hooks(const struct nft_chain *chain,
|
||||||
unsigned int hook_flags);
|
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)
|
static inline bool nft_chain_is_bound(struct nft_chain *chain)
|
||||||
{
|
{
|
||||||
return (chain->flags & NFT_CHAIN_BINDING) && chain->bound;
|
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 nft_chain_del(struct nft_chain *chain);
|
||||||
void nf_tables_chain_destroy(struct nft_ctx *ctx);
|
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
|
* struct nft_trans - nf_tables object update in transaction
|
||||||
*
|
*
|
||||||
* @list: used internally
|
* @list: used internally
|
||||||
|
* @binding_list: list of objects with possible bindings
|
||||||
* @msg_type: message type
|
* @msg_type: message type
|
||||||
* @put_net: ctx->net needs to be put
|
* @put_net: ctx->net needs to be put
|
||||||
* @ctx: transaction context
|
* @ctx: transaction context
|
||||||
|
@ -1565,6 +1581,7 @@ static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
|
||||||
*/
|
*/
|
||||||
struct nft_trans {
|
struct nft_trans {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
|
struct list_head binding_list;
|
||||||
int msg_type;
|
int msg_type;
|
||||||
bool put_net;
|
bool put_net;
|
||||||
struct nft_ctx ctx;
|
struct nft_ctx ctx;
|
||||||
|
@ -1575,6 +1592,7 @@ struct nft_trans_rule {
|
||||||
struct nft_rule *rule;
|
struct nft_rule *rule;
|
||||||
struct nft_flow_rule *flow;
|
struct nft_flow_rule *flow;
|
||||||
u32 rule_id;
|
u32 rule_id;
|
||||||
|
bool bound;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define nft_trans_rule(trans) \
|
#define nft_trans_rule(trans) \
|
||||||
|
@ -1583,6 +1601,8 @@ struct nft_trans_rule {
|
||||||
(((struct nft_trans_rule *)trans->data)->flow)
|
(((struct nft_trans_rule *)trans->data)->flow)
|
||||||
#define nft_trans_rule_id(trans) \
|
#define nft_trans_rule_id(trans) \
|
||||||
(((struct nft_trans_rule *)trans->data)->rule_id)
|
(((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_trans_set {
|
||||||
struct nft_set *set;
|
struct nft_set *set;
|
||||||
|
@ -1607,15 +1627,19 @@ struct nft_trans_set {
|
||||||
(((struct nft_trans_set *)trans->data)->gc_int)
|
(((struct nft_trans_set *)trans->data)->gc_int)
|
||||||
|
|
||||||
struct nft_trans_chain {
|
struct nft_trans_chain {
|
||||||
|
struct nft_chain *chain;
|
||||||
bool update;
|
bool update;
|
||||||
char *name;
|
char *name;
|
||||||
struct nft_stats __percpu *stats;
|
struct nft_stats __percpu *stats;
|
||||||
u8 policy;
|
u8 policy;
|
||||||
|
bool bound;
|
||||||
u32 chain_id;
|
u32 chain_id;
|
||||||
struct nft_base_chain *basechain;
|
struct nft_base_chain *basechain;
|
||||||
struct list_head hook_list;
|
struct list_head hook_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define nft_trans_chain(trans) \
|
||||||
|
(((struct nft_trans_chain *)trans->data)->chain)
|
||||||
#define nft_trans_chain_update(trans) \
|
#define nft_trans_chain_update(trans) \
|
||||||
(((struct nft_trans_chain *)trans->data)->update)
|
(((struct nft_trans_chain *)trans->data)->update)
|
||||||
#define nft_trans_chain_name(trans) \
|
#define nft_trans_chain_name(trans) \
|
||||||
|
@ -1624,6 +1648,8 @@ struct nft_trans_chain {
|
||||||
(((struct nft_trans_chain *)trans->data)->stats)
|
(((struct nft_trans_chain *)trans->data)->stats)
|
||||||
#define nft_trans_chain_policy(trans) \
|
#define nft_trans_chain_policy(trans) \
|
||||||
(((struct nft_trans_chain *)trans->data)->policy)
|
(((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) \
|
#define nft_trans_chain_id(trans) \
|
||||||
(((struct nft_trans_chain *)trans->data)->chain_id)
|
(((struct nft_trans_chain *)trans->data)->chain_id)
|
||||||
#define nft_trans_basechain(trans) \
|
#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 nftables_pernet {
|
||||||
struct list_head tables;
|
struct list_head tables;
|
||||||
struct list_head commit_list;
|
struct list_head commit_list;
|
||||||
|
struct list_head binding_list;
|
||||||
struct list_head module_list;
|
struct list_head module_list;
|
||||||
struct list_head notify_list;
|
struct list_head notify_list;
|
||||||
struct mutex commit_mutex;
|
struct mutex commit_mutex;
|
||||||
|
|
|
@ -1054,6 +1054,7 @@ struct xfrm_offload {
|
||||||
struct sec_path {
|
struct sec_path {
|
||||||
int len;
|
int len;
|
||||||
int olen;
|
int olen;
|
||||||
|
int verified_cnt;
|
||||||
|
|
||||||
struct xfrm_state *xvec[XFRM_MAX_DEPTH];
|
struct xfrm_state *xvec[XFRM_MAX_DEPTH];
|
||||||
struct xfrm_offload ovec[XFRM_MAX_OFFLOAD_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;
|
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) :
|
if ((first ? !isalpha(c) :
|
||||||
!isalnum(c)) &&
|
!isalnum(c)) &&
|
||||||
c != '_' &&
|
c != '_' &&
|
||||||
((c == '.' && !dot_ok) ||
|
c != '.')
|
||||||
c != '.'))
|
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -767,20 +766,20 @@ static const char *btf_str_by_offset(const struct btf *btf, u32 offset)
|
||||||
return NULL;
|
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 */
|
/* offset must be valid */
|
||||||
const char *src = btf_str_by_offset(btf, offset);
|
const char *src = btf_str_by_offset(btf, offset);
|
||||||
const char *src_limit;
|
const char *src_limit;
|
||||||
|
|
||||||
if (!__btf_name_char_ok(*src, true, dot_ok))
|
if (!__btf_name_char_ok(*src, true))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* set a limit on identifier length */
|
/* set a limit on identifier length */
|
||||||
src_limit = src + KSYM_NAME_LEN;
|
src_limit = src + KSYM_NAME_LEN;
|
||||||
src++;
|
src++;
|
||||||
while (*src && src < src_limit) {
|
while (*src && src < src_limit) {
|
||||||
if (!__btf_name_char_ok(*src, false, dot_ok))
|
if (!__btf_name_char_ok(*src, false))
|
||||||
return false;
|
return false;
|
||||||
src++;
|
src++;
|
||||||
}
|
}
|
||||||
|
@ -788,17 +787,14 @@ static bool __btf_name_valid(const struct btf *btf, u32 offset, bool dot_ok)
|
||||||
return !*src;
|
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)
|
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)
|
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)
|
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 ||
|
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");
|
btf_verifier_log_type(env, t, "Invalid name");
|
||||||
return -EINVAL;
|
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 &&
|
return prog->enforce_expected_attach_type &&
|
||||||
prog->expected_attach_type != attach_type ?
|
prog->expected_attach_type != attach_type ?
|
||||||
-EINVAL : 0;
|
-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:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3868,6 +3868,9 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
save_register_state(state, spi, reg, size);
|
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) &&
|
} else if (!reg && !(off % BPF_REG_SIZE) && is_bpf_st_mem(insn) &&
|
||||||
insn->imm != 0 && env->bpf_capable) {
|
insn->imm != 0 && env->bpf_capable) {
|
||||||
struct bpf_reg_state fake_reg = {};
|
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
|
/* 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_lock_ro(func[i]);
|
||||||
bpf_prog_kallsyms_add(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->jited = 1;
|
||||||
prog->bpf_func = func[0]->bpf_func;
|
prog->bpf_func = func[0]->bpf_func;
|
||||||
prog->jited_len = func[0]->jited_len;
|
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 = func;
|
||||||
prog->aux->func_cnt = env->subprog_cnt;
|
prog->aux->func_cnt = env->subprog_cnt;
|
||||||
bpf_prog_jit_attempt_done(prog);
|
bpf_prog_jit_attempt_done(prog);
|
||||||
|
|
|
@ -1362,12 +1362,6 @@ int sk_setsockopt(struct sock *sk, int level, int optname,
|
||||||
__sock_set_mark(sk, val);
|
__sock_set_mark(sk, val);
|
||||||
break;
|
break;
|
||||||
case SO_RCVMARK:
|
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);
|
sock_valbool_flag(sk, SOCK_RCVMARK, valbool);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -403,6 +403,24 @@ static int dsa_tree_setup_default_cpu(struct dsa_switch_tree *dst)
|
||||||
return 0;
|
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
|
/* 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
|
* 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
|
* 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)
|
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) {
|
list_for_each_entry(cpu_dp, &dst->ports, list) {
|
||||||
if (!dsa_port_is_cpu(cpu_dp))
|
if (!dsa_port_is_cpu(cpu_dp))
|
||||||
continue;
|
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 */
|
/* Prefer a local CPU port */
|
||||||
dsa_switch_for_each_port(dp, cpu_dp->ds) {
|
dsa_switch_for_each_port(dp, cpu_dp->ds) {
|
||||||
/* Prefer the first local CPU port found */
|
/* Prefer the first local CPU port found */
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
#define MAXNAME 32
|
#define MAXNAME 32
|
||||||
#define WPAN_PHY_ENTRY __array(char, wpan_phy_name, MAXNAME)
|
#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), \
|
wpan_phy_name(wpan_phy), \
|
||||||
MAXNAME)
|
MAXNAME)
|
||||||
#define WPAN_PHY_PR_FMT "%s"
|
#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);
|
secpath_reset(skb);
|
||||||
|
|
||||||
|
if (skb_needs_linearize(skb, skb->dev->features) &&
|
||||||
|
__skb_linearize(skb))
|
||||||
|
return -ENOMEM;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -164,6 +164,7 @@ int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(xfrm4_udp_encap_rcv);
|
||||||
|
|
||||||
int xfrm4_rcv(struct sk_buff *skb)
|
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);
|
secpath_reset(skb);
|
||||||
|
|
||||||
|
if (skb_needs_linearize(skb, skb->dev->features) &&
|
||||||
|
__skb_linearize(skb))
|
||||||
|
return -ENOMEM;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,9 @@ int xfrm6_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
|
||||||
__be32 *udpdata32;
|
__be32 *udpdata32;
|
||||||
__u16 encap_type = up->encap_type;
|
__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 this is not encapsulated socket, then just return now */
|
||||||
if (!encap_type)
|
if (!encap_type)
|
||||||
return 1;
|
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 */
|
/* either the frame has been decrypted or will be dropped */
|
||||||
status->flag |= RX_FLAG_DECRYPTED;
|
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))
|
rx->sdata->dev))
|
||||||
cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev,
|
cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev,
|
||||||
skb->data, skb->len);
|
skb->data, skb->len);
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
#define MAXNAME 32
|
#define MAXNAME 32
|
||||||
#define LOCAL_ENTRY __array(char, wpan_phy_name, MAXNAME)
|
#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)
|
wpan_phy_name(local->hw.phy), MAXNAME)
|
||||||
#define LOCAL_PR_FMT "%s"
|
#define LOCAL_PR_FMT "%s"
|
||||||
#define LOCAL_PR_ARG __entry->wpan_phy_name
|
#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)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
inet_sk_state_store(newsk, TCP_LISTEN);
|
||||||
err = kernel_listen(ssock, backlog);
|
err = kernel_listen(ssock, backlog);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -44,7 +44,7 @@ enum {
|
||||||
static struct percpu_counter mptcp_sockets_allocated ____cacheline_aligned_in_smp;
|
static struct percpu_counter mptcp_sockets_allocated ____cacheline_aligned_in_smp;
|
||||||
|
|
||||||
static void __mptcp_destroy_sock(struct sock *sk);
|
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);
|
DEFINE_PER_CPU(struct mptcp_delegated_action, mptcp_delegated_actions);
|
||||||
static struct net_device mptcp_napi_dev;
|
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);
|
struct mptcp_sock *msk = mptcp_sk(sk);
|
||||||
|
|
||||||
return !__mptcp_check_fallback(msk) &&
|
return ((1 << sk->sk_state) &
|
||||||
((1 << sk->sk_state) &
|
|
||||||
(TCPF_FIN_WAIT1 | TCPF_CLOSING | TCPF_LAST_ACK)) &&
|
(TCPF_FIN_WAIT1 | TCPF_CLOSING | TCPF_LAST_ACK)) &&
|
||||||
msk->write_seq == READ_ONCE(msk->snd_una);
|
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;
|
u64 rcv_data_fin_seq;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
if (__mptcp_check_fallback(msk))
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
/* Need to ack a DATA_FIN received from a peer while this side
|
/* Need to ack a DATA_FIN received from a peer while this side
|
||||||
* of the connection is in ESTABLISHED, FIN_WAIT1, or FIN_WAIT2.
|
* of the connection is in ESTABLISHED, FIN_WAIT1, or FIN_WAIT2.
|
||||||
* msk->rcv_data_fin was set when parsing the incoming options
|
* 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;
|
ret = true;
|
||||||
mptcp_send_ack(msk);
|
if (!__mptcp_check_fallback(msk))
|
||||||
|
mptcp_send_ack(msk);
|
||||||
mptcp_close_wake_up(sk);
|
mptcp_close_wake_up(sk);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -850,12 +847,12 @@ static bool __mptcp_finish_join(struct mptcp_sock *msk, struct sock *ssk)
|
||||||
return true;
|
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_subflow_context *tmp, *subflow;
|
||||||
struct mptcp_sock *msk = mptcp_sk(sk);
|
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);
|
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
|
||||||
bool slow = lock_sock_fast(ssk);
|
bool slow = lock_sock_fast(ssk);
|
||||||
|
|
||||||
|
@ -897,49 +894,6 @@ bool mptcp_schedule_work(struct sock *sk)
|
||||||
return false;
|
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)
|
static struct sock *mptcp_subflow_recv_lookup(const struct mptcp_sock *msk)
|
||||||
{
|
{
|
||||||
struct mptcp_subflow_context *subflow;
|
struct mptcp_subflow_context *subflow;
|
||||||
|
@ -1609,7 +1563,7 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
|
||||||
if (!mptcp_timer_pending(sk))
|
if (!mptcp_timer_pending(sk))
|
||||||
mptcp_reset_timer(sk);
|
mptcp_reset_timer(sk);
|
||||||
if (do_check_data_fin)
|
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)
|
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)
|
if (ret && ret != -EINPROGRESS && ret != -ERESTARTSYS && ret != -EINTR)
|
||||||
*copied_syn = 0;
|
*copied_syn = 0;
|
||||||
} else if (ret && ret != -EINPROGRESS) {
|
} 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;
|
inet_sk(sk)->defer_connect = 0;
|
||||||
|
|
||||||
|
@ -2158,9 +2118,6 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_and_clear_bit(MPTCP_WORK_EOF, &msk->flags))
|
|
||||||
mptcp_check_for_eof(msk);
|
|
||||||
|
|
||||||
if (sk->sk_shutdown & RCV_SHUTDOWN) {
|
if (sk->sk_shutdown & RCV_SHUTDOWN) {
|
||||||
/* race breaker: the shutdown could be after the
|
/* race breaker: the shutdown could be after the
|
||||||
* previous receive queue check
|
* 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);
|
need_push = (flags & MPTCP_CF_PUSH) && __mptcp_retransmit_pending_data(sk);
|
||||||
if (!dispose_it) {
|
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;
|
msk->subflow->state = SS_UNCONNECTED;
|
||||||
mptcp_subflow_ctx_reset(subflow);
|
mptcp_subflow_ctx_reset(subflow);
|
||||||
release_sock(ssk);
|
release_sock(ssk);
|
||||||
|
@ -2408,13 +2368,6 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
|
||||||
kfree_rcu(subflow, rcu);
|
kfree_rcu(subflow, rcu);
|
||||||
} else {
|
} else {
|
||||||
/* otherwise tcp will dispose of the ssk and subflow ctx */
|
/* 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);
|
__tcp_close(ssk, 0);
|
||||||
|
|
||||||
/* close acquired an extra ref */
|
/* 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)))
|
if (unlikely((1 << state) & (TCPF_CLOSE | TCPF_LISTEN)))
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
mptcp_check_data_fin_ack(sk);
|
|
||||||
|
|
||||||
mptcp_check_fastclose(msk);
|
mptcp_check_fastclose(msk);
|
||||||
|
|
||||||
mptcp_pm_nl_work(msk);
|
mptcp_pm_nl_work(msk);
|
||||||
|
|
||||||
if (test_and_clear_bit(MPTCP_WORK_EOF, &msk->flags))
|
mptcp_check_send_data_fin(sk);
|
||||||
mptcp_check_for_eof(msk);
|
mptcp_check_data_fin_ack(sk);
|
||||||
|
|
||||||
__mptcp_check_send_data_fin(sk);
|
|
||||||
mptcp_check_data_fin(sk);
|
mptcp_check_data_fin(sk);
|
||||||
|
|
||||||
if (test_and_clear_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags))
|
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;
|
break;
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case TCP_SYN_SENT:
|
case TCP_SYN_SENT:
|
||||||
tcp_disconnect(ssk, O_NONBLOCK);
|
WARN_ON_ONCE(tcp_disconnect(ssk, O_NONBLOCK));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (__mptcp_check_fallback(mptcp_sk(sk))) {
|
if (__mptcp_check_fallback(mptcp_sk(sk))) {
|
||||||
pr_debug("Fallback");
|
pr_debug("Fallback");
|
||||||
ssk->sk_shutdown |= how;
|
ssk->sk_shutdown |= how;
|
||||||
tcp_shutdown(ssk, 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 {
|
} else {
|
||||||
pr_debug("Sending DATA_FIN on subflow %p", ssk);
|
pr_debug("Sending DATA_FIN on subflow %p", ssk);
|
||||||
tcp_send_ack(ssk);
|
tcp_send_ack(ssk);
|
||||||
|
@ -2858,7 +2813,7 @@ static int mptcp_close_state(struct sock *sk)
|
||||||
return next & TCP_ACTION_FIN;
|
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_subflow_context *subflow;
|
||||||
struct mptcp_sock *msk = mptcp_sk(sk);
|
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);
|
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) {
|
mptcp_for_each_subflow(msk, subflow) {
|
||||||
struct sock *tcp_sk = mptcp_subflow_tcp_sock(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->write_seq, msk->write_seq + 1);
|
||||||
WRITE_ONCE(msk->snd_data_fin_enable, 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)
|
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;
|
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)
|
struct sock *ssk;
|
||||||
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
|
|
||||||
|
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)
|
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);
|
WRITE_ONCE(sk->sk_shutdown, SHUTDOWN_MASK);
|
||||||
|
|
||||||
if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) {
|
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);
|
inet_sk_state_store(sk, TCP_CLOSE);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -3073,15 +3029,20 @@ static int mptcp_disconnect(struct sock *sk, int flags)
|
||||||
{
|
{
|
||||||
struct mptcp_sock *msk = mptcp_sk(sk);
|
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
|
/* 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
|
* subflows cleanup code due to lock nesting (we are already under
|
||||||
* msk->firstsocket lock). Do nothing and leave the cleanup to the
|
* msk->firstsocket lock).
|
||||||
* caller.
|
|
||||||
*/
|
*/
|
||||||
if (msk->fastopening)
|
if (msk->fastopening)
|
||||||
return 0;
|
return -EBUSY;
|
||||||
|
|
||||||
mptcp_listen_inuse_dec(sk);
|
mptcp_check_listen_stop(sk);
|
||||||
inet_sk_state_store(sk, TCP_CLOSE);
|
inet_sk_state_store(sk, TCP_CLOSE);
|
||||||
|
|
||||||
mptcp_stop_timer(sk);
|
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);
|
inet_sk(nsk)->pinet6 = mptcp_inet6_sk(nsk);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
nsk->sk_wait_pending = 0;
|
||||||
__mptcp_init_sock(nsk);
|
__mptcp_init_sock(nsk);
|
||||||
|
|
||||||
msk = mptcp_sk(nsk);
|
msk = mptcp_sk(nsk);
|
||||||
|
@ -3327,9 +3289,14 @@ static void mptcp_release_cb(struct sock *sk)
|
||||||
for (;;) {
|
for (;;) {
|
||||||
unsigned long flags = (msk->cb_flags & MPTCP_FLAGS_PROCESS_CTX_NEED) |
|
unsigned long flags = (msk->cb_flags & MPTCP_FLAGS_PROCESS_CTX_NEED) |
|
||||||
msk->push_pending;
|
msk->push_pending;
|
||||||
|
struct list_head join_list;
|
||||||
|
|
||||||
if (!flags)
|
if (!flags)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&join_list);
|
||||||
|
list_splice_init(&msk->join_list, &join_list);
|
||||||
|
|
||||||
/* the following actions acquire the subflow socket lock
|
/* the following actions acquire the subflow socket lock
|
||||||
*
|
*
|
||||||
* 1) can't be invoked in atomic scope
|
* 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->push_pending = 0;
|
||||||
msk->cb_flags &= ~flags;
|
msk->cb_flags &= ~flags;
|
||||||
spin_unlock_bh(&sk->sk_lock.slock);
|
spin_unlock_bh(&sk->sk_lock.slock);
|
||||||
|
|
||||||
if (flags & BIT(MPTCP_FLUSH_JOIN_LIST))
|
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))
|
if (flags & BIT(MPTCP_PUSH_PENDING))
|
||||||
__mptcp_push_pending(sk, 0);
|
__mptcp_push_pending(sk, 0);
|
||||||
if (flags & BIT(MPTCP_RETRANSMIT))
|
if (flags & BIT(MPTCP_RETRANSMIT))
|
||||||
|
|
|
@ -113,7 +113,6 @@
|
||||||
/* MPTCP socket atomic flags */
|
/* MPTCP socket atomic flags */
|
||||||
#define MPTCP_NOSPACE 1
|
#define MPTCP_NOSPACE 1
|
||||||
#define MPTCP_WORK_RTX 2
|
#define MPTCP_WORK_RTX 2
|
||||||
#define MPTCP_WORK_EOF 3
|
|
||||||
#define MPTCP_FALLBACK_DONE 4
|
#define MPTCP_FALLBACK_DONE 4
|
||||||
#define MPTCP_WORK_CLOSE_SUBFLOW 5
|
#define MPTCP_WORK_CLOSE_SUBFLOW 5
|
||||||
|
|
||||||
|
@ -476,14 +475,13 @@ struct mptcp_subflow_context {
|
||||||
send_mp_fail : 1,
|
send_mp_fail : 1,
|
||||||
send_fastclose : 1,
|
send_fastclose : 1,
|
||||||
send_infinite_map : 1,
|
send_infinite_map : 1,
|
||||||
rx_eof : 1,
|
|
||||||
remote_key_valid : 1, /* received the peer key from */
|
remote_key_valid : 1, /* received the peer key from */
|
||||||
disposable : 1, /* ctx can be free at ulp release time */
|
disposable : 1, /* ctx can be free at ulp release time */
|
||||||
stale : 1, /* unable to snd/rcv data, do not use for xmit */
|
stale : 1, /* unable to snd/rcv data, do not use for xmit */
|
||||||
local_id_valid : 1, /* local_id is correctly initialized */
|
local_id_valid : 1, /* local_id is correctly initialized */
|
||||||
valid_csum_seen : 1, /* at least one csum validated */
|
valid_csum_seen : 1, /* at least one csum validated */
|
||||||
is_mptfo : 1, /* subflow is doing TFO */
|
is_mptfo : 1, /* subflow is doing TFO */
|
||||||
__unused : 8;
|
__unused : 9;
|
||||||
enum mptcp_data_avail data_avail;
|
enum mptcp_data_avail data_avail;
|
||||||
u32 remote_nonce;
|
u32 remote_nonce;
|
||||||
u64 thmac;
|
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_check_push(struct sock *sk, struct sock *ssk);
|
||||||
void __mptcp_data_acked(struct sock *sk);
|
void __mptcp_data_acked(struct sock *sk);
|
||||||
void __mptcp_error_report(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);
|
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)
|
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 mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
||||||
struct sock *parent = subflow->conn;
|
struct sock *parent = subflow->conn;
|
||||||
|
struct mptcp_sock *msk;
|
||||||
|
|
||||||
__subflow_state_change(sk);
|
__subflow_state_change(sk);
|
||||||
|
|
||||||
|
msk = mptcp_sk(parent);
|
||||||
if (subflow_simultaneous_connect(sk)) {
|
if (subflow_simultaneous_connect(sk)) {
|
||||||
mptcp_propagate_sndbuf(parent, sk);
|
mptcp_propagate_sndbuf(parent, sk);
|
||||||
mptcp_do_fallback(sk);
|
mptcp_do_fallback(sk);
|
||||||
mptcp_rcv_space_init(mptcp_sk(parent), sk);
|
mptcp_rcv_space_init(msk, sk);
|
||||||
pr_fallback(mptcp_sk(parent));
|
pr_fallback(msk);
|
||||||
subflow->conn_finished = 1;
|
subflow->conn_finished = 1;
|
||||||
mptcp_set_connected(parent);
|
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);
|
subflow_sched_work_if_closed(mptcp_sk(parent), sk);
|
||||||
|
|
||||||
if (__mptcp_check_fallback(mptcp_sk(parent)) &&
|
/* when the fallback subflow closes the rx side, trigger a 'dummy'
|
||||||
!subflow->rx_eof && subflow_is_done(sk)) {
|
* ingress data fin, so that the msk state will follow along
|
||||||
subflow->rx_eof = 1;
|
*/
|
||||||
mptcp_subflow_eof(parent);
|
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)
|
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->transport_header = skb->network_header;
|
||||||
|
|
||||||
skb_set_inner_ipproto(skb, next_protocol);
|
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) {
|
if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) {
|
||||||
bool check = false;
|
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->transport_header = skb->network_header;
|
||||||
|
|
||||||
skb_set_inner_ipproto(skb, next_protocol);
|
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) {
|
if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE) {
|
||||||
bool check = false;
|
bool check = false;
|
||||||
|
|
|
@ -151,6 +151,7 @@ static struct nft_trans *nft_trans_alloc_gfp(const struct nft_ctx *ctx,
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&trans->list);
|
INIT_LIST_HEAD(&trans->list);
|
||||||
|
INIT_LIST_HEAD(&trans->binding_list);
|
||||||
trans->msg_type = msg_type;
|
trans->msg_type = msg_type;
|
||||||
trans->ctx = *ctx;
|
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);
|
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->list);
|
||||||
|
list_del(&trans->binding_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nft_trans_destroy(struct nft_trans *trans)
|
||||||
|
{
|
||||||
|
nft_trans_list_del(trans);
|
||||||
kfree(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 nftables_pernet *nft_net;
|
||||||
struct net *net = ctx->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) {
|
switch (trans->msg_type) {
|
||||||
case NFT_MSG_NEWSET:
|
case NFT_MSG_NEWSET:
|
||||||
if (nft_trans_set(trans) == set)
|
if (nft_trans_set(trans) == set)
|
||||||
nft_trans_set_bound(trans) = true;
|
nft_trans_set_bound(trans) = bind;
|
||||||
break;
|
break;
|
||||||
case NFT_MSG_NEWSETELEM:
|
case NFT_MSG_NEWSETELEM:
|
||||||
if (nft_trans_elem_set(trans) == set)
|
if (nft_trans_elem_set(trans) == set)
|
||||||
nft_trans_elem_set_bound(trans) = true;
|
nft_trans_elem_set_bound(trans) = bind;
|
||||||
break;
|
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,
|
static int nft_netdev_register_hooks(struct net *net,
|
||||||
struct list_head *hook_list)
|
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);
|
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);
|
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]));
|
ntohl(nla_get_be32(ctx->nla[NFTA_CHAIN_ID]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
nft_trans_chain(trans) = ctx->chain;
|
||||||
nft_trans_commit_list_add_tail(ctx->net, trans);
|
nft_trans_commit_list_add_tail(ctx->net, trans);
|
||||||
|
|
||||||
return trans;
|
return trans;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,8 +443,7 @@ static int nft_delchain(struct nft_ctx *ctx)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nft_rule_expr_activate(const struct nft_ctx *ctx,
|
void nft_rule_expr_activate(const struct nft_ctx *ctx, struct nft_rule *rule)
|
||||||
struct nft_rule *rule)
|
|
||||||
{
|
{
|
||||||
struct nft_expr *expr;
|
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,
|
void nft_rule_expr_deactivate(const struct nft_ctx *ctx, struct nft_rule *rule,
|
||||||
struct nft_rule *rule,
|
enum nft_trans_phase phase)
|
||||||
enum nft_trans_phase phase)
|
|
||||||
{
|
{
|
||||||
struct nft_expr *expr;
|
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);
|
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)
|
static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
@ -503,6 +639,9 @@ static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set)
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
|
||||||
|
nft_map_deactivate(ctx, set);
|
||||||
|
|
||||||
nft_deactivate_next(ctx->net, set);
|
nft_deactivate_next(ctx->net, set);
|
||||||
ctx->table->use--;
|
ctx->table->use--;
|
||||||
|
|
||||||
|
@ -2226,7 +2365,7 @@ static int nft_basechain_init(struct nft_base_chain *basechain, u8 family,
|
||||||
return 0;
|
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;
|
int err;
|
||||||
|
|
||||||
|
@ -2528,6 +2667,8 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
|
||||||
nft_trans_basechain(trans) = basechain;
|
nft_trans_basechain(trans) = basechain;
|
||||||
INIT_LIST_HEAD(&nft_trans_chain_hooks(trans));
|
INIT_LIST_HEAD(&nft_trans_chain_hooks(trans));
|
||||||
list_splice(&hook.list, &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);
|
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);
|
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)
|
struct netlink_ext_ack *extack)
|
||||||
{
|
{
|
||||||
|
const struct nft_chain *chain = &basechain->chain;
|
||||||
const struct nlattr * const *nla = ctx->nla;
|
const struct nlattr * const *nla = ctx->nla;
|
||||||
struct nft_chain_hook chain_hook = {};
|
struct nft_chain_hook chain_hook = {};
|
||||||
struct nft_base_chain *basechain;
|
|
||||||
struct nft_hook *this, *hook;
|
struct nft_hook *this, *hook;
|
||||||
LIST_HEAD(chain_del_list);
|
LIST_HEAD(chain_del_list);
|
||||||
struct nft_trans *trans;
|
struct nft_trans *trans;
|
||||||
int err;
|
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,
|
err = nft_chain_parse_hook(ctx->net, basechain, nla, &chain_hook,
|
||||||
ctx->family, chain->flags, extack);
|
ctx->family, chain->flags, extack);
|
||||||
if (err < 0)
|
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)
|
if (chain->flags & NFT_CHAIN_HW_OFFLOAD)
|
||||||
return -EOPNOTSUPP;
|
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 &&
|
if (info->nlh->nlmsg_flags & NLM_F_NONREC &&
|
||||||
|
@ -3490,8 +3633,7 @@ static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
|
void nf_tables_rule_destroy(const struct nft_ctx *ctx, struct nft_rule *rule)
|
||||||
struct nft_rule *rule)
|
|
||||||
{
|
{
|
||||||
struct nft_expr *expr, *next;
|
struct nft_expr *expr, *next;
|
||||||
|
|
||||||
|
@ -3508,7 +3650,7 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
|
||||||
kfree(rule);
|
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);
|
nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_RELEASE);
|
||||||
nf_tables_rule_destroy(ctx, rule);
|
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;
|
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)
|
int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set)
|
||||||
{
|
{
|
||||||
u8 genmask = nft_genmask_next(ctx->net);
|
u8 genmask = nft_genmask_next(ctx->net);
|
||||||
|
@ -3844,7 +3980,7 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
|
||||||
if (flow)
|
if (flow)
|
||||||
nft_flow_rule_destroy(flow);
|
nft_flow_rule_destroy(flow);
|
||||||
err_release_rule:
|
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);
|
nf_tables_rule_destroy(&ctx, rule);
|
||||||
err_release_expr:
|
err_release_expr:
|
||||||
for (i = 0; i < n; i++) {
|
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))
|
if (!(flags & NFT_SET_TIMEOUT))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (flags & NFT_SET_ANONYMOUS)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
err = nf_msecs_to_jiffies64(nla[NFTA_SET_TIMEOUT], &desc.timeout);
|
err = nf_msecs_to_jiffies64(nla[NFTA_SET_TIMEOUT], &desc.timeout);
|
||||||
if (err)
|
if (err)
|
||||||
return 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 (nla[NFTA_SET_GC_INTERVAL] != NULL) {
|
||||||
if (!(flags & NFT_SET_TIMEOUT))
|
if (!(flags & NFT_SET_TIMEOUT))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (flags & NFT_SET_ANONYMOUS)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
desc.gc_int = ntohl(nla_get_be32(nla[NFTA_SET_GC_INTERVAL]));
|
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)
|
if (info->nlh->nlmsg_flags & NLM_F_REPLACE)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (nft_set_is_anonymous(set))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
err = nft_set_expr_alloc(&ctx, set, nla, exprs, &num_exprs, flags);
|
err = nft_set_expr_alloc(&ctx, set, nla, exprs, &num_exprs, flags);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
@ -4934,7 +5080,7 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
|
||||||
for (i = 0; i < set->num_exprs; i++)
|
for (i = 0; i < set->num_exprs; i++)
|
||||||
nft_expr_destroy(&ctx, set->exprs[i]);
|
nft_expr_destroy(&ctx, set->exprs[i]);
|
||||||
err_set_destroy:
|
err_set_destroy:
|
||||||
ops->destroy(set);
|
ops->destroy(&ctx, set);
|
||||||
err_set_init:
|
err_set_init:
|
||||||
kfree(set->name);
|
kfree(set->name);
|
||||||
err_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_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
|
||||||
list_del_rcu(&catchall->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);
|
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++)
|
for (i = 0; i < set->num_exprs; i++)
|
||||||
nft_expr_destroy(ctx, set->exprs[i]);
|
nft_expr_destroy(ctx, set->exprs[i]);
|
||||||
|
|
||||||
set->ops->destroy(set);
|
set->ops->destroy(ctx, set);
|
||||||
nft_set_catchall_destroy(ctx, set);
|
nft_set_catchall_destroy(ctx, set);
|
||||||
kfree(set->name);
|
kfree(set->name);
|
||||||
kvfree(set);
|
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)
|
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);
|
nft_clear(ctx->net, set);
|
||||||
|
}
|
||||||
|
|
||||||
set->use++;
|
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)
|
enum nft_trans_phase phase)
|
||||||
{
|
{
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
case NFT_TRANS_PREPARE:
|
case NFT_TRANS_PREPARE_ERROR:
|
||||||
|
nft_set_trans_unbind(ctx, set);
|
||||||
if (nft_set_is_anonymous(set))
|
if (nft_set_is_anonymous(set))
|
||||||
nft_deactivate_next(ctx->net, 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--;
|
set->use--;
|
||||||
return;
|
return;
|
||||||
case NFT_TRANS_ABORT:
|
case NFT_TRANS_ABORT:
|
||||||
case NFT_TRANS_RELEASE:
|
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--;
|
set->use--;
|
||||||
fallthrough;
|
fallthrough;
|
||||||
default:
|
default:
|
||||||
|
@ -5903,6 +6113,7 @@ static void nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
|
||||||
__nft_set_elem_expr_destroy(ctx, expr);
|
__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,
|
void nft_set_elem_destroy(const struct nft_set *set, void *elem,
|
||||||
bool destroy_expr)
|
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);
|
EXPORT_SYMBOL_GPL(nft_set_elem_destroy);
|
||||||
|
|
||||||
/* Only called from commit path, nft_setelem_data_deactivate() already deals
|
/* Destroy element. References have been already dropped in the preparation
|
||||||
* with the refcounting from the preparation phase.
|
* path via nft_setelem_data_deactivate().
|
||||||
*/
|
*/
|
||||||
static void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
|
void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
|
||||||
const struct nft_set *set, void *elem)
|
const struct nft_set *set, void *elem)
|
||||||
{
|
{
|
||||||
struct nft_set_ext *ext = nft_set_elem_ext(set, 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)
|
if (flags)
|
||||||
*nft_set_ext_flags(ext) = flags;
|
*nft_set_ext_flags(ext) = flags;
|
||||||
|
|
||||||
|
if (obj) {
|
||||||
|
*nft_set_ext_obj(ext) = obj;
|
||||||
|
obj->use++;
|
||||||
|
}
|
||||||
if (ulen > 0) {
|
if (ulen > 0) {
|
||||||
if (nft_set_ext_check(&tmpl, NFT_SET_EXT_USERDATA, ulen) < 0) {
|
if (nft_set_ext_check(&tmpl, NFT_SET_EXT_USERDATA, ulen) < 0) {
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto err_elem_userdata;
|
goto err_elem_free;
|
||||||
}
|
}
|
||||||
udata = nft_set_ext_userdata(ext);
|
udata = nft_set_ext_userdata(ext);
|
||||||
udata->len = ulen - 1;
|
udata->len = ulen - 1;
|
||||||
nla_memcpy(&udata->data, nla[NFTA_SET_ELEM_USERDATA], ulen);
|
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);
|
err = nft_set_elem_expr_setup(ctx, &tmpl, ext, expr_array, num_exprs);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto err_elem_free;
|
goto err_elem_free;
|
||||||
|
@ -6558,10 +6769,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
|
||||||
err_element_clash:
|
err_element_clash:
|
||||||
kfree(trans);
|
kfree(trans);
|
||||||
err_elem_free:
|
err_elem_free:
|
||||||
if (obj)
|
nft_set_elem_destroy(set, elem.priv, true);
|
||||||
obj->use--;
|
|
||||||
err_elem_userdata:
|
|
||||||
nf_tables_set_elem_destroy(ctx, set, elem.priv);
|
|
||||||
err_parse_data:
|
err_parse_data:
|
||||||
if (nla[NFTA_SET_ELEM_DATA] != NULL)
|
if (nla[NFTA_SET_ELEM_DATA] != NULL)
|
||||||
nft_data_release(&elem.data.val, desc.type);
|
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))
|
if (IS_ERR(set))
|
||||||
return PTR_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;
|
return -EBUSY;
|
||||||
|
|
||||||
nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
|
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)
|
void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
|
||||||
{
|
{
|
||||||
struct nft_chain *chain;
|
struct nft_chain *chain;
|
||||||
struct nft_rule *rule;
|
|
||||||
|
|
||||||
if (type == NFT_DATA_VERDICT) {
|
if (type == NFT_DATA_VERDICT) {
|
||||||
switch (data->verdict.code) {
|
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:
|
case NFT_GOTO:
|
||||||
chain = data->verdict.chain;
|
chain = data->verdict.chain;
|
||||||
chain->use++;
|
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;
|
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);
|
set = nft_set_lookup(table, nla[NFTA_SET_ELEM_LIST_SET], genmask);
|
||||||
if (IS_ERR(set))
|
if (IS_ERR(set))
|
||||||
return PTR_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;
|
return -EBUSY;
|
||||||
|
|
||||||
nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
|
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)
|
enum nft_trans_phase phase)
|
||||||
{
|
{
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
|
case NFT_TRANS_PREPARE_ERROR:
|
||||||
case NFT_TRANS_PREPARE:
|
case NFT_TRANS_PREPARE:
|
||||||
case NFT_TRANS_ABORT:
|
case NFT_TRANS_ABORT:
|
||||||
case NFT_TRANS_RELEASE:
|
case NFT_TRANS_RELEASE:
|
||||||
|
@ -8943,7 +9145,7 @@ static void nf_tables_trans_destroy_work(struct work_struct *w)
|
||||||
synchronize_rcu();
|
synchronize_rcu();
|
||||||
|
|
||||||
list_for_each_entry_safe(trans, next, &head, list) {
|
list_for_each_entry_safe(trans, next, &head, list) {
|
||||||
list_del(&trans->list);
|
nft_trans_list_del(trans);
|
||||||
nft_commit_release(trans);
|
nft_commit_release(trans);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9308,6 +9510,27 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
|
||||||
return 0;
|
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. */
|
/* 0. Validate ruleset, otherwise roll back for error reporting. */
|
||||||
if (nf_tables_validate(net) < 0)
|
if (nf_tables_validate(net) < 0)
|
||||||
return -EAGAIN;
|
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));
|
kfree(nft_trans_chain_name(trans));
|
||||||
nft_trans_destroy(trans);
|
nft_trans_destroy(trans);
|
||||||
} else {
|
} else {
|
||||||
if (nft_chain_is_bound(trans->ctx.chain)) {
|
if (nft_trans_chain_bound(trans)) {
|
||||||
nft_trans_destroy(trans);
|
nft_trans_destroy(trans);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -9700,6 +9923,10 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
|
||||||
nft_trans_destroy(trans);
|
nft_trans_destroy(trans);
|
||||||
break;
|
break;
|
||||||
case NFT_MSG_NEWRULE:
|
case NFT_MSG_NEWRULE:
|
||||||
|
if (nft_trans_rule_bound(trans)) {
|
||||||
|
nft_trans_destroy(trans);
|
||||||
|
break;
|
||||||
|
}
|
||||||
trans->ctx.chain->use--;
|
trans->ctx.chain->use--;
|
||||||
list_del_rcu(&nft_trans_rule(trans)->list);
|
list_del_rcu(&nft_trans_rule(trans)->list);
|
||||||
nft_rule_expr_deactivate(&trans->ctx,
|
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:
|
case NFT_MSG_DESTROYSET:
|
||||||
trans->ctx.table->use++;
|
trans->ctx.table->use++;
|
||||||
nft_clear(trans->ctx.net, nft_trans_set(trans));
|
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);
|
nft_trans_destroy(trans);
|
||||||
break;
|
break;
|
||||||
case NFT_MSG_NEWSETELEM:
|
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,
|
list_for_each_entry_safe_reverse(trans, next,
|
||||||
&nft_net->commit_list, list) {
|
&nft_net->commit_list, list) {
|
||||||
list_del(&trans->list);
|
nft_trans_list_del(trans);
|
||||||
nf_tables_abort_release(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)
|
static void nft_verdict_uninit(const struct nft_data *data)
|
||||||
{
|
{
|
||||||
struct nft_chain *chain;
|
struct nft_chain *chain;
|
||||||
struct nft_rule *rule;
|
|
||||||
|
|
||||||
switch (data->verdict.code) {
|
switch (data->verdict.code) {
|
||||||
case NFT_JUMP:
|
case NFT_JUMP:
|
||||||
case NFT_GOTO:
|
case NFT_GOTO:
|
||||||
chain = data->verdict.chain;
|
chain = data->verdict.chain;
|
||||||
chain->use--;
|
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;
|
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_for_each_entry_safe(set, ns, &table->sets, list) {
|
||||||
list_del(&set->list);
|
list_del(&set->list);
|
||||||
table->use--;
|
table->use--;
|
||||||
|
if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
|
||||||
|
nft_map_deactivate(&ctx, set);
|
||||||
|
|
||||||
nft_set_destroy(&ctx, set);
|
nft_set_destroy(&ctx, set);
|
||||||
}
|
}
|
||||||
list_for_each_entry_safe(obj, ne, &table->objects, list) {
|
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->tables);
|
||||||
INIT_LIST_HEAD(&nft_net->commit_list);
|
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->module_list);
|
||||||
INIT_LIST_HEAD(&nft_net->notify_list);
|
INIT_LIST_HEAD(&nft_net->notify_list);
|
||||||
mutex_init(&nft_net->commit_mutex);
|
mutex_init(&nft_net->commit_mutex);
|
||||||
|
|
|
@ -439,3 +439,4 @@ module_init(nfnl_osf_init);
|
||||||
module_exit(nfnl_osf_fini);
|
module_exit(nfnl_osf_fini);
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
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) {
|
switch (priv->data.verdict.code) {
|
||||||
case NFT_JUMP:
|
case NFT_JUMP:
|
||||||
case NFT_GOTO:
|
case NFT_GOTO:
|
||||||
if (nft_chain_is_bound(chain)) {
|
err = nf_tables_bind_chain(ctx, chain);
|
||||||
err = -EBUSY;
|
if (err < 0)
|
||||||
goto err1;
|
return err;
|
||||||
}
|
|
||||||
chain->bound = true;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -98,6 +96,31 @@ static void nft_immediate_activate(const struct nft_ctx *ctx,
|
||||||
const struct nft_expr *expr)
|
const struct nft_expr *expr)
|
||||||
{
|
{
|
||||||
const struct nft_immediate_expr *priv = nft_expr_priv(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));
|
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)
|
enum nft_trans_phase phase)
|
||||||
{
|
{
|
||||||
const struct nft_immediate_expr *priv = nft_expr_priv(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_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)
|
if (phase == NFT_TRANS_COMMIT)
|
||||||
return;
|
return;
|
||||||
|
@ -131,15 +191,27 @@ static void nft_immediate_destroy(const struct nft_ctx *ctx,
|
||||||
case NFT_GOTO:
|
case NFT_GOTO:
|
||||||
chain = data->verdict.chain;
|
chain = data->verdict.chain;
|
||||||
|
|
||||||
if (!nft_chain_is_bound(chain))
|
if (!nft_chain_binding(chain))
|
||||||
break;
|
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 = *ctx;
|
||||||
chain_ctx.chain = chain;
|
chain_ctx.chain = chain;
|
||||||
|
|
||||||
list_for_each_entry_safe(rule, n, &chain->rules, list)
|
chain->use--;
|
||||||
nf_tables_rule_release(&chain_ctx, rule);
|
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);
|
nf_tables_chain_destroy(&chain_ctx);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -271,13 +271,14 @@ static int nft_bitmap_init(const struct nft_set *set,
|
||||||
return 0;
|
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 *priv = nft_set_priv(set);
|
||||||
struct nft_bitmap_elem *be, *n;
|
struct nft_bitmap_elem *be, *n;
|
||||||
|
|
||||||
list_for_each_entry_safe(be, n, &priv->list, head)
|
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,
|
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;
|
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)
|
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 *priv = nft_set_priv(set);
|
||||||
|
struct nft_rhash_ctx rhash_ctx = {
|
||||||
|
.ctx = *ctx,
|
||||||
|
.set = set,
|
||||||
|
};
|
||||||
|
|
||||||
cancel_delayed_work_sync(&priv->gc_work);
|
cancel_delayed_work_sync(&priv->gc_work);
|
||||||
rcu_barrier();
|
rcu_barrier();
|
||||||
rhashtable_free_and_destroy(&priv->ht, nft_rhash_elem_destroy,
|
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 */
|
/* 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;
|
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 *priv = nft_set_priv(set);
|
||||||
struct nft_hash_elem *he;
|
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++) {
|
for (i = 0; i < priv->buckets; i++) {
|
||||||
hlist_for_each_entry_safe(he, next, &priv->table[i], node) {
|
hlist_for_each_entry_safe(he, next, &priv->table[i], node) {
|
||||||
hlist_del_rcu(&he->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_set_iter *iter)
|
||||||
{
|
{
|
||||||
struct nft_pipapo *priv = nft_set_priv(set);
|
struct nft_pipapo *priv = nft_set_priv(set);
|
||||||
|
struct net *net = read_pnet(&set->net);
|
||||||
struct nft_pipapo_match *m;
|
struct nft_pipapo_match *m;
|
||||||
struct nft_pipapo_field *f;
|
struct nft_pipapo_field *f;
|
||||||
int i, r;
|
int i, r;
|
||||||
|
|
||||||
rcu_read_lock();
|
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))
|
if (unlikely(!m))
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -2148,10 +2152,12 @@ static int nft_pipapo_init(const struct nft_set *set,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nft_set_pipapo_match_destroy() - Destroy elements from key mapping array
|
* nft_set_pipapo_match_destroy() - Destroy elements from key mapping array
|
||||||
|
* @ctx: context
|
||||||
* @set: nftables API set representation
|
* @set: nftables API set representation
|
||||||
* @m: matching data pointing to key mapping array
|
* @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_match *m)
|
||||||
{
|
{
|
||||||
struct nft_pipapo_field *f;
|
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;
|
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
|
* nft_pipapo_destroy() - Free private data for set and all committed elements
|
||||||
|
* @ctx: context
|
||||||
* @set: nftables API set representation
|
* @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 *priv = nft_set_priv(set);
|
||||||
struct nft_pipapo_match *m;
|
struct nft_pipapo_match *m;
|
||||||
|
@ -2186,7 +2194,7 @@ static void nft_pipapo_destroy(const struct nft_set *set)
|
||||||
if (m) {
|
if (m) {
|
||||||
rcu_barrier();
|
rcu_barrier();
|
||||||
|
|
||||||
nft_set_pipapo_match_destroy(set, m);
|
nft_set_pipapo_match_destroy(ctx, set, m);
|
||||||
|
|
||||||
#ifdef NFT_PIPAPO_ALIGN
|
#ifdef NFT_PIPAPO_ALIGN
|
||||||
free_percpu(m->scratch_aligned);
|
free_percpu(m->scratch_aligned);
|
||||||
|
@ -2203,7 +2211,7 @@ static void nft_pipapo_destroy(const struct nft_set *set)
|
||||||
m = priv->clone;
|
m = priv->clone;
|
||||||
|
|
||||||
if (priv->dirty)
|
if (priv->dirty)
|
||||||
nft_set_pipapo_match_destroy(set, m);
|
nft_set_pipapo_match_destroy(ctx, set, m);
|
||||||
|
|
||||||
#ifdef NFT_PIPAPO_ALIGN
|
#ifdef NFT_PIPAPO_ALIGN
|
||||||
free_percpu(priv->clone->scratch_aligned);
|
free_percpu(priv->clone->scratch_aligned);
|
||||||
|
|
|
@ -664,7 +664,8 @@ static int nft_rbtree_init(const struct nft_set *set,
|
||||||
return 0;
|
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 *priv = nft_set_priv(set);
|
||||||
struct nft_rbtree_elem *rbe;
|
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) {
|
while ((node = priv->root.rb_node) != NULL) {
|
||||||
rb_erase(node, &priv->root);
|
rb_erase(node, &priv->root);
|
||||||
rbe = rb_entry(node, struct nft_rbtree_elem, node);
|
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_DESCRIPTION("Passive OS fingerprint matching.");
|
||||||
MODULE_ALIAS("ipt_osf");
|
MODULE_ALIAS("ipt_osf");
|
||||||
MODULE_ALIAS("ip6t_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)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
sch_tree_lock(sch);
|
||||||
/* backup q->clg and q->loss_model */
|
/* backup q->clg and q->loss_model */
|
||||||
old_clg = q->clg;
|
old_clg = q->clg;
|
||||||
old_loss_model = q->loss_model;
|
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]);
|
ret = get_loss_clg(q, tb[TCA_NETEM_LOSS]);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
q->loss_model = old_loss_model;
|
q->loss_model = old_loss_model;
|
||||||
return ret;
|
goto unlock;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
q->loss_model = CLG_RANDOM;
|
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() */
|
/* capping jitter to the range acceptable by tabledist() */
|
||||||
q->jitter = min_t(s64, abs(q->jitter), INT_MAX);
|
q->jitter = min_t(s64, abs(q->jitter), INT_MAX);
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
sch_tree_unlock(sch);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
get_table_failure:
|
get_table_failure:
|
||||||
|
@ -1050,7 +1053,8 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
|
||||||
*/
|
*/
|
||||||
q->clg = old_clg;
|
q->clg = old_clg;
|
||||||
q->loss_model = old_loss_model;
|
q->loss_model = old_loss_model;
|
||||||
return ret;
|
|
||||||
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int netem_init(struct Qdisc *sch, struct nlattr *opt,
|
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));
|
memset(sp->ovec, 0, sizeof(sp->ovec));
|
||||||
sp->olen = 0;
|
sp->olen = 0;
|
||||||
sp->len = 0;
|
sp->len = 0;
|
||||||
|
sp->verified_cnt = 0;
|
||||||
|
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
@ -330,11 +331,10 @@ xfrm_inner_mode_encap_remove(struct xfrm_state *x,
|
||||||
{
|
{
|
||||||
switch (x->props.mode) {
|
switch (x->props.mode) {
|
||||||
case XFRM_MODE_BEET:
|
case XFRM_MODE_BEET:
|
||||||
switch (XFRM_MODE_SKB_CB(skb)->protocol) {
|
switch (x->sel.family) {
|
||||||
case IPPROTO_IPIP:
|
case AF_INET:
|
||||||
case IPPROTO_BEETPH:
|
|
||||||
return xfrm4_remove_beet_encap(x, skb);
|
return xfrm4_remove_beet_encap(x, skb);
|
||||||
case IPPROTO_IPV6:
|
case AF_INET6:
|
||||||
return xfrm6_remove_beet_encap(x, skb);
|
return xfrm6_remove_beet_encap(x, skb);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -310,6 +310,52 @@ static void xfrmi_scrub_packet(struct sk_buff *skb, bool xnet)
|
||||||
skb->mark = 0;
|
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)
|
static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
|
||||||
{
|
{
|
||||||
const struct xfrm_mode *inner_mode;
|
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 = {
|
static struct xfrm6_protocol xfrmi_esp6_protocol __read_mostly = {
|
||||||
.handler = xfrm6_rcv,
|
.handler = xfrmi6_rcv,
|
||||||
.input_handler = xfrm_input,
|
.input_handler = xfrmi6_input,
|
||||||
.cb_handler = xfrmi_rcv_cb,
|
.cb_handler = xfrmi_rcv_cb,
|
||||||
.err_handler = xfrmi6_err,
|
.err_handler = xfrmi6_err,
|
||||||
.priority = 10,
|
.priority = 10,
|
||||||
|
@ -996,8 +1042,8 @@ static struct xfrm6_tunnel xfrmi_ip6ip_handler __read_mostly = {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = {
|
static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = {
|
||||||
.handler = xfrm4_rcv,
|
.handler = xfrmi4_rcv,
|
||||||
.input_handler = xfrm_input,
|
.input_handler = xfrmi4_input,
|
||||||
.cb_handler = xfrmi_rcv_cb,
|
.cb_handler = xfrmi_rcv_cb,
|
||||||
.err_handler = xfrmi4_err,
|
.err_handler = xfrmi4_err,
|
||||||
.priority = 10,
|
.priority = 10,
|
||||||
|
|
|
@ -1831,6 +1831,7 @@ int xfrm_policy_flush(struct net *net, u8 type, bool task_valid)
|
||||||
|
|
||||||
__xfrm_policy_unlink(pol, dir);
|
__xfrm_policy_unlink(pol, dir);
|
||||||
spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
|
spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
|
||||||
|
xfrm_dev_policy_delete(pol);
|
||||||
cnt++;
|
cnt++;
|
||||||
xfrm_audit_policy_delete(pol, 1, task_valid);
|
xfrm_audit_policy_delete(pol, 1, task_valid);
|
||||||
xfrm_policy_kill(pol);
|
xfrm_policy_kill(pol);
|
||||||
|
@ -1869,6 +1870,7 @@ int xfrm_dev_policy_flush(struct net *net, struct net_device *dev,
|
||||||
|
|
||||||
__xfrm_policy_unlink(pol, dir);
|
__xfrm_policy_unlink(pol, dir);
|
||||||
spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
|
spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
|
||||||
|
xfrm_dev_policy_delete(pol);
|
||||||
cnt++;
|
cnt++;
|
||||||
xfrm_audit_policy_delete(pol, 1, task_valid);
|
xfrm_audit_policy_delete(pol, 1, task_valid);
|
||||||
xfrm_policy_kill(pol);
|
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))
|
if (xfrm_state_ok(tmpl, sp->xvec[idx], family, if_id))
|
||||||
return ++idx;
|
return ++idx;
|
||||||
if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT) {
|
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)
|
if (start == -1)
|
||||||
start = -2-idx;
|
start = -2-idx;
|
||||||
break;
|
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
|
* Order is _important_. Later we will implement
|
||||||
* some barriers, but at the moment barriers
|
* some barriers, but at the moment barriers
|
||||||
* are implied between each two transformations.
|
* 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--) {
|
for (i = xfrm_nr-1, k = 0; i >= 0; i--) {
|
||||||
k = xfrm_policy_ok(tpp[i], sp, k, family, if_id);
|
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);
|
xfrm_pols_put(pols, npols);
|
||||||
|
sp->verified_cnt = k;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLBLOCK);
|
XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLBLOCK);
|
||||||
|
|
29
tools/testing/selftests/bpf/prog_tests/subprogs_extable.c
Normal file
29
tools/testing/selftests/bpf/prog_tests/subprogs_extable.c
Normal file
|
@ -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);
|
||||||
|
}
|
51
tools/testing/selftests/bpf/progs/test_subprogs_extable.c
Normal file
51
tools/testing/selftests/bpf/progs/test_subprogs_extable.c
Normal file
|
@ -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);
|
" ::: __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";
|
char _license[] SEC("license") = "GPL";
|
||||||
|
|
|
@ -249,7 +249,7 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FIXTURE_SETUP() - Prepares the setup function for the fixture.
|
* 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
|
* @fixture_name: fixture name
|
||||||
*
|
*
|
||||||
|
@ -275,7 +275,7 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FIXTURE_TEARDOWN()
|
* 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
|
* @fixture_name: fixture name
|
||||||
*
|
*
|
||||||
|
@ -388,7 +388,7 @@
|
||||||
if (setjmp(_metadata->env) == 0) { \
|
if (setjmp(_metadata->env) == 0) { \
|
||||||
fixture_name##_setup(_metadata, &self, variant->data); \
|
fixture_name##_setup(_metadata, &self, variant->data); \
|
||||||
/* Let setup failure terminate early. */ \
|
/* Let setup failure terminate early. */ \
|
||||||
if (!_metadata->passed) \
|
if (!_metadata->passed || _metadata->skip) \
|
||||||
return; \
|
return; \
|
||||||
_metadata->setup_completed = true; \
|
_metadata->setup_completed = true; \
|
||||||
fixture_name##_##test_name(_metadata, &self, variant->data); \
|
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)
|
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
|
# utilities
|
||||||
|
|
||||||
|
@ -1216,7 +1223,7 @@ ipv4_tcp_novrf()
|
||||||
run_cmd nettest -d ${NSA_DEV} -r ${a}
|
run_cmd nettest -d ${NSA_DEV} -r ${a}
|
||||||
log_test_addr ${a} $? 1 "No server, device client, local conn"
|
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()
|
ipv4_tcp_vrf()
|
||||||
|
@ -1270,9 +1277,11 @@ ipv4_tcp_vrf()
|
||||||
log_test_addr ${a} $? 1 "Global server, local connection"
|
log_test_addr ${a} $? 1 "Global server, local connection"
|
||||||
|
|
||||||
# run MD5 tests
|
# run MD5 tests
|
||||||
setup_vrf_dup
|
if [ "$fips_enabled" = "0" ]; then
|
||||||
ipv4_tcp_md5
|
setup_vrf_dup
|
||||||
cleanup_vrf_dup
|
ipv4_tcp_md5
|
||||||
|
cleanup_vrf_dup
|
||||||
|
fi
|
||||||
|
|
||||||
#
|
#
|
||||||
# enable VRF global server
|
# enable VRF global server
|
||||||
|
@ -2772,7 +2781,7 @@ ipv6_tcp_novrf()
|
||||||
log_test_addr ${a} $? 1 "No server, device client, local conn"
|
log_test_addr ${a} $? 1 "No server, device client, local conn"
|
||||||
done
|
done
|
||||||
|
|
||||||
ipv6_tcp_md5_novrf
|
[ "$fips_enabled" = "1" ] || ipv6_tcp_md5_novrf
|
||||||
}
|
}
|
||||||
|
|
||||||
ipv6_tcp_vrf()
|
ipv6_tcp_vrf()
|
||||||
|
@ -2842,9 +2851,11 @@ ipv6_tcp_vrf()
|
||||||
log_test_addr ${a} $? 1 "Global server, local connection"
|
log_test_addr ${a} $? 1 "Global server, local connection"
|
||||||
|
|
||||||
# run MD5 tests
|
# run MD5 tests
|
||||||
setup_vrf_dup
|
if [ "$fips_enabled" = "0" ]; then
|
||||||
ipv6_tcp_md5
|
setup_vrf_dup
|
||||||
cleanup_vrf_dup
|
ipv6_tcp_md5
|
||||||
|
cleanup_vrf_dup
|
||||||
|
fi
|
||||||
|
|
||||||
#
|
#
|
||||||
# enable VRF global server
|
# enable VRF global server
|
||||||
|
|
|
@ -93,12 +93,16 @@ cleanup()
|
||||||
|
|
||||||
test_gretap()
|
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 ingress 8 0 "mirror to gretap"
|
||||||
full_test_span_gre_dir gt4 egress 0 8 "mirror to gretap"
|
full_test_span_gre_dir gt4 egress 0 8 "mirror to gretap"
|
||||||
}
|
}
|
||||||
|
|
||||||
test_ip6gretap()
|
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 ingress 8 0 "mirror to ip6gretap"
|
||||||
full_test_span_gre_dir gt6 egress 0 8 "mirror to ip6gretap"
|
full_test_span_gre_dir gt6 egress 0 8 "mirror to ip6gretap"
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,12 +90,16 @@ cleanup()
|
||||||
|
|
||||||
test_gretap()
|
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 ingress 8 0 "mirror to gretap"
|
||||||
full_test_span_gre_dir gt4 egress 0 8 "mirror to gretap"
|
full_test_span_gre_dir gt4 egress 0 8 "mirror to gretap"
|
||||||
}
|
}
|
||||||
|
|
||||||
test_ip6gretap()
|
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 ingress 8 0 "mirror to ip6gretap"
|
||||||
full_test_span_gre_dir gt6 egress 0 8 "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 TLS_PAYLOAD_MAX_LEN 16384
|
||||||
#define SOL_TLS 282
|
#define SOL_TLS 282
|
||||||
|
|
||||||
|
static int fips_enabled;
|
||||||
|
|
||||||
struct tls_crypto_info_keys {
|
struct tls_crypto_info_keys {
|
||||||
union {
|
union {
|
||||||
struct tls12_crypto_info_aes_gcm_128 aes128;
|
struct tls12_crypto_info_aes_gcm_128 aes128;
|
||||||
|
@ -235,7 +237,7 @@ FIXTURE_VARIANT(tls)
|
||||||
{
|
{
|
||||||
uint16_t tls_version;
|
uint16_t tls_version;
|
||||||
uint16_t cipher_type;
|
uint16_t cipher_type;
|
||||||
bool nopad;
|
bool nopad, fips_non_compliant;
|
||||||
};
|
};
|
||||||
|
|
||||||
FIXTURE_VARIANT_ADD(tls, 12_aes_gcm)
|
FIXTURE_VARIANT_ADD(tls, 12_aes_gcm)
|
||||||
|
@ -254,24 +256,28 @@ FIXTURE_VARIANT_ADD(tls, 12_chacha)
|
||||||
{
|
{
|
||||||
.tls_version = TLS_1_2_VERSION,
|
.tls_version = TLS_1_2_VERSION,
|
||||||
.cipher_type = TLS_CIPHER_CHACHA20_POLY1305,
|
.cipher_type = TLS_CIPHER_CHACHA20_POLY1305,
|
||||||
|
.fips_non_compliant = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
FIXTURE_VARIANT_ADD(tls, 13_chacha)
|
FIXTURE_VARIANT_ADD(tls, 13_chacha)
|
||||||
{
|
{
|
||||||
.tls_version = TLS_1_3_VERSION,
|
.tls_version = TLS_1_3_VERSION,
|
||||||
.cipher_type = TLS_CIPHER_CHACHA20_POLY1305,
|
.cipher_type = TLS_CIPHER_CHACHA20_POLY1305,
|
||||||
|
.fips_non_compliant = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
FIXTURE_VARIANT_ADD(tls, 13_sm4_gcm)
|
FIXTURE_VARIANT_ADD(tls, 13_sm4_gcm)
|
||||||
{
|
{
|
||||||
.tls_version = TLS_1_3_VERSION,
|
.tls_version = TLS_1_3_VERSION,
|
||||||
.cipher_type = TLS_CIPHER_SM4_GCM,
|
.cipher_type = TLS_CIPHER_SM4_GCM,
|
||||||
|
.fips_non_compliant = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
FIXTURE_VARIANT_ADD(tls, 13_sm4_ccm)
|
FIXTURE_VARIANT_ADD(tls, 13_sm4_ccm)
|
||||||
{
|
{
|
||||||
.tls_version = TLS_1_3_VERSION,
|
.tls_version = TLS_1_3_VERSION,
|
||||||
.cipher_type = TLS_CIPHER_SM4_CCM,
|
.cipher_type = TLS_CIPHER_SM4_CCM,
|
||||||
|
.fips_non_compliant = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
FIXTURE_VARIANT_ADD(tls, 12_aes_ccm)
|
FIXTURE_VARIANT_ADD(tls, 12_aes_ccm)
|
||||||
|
@ -311,6 +317,9 @@ FIXTURE_SETUP(tls)
|
||||||
int one = 1;
|
int one = 1;
|
||||||
int ret;
|
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,
|
tls_crypto_info_init(variant->tls_version, variant->cipher_type,
|
||||||
&tls12);
|
&tls12);
|
||||||
|
|
||||||
|
@ -1865,4 +1874,17 @@ TEST(prequeue) {
|
||||||
close(cfd);
|
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
|
TEST_HARNESS_MAIN
|
||||||
|
|
|
@ -264,60 +264,60 @@ setup_xfrm()
|
||||||
ip -netns host1 xfrm state add src ${HOST1_4} dst ${HOST2_4} \
|
ip -netns host1 xfrm state add src ${HOST1_4} dst ${HOST2_4} \
|
||||||
proto esp spi ${SPI_1} reqid 0 mode tunnel \
|
proto esp spi ${SPI_1} reqid 0 mode tunnel \
|
||||||
replay-window 4 replay-oseq 0x4 \
|
replay-window 4 replay-oseq 0x4 \
|
||||||
auth-trunc 'hmac(md5)' ${AUTH_1} 96 \
|
auth-trunc 'hmac(sha1)' ${AUTH_1} 96 \
|
||||||
enc 'cbc(des3_ede)' ${ENC_1} \
|
enc 'cbc(aes)' ${ENC_1} \
|
||||||
sel src ${h1_4} dst ${h2_4} ${devarg}
|
sel src ${h1_4} dst ${h2_4} ${devarg}
|
||||||
|
|
||||||
ip -netns host2 xfrm state add src ${HOST1_4} dst ${HOST2_4} \
|
ip -netns host2 xfrm state add src ${HOST1_4} dst ${HOST2_4} \
|
||||||
proto esp spi ${SPI_1} reqid 0 mode tunnel \
|
proto esp spi ${SPI_1} reqid 0 mode tunnel \
|
||||||
replay-window 4 replay-oseq 0x4 \
|
replay-window 4 replay-oseq 0x4 \
|
||||||
auth-trunc 'hmac(md5)' ${AUTH_1} 96 \
|
auth-trunc 'hmac(sha1)' ${AUTH_1} 96 \
|
||||||
enc 'cbc(des3_ede)' ${ENC_1} \
|
enc 'cbc(aes)' ${ENC_1} \
|
||||||
sel src ${h1_4} dst ${h2_4}
|
sel src ${h1_4} dst ${h2_4}
|
||||||
|
|
||||||
|
|
||||||
ip -netns host1 xfrm state add src ${HOST2_4} dst ${HOST1_4} \
|
ip -netns host1 xfrm state add src ${HOST2_4} dst ${HOST1_4} \
|
||||||
proto esp spi ${SPI_2} reqid 0 mode tunnel \
|
proto esp spi ${SPI_2} reqid 0 mode tunnel \
|
||||||
replay-window 4 replay-oseq 0x4 \
|
replay-window 4 replay-oseq 0x4 \
|
||||||
auth-trunc 'hmac(md5)' ${AUTH_2} 96 \
|
auth-trunc 'hmac(sha1)' ${AUTH_2} 96 \
|
||||||
enc 'cbc(des3_ede)' ${ENC_2} \
|
enc 'cbc(aes)' ${ENC_2} \
|
||||||
sel src ${h2_4} dst ${h1_4} ${devarg}
|
sel src ${h2_4} dst ${h1_4} ${devarg}
|
||||||
|
|
||||||
ip -netns host2 xfrm state add src ${HOST2_4} dst ${HOST1_4} \
|
ip -netns host2 xfrm state add src ${HOST2_4} dst ${HOST1_4} \
|
||||||
proto esp spi ${SPI_2} reqid 0 mode tunnel \
|
proto esp spi ${SPI_2} reqid 0 mode tunnel \
|
||||||
replay-window 4 replay-oseq 0x4 \
|
replay-window 4 replay-oseq 0x4 \
|
||||||
auth-trunc 'hmac(md5)' ${AUTH_2} 96 \
|
auth-trunc 'hmac(sha1)' ${AUTH_2} 96 \
|
||||||
enc 'cbc(des3_ede)' ${ENC_2} \
|
enc 'cbc(aes)' ${ENC_2} \
|
||||||
sel src ${h2_4} dst ${h1_4}
|
sel src ${h2_4} dst ${h1_4}
|
||||||
|
|
||||||
|
|
||||||
ip -6 -netns host1 xfrm state add src ${HOST1_6} dst ${HOST2_6} \
|
ip -6 -netns host1 xfrm state add src ${HOST1_6} dst ${HOST2_6} \
|
||||||
proto esp spi ${SPI_1} reqid 0 mode tunnel \
|
proto esp spi ${SPI_1} reqid 0 mode tunnel \
|
||||||
replay-window 4 replay-oseq 0x4 \
|
replay-window 4 replay-oseq 0x4 \
|
||||||
auth-trunc 'hmac(md5)' ${AUTH_1} 96 \
|
auth-trunc 'hmac(sha1)' ${AUTH_1} 96 \
|
||||||
enc 'cbc(des3_ede)' ${ENC_1} \
|
enc 'cbc(aes)' ${ENC_1} \
|
||||||
sel src ${h1_6} dst ${h2_6} ${devarg}
|
sel src ${h1_6} dst ${h2_6} ${devarg}
|
||||||
|
|
||||||
ip -6 -netns host2 xfrm state add src ${HOST1_6} dst ${HOST2_6} \
|
ip -6 -netns host2 xfrm state add src ${HOST1_6} dst ${HOST2_6} \
|
||||||
proto esp spi ${SPI_1} reqid 0 mode tunnel \
|
proto esp spi ${SPI_1} reqid 0 mode tunnel \
|
||||||
replay-window 4 replay-oseq 0x4 \
|
replay-window 4 replay-oseq 0x4 \
|
||||||
auth-trunc 'hmac(md5)' ${AUTH_1} 96 \
|
auth-trunc 'hmac(sha1)' ${AUTH_1} 96 \
|
||||||
enc 'cbc(des3_ede)' ${ENC_1} \
|
enc 'cbc(aes)' ${ENC_1} \
|
||||||
sel src ${h1_6} dst ${h2_6}
|
sel src ${h1_6} dst ${h2_6}
|
||||||
|
|
||||||
|
|
||||||
ip -6 -netns host1 xfrm state add src ${HOST2_6} dst ${HOST1_6} \
|
ip -6 -netns host1 xfrm state add src ${HOST2_6} dst ${HOST1_6} \
|
||||||
proto esp spi ${SPI_2} reqid 0 mode tunnel \
|
proto esp spi ${SPI_2} reqid 0 mode tunnel \
|
||||||
replay-window 4 replay-oseq 0x4 \
|
replay-window 4 replay-oseq 0x4 \
|
||||||
auth-trunc 'hmac(md5)' ${AUTH_2} 96 \
|
auth-trunc 'hmac(sha1)' ${AUTH_2} 96 \
|
||||||
enc 'cbc(des3_ede)' ${ENC_2} \
|
enc 'cbc(aes)' ${ENC_2} \
|
||||||
sel src ${h2_6} dst ${h1_6} ${devarg}
|
sel src ${h2_6} dst ${h1_6} ${devarg}
|
||||||
|
|
||||||
ip -6 -netns host2 xfrm state add src ${HOST2_6} dst ${HOST1_6} \
|
ip -6 -netns host2 xfrm state add src ${HOST2_6} dst ${HOST1_6} \
|
||||||
proto esp spi ${SPI_2} reqid 0 mode tunnel \
|
proto esp spi ${SPI_2} reqid 0 mode tunnel \
|
||||||
replay-window 4 replay-oseq 0x4 \
|
replay-window 4 replay-oseq 0x4 \
|
||||||
auth-trunc 'hmac(md5)' ${AUTH_2} 96 \
|
auth-trunc 'hmac(sha1)' ${AUTH_2} 96 \
|
||||||
enc 'cbc(des3_ede)' ${ENC_2} \
|
enc 'cbc(aes)' ${ENC_2} \
|
||||||
sel src ${h2_6} dst ${h1_6}
|
sel src ${h2_6} dst ${h1_6}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue