Including fixes from bpf and netfilter.

Previous releases - regressions:
 
  - Revert "net: rtnetlink: Enslave device before bringing it up",
    breaks the case inverse to the one it was trying to fix
 
  - net: dsa: fix oob access in DSA's netdevice event handler
    dereference netdev_priv() before check its a DSA port
 
  - sched: track device in tcf_block_get/put_ext() only for clsact
    binder types
 
  - net: tls, fix WARNING in __sk_msg_free when record becomes full
    during splice and MORE hint set
 
  - sfp-bus: fix SFP mode detect from bitrate
 
  - drv: stmmac: prevent DSA tags from breaking COE
 
 Previous releases - always broken:
 
  - bpf: fix no forward progress in in bpf_iter_udp if output
    buffer is too small
 
  - bpf: reject variable offset alu on registers with a type
    of PTR_TO_FLOW_KEYS to prevent oob access
 
  - netfilter: tighten input validation
 
  - net: add more sanity check in virtio_net_hdr_to_skb()
 
  - rxrpc: fix use of Don't Fragment flag on RESPONSE packets,
    avoid infinite loop
 
  - amt: do not use the portion of skb->cb area which may get clobbered
 
  - mptcp: improve validation of the MPTCPOPT_MP_JOIN MCTCP option
 
 Misc:
 
  - spring cleanup of inactive maintainers
 
 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE6jPA+I1ugmIBA4hXMUZtbf5SIrsFAmWpnvoACgkQMUZtbf5S
 Irvskg/+Or5tETxOmpQXxnj6ECZyrSp0Jcyd7+TIcos/7JfPdn3Kebl004SG4h/s
 bwKDOIIP1iSjQ+0NFsPjyYIVd6wFuCElSB7npV5uQAT6ptXx7A4Ym68/rVxodI8T
 6hiYV/mlPuZF8JjRhtp/VJL8sY1qnG7RIUB4oH3y9HQNfwZX0lIWChuUilHuWfbq
 zQ2Iu97tMkoIBjXrkIT3Qaj0aFxYbjCOrg9zy+FZ69a7Rmrswr//7amlCH6saNTx
 Ku7Wl8FXhe7O23OiM6GSl7AechSM1aJ5kOS3orseej0+aSp9eH3ekYGmbsQr6sjz
 ix/eZ7V7SUkJK3bEH5haeymk4TDV3lHE8SziMbosK4wVbHOyPwEmqCxppADYJLZs
 WycHZKcTBluFBOxknAofH7m5Hh0ToXkeTfpptSSGtRB4WncAOMsMapr3yS4WXg/q
 AnOo/tzCBgMrnSJtD/kjqgUiCk8vYoLc8lBR9K74l0zqI1sf13OfuTHvEgqIS6z1
 Ir/ewlAV6fCH8gQbyzjKUVlyjZS4+vFv19xg/2GgLf+LdyzcCOxUZkND3/DE6+OA
 Dgf9gtABYU4hGXMUfTfml3KCBTF65QmY8dIh17zraNylYUHEJ2lI4D+sdiqWUrXb
 mXPBJh4nOPwIV5t2gT80skNwF3aWPr6l4ieY2codSbP04rO74S8=
 =YhQQ
 -----END PGP SIGNATURE-----

Merge tag 'net-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net

Pull networking fixes from Jakub Kicinski:
 "Including fixes from bpf and netfilter.

  Previous releases - regressions:

   - Revert "net: rtnetlink: Enslave device before bringing it up",
     breaks the case inverse to the one it was trying to fix

   - net: dsa: fix oob access in DSA's netdevice event handler
     dereference netdev_priv() before check its a DSA port

   - sched: track device in tcf_block_get/put_ext() only for clsact
     binder types

   - net: tls, fix WARNING in __sk_msg_free when record becomes full
     during splice and MORE hint set

   - sfp-bus: fix SFP mode detect from bitrate

   - drv: stmmac: prevent DSA tags from breaking COE

  Previous releases - always broken:

   - bpf: fix no forward progress in in bpf_iter_udp if output buffer is
     too small

   - bpf: reject variable offset alu on registers with a type of
     PTR_TO_FLOW_KEYS to prevent oob access

   - netfilter: tighten input validation

   - net: add more sanity check in virtio_net_hdr_to_skb()

   - rxrpc: fix use of Don't Fragment flag on RESPONSE packets, avoid
     infinite loop

   - amt: do not use the portion of skb->cb area which may get clobbered

   - mptcp: improve validation of the MPTCPOPT_MP_JOIN MCTCP option

  Misc:

   - spring cleanup of inactive maintainers"

* tag 'net-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (88 commits)
  i40e: Include types.h to some headers
  ipv6: mcast: fix data-race in ipv6_mc_down / mld_ifc_work
  selftests: mlxsw: qos_pfc: Adjust the test to support 8 lanes
  selftests: mlxsw: qos_pfc: Remove wrong description
  mlxsw: spectrum_router: Register netdevice notifier before nexthop
  mlxsw: spectrum_acl_tcam: Fix stack corruption
  mlxsw: spectrum_acl_tcam: Fix NULL pointer dereference in error path
  mlxsw: spectrum_acl_erp: Fix error flow of pool allocation failure
  ethtool: netlink: Add missing ethnl_ops_begin/complete
  selftests: bonding: Add more missing config options
  selftests: netdevsim: add a config file
  libbpf: warn on unexpected __arg_ctx type when rewriting BTF
  selftests/bpf: add tests confirming type logic in kernel for __arg_ctx
  bpf: enforce types for __arg_ctx-tagged arguments in global subprogs
  bpf: extract bpf_ctx_convert_map logic and make it more reusable
  libbpf: feature-detect arg:ctx tag support in kernel
  ipvs: avoid stat macros calls from preemptible context
  netfilter: nf_tables: reject NFT_SET_CONCAT with not field length description
  netfilter: nf_tables: skip dead set elements in netlink dump
  netfilter: nf_tables: do not allow mismatch field size and set key length
  ...
This commit is contained in:
Linus Torvalds 2024-01-18 17:33:50 -08:00
commit 736b5545d3
90 changed files with 1366 additions and 235 deletions

17
CREDITS
View File

@ -179,6 +179,7 @@ E: ralf@gnu.org
P: 1024/AF7B30C1 CF 97 C2 CC 6D AE A7 FE C8 BA 9C FC 88 DE 32 C3
D: Linux/MIPS port
D: Linux/68k hacker
D: AX25 maintainer
S: Hauptstrasse 19
S: 79837 St. Blasien
S: Germany
@ -677,6 +678,10 @@ D: Media subsystem (V4L/DVB) drivers and core
D: EDAC drivers and EDAC 3.0 core rework
S: Brazil
N: Landen Chao
E: Landen.Chao@mediatek.com
D: MT7531 Ethernet switch support
N: Raymond Chen
E: raymondc@microsoft.com
D: Author of Configure script
@ -814,6 +819,10 @@ D: Support for Xircom PGSDB9 (firmware and host driver)
S: Bucharest
S: Romania
N: John Crispin
E: john@phrozen.org
D: MediaTek MT7623 Gigabit ethernet support
N: Laurence Culhane
E: loz@holmes.demon.co.uk
D: Wrote the initial alpha SLIP code
@ -1538,6 +1547,10 @@ N: Andrew Haylett
E: ajh@primag.co.uk
D: Selection mechanism
N: Johan Hedberg
E: johan.hedberg@gmail.com
D: Bluetooth subsystem maintainer
N: Andre Hedrick
E: andre@linux-ide.org
E: andre@linuxdiskcert.org
@ -3052,6 +3065,10 @@ S: Demonstratsii 8-382
S: Tula 300000
S: Russia
N: Thomas Petazzoni
E: thomas.petazzoni@bootlin.com
D: Driver for the Marvell Armada 370/XP network unit.
N: Gordon Peters
E: GordPeters@smarttech.com
D: Isochronous receive for IEEE 1394 driver (OHCI module).

View File

@ -3390,9 +3390,8 @@ F: Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml
F: drivers/iio/adc/hx711.c
AX.25 NETWORK LAYER
M: Ralf Baechle <ralf@linux-mips.org>
L: linux-hams@vger.kernel.org
S: Maintained
S: Orphan
W: https://linux-ax25.in-berlin.de
F: include/net/ax25.h
F: include/uapi/linux/ax25.h
@ -3631,7 +3630,6 @@ F: drivers/mtd/devices/block2mtd.c
BLUETOOTH DRIVERS
M: Marcel Holtmann <marcel@holtmann.org>
M: Johan Hedberg <johan.hedberg@gmail.com>
M: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
L: linux-bluetooth@vger.kernel.org
S: Supported
@ -4726,11 +4724,8 @@ F: drivers/i2c/busses/i2c-octeon*
F: drivers/i2c/busses/i2c-thunderx*
CAVIUM LIQUIDIO NETWORK DRIVER
M: Derek Chickles <dchickles@marvell.com>
M: Satanand Burla <sburla@marvell.com>
M: Felix Manlunas <fmanlunas@marvell.com>
L: netdev@vger.kernel.org
S: Supported
S: Orphan
W: http://www.marvell.com
F: drivers/net/ethernet/cavium/liquidio/
@ -10239,7 +10234,6 @@ IBM Power SRIOV Virtual NIC Device Driver
M: Haren Myneni <haren@linux.ibm.com>
M: Rick Lindsley <ricklind@linux.ibm.com>
R: Nick Child <nnac123@linux.ibm.com>
R: Dany Madden <danymadden@us.ibm.com>
R: Thomas Falcon <tlfalcon@linux.ibm.com>
L: netdev@vger.kernel.org
S: Supported
@ -13003,10 +12997,10 @@ S: Maintained
F: drivers/thermal/armada_thermal.c
MARVELL MVNETA ETHERNET DRIVER
M: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
M: Marcin Wojtas <marcin.s.wojtas@gmail.com>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/ethernet/marvell/mvneta.*
F: drivers/net/ethernet/marvell/mvneta*
MARVELL MVPP2 ETHERNET DRIVER
M: Marcin Wojtas <marcin.s.wojtas@gmail.com>
@ -13656,7 +13650,6 @@ F: drivers/dma/mediatek/
MEDIATEK ETHERNET DRIVER
M: Felix Fietkau <nbd@nbd.name>
M: John Crispin <john@phrozen.org>
M: Sean Wang <sean.wang@mediatek.com>
M: Mark Lee <Mark-MC.Lee@mediatek.com>
M: Lorenzo Bianconi <lorenzo@kernel.org>
@ -13812,7 +13805,6 @@ F: include/soc/mediatek/smi.h
MEDIATEK SWITCH DRIVER
M: Arınç ÜNAL <arinc.unal@arinc9.com>
M: Daniel Golle <daniel@makrotopia.org>
M: Landen Chao <Landen.Chao@mediatek.com>
M: DENG Qingfang <dqfext@gmail.com>
M: Sean Wang <sean.wang@mediatek.com>
L: netdev@vger.kernel.org

View File

@ -11,7 +11,7 @@
#include <linux/net.h>
#include <linux/igmp.h>
#include <linux/workqueue.h>
#include <net/sch_generic.h>
#include <net/pkt_sched.h>
#include <net/net_namespace.h>
#include <net/ip.h>
#include <net/udp.h>
@ -80,11 +80,11 @@ static struct mld2_grec mldv2_zero_grec;
static struct amt_skb_cb *amt_skb_cb(struct sk_buff *skb)
{
BUILD_BUG_ON(sizeof(struct amt_skb_cb) + sizeof(struct qdisc_skb_cb) >
BUILD_BUG_ON(sizeof(struct amt_skb_cb) + sizeof(struct tc_skb_cb) >
sizeof_field(struct sk_buff, cb));
return (struct amt_skb_cb *)((void *)skb->cb +
sizeof(struct qdisc_skb_cb));
sizeof(struct tc_skb_cb));
}
static void __amt_source_gc_work(void)

View File

@ -1135,6 +1135,8 @@ static int vsc73xx_gpio_probe(struct vsc73xx *vsc)
vsc->gc.label = devm_kasprintf(vsc->dev, GFP_KERNEL, "VSC%04x",
vsc->chipid);
if (!vsc->gc.label)
return -ENOMEM;
vsc->gc.ngpio = 4;
vsc->gc.owner = THIS_MODULE;
vsc->gc.parent = vsc->dev;

View File

@ -1490,7 +1490,7 @@ int cn23xx_get_vf_stats(struct octeon_device *oct, int vfidx,
mbox_cmd.q_no = vfidx * oct->sriov_info.rings_per_vf;
mbox_cmd.recv_len = 0;
mbox_cmd.recv_status = 0;
mbox_cmd.fn = (octeon_mbox_callback_t)cn23xx_get_vf_stats_callback;
mbox_cmd.fn = cn23xx_get_vf_stats_callback;
ctx.stats = stats;
atomic_set(&ctx.status, 0);
mbox_cmd.fn_arg = (void *)&ctx;

View File

@ -429,7 +429,7 @@ int cn23xx_octeon_pfvf_handshake(struct octeon_device *oct)
mbox_cmd.q_no = 0;
mbox_cmd.recv_len = 0;
mbox_cmd.recv_status = 0;
mbox_cmd.fn = (octeon_mbox_callback_t)octeon_pfvf_hs_callback;
mbox_cmd.fn = octeon_pfvf_hs_callback;
mbox_cmd.fn_arg = &status;
octeon_mbox_write(oct, &mbox_cmd);

View File

@ -57,7 +57,10 @@ union octeon_mbox_message {
} s;
};
typedef void (*octeon_mbox_callback_t)(void *, void *, void *);
struct octeon_mbox_cmd;
typedef void (*octeon_mbox_callback_t)(struct octeon_device *,
struct octeon_mbox_cmd *, void *);
struct octeon_mbox_cmd {
union octeon_mbox_message msg;

View File

@ -5,6 +5,7 @@
#define _I40E_ADMINQ_CMD_H_
#include <linux/bits.h>
#include <linux/types.h>
/* This header file defines the i40e Admin Queue commands and is shared between
* i40e Firmware and Software.

View File

@ -4,6 +4,7 @@
#ifndef _I40E_DIAG_H_
#define _I40E_DIAG_H_
#include <linux/types.h>
#include "i40e_adminq_cmd.h"
/* forward-declare the HW struct for the compiler */

View File

@ -506,6 +506,7 @@ u32 rpm2_get_lmac_fifo_len(void *rpmd, int lmac_id)
rpm_t *rpm = rpmd;
u8 num_lmacs;
u32 fifo_len;
u16 max_lmac;
lmac_info = rpm_read(rpm, 0, RPM2_CMRX_RX_LMACS);
/* LMACs are divided into two groups and each group
@ -513,7 +514,11 @@ u32 rpm2_get_lmac_fifo_len(void *rpmd, int lmac_id)
* Group0 lmac_id range {0..3}
* Group1 lmac_id range {4..7}
*/
max_lmac = (rpm_read(rpm, 0, CGX_CONST) >> 24) & 0xFF;
if (max_lmac > 4)
fifo_len = rpm->mac_ops->fifo_len / 2;
else
fifo_len = rpm->mac_ops->fifo_len;
if (lmac_id < 4) {
num_lmacs = hweight8(lmac_info & 0xF);

View File

@ -301,6 +301,7 @@ mlxsw_sp_acl_erp_table_alloc(struct mlxsw_sp_acl_erp_core *erp_core,
unsigned long *p_index)
{
unsigned int num_rows, entry_size;
unsigned long index;
/* We only allow allocations of entire rows */
if (num_erps % erp_core->num_erp_banks != 0)
@ -309,10 +310,11 @@ mlxsw_sp_acl_erp_table_alloc(struct mlxsw_sp_acl_erp_core *erp_core,
entry_size = erp_core->erpt_entries_size[region_type];
num_rows = num_erps / erp_core->num_erp_banks;
*p_index = gen_pool_alloc(erp_core->erp_tables, num_rows * entry_size);
if (*p_index == 0)
index = gen_pool_alloc(erp_core->erp_tables, num_rows * entry_size);
if (!index)
return -ENOBUFS;
*p_index -= MLXSW_SP_ACL_ERP_GENALLOC_OFFSET;
*p_index = index - MLXSW_SP_ACL_ERP_GENALLOC_OFFSET;
return 0;
}

View File

@ -681,13 +681,13 @@ static void
mlxsw_sp_acl_tcam_region_destroy(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam_region *region)
{
struct mlxsw_sp_acl_tcam *tcam = mlxsw_sp_acl_to_tcam(mlxsw_sp->acl);
const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
ops->region_fini(mlxsw_sp, region->priv);
mlxsw_sp_acl_tcam_region_disable(mlxsw_sp, region);
mlxsw_sp_acl_tcam_region_free(mlxsw_sp, region);
mlxsw_sp_acl_tcam_region_id_put(region->group->tcam,
region->id);
mlxsw_sp_acl_tcam_region_id_put(tcam, region->id);
kfree(region);
}
@ -1564,6 +1564,8 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
tcam->max_groups = max_groups;
tcam->max_group_size = MLXSW_CORE_RES_GET(mlxsw_sp->core,
ACL_MAX_GROUP_SIZE);
tcam->max_group_size = min_t(unsigned int, tcam->max_group_size,
MLXSW_REG_PAGT_ACL_MAX_NUM);
err = ops->init(mlxsw_sp, tcam->priv, tcam);
if (err)

View File

@ -11472,6 +11472,13 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
if (err)
goto err_register_netevent_notifier;
mlxsw_sp->router->netdevice_nb.notifier_call =
mlxsw_sp_router_netdevice_event;
err = register_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
&mlxsw_sp->router->netdevice_nb);
if (err)
goto err_register_netdev_notifier;
mlxsw_sp->router->nexthop_nb.notifier_call =
mlxsw_sp_nexthop_obj_event;
err = register_nexthop_notifier(mlxsw_sp_net(mlxsw_sp),
@ -11487,22 +11494,15 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
if (err)
goto err_register_fib_notifier;
mlxsw_sp->router->netdevice_nb.notifier_call =
mlxsw_sp_router_netdevice_event;
err = register_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
&mlxsw_sp->router->netdevice_nb);
if (err)
goto err_register_netdev_notifier;
return 0;
err_register_netdev_notifier:
unregister_fib_notifier(mlxsw_sp_net(mlxsw_sp),
&mlxsw_sp->router->fib_nb);
err_register_fib_notifier:
unregister_nexthop_notifier(mlxsw_sp_net(mlxsw_sp),
&mlxsw_sp->router->nexthop_nb);
err_register_nexthop_notifier:
unregister_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
&router->netdevice_nb);
err_register_netdev_notifier:
unregister_netevent_notifier(&mlxsw_sp->router->netevent_nb);
err_register_netevent_notifier:
unregister_inet6addr_validator_notifier(&router->inet6addr_valid_nb);
@ -11550,11 +11550,11 @@ void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
{
struct mlxsw_sp_router *router = mlxsw_sp->router;
unregister_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
&router->netdevice_nb);
unregister_fib_notifier(mlxsw_sp_net(mlxsw_sp), &router->fib_nb);
unregister_nexthop_notifier(mlxsw_sp_net(mlxsw_sp),
&router->nexthop_nb);
unregister_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
&router->netdevice_nb);
unregister_netevent_notifier(&router->netevent_nb);
unregister_inet6addr_validator_notifier(&router->inet6addr_valid_nb);
unregister_inetaddr_validator_notifier(&router->inetaddr_valid_nb);

View File

@ -414,6 +414,7 @@ static const u64 fix_mac[] = {
END_SIGN
};
MODULE_DESCRIPTION("Neterion 10GbE driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);

View File

@ -396,7 +396,7 @@ nla_put_failure:
struct rtnl_link_ops rmnet_link_ops __read_mostly = {
.kind = "rmnet",
.maxtype = __IFLA_RMNET_MAX,
.maxtype = IFLA_RMNET_MAX,
.priv_size = sizeof(struct rmnet_priv),
.setup = rmnet_vnd_setup,
.validate = rmnet_rtnl_validate,

View File

@ -1949,7 +1949,7 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
struct ravb_tstamp_skb *ts_skb;
struct ravb_tx_desc *desc;
unsigned long flags;
u32 dma_addr;
dma_addr_t dma_addr;
void *buffer;
u32 entry;
u32 len;

View File

@ -267,6 +267,7 @@ struct stmmac_priv {
u32 msg_enable;
int wolopts;
int wol_irq;
bool wol_irq_disabled;
int clk_csr;
struct timer_list eee_ctrl_timer;
int lpi_irq;

View File

@ -321,8 +321,9 @@ static int stmmac_ethtool_get_link_ksettings(struct net_device *dev,
{
struct stmmac_priv *priv = netdev_priv(dev);
if (priv->hw->pcs & STMMAC_PCS_RGMII ||
priv->hw->pcs & STMMAC_PCS_SGMII) {
if (!(priv->plat->flags & STMMAC_FLAG_HAS_INTEGRATED_PCS) &&
(priv->hw->pcs & STMMAC_PCS_RGMII ||
priv->hw->pcs & STMMAC_PCS_SGMII)) {
struct rgmii_adv adv;
u32 supported, advertising, lp_advertising;
@ -407,8 +408,9 @@ stmmac_ethtool_set_link_ksettings(struct net_device *dev,
{
struct stmmac_priv *priv = netdev_priv(dev);
if (priv->hw->pcs & STMMAC_PCS_RGMII ||
priv->hw->pcs & STMMAC_PCS_SGMII) {
if (!(priv->plat->flags & STMMAC_FLAG_HAS_INTEGRATED_PCS) &&
(priv->hw->pcs & STMMAC_PCS_RGMII ||
priv->hw->pcs & STMMAC_PCS_SGMII)) {
/* Only support ANE */
if (cmd->base.autoneg != AUTONEG_ENABLE)
return -EINVAL;
@ -830,10 +832,16 @@ static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
if (wol->wolopts) {
pr_info("stmmac: wakeup enable\n");
device_set_wakeup_enable(priv->device, 1);
/* Avoid unbalanced enable_irq_wake calls */
if (priv->wol_irq_disabled)
enable_irq_wake(priv->wol_irq);
priv->wol_irq_disabled = false;
} else {
device_set_wakeup_enable(priv->device, 0);
/* Avoid unbalanced disable_irq_wake calls */
if (!priv->wol_irq_disabled)
disable_irq_wake(priv->wol_irq);
priv->wol_irq_disabled = true;
}
mutex_lock(&priv->lock);

View File

@ -3628,6 +3628,7 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
/* Request the Wake IRQ in case of another line
* is used for WoL
*/
priv->wol_irq_disabled = true;
if (priv->wol_irq > 0 && priv->wol_irq != dev->irq) {
int_name = priv->int_name_wol;
sprintf(int_name, "%s:%s", dev->name, "wol");
@ -4434,6 +4435,28 @@ dma_map_err:
return NETDEV_TX_OK;
}
/**
* stmmac_has_ip_ethertype() - Check if packet has IP ethertype
* @skb: socket buffer to check
*
* Check if a packet has an ethertype that will trigger the IP header checks
* and IP/TCP checksum engine of the stmmac core.
*
* Return: true if the ethertype can trigger the checksum engine, false
* otherwise
*/
static bool stmmac_has_ip_ethertype(struct sk_buff *skb)
{
int depth = 0;
__be16 proto;
proto = __vlan_get_protocol(skb, eth_header_parse_protocol(skb),
&depth);
return (depth <= ETH_HLEN) &&
(proto == htons(ETH_P_IP) || proto == htons(ETH_P_IPV6));
}
/**
* stmmac_xmit - Tx entry point of the driver
* @skb : the socket buffer
@ -4498,9 +4521,13 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
/* DWMAC IPs can be synthesized to support tx coe only for a few tx
* queues. In that case, checksum offloading for those queues that don't
* support tx coe needs to fallback to software checksum calculation.
*
* Packets that won't trigger the COE e.g. most DSA-tagged packets will
* also have to be checksummed in software.
*/
if (csum_insertion &&
priv->plat->tx_queues_cfg[queue].coe_unsupported) {
(priv->plat->tx_queues_cfg[queue].coe_unsupported ||
!stmmac_has_ip_ethertype(skb))) {
if (unlikely(skb_checksum_help(skb)))
goto dma_map_err;
csum_insertion = !csum_insertion;
@ -5065,7 +5092,7 @@ static void stmmac_dispatch_skb_zc(struct stmmac_priv *priv, u32 queue,
stmmac_rx_vlan(priv->dev, skb);
skb->protocol = eth_type_trans(skb, priv->dev);
if (unlikely(!coe))
if (unlikely(!coe) || !stmmac_has_ip_ethertype(skb))
skb_checksum_none_assert(skb);
else
skb->ip_summed = CHECKSUM_UNNECESSARY;
@ -5588,7 +5615,7 @@ drain_data:
skb->protocol = eth_type_trans(skb, priv->dev);
if (unlikely(!coe))
if (unlikely(!coe) || !stmmac_has_ip_ethertype(skb))
skb_checksum_none_assert(skb);
else
skb->ip_summed = CHECKSUM_UNNECESSARY;

View File

@ -56,7 +56,7 @@
#define AM65_CPSW_MAX_PORTS 8
#define AM65_CPSW_MIN_PACKET_SIZE VLAN_ETH_ZLEN
#define AM65_CPSW_MAX_PACKET_SIZE (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)
#define AM65_CPSW_MAX_PACKET_SIZE 2024
#define AM65_CPSW_REG_CTL 0x004
#define AM65_CPSW_REG_STAT_PORT_EN 0x014
@ -2244,7 +2244,8 @@ am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx)
eth_hw_addr_set(port->ndev, port->slave.mac_addr);
port->ndev->min_mtu = AM65_CPSW_MIN_PACKET_SIZE;
port->ndev->max_mtu = AM65_CPSW_MAX_PACKET_SIZE;
port->ndev->max_mtu = AM65_CPSW_MAX_PACKET_SIZE -
(VLAN_ETH_HLEN + ETH_FCS_LEN);
port->ndev->hw_features = NETIF_F_SG |
NETIF_F_RXCSUM |
NETIF_F_HW_CSUM |

View File

@ -26,7 +26,7 @@ config NGBE
tristate "Wangxun(R) GbE PCI Express adapters support"
depends on PCI
select LIBWX
select PHYLIB
select PHYLINK
help
This driver supports Wangxun(R) GbE PCI Express family of
adapters.

View File

@ -2769,4 +2769,5 @@ void wx_set_ring(struct wx *wx, u32 new_tx_count,
}
EXPORT_SYMBOL(wx_set_ring);
MODULE_DESCRIPTION("Common library for Wangxun(R) Ethernet drivers.");
MODULE_LICENSE("GPL");

View File

@ -369,6 +369,12 @@ static int nsim_init_netdevsim_vf(struct netdevsim *ns)
return err;
}
static void nsim_exit_netdevsim(struct netdevsim *ns)
{
nsim_udp_tunnels_info_destroy(ns->netdev);
mock_phc_destroy(ns->phc);
}
struct netdevsim *
nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port)
{
@ -417,8 +423,7 @@ void nsim_destroy(struct netdevsim *ns)
}
rtnl_unlock();
if (nsim_dev_port_is_pf(ns->nsim_dev_port))
nsim_udp_tunnels_info_destroy(dev);
mock_phc_destroy(ns->phc);
nsim_exit_netdevsim(ns);
free_netdev(dev);
}

View File

@ -3338,8 +3338,10 @@ static int lan8814_probe(struct phy_device *phydev)
#define LAN8841_ADC_CHANNEL_MASK 198
#define LAN8841_PTP_RX_PARSE_L2_ADDR_EN 370
#define LAN8841_PTP_RX_PARSE_IP_ADDR_EN 371
#define LAN8841_PTP_RX_VERSION 374
#define LAN8841_PTP_TX_PARSE_L2_ADDR_EN 434
#define LAN8841_PTP_TX_PARSE_IP_ADDR_EN 435
#define LAN8841_PTP_TX_VERSION 438
#define LAN8841_PTP_CMD_CTL 256
#define LAN8841_PTP_CMD_CTL_PTP_ENABLE BIT(2)
#define LAN8841_PTP_CMD_CTL_PTP_DISABLE BIT(1)
@ -3383,6 +3385,12 @@ static int lan8841_config_init(struct phy_device *phydev)
phy_write_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG,
LAN8841_PTP_RX_PARSE_IP_ADDR_EN, 0);
/* Disable checking for minorVersionPTP field */
phy_write_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG,
LAN8841_PTP_RX_VERSION, 0xff00);
phy_write_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG,
LAN8841_PTP_TX_VERSION, 0xff00);
/* 100BT Clause 40 improvenent errata */
phy_write_mmd(phydev, LAN8841_MMD_ANALOG_REG,
LAN8841_ANALOG_CONTROL_1,
@ -4839,6 +4847,7 @@ static struct phy_driver ksphy_driver[] = {
.flags = PHY_POLL_CABLE_TEST,
.driver_data = &ksz9131_type,
.probe = kszphy_probe,
.soft_reset = genphy_soft_reset,
.config_init = ksz9131_config_init,
.config_intr = kszphy_config_intr,
.config_aneg = ksz9131_config_aneg,

View File

@ -151,10 +151,6 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
unsigned int br_min, br_nom, br_max;
__ETHTOOL_DECLARE_LINK_MODE_MASK(modes) = { 0, };
phylink_set(modes, Autoneg);
phylink_set(modes, Pause);
phylink_set(modes, Asym_Pause);
/* Decode the bitrate information to MBd */
br_min = br_nom = br_max = 0;
if (id->base.br_nominal) {
@ -339,6 +335,10 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
}
}
phylink_set(modes, Autoneg);
phylink_set(modes, Pause);
phylink_set(modes, Asym_Pause);
if (bus->sfp_quirk && bus->sfp_quirk->modes)
bus->sfp_quirk->modes(id, modes, interfaces);

View File

@ -752,4 +752,5 @@ EXPORT_SYMBOL(slhc_compress);
EXPORT_SYMBOL(slhc_uncompress);
EXPORT_SYMBOL(slhc_toss);
MODULE_DESCRIPTION("Compression helpers for SLIP (serial line)");
MODULE_LICENSE("Dual BSD/GPL");

View File

@ -1437,5 +1437,6 @@ out:
}
#endif
MODULE_DESCRIPTION("SLIP (serial line) protocol module");
MODULE_LICENSE("GPL");
MODULE_ALIAS_LDISC(N_SLIP);

View File

@ -4295,10 +4295,11 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
{
vq_callback_t **callbacks;
struct virtqueue **vqs;
int ret = -ENOMEM;
int i, total_vqs;
const char **names;
int ret = -ENOMEM;
int total_vqs;
bool *ctx;
u16 i;
/* We expect 1 RX virtqueue followed by 1 TX virtqueue, followed by
* possible N-1 RX/TX queue pairs used in multiqueue mode, followed by
@ -4335,8 +4336,8 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
for (i = 0; i < vi->max_queue_pairs; i++) {
callbacks[rxq2vq(i)] = skb_recv_done;
callbacks[txq2vq(i)] = skb_xmit_done;
sprintf(vi->rq[i].name, "input.%d", i);
sprintf(vi->sq[i].name, "output.%d", i);
sprintf(vi->rq[i].name, "input.%u", i);
sprintf(vi->sq[i].name, "output.%u", i);
names[rxq2vq(i)] = vi->rq[i].name;
names[txq2vq(i)] = vi->sq[i].name;
if (ctx)

View File

@ -28,6 +28,7 @@
static struct spi_device *g_spi;
MODULE_DESCRIPTION("Slic Maxim DS26522 driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Zhao Qiang<B45475@freescale.com>");

View File

@ -512,7 +512,7 @@ s32 btf_find_dtor_kfunc(struct btf *btf, u32 btf_id);
int register_btf_id_dtor_kfuncs(const struct btf_id_dtor_kfunc *dtors, u32 add_cnt,
struct module *owner);
struct btf_struct_meta *btf_find_struct_meta(const struct btf *btf, u32 btf_id);
const struct btf_member *
const struct btf_type *
btf_get_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf,
const struct btf_type *t, enum bpf_prog_type prog_type,
int arg);

View File

@ -42,7 +42,7 @@ static inline int nf_bridge_get_physinif(const struct sk_buff *skb)
if (!nf_bridge)
return 0;
return nf_bridge->physindev ? nf_bridge->physindev->ifindex : 0;
return nf_bridge->physinif;
}
static inline int nf_bridge_get_physoutif(const struct sk_buff *skb)
@ -56,11 +56,11 @@ static inline int nf_bridge_get_physoutif(const struct sk_buff *skb)
}
static inline struct net_device *
nf_bridge_get_physindev(const struct sk_buff *skb)
nf_bridge_get_physindev(const struct sk_buff *skb, struct net *net)
{
const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
return nf_bridge ? nf_bridge->physindev : NULL;
return nf_bridge ? dev_get_by_index_rcu(net, nf_bridge->physinif) : NULL;
}
static inline struct net_device *

View File

@ -295,7 +295,7 @@ struct nf_bridge_info {
u8 bridged_dnat:1;
u8 sabotage_in_done:1;
__u16 frag_max_size;
struct net_device *physindev;
int physinif;
/* always valid & non-NULL from FORWARD on, for physdev match */
struct net_device *physoutdev;

View File

@ -3,6 +3,8 @@
#define _LINUX_VIRTIO_NET_H
#include <linux/if_vlan.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/udp.h>
#include <uapi/linux/tcp.h>
#include <uapi/linux/virtio_net.h>
@ -49,6 +51,7 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
const struct virtio_net_hdr *hdr,
bool little_endian)
{
unsigned int nh_min_len = sizeof(struct iphdr);
unsigned int gso_type = 0;
unsigned int thlen = 0;
unsigned int p_off = 0;
@ -65,6 +68,7 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
gso_type = SKB_GSO_TCPV6;
ip_proto = IPPROTO_TCP;
thlen = sizeof(struct tcphdr);
nh_min_len = sizeof(struct ipv6hdr);
break;
case VIRTIO_NET_HDR_GSO_UDP:
gso_type = SKB_GSO_UDP;
@ -100,7 +104,8 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
if (!skb_partial_csum_set(skb, start, off))
return -EINVAL;
p_off = skb_transport_offset(skb) + thlen;
nh_min_len = max_t(u32, nh_min_len, skb_transport_offset(skb));
p_off = nh_min_len + thlen;
if (!pskb_may_pull(skb, p_off))
return -EINVAL;
} else {
@ -140,7 +145,7 @@ retry:
skb_set_transport_header(skb, keys.control.thoff);
} else if (gso_type) {
p_off = thlen;
p_off = nh_min_len + thlen;
if (!pskb_may_pull(skb, p_off))
return -EINVAL;
}

View File

@ -128,7 +128,7 @@ netdev_txq_completed_mb(struct netdev_queue *dev_queue,
netdev_txq_completed_mb(txq, pkts, bytes); \
\
_res = -1; \
if (pkts && likely(get_desc > start_thrs)) { \
if (pkts && likely(get_desc >= start_thrs)) { \
_res = 1; \
if (unlikely(netif_tx_queue_stopped(txq)) && \
!(down_cond)) { \

View File

@ -5615,21 +5615,46 @@ static u8 bpf_ctx_convert_map[] = {
#undef BPF_MAP_TYPE
#undef BPF_LINK_TYPE
const struct btf_member *
static const struct btf_type *find_canonical_prog_ctx_type(enum bpf_prog_type prog_type)
{
const struct btf_type *conv_struct;
const struct btf_member *ctx_type;
conv_struct = bpf_ctx_convert.t;
if (!conv_struct)
return NULL;
/* prog_type is valid bpf program type. No need for bounds check. */
ctx_type = btf_type_member(conv_struct) + bpf_ctx_convert_map[prog_type] * 2;
/* ctx_type is a pointer to prog_ctx_type in vmlinux.
* Like 'struct __sk_buff'
*/
return btf_type_by_id(btf_vmlinux, ctx_type->type);
}
static int find_kern_ctx_type_id(enum bpf_prog_type prog_type)
{
const struct btf_type *conv_struct;
const struct btf_member *ctx_type;
conv_struct = bpf_ctx_convert.t;
if (!conv_struct)
return -EFAULT;
/* prog_type is valid bpf program type. No need for bounds check. */
ctx_type = btf_type_member(conv_struct) + bpf_ctx_convert_map[prog_type] * 2 + 1;
/* ctx_type is a pointer to prog_ctx_type in vmlinux.
* Like 'struct sk_buff'
*/
return ctx_type->type;
}
const struct btf_type *
btf_get_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf,
const struct btf_type *t, enum bpf_prog_type prog_type,
int arg)
{
const struct btf_type *conv_struct;
const struct btf_type *ctx_struct;
const struct btf_member *ctx_type;
const struct btf_type *ctx_type;
const char *tname, *ctx_tname;
conv_struct = bpf_ctx_convert.t;
if (!conv_struct) {
bpf_log(log, "btf_vmlinux is malformed\n");
return NULL;
}
t = btf_type_by_id(btf, t->type);
while (btf_type_is_modifier(t))
t = btf_type_by_id(btf, t->type);
@ -5646,17 +5671,15 @@ btf_get_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf,
bpf_log(log, "arg#%d struct doesn't have a name\n", arg);
return NULL;
}
/* prog_type is valid bpf program type. No need for bounds check. */
ctx_type = btf_type_member(conv_struct) + bpf_ctx_convert_map[prog_type] * 2;
/* ctx_struct is a pointer to prog_ctx_type in vmlinux.
* Like 'struct __sk_buff'
*/
ctx_struct = btf_type_by_id(btf_vmlinux, ctx_type->type);
if (!ctx_struct)
ctx_type = find_canonical_prog_ctx_type(prog_type);
if (!ctx_type) {
bpf_log(log, "btf_vmlinux is malformed\n");
/* should not happen */
return NULL;
}
again:
ctx_tname = btf_name_by_offset(btf_vmlinux, ctx_struct->name_off);
ctx_tname = btf_name_by_offset(btf_vmlinux, ctx_type->name_off);
if (!ctx_tname) {
/* should not happen */
bpf_log(log, "Please fix kernel include/linux/bpf_types.h\n");
@ -5677,28 +5700,167 @@ again:
/* bpf_user_pt_regs_t is a typedef, so resolve it to
* underlying struct and check name again
*/
if (!btf_type_is_modifier(ctx_struct))
if (!btf_type_is_modifier(ctx_type))
return NULL;
while (btf_type_is_modifier(ctx_struct))
ctx_struct = btf_type_by_id(btf_vmlinux, ctx_struct->type);
while (btf_type_is_modifier(ctx_type))
ctx_type = btf_type_by_id(btf_vmlinux, ctx_type->type);
goto again;
}
return ctx_type;
}
/* forward declarations for arch-specific underlying types of
* bpf_user_pt_regs_t; this avoids the need for arch-specific #ifdef
* compilation guards below for BPF_PROG_TYPE_PERF_EVENT checks, but still
* works correctly with __builtin_types_compatible_p() on respective
* architectures
*/
struct user_regs_struct;
struct user_pt_regs;
static int btf_validate_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf,
const struct btf_type *t, int arg,
enum bpf_prog_type prog_type,
enum bpf_attach_type attach_type)
{
const struct btf_type *ctx_type;
const char *tname, *ctx_tname;
if (!btf_is_ptr(t)) {
bpf_log(log, "arg#%d type isn't a pointer\n", arg);
return -EINVAL;
}
t = btf_type_by_id(btf, t->type);
/* KPROBE and PERF_EVENT programs allow bpf_user_pt_regs_t typedef */
if (prog_type == BPF_PROG_TYPE_KPROBE || prog_type == BPF_PROG_TYPE_PERF_EVENT) {
while (btf_type_is_modifier(t) && !btf_type_is_typedef(t))
t = btf_type_by_id(btf, t->type);
if (btf_type_is_typedef(t)) {
tname = btf_name_by_offset(btf, t->name_off);
if (tname && strcmp(tname, "bpf_user_pt_regs_t") == 0)
return 0;
}
}
/* all other program types don't use typedefs for context type */
while (btf_type_is_modifier(t))
t = btf_type_by_id(btf, t->type);
/* `void *ctx __arg_ctx` is always valid */
if (btf_type_is_void(t))
return 0;
tname = btf_name_by_offset(btf, t->name_off);
if (str_is_empty(tname)) {
bpf_log(log, "arg#%d type doesn't have a name\n", arg);
return -EINVAL;
}
/* special cases */
switch (prog_type) {
case BPF_PROG_TYPE_KPROBE:
if (__btf_type_is_struct(t) && strcmp(tname, "pt_regs") == 0)
return 0;
break;
case BPF_PROG_TYPE_PERF_EVENT:
if (__builtin_types_compatible_p(bpf_user_pt_regs_t, struct pt_regs) &&
__btf_type_is_struct(t) && strcmp(tname, "pt_regs") == 0)
return 0;
if (__builtin_types_compatible_p(bpf_user_pt_regs_t, struct user_pt_regs) &&
__btf_type_is_struct(t) && strcmp(tname, "user_pt_regs") == 0)
return 0;
if (__builtin_types_compatible_p(bpf_user_pt_regs_t, struct user_regs_struct) &&
__btf_type_is_struct(t) && strcmp(tname, "user_regs_struct") == 0)
return 0;
break;
case BPF_PROG_TYPE_RAW_TRACEPOINT:
case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:
/* allow u64* as ctx */
if (btf_is_int(t) && t->size == 8)
return 0;
break;
case BPF_PROG_TYPE_TRACING:
switch (attach_type) {
case BPF_TRACE_RAW_TP:
/* tp_btf program is TRACING, so need special case here */
if (__btf_type_is_struct(t) &&
strcmp(tname, "bpf_raw_tracepoint_args") == 0)
return 0;
/* allow u64* as ctx */
if (btf_is_int(t) && t->size == 8)
return 0;
break;
case BPF_TRACE_ITER:
/* allow struct bpf_iter__xxx types only */
if (__btf_type_is_struct(t) &&
strncmp(tname, "bpf_iter__", sizeof("bpf_iter__") - 1) == 0)
return 0;
break;
case BPF_TRACE_FENTRY:
case BPF_TRACE_FEXIT:
case BPF_MODIFY_RETURN:
/* allow u64* as ctx */
if (btf_is_int(t) && t->size == 8)
return 0;
break;
default:
break;
}
break;
case BPF_PROG_TYPE_LSM:
case BPF_PROG_TYPE_STRUCT_OPS:
/* allow u64* as ctx */
if (btf_is_int(t) && t->size == 8)
return 0;
break;
case BPF_PROG_TYPE_TRACEPOINT:
case BPF_PROG_TYPE_SYSCALL:
case BPF_PROG_TYPE_EXT:
return 0; /* anything goes */
default:
break;
}
ctx_type = find_canonical_prog_ctx_type(prog_type);
if (!ctx_type) {
/* should not happen */
bpf_log(log, "btf_vmlinux is malformed\n");
return -EINVAL;
}
/* resolve typedefs and check that underlying structs are matching as well */
while (btf_type_is_modifier(ctx_type))
ctx_type = btf_type_by_id(btf_vmlinux, ctx_type->type);
/* if program type doesn't have distinctly named struct type for
* context, then __arg_ctx argument can only be `void *`, which we
* already checked above
*/
if (!__btf_type_is_struct(ctx_type)) {
bpf_log(log, "arg#%d should be void pointer\n", arg);
return -EINVAL;
}
ctx_tname = btf_name_by_offset(btf_vmlinux, ctx_type->name_off);
if (!__btf_type_is_struct(t) || strcmp(ctx_tname, tname) != 0) {
bpf_log(log, "arg#%d should be `struct %s *`\n", arg, ctx_tname);
return -EINVAL;
}
return 0;
}
static int btf_translate_to_vmlinux(struct bpf_verifier_log *log,
struct btf *btf,
const struct btf_type *t,
enum bpf_prog_type prog_type,
int arg)
{
const struct btf_member *prog_ctx_type, *kern_ctx_type;
prog_ctx_type = btf_get_prog_ctx_type(log, btf, t, prog_type, arg);
if (!prog_ctx_type)
if (!btf_get_prog_ctx_type(log, btf, t, prog_type, arg))
return -ENOENT;
kern_ctx_type = prog_ctx_type + 1;
return kern_ctx_type->type;
return find_kern_ctx_type_id(prog_type);
}
int get_kern_ctx_btf_id(struct bpf_verifier_log *log, enum bpf_prog_type prog_type)
@ -6934,6 +7096,23 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
return -EINVAL;
}
for (i = 0; i < nargs; i++) {
const char *tag;
if (sub->args[i].arg_type != ARG_PTR_TO_CTX)
continue;
/* check if arg has "arg:ctx" tag */
t = btf_type_by_id(btf, args[i].type);
tag = btf_find_decl_tag_value(btf, fn_t, i, "arg:");
if (IS_ERR_OR_NULL(tag) || strcmp(tag, "ctx") != 0)
continue;
if (btf_validate_prog_ctx_type(log, btf, t, i, prog_type,
prog->expected_attach_type))
return -EINVAL;
}
sub->arg_cnt = nargs;
sub->args_cached = true;

View File

@ -12826,6 +12826,10 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
}
switch (base_type(ptr_reg->type)) {
case PTR_TO_FLOW_KEYS:
if (known)
break;
fallthrough;
case CONST_PTR_TO_MAP:
/* smin_val represents the known value */
if (known && smin_val == 0 && opcode == BPF_ADD)

View File

@ -279,8 +279,17 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_
if ((READ_ONCE(neigh->nud_state) & NUD_CONNECTED) &&
READ_ONCE(neigh->hh.hh_len)) {
struct net_device *br_indev;
br_indev = nf_bridge_get_physindev(skb, net);
if (!br_indev) {
neigh_release(neigh);
goto free_skb;
}
neigh_hh_bridge(&neigh->hh, skb);
skb->dev = nf_bridge->physindev;
skb->dev = br_indev;
ret = br_handle_frame_finish(net, sk, skb);
} else {
/* the neighbour function below overwrites the complete
@ -352,12 +361,18 @@ br_nf_ipv4_daddr_was_changed(const struct sk_buff *skb,
*/
static int br_nf_pre_routing_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
struct net_device *dev = skb->dev, *br_indev;
struct iphdr *iph = ip_hdr(skb);
struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
struct rtable *rt;
int err;
br_indev = nf_bridge_get_physindev(skb, net);
if (!br_indev) {
kfree_skb(skb);
return 0;
}
nf_bridge->frag_max_size = IPCB(skb)->frag_max_size;
if (nf_bridge->pkt_otherhost) {
@ -397,7 +412,7 @@ free_skb:
} else {
if (skb_dst(skb)->dev == dev) {
bridged_dnat:
skb->dev = nf_bridge->physindev;
skb->dev = br_indev;
nf_bridge_update_protocol(skb);
nf_bridge_push_encap_header(skb);
br_nf_hook_thresh(NF_BR_PRE_ROUTING,
@ -410,7 +425,7 @@ bridged_dnat:
skb->pkt_type = PACKET_HOST;
}
} else {
rt = bridge_parent_rtable(nf_bridge->physindev);
rt = bridge_parent_rtable(br_indev);
if (!rt) {
kfree_skb(skb);
return 0;
@ -419,7 +434,7 @@ bridged_dnat:
skb_dst_set_noref(skb, &rt->dst);
}
skb->dev = nf_bridge->physindev;
skb->dev = br_indev;
nf_bridge_update_protocol(skb);
nf_bridge_push_encap_header(skb);
br_nf_hook_thresh(NF_BR_PRE_ROUTING, net, sk, skb, skb->dev, NULL,
@ -456,7 +471,7 @@ struct net_device *setup_pre_routing(struct sk_buff *skb, const struct net *net)
}
nf_bridge->in_prerouting = 1;
nf_bridge->physindev = skb->dev;
nf_bridge->physinif = skb->dev->ifindex;
skb->dev = brnf_get_logical_dev(skb, skb->dev, net);
if (skb->protocol == htons(ETH_P_8021Q))
@ -553,7 +568,11 @@ static int br_nf_forward_finish(struct net *net, struct sock *sk, struct sk_buff
if (skb->protocol == htons(ETH_P_IPV6))
nf_bridge->frag_max_size = IP6CB(skb)->frag_max_size;
in = nf_bridge->physindev;
in = nf_bridge_get_physindev(skb, net);
if (!in) {
kfree_skb(skb);
return 0;
}
if (nf_bridge->pkt_otherhost) {
skb->pkt_type = PACKET_OTHERHOST;
nf_bridge->pkt_otherhost = false;
@ -899,6 +918,13 @@ static unsigned int ip_sabotage_in(void *priv,
static void br_nf_pre_routing_finish_bridge_slow(struct sk_buff *skb)
{
struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
struct net_device *br_indev;
br_indev = nf_bridge_get_physindev(skb, dev_net(skb->dev));
if (!br_indev) {
kfree_skb(skb);
return;
}
skb_pull(skb, ETH_HLEN);
nf_bridge->bridged_dnat = 0;
@ -908,7 +934,7 @@ static void br_nf_pre_routing_finish_bridge_slow(struct sk_buff *skb)
skb_copy_to_linear_data_offset(skb, -(ETH_HLEN - ETH_ALEN),
nf_bridge->neigh_header,
ETH_HLEN - ETH_ALEN);
skb->dev = nf_bridge->physindev;
skb->dev = br_indev;
nf_bridge->physoutdev = NULL;
br_handle_frame_finish(dev_net(skb->dev), NULL, skb);

View File

@ -102,9 +102,15 @@ static int br_nf_pre_routing_finish_ipv6(struct net *net, struct sock *sk, struc
{
struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
struct rtable *rt;
struct net_device *dev = skb->dev;
struct net_device *dev = skb->dev, *br_indev;
const struct nf_ipv6_ops *v6ops = nf_get_ipv6_ops();
br_indev = nf_bridge_get_physindev(skb, net);
if (!br_indev) {
kfree_skb(skb);
return 0;
}
nf_bridge->frag_max_size = IP6CB(skb)->frag_max_size;
if (nf_bridge->pkt_otherhost) {
@ -122,7 +128,7 @@ static int br_nf_pre_routing_finish_ipv6(struct net *net, struct sock *sk, struc
}
if (skb_dst(skb)->dev == dev) {
skb->dev = nf_bridge->physindev;
skb->dev = br_indev;
nf_bridge_update_protocol(skb);
nf_bridge_push_encap_header(skb);
br_nf_hook_thresh(NF_BR_PRE_ROUTING,
@ -133,7 +139,7 @@ static int br_nf_pre_routing_finish_ipv6(struct net *net, struct sock *sk, struc
ether_addr_copy(eth_hdr(skb)->h_dest, dev->dev_addr);
skb->pkt_type = PACKET_HOST;
} else {
rt = bridge_parent_rtable(nf_bridge->physindev);
rt = bridge_parent_rtable(br_indev);
if (!rt) {
kfree_skb(skb);
return 0;
@ -142,7 +148,7 @@ static int br_nf_pre_routing_finish_ipv6(struct net *net, struct sock *sk, struc
skb_dst_set_noref(skb, &rt->dst);
}
skb->dev = nf_bridge->physindev;
skb->dev = br_indev;
nf_bridge_update_protocol(skb);
nf_bridge_push_encap_header(skb);
br_nf_hook_thresh(NF_BR_PRE_ROUTING, net, sk, skb,

View File

@ -2899,13 +2899,6 @@ static int do_setlink(const struct sk_buff *skb,
call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
}
if (tb[IFLA_MASTER]) {
err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]), extack);
if (err)
goto errout;
status |= DO_SETLINK_MODIFIED;
}
if (ifm->ifi_flags || ifm->ifi_change) {
err = dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm),
extack);
@ -2913,6 +2906,13 @@ static int do_setlink(const struct sk_buff *skb,
goto errout;
}
if (tb[IFLA_MASTER]) {
err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]), extack);
if (err)
goto errout;
status |= DO_SETLINK_MODIFIED;
}
if (tb[IFLA_CARRIER]) {
err = dev_change_carrier(dev, nla_get_u8(tb[IFLA_CARRIER]));
if (err)

View File

@ -2806,13 +2806,14 @@ EXPORT_SYMBOL_GPL(dsa_user_dev_check);
static int dsa_user_changeupper(struct net_device *dev,
struct netdev_notifier_changeupper_info *info)
{
struct dsa_port *dp = dsa_user_to_port(dev);
struct netlink_ext_ack *extack;
int err = NOTIFY_DONE;
struct dsa_port *dp;
if (!dsa_user_dev_check(dev))
return err;
dp = dsa_user_to_port(dev);
extack = netdev_notifier_info_to_extack(&info->info);
if (netif_is_bridge_master(info->upper_dev)) {
@ -2865,11 +2866,13 @@ static int dsa_user_changeupper(struct net_device *dev,
static int dsa_user_prechangeupper(struct net_device *dev,
struct netdev_notifier_changeupper_info *info)
{
struct dsa_port *dp = dsa_user_to_port(dev);
struct dsa_port *dp;
if (!dsa_user_dev_check(dev))
return NOTIFY_DONE;
dp = dsa_user_to_port(dev);
if (netif_is_bridge_master(info->upper_dev) && !info->linking)
dsa_port_pre_bridge_leave(dp, info->upper_dev);
else if (netif_is_lag_master(info->upper_dev) && !info->linking)

View File

@ -234,17 +234,20 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info)
dev = req_info.dev;
rtnl_lock();
ret = ethnl_ops_begin(dev);
if (ret < 0)
goto out_rtnl;
ethnl_features_to_bitmap(old_active, dev->features);
ethnl_features_to_bitmap(old_wanted, dev->wanted_features);
ret = ethnl_parse_bitset(req_wanted, req_mask, NETDEV_FEATURE_COUNT,
tb[ETHTOOL_A_FEATURES_WANTED],
netdev_features_strings, info->extack);
if (ret < 0)
goto out_rtnl;
goto out_ops;
if (ethnl_bitmap_to_features(req_mask) & ~NETIF_F_ETHTOOL_BITS) {
GENL_SET_ERR_MSG(info, "attempt to change non-ethtool features");
ret = -EINVAL;
goto out_rtnl;
goto out_ops;
}
/* set req_wanted bits not in req_mask from old_wanted */
@ -281,6 +284,8 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info)
if (mod)
netdev_features_change(dev);
out_ops:
ethnl_ops_complete(dev);
out_rtnl:
rtnl_unlock();
ethnl_parse_header_dev_put(&req_info);

View File

@ -167,4 +167,5 @@ static void __exit hsr_exit(void)
module_init(hsr_init);
module_exit(hsr_exit);
MODULE_DESCRIPTION("High-availability Seamless Redundancy (HSR) driver");
MODULE_LICENSE("GPL");

View File

@ -239,7 +239,6 @@ static int nf_reject_fill_skb_dst(struct sk_buff *skb_in)
void nf_send_reset(struct net *net, struct sock *sk, struct sk_buff *oldskb,
int hook)
{
struct net_device *br_indev __maybe_unused;
struct sk_buff *nskb;
struct iphdr *niph;
const struct tcphdr *oth;
@ -289,9 +288,13 @@ void nf_send_reset(struct net *net, struct sock *sk, struct sk_buff *oldskb,
* build the eth header using the original destination's MAC as the
* source, and send the RST packet directly.
*/
br_indev = nf_bridge_get_physindev(oldskb);
if (br_indev) {
if (nf_bridge_info_exists(oldskb)) {
struct ethhdr *oeth = eth_hdr(oldskb);
struct net_device *br_indev;
br_indev = nf_bridge_get_physindev(oldskb, net);
if (!br_indev)
goto free_nskb;
nskb->dev = br_indev;
niph->tot_len = htons(nskb->len);

View File

@ -805,7 +805,7 @@ void udp_flush_pending_frames(struct sock *sk)
if (up->pending) {
up->len = 0;
up->pending = 0;
WRITE_ONCE(up->pending, 0);
ip_flush_pending_frames(sk);
}
}
@ -993,7 +993,7 @@ int udp_push_pending_frames(struct sock *sk)
out:
up->len = 0;
up->pending = 0;
WRITE_ONCE(up->pending, 0);
return err;
}
EXPORT_SYMBOL(udp_push_pending_frames);
@ -1070,7 +1070,7 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
fl4 = &inet->cork.fl.u.ip4;
if (up->pending) {
if (READ_ONCE(up->pending)) {
/*
* There are pending frames.
* The socket lock must be held while it's corked.
@ -1269,7 +1269,7 @@ back_from_confirm:
fl4->saddr = saddr;
fl4->fl4_dport = dport;
fl4->fl4_sport = inet->inet_sport;
up->pending = AF_INET;
WRITE_ONCE(up->pending, AF_INET);
do_append_data:
up->len += ulen;
@ -1281,7 +1281,7 @@ do_append_data:
else if (!corkreq)
err = udp_push_pending_frames(sk);
else if (unlikely(skb_queue_empty(&sk->sk_write_queue)))
up->pending = 0;
WRITE_ONCE(up->pending, 0);
release_sock(sk);
out:
@ -1319,7 +1319,7 @@ void udp_splice_eof(struct socket *sock)
struct sock *sk = sock->sk;
struct udp_sock *up = udp_sk(sk);
if (!up->pending || udp_test_bit(CORK, sk))
if (!READ_ONCE(up->pending) || udp_test_bit(CORK, sk))
return;
lock_sock(sk);
@ -3137,16 +3137,18 @@ static struct sock *bpf_iter_udp_batch(struct seq_file *seq)
struct bpf_udp_iter_state *iter = seq->private;
struct udp_iter_state *state = &iter->state;
struct net *net = seq_file_net(seq);
int resume_bucket, resume_offset;
struct udp_table *udptable;
unsigned int batch_sks = 0;
bool resized = false;
struct sock *sk;
resume_bucket = state->bucket;
resume_offset = iter->offset;
/* The current batch is done, so advance the bucket. */
if (iter->st_bucket_done) {
if (iter->st_bucket_done)
state->bucket++;
iter->offset = 0;
}
udptable = udp_get_table_seq(seq, net);
@ -3166,19 +3168,19 @@ again:
for (; state->bucket <= udptable->mask; state->bucket++) {
struct udp_hslot *hslot2 = &udptable->hash2[state->bucket];
if (hlist_empty(&hslot2->head)) {
iter->offset = 0;
if (hlist_empty(&hslot2->head))
continue;
}
iter->offset = 0;
spin_lock_bh(&hslot2->lock);
udp_portaddr_for_each_entry(sk, &hslot2->head) {
if (seq_sk_match(seq, sk)) {
/* Resume from the last iterated socket at the
* offset in the bucket before iterator was stopped.
*/
if (iter->offset) {
--iter->offset;
if (state->bucket == resume_bucket &&
iter->offset < resume_offset) {
++iter->offset;
continue;
}
if (iter->end_sk < iter->max_sk) {
@ -3192,9 +3194,6 @@ again:
if (iter->end_sk)
break;
/* Reset the current bucket's offset before moving to the next bucket. */
iter->offset = 0;
}
/* All done: no batch made. */
@ -3213,7 +3212,6 @@ again:
/* After allocating a larger batch, retry one more time to grab
* the whole bucket.
*/
state->bucket--;
goto again;
}
done:

View File

@ -2722,8 +2722,12 @@ void ipv6_mc_down(struct inet6_dev *idev)
synchronize_net();
mld_query_stop_work(idev);
mld_report_stop_work(idev);
mutex_lock(&idev->mc_lock);
mld_ifc_stop_work(idev);
mld_gq_stop_work(idev);
mutex_unlock(&idev->mc_lock);
mld_dad_stop_work(idev);
}

View File

@ -278,7 +278,6 @@ static int nf_reject6_fill_skb_dst(struct sk_buff *skb_in)
void nf_send_reset6(struct net *net, struct sock *sk, struct sk_buff *oldskb,
int hook)
{
struct net_device *br_indev __maybe_unused;
struct sk_buff *nskb;
struct tcphdr _otcph;
const struct tcphdr *otcph;
@ -354,9 +353,15 @@ void nf_send_reset6(struct net *net, struct sock *sk, struct sk_buff *oldskb,
* build the eth header using the original destination's MAC as the
* source, and send the RST packet directly.
*/
br_indev = nf_bridge_get_physindev(oldskb);
if (br_indev) {
if (nf_bridge_info_exists(oldskb)) {
struct ethhdr *oeth = eth_hdr(oldskb);
struct net_device *br_indev;
br_indev = nf_bridge_get_physindev(oldskb, net);
if (!br_indev) {
kfree_skb(nskb);
return;
}
nskb->dev = br_indev;
nskb->protocol = htons(ETH_P_IPV6);

View File

@ -1135,7 +1135,7 @@ static void udp_v6_flush_pending_frames(struct sock *sk)
udp_flush_pending_frames(sk);
else if (up->pending) {
up->len = 0;
up->pending = 0;
WRITE_ONCE(up->pending, 0);
ip6_flush_pending_frames(sk);
}
}
@ -1313,7 +1313,7 @@ static int udp_v6_push_pending_frames(struct sock *sk)
&inet_sk(sk)->cork.base);
out:
up->len = 0;
up->pending = 0;
WRITE_ONCE(up->pending, 0);
return err;
}
@ -1370,7 +1370,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
default:
return -EINVAL;
}
} else if (!up->pending) {
} else if (!READ_ONCE(up->pending)) {
if (sk->sk_state != TCP_ESTABLISHED)
return -EDESTADDRREQ;
daddr = &sk->sk_v6_daddr;
@ -1401,8 +1401,8 @@ do_udp_sendmsg:
return -EMSGSIZE;
getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
if (up->pending) {
if (up->pending == AF_INET)
if (READ_ONCE(up->pending)) {
if (READ_ONCE(up->pending) == AF_INET)
return udp_sendmsg(sk, msg, len);
/*
* There are pending frames.
@ -1593,7 +1593,7 @@ back_from_confirm:
goto out;
}
up->pending = AF_INET6;
WRITE_ONCE(up->pending, AF_INET6);
do_append_data:
if (ipc6.dontfrag < 0)
@ -1607,7 +1607,7 @@ do_append_data:
else if (!corkreq)
err = udp_v6_push_pending_frames(sk);
else if (unlikely(skb_queue_empty(&sk->sk_write_queue)))
up->pending = 0;
WRITE_ONCE(up->pending, 0);
if (err > 0)
err = inet6_test_bit(RECVERR6, sk) ? net_xmit_errno(err) : 0;
@ -1648,7 +1648,7 @@ static void udpv6_splice_eof(struct socket *sock)
struct sock *sk = sock->sk;
struct udp_sock *up = udp_sk(sk);
if (!up->pending || udp_test_bit(CORK, sk))
if (!READ_ONCE(up->pending) || udp_test_bit(CORK, sk))
return;
lock_sock(sk);

View File

@ -123,8 +123,8 @@ static void mptcp_parse_option(const struct sk_buff *skb,
break;
case MPTCPOPT_MP_JOIN:
mp_opt->suboptions |= OPTIONS_MPTCP_MPJ;
if (opsize == TCPOLEN_MPTCP_MPJ_SYN) {
mp_opt->suboptions |= OPTION_MPTCP_MPJ_SYN;
mp_opt->backup = *ptr++ & MPTCPOPT_BACKUP;
mp_opt->join_id = *ptr++;
mp_opt->token = get_unaligned_be32(ptr);
@ -135,6 +135,7 @@ static void mptcp_parse_option(const struct sk_buff *skb,
mp_opt->backup, mp_opt->join_id,
mp_opt->token, mp_opt->nonce);
} else if (opsize == TCPOLEN_MPTCP_MPJ_SYNACK) {
mp_opt->suboptions |= OPTION_MPTCP_MPJ_SYNACK;
mp_opt->backup = *ptr++ & MPTCPOPT_BACKUP;
mp_opt->join_id = *ptr++;
mp_opt->thmac = get_unaligned_be64(ptr);
@ -145,11 +146,10 @@ static void mptcp_parse_option(const struct sk_buff *skb,
mp_opt->backup, mp_opt->join_id,
mp_opt->thmac, mp_opt->nonce);
} else if (opsize == TCPOLEN_MPTCP_MPJ_ACK) {
mp_opt->suboptions |= OPTION_MPTCP_MPJ_ACK;
ptr += 2;
memcpy(mp_opt->hmac, ptr, MPTCPOPT_HMAC_LEN);
pr_debug("MP_JOIN hmac");
} else {
mp_opt->suboptions &= ~OPTIONS_MPTCP_MPJ;
}
break;

View File

@ -157,8 +157,8 @@ static int subflow_check_req(struct request_sock *req,
mptcp_get_options(skb, &mp_opt);
opt_mp_capable = !!(mp_opt.suboptions & OPTIONS_MPTCP_MPC);
opt_mp_join = !!(mp_opt.suboptions & OPTIONS_MPTCP_MPJ);
opt_mp_capable = !!(mp_opt.suboptions & OPTION_MPTCP_MPC_SYN);
opt_mp_join = !!(mp_opt.suboptions & OPTION_MPTCP_MPJ_SYN);
if (opt_mp_capable) {
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MPCAPABLEPASSIVE);
@ -254,8 +254,8 @@ int mptcp_subflow_init_cookie_req(struct request_sock *req,
subflow_init_req(req, sk_listener);
mptcp_get_options(skb, &mp_opt);
opt_mp_capable = !!(mp_opt.suboptions & OPTIONS_MPTCP_MPC);
opt_mp_join = !!(mp_opt.suboptions & OPTIONS_MPTCP_MPJ);
opt_mp_capable = !!(mp_opt.suboptions & OPTION_MPTCP_MPC_ACK);
opt_mp_join = !!(mp_opt.suboptions & OPTION_MPTCP_MPJ_ACK);
if (opt_mp_capable && opt_mp_join)
return -EINVAL;
@ -486,7 +486,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
mptcp_get_options(skb, &mp_opt);
if (subflow->request_mptcp) {
if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPC)) {
if (!(mp_opt.suboptions & OPTION_MPTCP_MPC_SYNACK)) {
MPTCP_INC_STATS(sock_net(sk),
MPTCP_MIB_MPCAPABLEACTIVEFALLBACK);
mptcp_do_fallback(sk);
@ -506,7 +506,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
} else if (subflow->request_join) {
u8 hmac[SHA256_DIGEST_SIZE];
if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPJ)) {
if (!(mp_opt.suboptions & OPTION_MPTCP_MPJ_SYNACK)) {
subflow->reset_reason = MPTCP_RST_EMPTCP;
goto do_reset;
}
@ -783,12 +783,13 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
* options.
*/
mptcp_get_options(skb, &mp_opt);
if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPC))
if (!(mp_opt.suboptions &
(OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_ACK)))
fallback = true;
} else if (subflow_req->mp_join) {
mptcp_get_options(skb, &mp_opt);
if (!(mp_opt.suboptions & OPTIONS_MPTCP_MPJ) ||
if (!(mp_opt.suboptions & OPTION_MPTCP_MPJ_ACK) ||
!subflow_hmac_valid(req, &mp_opt) ||
!mptcp_can_accept_new_subflow(subflow_req->msk)) {
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC);

View File

@ -138,9 +138,9 @@ hash_netiface4_data_next(struct hash_netiface4_elem *next,
#include "ip_set_hash_gen.h"
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
static const char *get_physindev_name(const struct sk_buff *skb)
static const char *get_physindev_name(const struct sk_buff *skb, struct net *net)
{
struct net_device *dev = nf_bridge_get_physindev(skb);
struct net_device *dev = nf_bridge_get_physindev(skb, net);
return dev ? dev->name : NULL;
}
@ -177,7 +177,7 @@ hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
const char *eiface = SRCDIR ? get_physindev_name(skb) :
const char *eiface = SRCDIR ? get_physindev_name(skb, xt_net(par)) :
get_physoutdev_name(skb);
if (!eiface)
@ -395,7 +395,7 @@ hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
const char *eiface = SRCDIR ? get_physindev_name(skb) :
const char *eiface = SRCDIR ? get_physindev_name(skb, xt_net(par)) :
get_physoutdev_name(skb);
if (!eiface)

View File

@ -271,7 +271,7 @@ static inline bool decrement_ttl(struct netns_ipvs *ipvs,
skb->dev = dst->dev;
icmpv6_send(skb, ICMPV6_TIME_EXCEED,
ICMPV6_EXC_HOPLIMIT, 0);
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
return false;
}
@ -286,7 +286,7 @@ static inline bool decrement_ttl(struct netns_ipvs *ipvs,
{
if (ip_hdr(skb)->ttl <= 1) {
/* Tell the sender its packet died... */
__IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS);
IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS);
icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
return false;
}

View File

@ -111,7 +111,8 @@ nf_log_dump_packet_common(struct nf_log_buf *m, u8 pf,
unsigned int hooknum, const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const struct nf_loginfo *loginfo, const char *prefix)
const struct nf_loginfo *loginfo, const char *prefix,
struct net *net)
{
const struct net_device *physoutdev __maybe_unused;
const struct net_device *physindev __maybe_unused;
@ -121,7 +122,7 @@ nf_log_dump_packet_common(struct nf_log_buf *m, u8 pf,
in ? in->name : "",
out ? out->name : "");
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
physindev = nf_bridge_get_physindev(skb);
physindev = nf_bridge_get_physindev(skb, net);
if (physindev && in != physindev)
nf_log_buf_add(m, "PHYSIN=%s ", physindev->name);
physoutdev = nf_bridge_get_physoutdev(skb);
@ -148,7 +149,7 @@ static void nf_log_arp_packet(struct net *net, u_int8_t pf,
loginfo = &default_loginfo;
nf_log_dump_packet_common(m, pf, hooknum, skb, in, out, loginfo,
prefix);
prefix, net);
dump_arp_packet(m, loginfo, skb, skb_network_offset(skb));
nf_log_buf_close(m);
@ -845,7 +846,7 @@ static void nf_log_ip_packet(struct net *net, u_int8_t pf,
loginfo = &default_loginfo;
nf_log_dump_packet_common(m, pf, hooknum, skb, in,
out, loginfo, prefix);
out, loginfo, prefix, net);
if (in)
dump_mac_header(m, loginfo, skb);
@ -880,7 +881,7 @@ static void nf_log_ip6_packet(struct net *net, u_int8_t pf,
loginfo = &default_loginfo;
nf_log_dump_packet_common(m, pf, hooknum, skb, in, out,
loginfo, prefix);
loginfo, prefix, net);
if (in)
dump_mac_header(m, loginfo, skb);
@ -916,7 +917,7 @@ static void nf_log_unknown_packet(struct net *net, u_int8_t pf,
loginfo = &default_loginfo;
nf_log_dump_packet_common(m, pf, hooknum, skb, in, out, loginfo,
prefix);
prefix, net);
dump_mac_header(m, loginfo, skb);

View File

@ -82,11 +82,9 @@ static void __nf_queue_entry_init_physdevs(struct nf_queue_entry *entry)
{
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
const struct sk_buff *skb = entry->skb;
struct nf_bridge_info *nf_bridge;
nf_bridge = nf_bridge_info_get(skb);
if (nf_bridge) {
entry->physin = nf_bridge_get_physindev(skb);
if (nf_bridge_info_exists(skb)) {
entry->physin = nf_bridge_get_physindev(skb, entry->state.net);
entry->physout = nf_bridge_get_physoutdev(skb);
} else {
entry->physin = NULL;

View File

@ -2977,6 +2977,9 @@ static int nf_tables_delchain(struct sk_buff *skb, const struct nfnl_info *info,
*/
int nft_register_expr(struct nft_expr_type *type)
{
if (WARN_ON_ONCE(type->maxattr > NFT_EXPR_MAXATTR))
return -ENOMEM;
nfnl_lock(NFNL_SUBSYS_NFTABLES);
if (type->family == NFPROTO_UNSPEC)
list_add_tail_rcu(&type->list, &nf_tables_expressions);
@ -3271,14 +3274,13 @@ int nft_expr_clone(struct nft_expr *dst, struct nft_expr *src)
{
int err;
if (src->ops->clone) {
if (WARN_ON_ONCE(!src->ops->clone))
return -EINVAL;
dst->ops = src->ops;
err = src->ops->clone(dst, src);
if (err < 0)
return err;
} else {
memcpy(dst, src, src->ops->size);
}
__module_get(src->ops->type->owner);
@ -4811,8 +4813,8 @@ static int nft_set_desc_concat_parse(const struct nlattr *attr,
static int nft_set_desc_concat(struct nft_set_desc *desc,
const struct nlattr *nla)
{
u32 num_regs = 0, key_num_regs = 0;
struct nlattr *attr;
u32 num_regs = 0;
int rem, err, i;
nla_for_each_nested(attr, nla, rem) {
@ -4827,6 +4829,10 @@ static int nft_set_desc_concat(struct nft_set_desc *desc,
for (i = 0; i < desc->field_count; i++)
num_regs += DIV_ROUND_UP(desc->field_len[i], sizeof(u32));
key_num_regs = DIV_ROUND_UP(desc->klen, sizeof(u32));
if (key_num_regs != num_regs)
return -EINVAL;
if (num_regs > NFT_REG32_COUNT)
return -E2BIG;
@ -5048,19 +5054,31 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
}
desc.policy = NFT_SET_POL_PERFORMANCE;
if (nla[NFTA_SET_POLICY] != NULL)
if (nla[NFTA_SET_POLICY] != NULL) {
desc.policy = ntohl(nla_get_be32(nla[NFTA_SET_POLICY]));
switch (desc.policy) {
case NFT_SET_POL_PERFORMANCE:
case NFT_SET_POL_MEMORY:
break;
default:
return -EOPNOTSUPP;
}
}
if (nla[NFTA_SET_DESC] != NULL) {
err = nf_tables_set_desc_parse(&desc, nla[NFTA_SET_DESC]);
if (err < 0)
return err;
if (desc.field_count > 1 && !(flags & NFT_SET_CONCAT))
if (desc.field_count > 1) {
if (!(flags & NFT_SET_CONCAT))
return -EINVAL;
} else if (flags & NFT_SET_CONCAT) {
return -EINVAL;
}
} else if (flags & NFT_SET_CONCAT) {
return -EINVAL;
}
if (nla[NFTA_SET_EXPR] || nla[NFTA_SET_EXPRESSIONS])
desc.expr = true;
@ -5704,7 +5722,7 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
struct nft_set_dump_args *args;
if (nft_set_elem_expired(ext))
if (nft_set_elem_expired(ext) || nft_set_elem_is_dead(ext))
return 0;
args = container_of(iter, struct nft_set_dump_args, iter);
@ -6568,7 +6586,7 @@ static int nft_setelem_catchall_deactivate(const struct net *net,
list_for_each_entry(catchall, &set->catchall_list, list) {
ext = nft_set_elem_ext(set, catchall->elem);
if (!nft_is_active(net, ext))
if (!nft_is_active_next(net, ext))
continue;
kfree(elem->priv);

View File

@ -508,7 +508,7 @@ __build_packet_message(struct nfnl_log_net *log,
htonl(br_port_get_rcu(indev)->br->dev->ifindex)))
goto nla_put_failure;
} else {
struct net_device *physindev;
int physinif;
/* Case 2: indev is bridge group, we need to look for
* physical device (when called from ipv4) */
@ -516,10 +516,10 @@ __build_packet_message(struct nfnl_log_net *log,
htonl(indev->ifindex)))
goto nla_put_failure;
physindev = nf_bridge_get_physindev(skb);
if (physindev &&
physinif = nf_bridge_get_physinif(skb);
if (physinif &&
nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSINDEV,
htonl(physindev->ifindex)))
htonl(physinif)))
goto nla_put_failure;
}
#endif

View File

@ -58,6 +58,7 @@ static inline bool nft_limit_eval(struct nft_limit_priv *priv, u64 cost)
static int nft_limit_init(struct nft_limit_priv *priv,
const struct nlattr * const tb[], bool pkts)
{
bool invert = false;
u64 unit, tokens;
if (tb[NFTA_LIMIT_RATE] == NULL ||
@ -90,19 +91,23 @@ static int nft_limit_init(struct nft_limit_priv *priv,
priv->rate);
}
if (tb[NFTA_LIMIT_FLAGS]) {
u32 flags = ntohl(nla_get_be32(tb[NFTA_LIMIT_FLAGS]));
if (flags & ~NFT_LIMIT_F_INV)
return -EOPNOTSUPP;
if (flags & NFT_LIMIT_F_INV)
invert = true;
}
priv->limit = kmalloc(sizeof(*priv->limit), GFP_KERNEL_ACCOUNT);
if (!priv->limit)
return -ENOMEM;
priv->limit->tokens = tokens;
priv->tokens_max = priv->limit->tokens;
if (tb[NFTA_LIMIT_FLAGS]) {
u32 flags = ntohl(nla_get_be32(tb[NFTA_LIMIT_FLAGS]));
if (flags & NFT_LIMIT_F_INV)
priv->invert = true;
}
priv->invert = invert;
priv->limit->last = ktime_get_ns();
spin_lock_init(&priv->limit->lock);

View File

@ -59,7 +59,7 @@ physdev_mt(const struct sk_buff *skb, struct xt_action_param *par)
(!!outdev ^ !(info->invert & XT_PHYSDEV_OP_BRIDGED)))
return false;
physdev = nf_bridge_get_physindev(skb);
physdev = nf_bridge_get_physindev(skb, xt_net(par));
indev = physdev ? physdev->name : NULL;
if ((info->bitmask & XT_PHYSDEV_OP_ISIN &&

View File

@ -858,4 +858,5 @@ void nfc_digital_unregister_device(struct nfc_digital_dev *ddev)
}
EXPORT_SYMBOL(nfc_digital_unregister_device);
MODULE_DESCRIPTION("NFC Digital protocol stack");
MODULE_LICENSE("GPL");

View File

@ -1577,4 +1577,5 @@ static void nci_cmd_work(struct work_struct *work)
}
}
MODULE_DESCRIPTION("NFC Controller Interface");
MODULE_LICENSE("GPL");

View File

@ -319,4 +319,5 @@ done:
}
EXPORT_SYMBOL_GPL(nci_spi_read);
MODULE_DESCRIPTION("NFC Controller Interface (NCI) SPI link layer");
MODULE_LICENSE("GPL");

View File

@ -1079,6 +1079,7 @@ void rxrpc_send_version_request(struct rxrpc_local *local,
/*
* local_object.c
*/
void rxrpc_local_dont_fragment(const struct rxrpc_local *local, bool set);
struct rxrpc_local *rxrpc_lookup_local(struct net *, const struct sockaddr_rxrpc *);
struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *, enum rxrpc_local_trace);
struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *, enum rxrpc_local_trace);

View File

@ -36,6 +36,17 @@ static void rxrpc_encap_err_rcv(struct sock *sk, struct sk_buff *skb, int err,
return ipv6_icmp_error(sk, skb, err, port, info, payload);
}
/*
* Set or clear the Don't Fragment flag on a socket.
*/
void rxrpc_local_dont_fragment(const struct rxrpc_local *local, bool set)
{
if (set)
ip_sock_set_mtu_discover(local->socket->sk, IP_PMTUDISC_DO);
else
ip_sock_set_mtu_discover(local->socket->sk, IP_PMTUDISC_DONT);
}
/*
* Compare a local to an address. Return -ve, 0 or +ve to indicate less than,
* same or greater than.
@ -203,7 +214,7 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
ip_sock_set_recverr(usk);
/* we want to set the don't fragment bit */
ip_sock_set_mtu_discover(usk, IP_PMTUDISC_DO);
rxrpc_local_dont_fragment(local, true);
/* We want receive timestamps. */
sock_enable_timestamps(usk);

View File

@ -494,14 +494,12 @@ send_fragmentable:
switch (conn->local->srx.transport.family) {
case AF_INET6:
case AF_INET:
ip_sock_set_mtu_discover(conn->local->socket->sk,
IP_PMTUDISC_DONT);
rxrpc_local_dont_fragment(conn->local, false);
rxrpc_inc_stat(call->rxnet, stat_tx_data_send_frag);
ret = do_udp_sendmsg(conn->local->socket, &msg, len);
conn->peer->last_tx_at = ktime_get_seconds();
ip_sock_set_mtu_discover(conn->local->socket->sk,
IP_PMTUDISC_DO);
rxrpc_local_dont_fragment(conn->local, true);
break;
default:

View File

@ -724,7 +724,9 @@ static int rxkad_send_response(struct rxrpc_connection *conn,
serial = atomic_inc_return(&conn->serial);
whdr.serial = htonl(serial);
rxrpc_local_dont_fragment(conn->local, false);
ret = kernel_sendmsg(conn->local->socket, &msg, iov, 3, len);
rxrpc_local_dont_fragment(conn->local, true);
if (ret < 0) {
trace_rxrpc_tx_fail(conn->debug_id, serial, ret,
rxrpc_tx_point_rxkad_response);

View File

@ -1424,6 +1424,14 @@ static void tcf_block_owner_del(struct tcf_block *block,
WARN_ON(1);
}
static bool tcf_block_tracks_dev(struct tcf_block *block,
struct tcf_block_ext_info *ei)
{
return tcf_block_shared(block) &&
(ei->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS ||
ei->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS);
}
int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
struct tcf_block_ext_info *ei,
struct netlink_ext_ack *extack)
@ -1462,7 +1470,7 @@ int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
if (err)
goto err_block_offload_bind;
if (tcf_block_shared(block)) {
if (tcf_block_tracks_dev(block, ei)) {
err = xa_insert(&block->ports, dev->ifindex, dev, GFP_KERNEL);
if (err) {
NL_SET_ERR_MSG(extack, "block dev insert failed");
@ -1516,7 +1524,7 @@ void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q,
if (!block)
return;
if (tcf_block_shared(block))
if (tcf_block_tracks_dev(block, ei))
xa_erase(&block->ports, dev->ifindex);
tcf_chain0_head_change_cb_del(block, ei);
tcf_block_owner_del(block, q, ei->binder_type);

View File

@ -2280,6 +2280,7 @@ static void __exit exit_rpcsec_gss(void)
}
MODULE_ALIAS("rpc-auth-6");
MODULE_DESCRIPTION("Sun RPC Kerberos RPCSEC_GSS client authentication");
MODULE_LICENSE("GPL");
module_param_named(expired_cred_retry_delay,
gss_expired_cred_retry_delay,

View File

@ -650,6 +650,7 @@ static void __exit cleanup_kerberos_module(void)
gss_mech_unregister(&gss_kerberos_mech);
}
MODULE_DESCRIPTION("Sun RPC Kerberos 5 module");
MODULE_LICENSE("GPL");
module_init(init_kerberos_module);
module_exit(cleanup_kerberos_module);

View File

@ -148,6 +148,7 @@ cleanup_sunrpc(void)
#endif
rcu_barrier(); /* Wait for completion of call_rcu()'s */
}
MODULE_DESCRIPTION("Sun RPC core");
MODULE_LICENSE("GPL");
fs_initcall(init_sunrpc); /* Ensure we're initialised before nfs */
module_exit(cleanup_sunrpc);

View File

@ -1052,7 +1052,11 @@ alloc_encrypted:
if (ret < 0)
goto send_end;
tls_ctx->pending_open_record_frags = true;
if (full_record || eor || sk_msg_full(msg_pl))
if (sk_msg_full(msg_pl))
full_record = true;
if (full_record || eor)
goto copied;
continue;
}

View File

@ -6695,6 +6695,67 @@ static struct {
/* all other program types don't have "named" context structs */
};
static bool need_func_arg_type_fixup(const struct btf *btf, const struct bpf_program *prog,
const char *subprog_name, int arg_idx,
int arg_type_id, const char *ctx_name)
{
const struct btf_type *t;
const char *tname;
/* check if existing parameter already matches verifier expectations */
t = skip_mods_and_typedefs(btf, arg_type_id, NULL);
if (!btf_is_ptr(t))
goto out_warn;
/* typedef bpf_user_pt_regs_t is a special PITA case, valid for kprobe
* and perf_event programs, so check this case early on and forget
* about it for subsequent checks
*/
while (btf_is_mod(t))
t = btf__type_by_id(btf, t->type);
if (btf_is_typedef(t) &&
(prog->type == BPF_PROG_TYPE_KPROBE || prog->type == BPF_PROG_TYPE_PERF_EVENT)) {
tname = btf__str_by_offset(btf, t->name_off) ?: "<anon>";
if (strcmp(tname, "bpf_user_pt_regs_t") == 0)
return false; /* canonical type for kprobe/perf_event */
}
/* now we can ignore typedefs moving forward */
t = skip_mods_and_typedefs(btf, t->type, NULL);
/* if it's `void *`, definitely fix up BTF info */
if (btf_is_void(t))
return true;
/* if it's already proper canonical type, no need to fix up */
tname = btf__str_by_offset(btf, t->name_off) ?: "<anon>";
if (btf_is_struct(t) && strcmp(tname, ctx_name) == 0)
return false;
/* special cases */
switch (prog->type) {
case BPF_PROG_TYPE_KPROBE:
case BPF_PROG_TYPE_PERF_EVENT:
/* `struct pt_regs *` is expected, but we need to fix up */
if (btf_is_struct(t) && strcmp(tname, "pt_regs") == 0)
return true;
break;
case BPF_PROG_TYPE_RAW_TRACEPOINT:
case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:
/* allow u64* as ctx */
if (btf_is_int(t) && t->size == 8)
return true;
break;
default:
break;
}
out_warn:
pr_warn("prog '%s': subprog '%s' arg#%d is expected to be of `struct %s *` type\n",
prog->name, subprog_name, arg_idx, ctx_name);
return false;
}
static int clone_func_btf_info(struct btf *btf, int orig_fn_id, struct bpf_program *prog)
{
int fn_id, fn_proto_id, ret_type_id, orig_proto_id;
@ -6757,6 +6818,69 @@ static int clone_func_btf_info(struct btf *btf, int orig_fn_id, struct bpf_progr
return fn_id;
}
static int probe_kern_arg_ctx_tag(void)
{
/* To minimize merge conflicts with BPF token series that refactors
* feature detection code a lot, we don't integrate
* probe_kern_arg_ctx_tag() into kernel_supports() feature-detection
* framework yet, doing our own caching internally.
* This will be cleaned up a bit later when bpf/bpf-next trees settle.
*/
static int cached_result = -1;
static const char strs[] = "\0a\0b\0arg:ctx\0";
const __u32 types[] = {
/* [1] INT */
BTF_TYPE_INT_ENC(1 /* "a" */, BTF_INT_SIGNED, 0, 32, 4),
/* [2] PTR -> VOID */
BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 0),
/* [3] FUNC_PROTO `int(void *a)` */
BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 1), 1),
BTF_PARAM_ENC(1 /* "a" */, 2),
/* [4] FUNC 'a' -> FUNC_PROTO (main prog) */
BTF_TYPE_ENC(1 /* "a" */, BTF_INFO_ENC(BTF_KIND_FUNC, 0, BTF_FUNC_GLOBAL), 3),
/* [5] FUNC_PROTO `int(void *b __arg_ctx)` */
BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 1), 1),
BTF_PARAM_ENC(3 /* "b" */, 2),
/* [6] FUNC 'b' -> FUNC_PROTO (subprog) */
BTF_TYPE_ENC(3 /* "b" */, BTF_INFO_ENC(BTF_KIND_FUNC, 0, BTF_FUNC_GLOBAL), 5),
/* [7] DECL_TAG 'arg:ctx' -> func 'b' arg 'b' */
BTF_TYPE_DECL_TAG_ENC(5 /* "arg:ctx" */, 6, 0),
};
const struct bpf_insn insns[] = {
/* main prog */
BPF_CALL_REL(+1),
BPF_EXIT_INSN(),
/* global subprog */
BPF_EMIT_CALL(BPF_FUNC_get_func_ip), /* needs PTR_TO_CTX */
BPF_EXIT_INSN(),
};
const struct bpf_func_info_min func_infos[] = {
{ 0, 4 }, /* main prog -> FUNC 'a' */
{ 2, 6 }, /* subprog -> FUNC 'b' */
};
LIBBPF_OPTS(bpf_prog_load_opts, opts);
int prog_fd, btf_fd, insn_cnt = ARRAY_SIZE(insns);
if (cached_result >= 0)
return cached_result;
btf_fd = libbpf__load_raw_btf((char *)types, sizeof(types), strs, sizeof(strs));
if (btf_fd < 0)
return 0;
opts.prog_btf_fd = btf_fd;
opts.func_info = &func_infos;
opts.func_info_cnt = ARRAY_SIZE(func_infos);
opts.func_info_rec_size = sizeof(func_infos[0]);
prog_fd = bpf_prog_load(BPF_PROG_TYPE_KPROBE, "det_arg_ctx",
"GPL", insns, insn_cnt, &opts);
close(btf_fd);
cached_result = probe_fd(prog_fd);
return cached_result;
}
/* Check if main program or global subprog's function prototype has `arg:ctx`
* argument tags, and, if necessary, substitute correct type to match what BPF
* verifier would expect, taking into account specific program type. This
@ -6766,7 +6890,7 @@ static int clone_func_btf_info(struct btf *btf, int orig_fn_id, struct bpf_progr
*/
static int bpf_program_fixup_func_info(struct bpf_object *obj, struct bpf_program *prog)
{
const char *ctx_name = NULL, *ctx_tag = "arg:ctx";
const char *ctx_name = NULL, *ctx_tag = "arg:ctx", *fn_name;
struct bpf_func_info_min *func_rec;
struct btf_type *fn_t, *fn_proto_t;
struct btf *btf = obj->btf;
@ -6780,6 +6904,10 @@ static int bpf_program_fixup_func_info(struct bpf_object *obj, struct bpf_progra
if (!obj->btf_ext || !prog->func_info)
return 0;
/* don't do any fix ups if kernel natively supports __arg_ctx */
if (probe_kern_arg_ctx_tag() > 0)
return 0;
/* some BPF program types just don't have named context structs, so
* this fallback mechanism doesn't work for them
*/
@ -6842,15 +6970,11 @@ static int bpf_program_fixup_func_info(struct bpf_object *obj, struct bpf_progra
if (arg_idx < 0 || arg_idx >= arg_cnt)
continue;
/* check if existing parameter already matches verifier expectations */
/* check if we should fix up argument type */
p = &btf_params(fn_proto_t)[arg_idx];
t = skip_mods_and_typedefs(btf, p->type, NULL);
if (btf_is_ptr(t) &&
(t = skip_mods_and_typedefs(btf, t->type, NULL)) &&
btf_is_struct(t) &&
strcmp(btf__str_by_offset(btf, t->name_off), ctx_name) == 0) {
continue; /* no need for fix up */
}
fn_name = btf__str_by_offset(btf, fn_t->name_off) ?: "<anon>";
if (!need_func_arg_type_fixup(btf, prog, fn_name, arg_idx, p->type, ctx_name))
continue;
/* clone fn/fn_proto, unless we already did it for another arg */
if (func_rec->type_id == orig_fn_id) {

View File

@ -0,0 +1,135 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2024 Meta
#include <test_progs.h>
#include "network_helpers.h"
#include "sock_iter_batch.skel.h"
#define TEST_NS "sock_iter_batch_netns"
static const int nr_soreuse = 4;
static void do_test(int sock_type, bool onebyone)
{
int err, i, nread, to_read, total_read, iter_fd = -1;
int first_idx, second_idx, indices[nr_soreuse];
struct bpf_link *link = NULL;
struct sock_iter_batch *skel;
int *fds[2] = {};
skel = sock_iter_batch__open();
if (!ASSERT_OK_PTR(skel, "sock_iter_batch__open"))
return;
/* Prepare 2 buckets of sockets in the kernel hashtable */
for (i = 0; i < ARRAY_SIZE(fds); i++) {
int local_port;
fds[i] = start_reuseport_server(AF_INET6, sock_type, "::1", 0, 0,
nr_soreuse);
if (!ASSERT_OK_PTR(fds[i], "start_reuseport_server"))
goto done;
local_port = get_socket_local_port(*fds[i]);
if (!ASSERT_GE(local_port, 0, "get_socket_local_port"))
goto done;
skel->rodata->ports[i] = ntohs(local_port);
}
err = sock_iter_batch__load(skel);
if (!ASSERT_OK(err, "sock_iter_batch__load"))
goto done;
link = bpf_program__attach_iter(sock_type == SOCK_STREAM ?
skel->progs.iter_tcp_soreuse :
skel->progs.iter_udp_soreuse,
NULL);
if (!ASSERT_OK_PTR(link, "bpf_program__attach_iter"))
goto done;
iter_fd = bpf_iter_create(bpf_link__fd(link));
if (!ASSERT_GE(iter_fd, 0, "bpf_iter_create"))
goto done;
/* Test reading a bucket (either from fds[0] or fds[1]).
* Only read "nr_soreuse - 1" number of sockets
* from a bucket and leave one socket out from
* that bucket on purpose.
*/
to_read = (nr_soreuse - 1) * sizeof(*indices);
total_read = 0;
first_idx = -1;
do {
nread = read(iter_fd, indices, onebyone ? sizeof(*indices) : to_read);
if (nread <= 0 || nread % sizeof(*indices))
break;
total_read += nread;
if (first_idx == -1)
first_idx = indices[0];
for (i = 0; i < nread / sizeof(*indices); i++)
ASSERT_EQ(indices[i], first_idx, "first_idx");
} while (total_read < to_read);
ASSERT_EQ(nread, onebyone ? sizeof(*indices) : to_read, "nread");
ASSERT_EQ(total_read, to_read, "total_read");
free_fds(fds[first_idx], nr_soreuse);
fds[first_idx] = NULL;
/* Read the "whole" second bucket */
to_read = nr_soreuse * sizeof(*indices);
total_read = 0;
second_idx = !first_idx;
do {
nread = read(iter_fd, indices, onebyone ? sizeof(*indices) : to_read);
if (nread <= 0 || nread % sizeof(*indices))
break;
total_read += nread;
for (i = 0; i < nread / sizeof(*indices); i++)
ASSERT_EQ(indices[i], second_idx, "second_idx");
} while (total_read <= to_read);
ASSERT_EQ(nread, 0, "nread");
/* Both so_reuseport ports should be in different buckets, so
* total_read must equal to the expected to_read.
*
* For a very unlikely case, both ports collide at the same bucket,
* the bucket offset (i.e. 3) will be skipped and it cannot
* expect the to_read number of bytes.
*/
if (skel->bss->bucket[0] != skel->bss->bucket[1])
ASSERT_EQ(total_read, to_read, "total_read");
done:
for (i = 0; i < ARRAY_SIZE(fds); i++)
free_fds(fds[i], nr_soreuse);
if (iter_fd < 0)
close(iter_fd);
bpf_link__destroy(link);
sock_iter_batch__destroy(skel);
}
void test_sock_iter_batch(void)
{
struct nstoken *nstoken = NULL;
SYS_NOFAIL("ip netns del " TEST_NS " &> /dev/null");
SYS(done, "ip netns add %s", TEST_NS);
SYS(done, "ip -net %s link set dev lo up", TEST_NS);
nstoken = open_netns(TEST_NS);
if (!ASSERT_OK_PTR(nstoken, "open_netns"))
goto done;
if (test__start_subtest("tcp")) {
do_test(SOCK_STREAM, true);
do_test(SOCK_STREAM, false);
}
if (test__start_subtest("udp")) {
do_test(SOCK_DGRAM, true);
do_test(SOCK_DGRAM, false);
}
close_netns(nstoken);
done:
SYS_NOFAIL("ip netns del " TEST_NS " &> /dev/null");
}

View File

@ -47,6 +47,19 @@ static void subtest_ctx_arg_rewrite(void)
struct btf *btf = NULL;
__u32 info_len = sizeof(info);
int err, fd, i;
struct btf *kern_btf = NULL;
kern_btf = btf__load_vmlinux_btf();
if (!ASSERT_OK_PTR(kern_btf, "kern_btf_load"))
return;
/* simple detection of kernel native arg:ctx tag support */
if (btf__find_by_name_kind(kern_btf, "bpf_subprog_arg_info", BTF_KIND_STRUCT) > 0) {
test__skip();
btf__free(kern_btf);
return;
}
btf__free(kern_btf);
skel = test_global_func_ctx_args__open();
if (!ASSERT_OK_PTR(skel, "skel_open"))

View File

@ -72,6 +72,8 @@
#define inet_rcv_saddr sk.__sk_common.skc_rcv_saddr
#define inet_dport sk.__sk_common.skc_dport
#define udp_portaddr_hash inet.sk.__sk_common.skc_u16hashes[1]
#define ir_loc_addr req.__req_common.skc_rcv_saddr
#define ir_num req.__req_common.skc_num
#define ir_rmt_addr req.__req_common.skc_daddr
@ -85,6 +87,7 @@
#define sk_rmem_alloc sk_backlog.rmem_alloc
#define sk_refcnt __sk_common.skc_refcnt
#define sk_state __sk_common.skc_state
#define sk_net __sk_common.skc_net
#define sk_v6_daddr __sk_common.skc_v6_daddr
#define sk_v6_rcv_saddr __sk_common.skc_v6_rcv_saddr
#define sk_flags __sk_common.skc_flags

View File

@ -0,0 +1,91 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2024 Meta
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_endian.h>
#include "bpf_tracing_net.h"
#include "bpf_kfuncs.h"
#define ATTR __always_inline
#include "test_jhash.h"
static bool ipv6_addr_loopback(const struct in6_addr *a)
{
return (a->s6_addr32[0] | a->s6_addr32[1] |
a->s6_addr32[2] | (a->s6_addr32[3] ^ bpf_htonl(1))) == 0;
}
volatile const __u16 ports[2];
unsigned int bucket[2];
SEC("iter/tcp")
int iter_tcp_soreuse(struct bpf_iter__tcp *ctx)
{
struct sock *sk = (struct sock *)ctx->sk_common;
struct inet_hashinfo *hinfo;
unsigned int hash;
struct net *net;
int idx;
if (!sk)
return 0;
sk = bpf_rdonly_cast(sk, bpf_core_type_id_kernel(struct sock));
if (sk->sk_family != AF_INET6 ||
sk->sk_state != TCP_LISTEN ||
!ipv6_addr_loopback(&sk->sk_v6_rcv_saddr))
return 0;
if (sk->sk_num == ports[0])
idx = 0;
else if (sk->sk_num == ports[1])
idx = 1;
else
return 0;
/* bucket selection as in inet_lhash2_bucket_sk() */
net = sk->sk_net.net;
hash = jhash2(sk->sk_v6_rcv_saddr.s6_addr32, 4, net->hash_mix);
hash ^= sk->sk_num;
hinfo = net->ipv4.tcp_death_row.hashinfo;
bucket[idx] = hash & hinfo->lhash2_mask;
bpf_seq_write(ctx->meta->seq, &idx, sizeof(idx));
return 0;
}
#define udp_sk(ptr) container_of(ptr, struct udp_sock, inet.sk)
SEC("iter/udp")
int iter_udp_soreuse(struct bpf_iter__udp *ctx)
{
struct sock *sk = (struct sock *)ctx->udp_sk;
struct udp_table *udptable;
int idx;
if (!sk)
return 0;
sk = bpf_rdonly_cast(sk, bpf_core_type_id_kernel(struct sock));
if (sk->sk_family != AF_INET6 ||
!ipv6_addr_loopback(&sk->sk_v6_rcv_saddr))
return 0;
if (sk->sk_num == ports[0])
idx = 0;
else if (sk->sk_num == ports[1])
idx = 1;
else
return 0;
/* bucket selection as in udp_hashslot2() */
udptable = sk->sk_net.net->ipv4.udp_table;
bucket[idx] = udp_sk(sk)->udp_portaddr_hash & udptable->mask;
bpf_seq_write(ctx->meta->seq, &idx, sizeof(idx));
return 0;
}
char _license[] SEC("license") = "GPL";

View File

@ -69,3 +69,34 @@ u32 jhash(const void *key, u32 length, u32 initval)
return c;
}
static __always_inline u32 jhash2(const u32 *k, u32 length, u32 initval)
{
u32 a, b, c;
/* Set up the internal state */
a = b = c = JHASH_INITVAL + (length<<2) + initval;
/* Handle most of the key */
while (length > 3) {
a += k[0];
b += k[1];
c += k[2];
__jhash_mix(a, b, c);
length -= 3;
k += 3;
}
/* Handle the last 3 u32's */
switch (length) {
case 3: c += k[2];
case 2: b += k[1];
case 1: a += k[0];
__jhash_final(a, b, c);
break;
case 0: /* Nothing left to add */
break;
}
return c;
}

View File

@ -3,6 +3,7 @@
#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include "bpf_misc.h"
#include "xdp_metadata.h"
#include "bpf_kfuncs.h"
@ -138,25 +139,182 @@ __weak int subprog_ctx_tag(void *ctx __arg_ctx)
return bpf_get_stack(ctx, stack, sizeof(stack), 0);
}
__weak int raw_tp_canonical(struct bpf_raw_tracepoint_args *ctx __arg_ctx)
{
return 0;
}
__weak int raw_tp_u64_array(u64 *ctx __arg_ctx)
{
return 0;
}
SEC("?raw_tp")
__success __log_level(2)
int arg_tag_ctx_raw_tp(void *ctx)
{
return subprog_ctx_tag(ctx);
return subprog_ctx_tag(ctx) + raw_tp_canonical(ctx) + raw_tp_u64_array(ctx);
}
SEC("?raw_tp.w")
__success __log_level(2)
int arg_tag_ctx_raw_tp_writable(void *ctx)
{
return subprog_ctx_tag(ctx) + raw_tp_canonical(ctx) + raw_tp_u64_array(ctx);
}
SEC("?tp_btf/sys_enter")
__success __log_level(2)
int arg_tag_ctx_raw_tp_btf(void *ctx)
{
return subprog_ctx_tag(ctx) + raw_tp_canonical(ctx) + raw_tp_u64_array(ctx);
}
struct whatever { };
__weak int tp_whatever(struct whatever *ctx __arg_ctx)
{
return 0;
}
SEC("?tp")
__success __log_level(2)
int arg_tag_ctx_tp(void *ctx)
{
return subprog_ctx_tag(ctx);
return subprog_ctx_tag(ctx) + tp_whatever(ctx);
}
__weak int kprobe_subprog_pt_regs(struct pt_regs *ctx __arg_ctx)
{
return 0;
}
__weak int kprobe_subprog_typedef(bpf_user_pt_regs_t *ctx __arg_ctx)
{
return 0;
}
SEC("?kprobe")
__success __log_level(2)
int arg_tag_ctx_kprobe(void *ctx)
{
return subprog_ctx_tag(ctx);
return subprog_ctx_tag(ctx) +
kprobe_subprog_pt_regs(ctx) +
kprobe_subprog_typedef(ctx);
}
__weak int perf_subprog_regs(
#if defined(bpf_target_riscv)
struct user_regs_struct *ctx __arg_ctx
#elif defined(bpf_target_s390)
/* user_pt_regs typedef is anonymous struct, so only `void *` works */
void *ctx __arg_ctx
#elif defined(bpf_target_loongarch) || defined(bpf_target_arm64) || defined(bpf_target_powerpc)
struct user_pt_regs *ctx __arg_ctx
#else
struct pt_regs *ctx __arg_ctx
#endif
)
{
return 0;
}
__weak int perf_subprog_typedef(bpf_user_pt_regs_t *ctx __arg_ctx)
{
return 0;
}
__weak int perf_subprog_canonical(struct bpf_perf_event_data *ctx __arg_ctx)
{
return 0;
}
SEC("?perf_event")
__success __log_level(2)
int arg_tag_ctx_perf(void *ctx)
{
return subprog_ctx_tag(ctx) +
perf_subprog_regs(ctx) +
perf_subprog_typedef(ctx) +
perf_subprog_canonical(ctx);
}
__weak int iter_subprog_void(void *ctx __arg_ctx)
{
return 0;
}
__weak int iter_subprog_typed(struct bpf_iter__task *ctx __arg_ctx)
{
return 0;
}
SEC("?iter/task")
__success __log_level(2)
int arg_tag_ctx_iter_task(struct bpf_iter__task *ctx)
{
return (iter_subprog_void(ctx) + iter_subprog_typed(ctx)) & 1;
}
__weak int tracing_subprog_void(void *ctx __arg_ctx)
{
return 0;
}
__weak int tracing_subprog_u64(u64 *ctx __arg_ctx)
{
return 0;
}
int acc;
SEC("?fentry/" SYS_PREFIX "sys_nanosleep")
__success __log_level(2)
int BPF_PROG(arg_tag_ctx_fentry)
{
acc += tracing_subprog_void(ctx) + tracing_subprog_u64(ctx);
return 0;
}
SEC("?fexit/" SYS_PREFIX "sys_nanosleep")
__success __log_level(2)
int BPF_PROG(arg_tag_ctx_fexit)
{
acc += tracing_subprog_void(ctx) + tracing_subprog_u64(ctx);
return 0;
}
SEC("?fmod_ret/" SYS_PREFIX "sys_nanosleep")
__success __log_level(2)
int BPF_PROG(arg_tag_ctx_fmod_ret)
{
return tracing_subprog_void(ctx) + tracing_subprog_u64(ctx);
}
SEC("?lsm/bpf")
__success __log_level(2)
int BPF_PROG(arg_tag_ctx_lsm)
{
return tracing_subprog_void(ctx) + tracing_subprog_u64(ctx);
}
SEC("?struct_ops/test_1")
__success __log_level(2)
int BPF_PROG(arg_tag_ctx_struct_ops)
{
return tracing_subprog_void(ctx) + tracing_subprog_u64(ctx);
}
SEC(".struct_ops")
struct bpf_dummy_ops dummy_1 = {
.test_1 = (void *)arg_tag_ctx_struct_ops,
};
SEC("?syscall")
__success __log_level(2)
int arg_tag_ctx_syscall(void *ctx)
{
return tracing_subprog_void(ctx) + tracing_subprog_u64(ctx) + tp_whatever(ctx);
}
__weak int subprog_dynptr(struct bpf_dynptr *dptr)

View File

@ -146,4 +146,23 @@ l0_%=: exit; \
: __clobber_all);
}
SEC("flow_dissector")
__description("flow_keys illegal alu op with variable offset")
__failure __msg("R7 pointer arithmetic on flow_keys prohibited")
__naked void flow_keys_illegal_variable_offset_alu(void)
{
asm volatile(" \
r6 = r1; \
r7 = *(u64*)(r6 + %[flow_keys_off]); \
r8 = 8; \
r8 /= 1; \
r8 &= 8; \
r7 += r8; \
r0 = *(u64*)(r7 + 0); \
exit; \
" :
: __imm_const(flow_keys_off, offsetof(struct __sk_buff, flow_keys))
: __clobber_all);
}
char _license[] SEC("license") = "GPL";

View File

@ -1,2 +1,10 @@
CONFIG_BONDING=y
CONFIG_BRIDGE=y
CONFIG_DUMMY=y
CONFIG_IPV6=y
CONFIG_MACVLAN=y
CONFIG_NET_ACT_GACT=y
CONFIG_NET_CLS_FLOWER=y
CONFIG_NET_SCH_INGRESS=y
CONFIG_NLMON=y
CONFIG_VETH=y

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Regression Test:

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Regression Test:

View File

@ -40,7 +40,6 @@
# | + $swp1 $swp3 + + $swp4 |
# | | iPOOL1 iPOOL0 | | iPOOL2 |
# | | ePOOL4 ePOOL5 | | ePOOL4 |
# | | 1Gbps | | 1Gbps |
# | | PFC:enabled=1 | | PFC:enabled=1 |
# | +-|----------------------|-+ +-|------------------------+ |
# | | + $swp1.111 $swp3.111 + | | + $swp4.111 | |
@ -120,6 +119,9 @@ h2_destroy()
switch_create()
{
local lanes_swp4
local pg1_size
# pools
# -----
@ -229,7 +231,20 @@ switch_create()
dcb pfc set dev $swp4 prio-pfc all:off 1:on
# PG0 will get autoconfigured to Xoff, give PG1 arbitrarily 100K, which
# is (-2*MTU) about 80K of delay provision.
dcb buffer set dev $swp4 buffer-size all:0 1:$_100KB
pg1_size=$_100KB
setup_wait_dev_with_timeout $swp4
lanes_swp4=$(ethtool $swp4 | grep 'Lanes:')
lanes_swp4=${lanes_swp4#*"Lanes: "}
# 8-lane ports use two buffers among which the configured buffer
# is split, so double the size to get twice (20K + 80K).
if [[ $lanes_swp4 -eq 8 ]]; then
pg1_size=$((pg1_size * 2))
fi
dcb buffer set dev $swp4 buffer-size all:0 1:$pg1_size
# bridges
# -------

View File

@ -10,7 +10,8 @@ lib_dir=$(dirname $0)/../../../../net/forwarding
ALL_TESTS="single_mask_test identical_filters_test two_masks_test \
multiple_masks_test ctcam_edge_cases_test delta_simple_test \
delta_two_masks_one_key_test delta_simple_rehash_test \
bloom_simple_test bloom_complex_test bloom_delta_test"
bloom_simple_test bloom_complex_test bloom_delta_test \
max_erp_entries_test max_group_size_test"
NUM_NETIFS=2
source $lib_dir/lib.sh
source $lib_dir/tc_common.sh
@ -983,6 +984,109 @@ bloom_delta_test()
log_test "bloom delta test ($tcflags)"
}
max_erp_entries_test()
{
# The number of eRP entries is limited. Once the maximum number of eRPs
# has been reached, filters cannot be added. This test verifies that
# when this limit is reached, inserstion fails without crashing.
RET=0
local num_masks=32
local num_regions=15
local chain_failed
local mask_failed
local ret
if [[ "$tcflags" != "skip_sw" ]]; then
return 0;
fi
for ((i=1; i < $num_regions; i++)); do
for ((j=$num_masks; j >= 0; j--)); do
tc filter add dev $h2 ingress chain $i protocol ip \
pref $i handle $j flower $tcflags \
dst_ip 192.1.0.0/$j &> /dev/null
ret=$?
if [ $ret -ne 0 ]; then
chain_failed=$i
mask_failed=$j
break 2
fi
done
done
# We expect to exceed the maximum number of eRP entries, so that
# insertion eventually fails. Otherwise, the test should be adjusted to
# add more filters.
check_fail $ret "expected to exceed number of eRP entries"
for ((; i >= 1; i--)); do
for ((j=0; j <= $num_masks; j++)); do
tc filter del dev $h2 ingress chain $i protocol ip \
pref $i handle $j flower &> /dev/null
done
done
log_test "max eRP entries test ($tcflags). " \
"max chain $chain_failed, mask $mask_failed"
}
max_group_size_test()
{
# The number of ACLs in an ACL group is limited. Once the maximum
# number of ACLs has been reached, filters cannot be added. This test
# verifies that when this limit is reached, insertion fails without
# crashing.
RET=0
local num_acls=32
local max_size
local ret
if [[ "$tcflags" != "skip_sw" ]]; then
return 0;
fi
for ((i=1; i < $num_acls; i++)); do
if [[ $(( i % 2 )) == 1 ]]; then
tc filter add dev $h2 ingress pref $i proto ipv4 \
flower $tcflags dst_ip 198.51.100.1/32 \
ip_proto tcp tcp_flags 0x01/0x01 \
action drop &> /dev/null
else
tc filter add dev $h2 ingress pref $i proto ipv6 \
flower $tcflags dst_ip 2001:db8:1::1/128 \
action drop &> /dev/null
fi
ret=$?
[[ $ret -ne 0 ]] && max_size=$((i - 1)) && break
done
# We expect to exceed the maximum number of ACLs in a group, so that
# insertion eventually fails. Otherwise, the test should be adjusted to
# add more filters.
check_fail $ret "expected to exceed number of ACLs in a group"
for ((; i >= 1; i--)); do
if [[ $(( i % 2 )) == 1 ]]; then
tc filter del dev $h2 ingress pref $i proto ipv4 \
flower $tcflags dst_ip 198.51.100.1/32 \
ip_proto tcp tcp_flags 0x01/0x01 \
action drop &> /dev/null
else
tc filter del dev $h2 ingress pref $i proto ipv6 \
flower $tcflags dst_ip 2001:db8:1::1/128 \
action drop &> /dev/null
fi
done
log_test "max ACL group size test ($tcflags). max size $max_size"
}
setup_prepare()
{
h1=${NETIFS[p1]}

View File

@ -0,0 +1,10 @@
CONFIG_DUMMY=y
CONFIG_GENEVE=m
CONFIG_IPV6=y
CONFIG_NETDEVSIM=m
CONFIG_NET_SCH_MQPRIO=y
CONFIG_NET_SCH_MULTIQ=y
CONFIG_NET_SCH_PRIO=y
CONFIG_PSAMPLE=y
CONFIG_PTP_1588_CLOCK_MOCK=y
CONFIG_VXLAN=m

View File

@ -51,6 +51,7 @@ function make_netdev {
fi
echo $NSIM_ID $@ > /sys/bus/netdevsim/new_device
udevadm settle
# get new device name
ls /sys/bus/netdevsim/devices/netdevsim${NSIM_ID}/net/
}

View File

@ -8,16 +8,20 @@ NSIM_NETDEV=$(make_netdev)
set -o pipefail
# Since commit 2b3ddcb35357 ("ethtool: fec: Change the prompt ...")
# in ethtool CLI the Configured lines start with Supported/Configured.
configured=$($ETHTOOL --show-fec $NSIM_NETDEV | tail -2 | head -1 | cut -d' ' -f1)
# netdevsim starts out with None/None
s=$($ETHTOOL --show-fec $NSIM_NETDEV | tail -2)
check $? "$s" "Configured FEC encodings: None
check $? "$s" "$configured FEC encodings: None
Active FEC encoding: None"
# Test Auto
$ETHTOOL --set-fec $NSIM_NETDEV encoding auto
check $?
s=$($ETHTOOL --show-fec $NSIM_NETDEV | tail -2)
check $? "$s" "Configured FEC encodings: Auto
check $? "$s" "$configured FEC encodings: Auto
Active FEC encoding: Off"
# Test case in-sensitivity
@ -25,7 +29,7 @@ for o in off Off OFF; do
$ETHTOOL --set-fec $NSIM_NETDEV encoding $o
check $?
s=$($ETHTOOL --show-fec $NSIM_NETDEV | tail -2)
check $? "$s" "Configured FEC encodings: Off
check $? "$s" "$configured FEC encodings: Off
Active FEC encoding: Off"
done
@ -33,7 +37,7 @@ for o in BaseR baser BAser; do
$ETHTOOL --set-fec $NSIM_NETDEV encoding $o
check $?
s=$($ETHTOOL --show-fec $NSIM_NETDEV | tail -2)
check $? "$s" "Configured FEC encodings: BaseR
check $? "$s" "$configured FEC encodings: BaseR
Active FEC encoding: BaseR"
done
@ -41,7 +45,7 @@ for o in llrs rs; do
$ETHTOOL --set-fec $NSIM_NETDEV encoding $o
check $?
s=$($ETHTOOL --show-fec $NSIM_NETDEV | tail -2)
check $? "$s" "Configured FEC encodings: ${o^^}
check $? "$s" "$configured FEC encodings: ${o^^}
Active FEC encoding: ${o^^}"
done
@ -49,13 +53,13 @@ done
$ETHTOOL --set-fec $NSIM_NETDEV encoding rs llrs
check $?
s=$($ETHTOOL --show-fec $NSIM_NETDEV | tail -2)
check $? "$s" "Configured FEC encodings: RS LLRS
check $? "$s" "$configured FEC encodings: RS LLRS
Active FEC encoding: LLRS"
$ETHTOOL --set-fec $NSIM_NETDEV encoding rs off auto
check $?
s=$($ETHTOOL --show-fec $NSIM_NETDEV | tail -2)
check $? "$s" "Configured FEC encodings: Auto Off RS
check $? "$s" "$configured FEC encodings: Auto Off RS
Active FEC encoding: RS"
# Make sure other link modes are rejected

View File

@ -233,6 +233,7 @@ function print_tables {
function get_netdev_name {
local -n old=$1
udevadm settle
new=$(ls /sys/class/net)
for netdev in $new; do

0
tools/testing/selftests/net/forwarding/lib.sh Executable file → Normal file
View File

View File

@ -28,6 +28,7 @@ ALL_TESTS="
kci_test_neigh_get
kci_test_bridge_parent_id
kci_test_address_proto
kci_test_enslave_bonding
"
devdummy="test-dummy0"
@ -1241,6 +1242,31 @@ kci_test_address_proto()
return $ret
}
kci_test_enslave_bonding()
{
local bond="bond123"
local ret=0
setup_ns testns
if [ $? -ne 0 ]; then
end_test "SKIP bonding tests: cannot add net namespace $testns"
return $ksft_skip
fi
run_cmd ip -netns $testns link add dev $bond type bond mode balance-rr
run_cmd ip -netns $testns link add dev $devdummy type dummy
run_cmd ip -netns $testns link set dev $devdummy up
run_cmd ip -netns $testns link set dev $devdummy master $bond down
if [ $ret -ne 0 ]; then
end_test "FAIL: initially up interface added to a bond and set down"
ip netns del "$testns"
return 1
fi
end_test "PASS: enslave interface in a bond"
ip netns del "$testns"
}
kci_test_rtnl()
{
local current_test

View File

@ -52,5 +52,5 @@ $(OUTPUT)/%_ipv6: %.c
$(OUTPUT)/icmps-accept_ipv4: CFLAGS+= -DTEST_ICMPS_ACCEPT
$(OUTPUT)/icmps-accept_ipv6: CFLAGS+= -DTEST_ICMPS_ACCEPT
$(OUTPUT)/bench-lookups_ipv4: LDFLAGS+= -lm
$(OUTPUT)/bench-lookups_ipv6: LDFLAGS+= -lm
$(OUTPUT)/bench-lookups_ipv4: LDLIBS+= -lm
$(OUTPUT)/bench-lookups_ipv6: LDLIBS+= -lm

View File

@ -707,6 +707,20 @@ TEST_F(tls, splice_from_pipe)
EXPECT_EQ(memcmp(mem_send, mem_recv, send_len), 0);
}
TEST_F(tls, splice_more)
{
unsigned int f = SPLICE_F_NONBLOCK | SPLICE_F_MORE | SPLICE_F_GIFT;
int send_len = TLS_PAYLOAD_MAX_LEN;
char mem_send[TLS_PAYLOAD_MAX_LEN];
int i, send_pipe = 1;
int p[2];
ASSERT_GE(pipe(p), 0);
EXPECT_GE(write(p[1], mem_send, send_len), 0);
for (i = 0; i < 32; i++)
EXPECT_EQ(splice(p[0], NULL, self->fd, NULL, send_pipe, f), 1);
}
TEST_F(tls, splice_from_pipe2)
{
int send_len = 16000;