Including fixes from netfilter.

Current release - regressions:
 
  - 4 fixes for the netdev per-instance locking
 
 Current release - new code bugs:
 
  - consolidate more code between existing Rx zero-copy and uring so that
    the latter doesn't miss / have to duplicate the safety checks
 
 Previous releases - regressions:
 
  - ipv6: fix omitted Netlink attributes when using SKIP_STATS
 
 Previous releases - always broken:
 
  - net: fix geneve_opt length integer overflow
 
  - udp: fix multiple wrap arounds of sk->sk_rmem_alloc when it
    approaches INT_MAX
 
  - dsa: mvpp2: add a lock to avoid corruption of the shared TCAM
 
  - dsa: airoha: fix issues with traffic QoS configuration / offload,
    and flow table offload
 
 Misc:
 
  - touch up the Netlink YAML specs of old families to make them usable
    for user space C codegen
 
 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE6jPA+I1ugmIBA4hXMUZtbf5SIrsFAmfv+nEACgkQMUZtbf5S
 Irs01A//d20bpdDVz2sRLdAzzIaGDLdOmw4T92e9eW7WkhUSGNAG7vZCv5lanIxq
 toQMLAahyJrMdizGPLfhH+csz3eQMwYUwlIRXNfJTEdk9o/+naWdtzbPDJdjcAu/
 jRwOKx44JtbXIwmzFe/vNwP8ex+JMZqjvdcCZcJONc4XVpHeAeKbPsd9c8aX8DR2
 pSMR/3mpAHXFd54mFVUSEDXCZBClpAT0sjZ4RMt3pZKELp+8N2AAi0nFt9r0W+YB
 ZPhYX2hSJ+msuUa24jeBHWhrxvV/PVbKDg7S58F6+Us2hDKyYx9k6IEQeadntd9c
 EzZSboSgzjf1ew6Yuitv1o9b/C1NCdzflES7kXgibFGUJ+6bP2pv5bgOc4mDhTz4
 zeY9EqxguN1dpFX+Y7gyCQcUe/6UACi6Y4h1aCmdZkCoenf9FsJPoeSWWqmttDNN
 5DEx3szJZKY+O4okmfpCFJ1SnfEe9E4Ek/+s6aIWNXu6C3EsnX6Q8Kj4Qz74UuLP
 LpGFCqRwpDLyfqZIEaX6Ed6sWykLg6TWU0/B2jWmFyQ/KQCCjhL79iaDllAMOOoT
 hN5sJAUiHk1QoMBW37nEu/WYWX5vqCVhltJBfPVtVS9dgJQChDCp/mrJ9ZJi3wof
 FyPeLaOh9N6IhR+L4Iipvuu/94dfPHtj8o5dnPkrh1fwxueUFFI=
 =phQZ
 -----END PGP SIGNATURE-----

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

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

  Current release - regressions:

   - four fixes for the netdev per-instance locking

  Current release - new code bugs:

   - consolidate more code between existing Rx zero-copy and uring so
     that the latter doesn't miss / have to duplicate the safety checks

  Previous releases - regressions:

   - ipv6: fix omitted Netlink attributes when using SKIP_STATS

  Previous releases - always broken:

   - net: fix geneve_opt length integer overflow

   - udp: fix multiple wrap arounds of sk->sk_rmem_alloc when it
     approaches INT_MAX

   - dsa: mvpp2: add a lock to avoid corruption of the shared TCAM

   - dsa: airoha: fix issues with traffic QoS configuration / offload,
     and flow table offload

  Misc:

   - touch up the Netlink YAML specs of old families to make them usable
     for user space C codegen"

* tag 'net-6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (56 commits)
  selftests: net: amt: indicate progress in the stress test
  netlink: specs: rt_route: pull the ifa- prefix out of the names
  netlink: specs: rt_addr: pull the ifa- prefix out of the names
  netlink: specs: rt_addr: fix get multi command name
  netlink: specs: rt_addr: fix the spec format / schema failures
  net: avoid false positive warnings in __net_mp_close_rxq()
  net: move mp dev config validation to __net_mp_open_rxq()
  net: ibmveth: make veth_pool_store stop hanging
  arcnet: Add NULL check in com20020pci_probe()
  ipv6: Do not consider link down nexthops in path selection
  ipv6: Start path selection from the first nexthop
  usbnet:fix NPE during rx_complete
  net: octeontx2: Handle XDP_ABORTED and XDP invalid as XDP_DROP
  net: fix geneve_opt length integer overflow
  io_uring/zcrx: fix selftests w/ updated netdev Python helpers
  selftests: net: use netdevsim in netns test
  docs: net: document netdev notifier expectations
  net: dummy: request ops lock
  netdevsim: add dummy device notifiers
  net: rename rtnl_net_debug to lock_debug
  ...
This commit is contained in:
Linus Torvalds 2025-04-04 09:15:35 -07:00
commit 61f96e684e
69 changed files with 865 additions and 443 deletions

View File

@ -3670,6 +3670,10 @@ S: 149 Union St.
S: Kingston, Ontario
S: Canada K7L 2P4
N: Pravin B Shelar
E: pshelar@ovn.org
D: Open vSwitch maintenance and contributions
N: John Shifflett
E: john@geolog.com
E: jshiffle@netcom.com

View File

@ -78,45 +78,46 @@ definitions:
attribute-sets:
-
name: addr-attrs
name-prefix: ifa-
attributes:
-
name: ifa-address
name: address
type: binary
display-hint: ipv4
-
name: ifa-local
name: local
type: binary
display-hint: ipv4
-
name: ifa-label
name: label
type: string
-
name: ifa-broadcast
name: broadcast
type: binary
display-hint: ipv4
-
name: ifa-anycast
name: anycast
type: binary
-
name: ifa-cacheinfo
name: cacheinfo
type: binary
struct: ifa-cacheinfo
-
name: ifa-multicast
name: multicast
type: binary
-
name: ifa-flags
name: flags
type: u32
enum: ifa-flags
enum-as-flags: true
-
name: ifa-rt-priority
name: rt-priority
type: u32
-
name: ifa-target-netnsid
name: target-netnsid
type: binary
-
name: ifa-proto
name: proto
type: u8
@ -137,10 +138,10 @@ operations:
- ifa-prefixlen
- ifa-scope
- ifa-index
- ifa-address
- ifa-label
- ifa-local
- ifa-cacheinfo
- address
- label
- local
- cacheinfo
-
name: deladdr
doc: Remove address
@ -154,8 +155,8 @@ operations:
- ifa-prefixlen
- ifa-scope
- ifa-index
- ifa-address
- ifa-local
- address
- local
-
name: getaddr
doc: Dump address information.
@ -169,7 +170,7 @@ operations:
value: 20
attributes: *ifaddr-all
-
name: getmaddrs
name: getmulticast
doc: Get / dump IPv4/IPv6 multicast addresses.
attribute-set: addr-attrs
fixed-header: ifaddrmsg
@ -182,11 +183,12 @@ operations:
reply:
value: 58
attributes: &mcaddr-attrs
- ifa-multicast
- ifa-cacheinfo
- multicast
- cacheinfo
dump:
request:
value: 58
attributes:
- ifa-family
reply:
value: 58

View File

@ -80,165 +80,167 @@ definitions:
attribute-sets:
-
name: route-attrs
name-prefix: rta-
attributes:
-
name: rta-dst
name: dst
type: binary
display-hint: ipv4
-
name: rta-src
name: src
type: binary
display-hint: ipv4
-
name: rta-iif
name: iif
type: u32
-
name: rta-oif
name: oif
type: u32
-
name: rta-gateway
name: gateway
type: binary
display-hint: ipv4
-
name: rta-priority
name: priority
type: u32
-
name: rta-prefsrc
name: prefsrc
type: binary
display-hint: ipv4
-
name: rta-metrics
name: metrics
type: nest
nested-attributes: rta-metrics
nested-attributes: metrics
-
name: rta-multipath
name: multipath
type: binary
-
name: rta-protoinfo # not used
name: protoinfo # not used
type: binary
-
name: rta-flow
name: flow
type: u32
-
name: rta-cacheinfo
name: cacheinfo
type: binary
struct: rta-cacheinfo
-
name: rta-session # not used
name: session # not used
type: binary
-
name: rta-mp-algo # not used
name: mp-algo # not used
type: binary
-
name: rta-table
name: table
type: u32
-
name: rta-mark
name: mark
type: u32
-
name: rta-mfc-stats
name: mfc-stats
type: binary
-
name: rta-via
name: via
type: binary
-
name: rta-newdst
name: newdst
type: binary
-
name: rta-pref
name: pref
type: u8
-
name: rta-encap-type
name: encap-type
type: u16
-
name: rta-encap
name: encap
type: binary # tunnel specific nest
-
name: rta-expires
name: expires
type: u32
-
name: rta-pad
name: pad
type: binary
-
name: rta-uid
name: uid
type: u32
-
name: rta-ttl-propagate
name: ttl-propagate
type: u8
-
name: rta-ip-proto
name: ip-proto
type: u8
-
name: rta-sport
name: sport
type: u16
-
name: rta-dport
name: dport
type: u16
-
name: rta-nh-id
name: nh-id
type: u32
-
name: rta-flowlabel
name: flowlabel
type: u32
byte-order: big-endian
display-hint: hex
-
name: rta-metrics
name: metrics
name-prefix: rtax-
attributes:
-
name: rtax-unspec
name: unspec
type: unused
value: 0
-
name: rtax-lock
name: lock
type: u32
-
name: rtax-mtu
name: mtu
type: u32
-
name: rtax-window
name: window
type: u32
-
name: rtax-rtt
name: rtt
type: u32
-
name: rtax-rttvar
name: rttvar
type: u32
-
name: rtax-ssthresh
name: ssthresh
type: u32
-
name: rtax-cwnd
name: cwnd
type: u32
-
name: rtax-advmss
name: advmss
type: u32
-
name: rtax-reordering
name: reordering
type: u32
-
name: rtax-hoplimit
name: hoplimit
type: u32
-
name: rtax-initcwnd
name: initcwnd
type: u32
-
name: rtax-features
name: features
type: u32
-
name: rtax-rto-min
name: rto-min
type: u32
-
name: rtax-initrwnd
name: initrwnd
type: u32
-
name: rtax-quickack
name: quickack
type: u32
-
name: rtax-cc-algo
name: cc-algo
type: string
-
name: rtax-fastopen-no-cookie
name: fastopen-no-cookie
type: u32
operations:
@ -254,18 +256,18 @@ operations:
value: 26
attributes:
- rtm-family
- rta-src
- src
- rtm-src-len
- rta-dst
- dst
- rtm-dst-len
- rta-iif
- rta-oif
- rta-ip-proto
- rta-sport
- rta-dport
- rta-mark
- rta-uid
- rta-flowlabel
- iif
- oif
- ip-proto
- sport
- dport
- mark
- uid
- flowlabel
reply:
value: 24
attributes: &all-route-attrs
@ -278,34 +280,34 @@ operations:
- rtm-scope
- rtm-type
- rtm-flags
- rta-dst
- rta-src
- rta-iif
- rta-oif
- rta-gateway
- rta-priority
- rta-prefsrc
- rta-metrics
- rta-multipath
- rta-flow
- rta-cacheinfo
- rta-table
- rta-mark
- rta-mfc-stats
- rta-via
- rta-newdst
- rta-pref
- rta-encap-type
- rta-encap
- rta-expires
- rta-pad
- rta-uid
- rta-ttl-propagate
- rta-ip-proto
- rta-sport
- rta-dport
- rta-nh-id
- rta-flowlabel
- dst
- src
- iif
- oif
- gateway
- priority
- prefsrc
- metrics
- multipath
- flow
- cacheinfo
- table
- mark
- mfc-stats
- via
- newdst
- pref
- encap-type
- encap
- expires
- pad
- uid
- ttl-propagate
- ip-proto
- sport
- dport
- nh-id
- flowlabel
dump:
request:
value: 26

View File

@ -343,6 +343,29 @@ there are two sets of interfaces: ``dev_xxx`` and ``netif_xxx`` (e.g.,
acquiring the instance lock themselves, while the ``netif_xxx`` functions
assume that the driver has already acquired the instance lock.
Notifiers and netdev instance lock
==================================
For device drivers that implement shaping or queue management APIs,
some of the notifiers (``enum netdev_cmd``) are running under the netdev
instance lock.
For devices with locked ops, currently only the following notifiers are
running under the lock:
* ``NETDEV_REGISTER``
* ``NETDEV_UP``
The following notifiers are running without the lock:
* ``NETDEV_UNREGISTER``
There are no clear expectations for the remaining notifiers. Notifiers not on
the list may run with or without the instance lock, potentially even invoking
the same notifier type with and without the lock from different code paths.
The goal is to eventually ensure that all (or most, with a few documented
exceptions) notifiers run under the instance lock. Please extend this
documentation whenever you make explicit assumption about lock being held
from a notifier.
NETDEV_INTERNAL symbol namespace
================================

View File

@ -18131,7 +18131,9 @@ F: drivers/irqchip/irq-ompic.c
F: drivers/irqchip/irq-or1k-*
OPENVSWITCH
M: Pravin B Shelar <pshelar@ovn.org>
M: Aaron Conole <aconole@redhat.com>
M: Eelco Chaudron <echaudro@redhat.com>
M: Ilya Maximets <i.maximets@ovn.org>
L: netdev@vger.kernel.org
L: dev@openvswitch.org
S: Maintained
@ -19903,7 +19905,7 @@ F: Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml
F: drivers/i2c/busses/i2c-qcom-geni.c
QUALCOMM I2C CCI DRIVER
M: Loic Poulain <loic.poulain@linaro.org>
M: Loic Poulain <loic.poulain@oss.qualcomm.com>
M: Robert Foss <rfoss@kernel.org>
L: linux-i2c@vger.kernel.org
L: linux-arm-msm@vger.kernel.org
@ -20036,7 +20038,7 @@ F: Documentation/devicetree/bindings/media/*venus*
F: drivers/media/platform/qcom/venus/
QUALCOMM WCN36XX WIRELESS DRIVER
M: Loic Poulain <loic.poulain@linaro.org>
M: Loic Poulain <loic.poulain@oss.qualcomm.com>
L: wcn36xx@lists.infradead.org
S: Supported
W: https://wireless.wiki.kernel.org/en/users/Drivers/wcn36xx
@ -26075,7 +26077,7 @@ F: kernel/workqueue.c
F: kernel/workqueue_internal.h
WWAN DRIVERS
M: Loic Poulain <loic.poulain@linaro.org>
M: Loic Poulain <loic.poulain@oss.qualcomm.com>
M: Sergey Ryazanov <ryazanov.s.a@gmail.com>
R: Johannes Berg <johannes@sipsolutions.net>
L: netdev@vger.kernel.org

View File

@ -251,18 +251,33 @@ static int com20020pci_probe(struct pci_dev *pdev,
card->tx_led.default_trigger = devm_kasprintf(&pdev->dev,
GFP_KERNEL, "arc%d-%d-tx",
dev->dev_id, i);
if (!card->tx_led.default_trigger) {
ret = -ENOMEM;
goto err_free_arcdev;
}
card->tx_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
"pci:green:tx:%d-%d",
dev->dev_id, i);
if (!card->tx_led.name) {
ret = -ENOMEM;
goto err_free_arcdev;
}
card->tx_led.dev = &dev->dev;
card->recon_led.brightness_set = led_recon_set;
card->recon_led.default_trigger = devm_kasprintf(&pdev->dev,
GFP_KERNEL, "arc%d-%d-recon",
dev->dev_id, i);
if (!card->recon_led.default_trigger) {
ret = -ENOMEM;
goto err_free_arcdev;
}
card->recon_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
"pci:red:recon:%d-%d",
dev->dev_id, i);
if (!card->recon_led.name) {
ret = -ENOMEM;
goto err_free_arcdev;
}
card->recon_led.dev = &dev->dev;
ret = devm_led_classdev_register(&pdev->dev, &card->tx_led);

View File

@ -7350,13 +7350,13 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
err = mv88e6xxx_switch_reset(chip);
mv88e6xxx_reg_unlock(chip);
if (err)
goto out;
goto out_phy;
if (np) {
chip->irq = of_irq_get(np, 0);
if (chip->irq == -EPROBE_DEFER) {
err = chip->irq;
goto out;
goto out_phy;
}
}
@ -7375,7 +7375,7 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
mv88e6xxx_reg_unlock(chip);
if (err)
goto out;
goto out_phy;
if (chip->info->g2_irqs > 0) {
err = mv88e6xxx_g2_irq_setup(chip);
@ -7409,6 +7409,8 @@ out_g1_irq:
mv88e6xxx_g1_irq_free(chip);
else
mv88e6xxx_irq_poll_free(chip);
out_phy:
mv88e6xxx_phy_destroy(chip);
out:
if (pdata)
dev_put(pdata->netdev);
@ -7431,7 +7433,6 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev)
mv88e6xxx_ptp_free(chip);
}
mv88e6xxx_phy_destroy(chip);
mv88e6xxx_unregister_switch(chip);
mv88e6xxx_g1_vtu_prob_irq_free(chip);
@ -7444,6 +7445,8 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev)
mv88e6xxx_g1_irq_free(chip);
else
mv88e6xxx_irq_poll_free(chip);
mv88e6xxx_phy_destroy(chip);
}
static void mv88e6xxx_shutdown(struct mdio_device *mdiodev)

View File

@ -229,7 +229,10 @@ static void mv88e6xxx_phy_ppu_state_init(struct mv88e6xxx_chip *chip)
static void mv88e6xxx_phy_ppu_state_destroy(struct mv88e6xxx_chip *chip)
{
mutex_lock(&chip->ppu_mutex);
del_timer_sync(&chip->ppu_timer);
cancel_work_sync(&chip->ppu_work);
mutex_unlock(&chip->ppu_mutex);
}
int mv88e6185_phy_ppu_read(struct mv88e6xxx_chip *chip, struct mii_bus *bus,

View File

@ -105,6 +105,7 @@ static void dummy_setup(struct net_device *dev)
dev->netdev_ops = &dummy_netdev_ops;
dev->ethtool_ops = &dummy_ethtool_ops;
dev->needs_free_netdev = true;
dev->request_ops_lock = true;
/* Fill in device structure with ethernet-generic values. */
dev->flags |= IFF_NOARP;

View File

@ -2028,7 +2028,7 @@ static int airoha_qdma_set_tx_ets_sched(struct airoha_gdm_port *port,
struct tc_ets_qopt_offload_replace_params *p = &opt->replace_params;
enum tx_sched_mode mode = TC_SCH_SP;
u16 w[AIROHA_NUM_QOS_QUEUES] = {};
int i, nstrict = 0, nwrr, qidx;
int i, nstrict = 0;
if (p->bands > AIROHA_NUM_QOS_QUEUES)
return -EINVAL;
@ -2046,17 +2046,17 @@ static int airoha_qdma_set_tx_ets_sched(struct airoha_gdm_port *port,
* lowest priorities with respect to SP ones.
* e.g: WRR0, WRR1, .., WRRm, SP0, SP1, .., SPn
*/
nwrr = p->bands - nstrict;
qidx = nstrict && nwrr ? nstrict : 0;
for (i = 1; i <= p->bands; i++) {
if (p->priomap[i % AIROHA_NUM_QOS_QUEUES] != qidx)
for (i = 0; i < nstrict; i++) {
if (p->priomap[p->bands - i - 1] != i)
return -EINVAL;
qidx = i == nwrr ? 0 : qidx + 1;
}
for (i = 0; i < nwrr; i++)
for (i = 0; i < p->bands - nstrict; i++) {
if (p->priomap[i] != nstrict + i)
return -EINVAL;
w[i] = p->weights[nstrict + i];
}
if (!nstrict)
mode = TC_SCH_WRR8;
@ -2358,7 +2358,7 @@ static int airoha_tc_get_htb_get_leaf_queue(struct airoha_gdm_port *port,
return -EINVAL;
}
opt->qid = channel;
opt->qid = AIROHA_NUM_TX_RING + channel;
return 0;
}
@ -2454,6 +2454,19 @@ static void airoha_metadata_dst_free(struct airoha_gdm_port *port)
}
}
bool airoha_is_valid_gdm_port(struct airoha_eth *eth,
struct airoha_gdm_port *port)
{
int i;
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
if (eth->ports[i] == port)
return true;
}
return false;
}
static int airoha_alloc_gdm_port(struct airoha_eth *eth,
struct device_node *np, int index)
{

View File

@ -532,6 +532,9 @@ u32 airoha_rmw(void __iomem *base, u32 offset, u32 mask, u32 val);
#define airoha_qdma_clear(qdma, offset, val) \
airoha_rmw((qdma)->regs, (offset), (val), 0)
bool airoha_is_valid_gdm_port(struct airoha_eth *eth,
struct airoha_gdm_port *port);
void airoha_ppe_check_skb(struct airoha_ppe *ppe, u16 hash);
int airoha_ppe_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
void *cb_priv);

View File

@ -197,7 +197,8 @@ static int airoha_get_dsa_port(struct net_device **dev)
#endif
}
static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
struct airoha_foe_entry *hwe,
struct net_device *dev, int type,
struct airoha_flow_data *data,
int l4proto)
@ -225,6 +226,9 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe,
struct airoha_gdm_port *port = netdev_priv(dev);
u8 pse_port;
if (!airoha_is_valid_gdm_port(eth, port))
return -EINVAL;
if (dsa_port >= 0)
pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id;
else
@ -633,7 +637,7 @@ static int airoha_ppe_flow_offload_replace(struct airoha_gdm_port *port,
!is_valid_ether_addr(data.eth.h_dest))
return -EINVAL;
err = airoha_ppe_foe_entry_prepare(&hwe, odev, offload_type,
err = airoha_ppe_foe_entry_prepare(eth, &hwe, odev, offload_type,
&data, l4proto);
if (err)
return err;

View File

@ -15909,7 +15909,7 @@ static int bnxt_queue_start(struct net_device *dev, void *qmem, int idx)
goto err_reset;
}
napi_enable(&bnapi->napi);
napi_enable_locked(&bnapi->napi);
bnxt_db_nq_arm(bp, &cpr->cp_db, cpr->cp_raw_cons);
for (i = 0; i < bp->nr_vnics; i++) {
@ -15931,7 +15931,7 @@ static int bnxt_queue_start(struct net_device *dev, void *qmem, int idx)
err_reset:
netdev_err(bp->dev, "Unexpected HWRM error during queue start rc: %d\n",
rc);
napi_enable(&bnapi->napi);
napi_enable_locked(&bnapi->napi);
bnxt_db_nq_arm(bp, &cpr->cp_db, cpr->cp_raw_cons);
bnxt_reset_task(bp, true);
return rc;
@ -15971,7 +15971,7 @@ static int bnxt_queue_stop(struct net_device *dev, void *qmem, int idx)
* completion is handled in NAPI to guarantee no more DMA on that ring
* after seeing the completion.
*/
napi_disable(&bnapi->napi);
napi_disable_locked(&bnapi->napi);
if (bp->tph_mode) {
bnxt_hwrm_cp_ring_free(bp, rxr->rx_cpr);

View File

@ -392,7 +392,9 @@ gve_get_ethtool_stats(struct net_device *netdev,
*/
data[i++] = 0;
data[i++] = 0;
data[i++] = tx->dqo_tx.tail - tx->dqo_tx.head;
data[i++] =
(tx->dqo_tx.tail - tx->dqo_tx.head) &
tx->mask;
}
do {
start =

View File

@ -1802,18 +1802,22 @@ static ssize_t veth_pool_store(struct kobject *kobj, struct attribute *attr,
long value = simple_strtol(buf, NULL, 10);
long rc;
rtnl_lock();
if (attr == &veth_active_attr) {
if (value && !pool->active) {
if (netif_running(netdev)) {
if (ibmveth_alloc_buffer_pool(pool)) {
netdev_err(netdev,
"unable to alloc pool\n");
return -ENOMEM;
rc = -ENOMEM;
goto unlock_err;
}
pool->active = 1;
ibmveth_close(netdev);
if ((rc = ibmveth_open(netdev)))
return rc;
rc = ibmveth_open(netdev);
if (rc)
goto unlock_err;
} else {
pool->active = 1;
}
@ -1833,48 +1837,59 @@ static ssize_t veth_pool_store(struct kobject *kobj, struct attribute *attr,
if (i == IBMVETH_NUM_BUFF_POOLS) {
netdev_err(netdev, "no active pool >= MTU\n");
return -EPERM;
rc = -EPERM;
goto unlock_err;
}
if (netif_running(netdev)) {
ibmveth_close(netdev);
pool->active = 0;
if ((rc = ibmveth_open(netdev)))
return rc;
rc = ibmveth_open(netdev);
if (rc)
goto unlock_err;
}
pool->active = 0;
}
} else if (attr == &veth_num_attr) {
if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT) {
return -EINVAL;
rc = -EINVAL;
goto unlock_err;
} else {
if (netif_running(netdev)) {
ibmveth_close(netdev);
pool->size = value;
if ((rc = ibmveth_open(netdev)))
return rc;
rc = ibmveth_open(netdev);
if (rc)
goto unlock_err;
} else {
pool->size = value;
}
}
} else if (attr == &veth_size_attr) {
if (value <= IBMVETH_BUFF_OH || value > IBMVETH_MAX_BUF_SIZE) {
return -EINVAL;
rc = -EINVAL;
goto unlock_err;
} else {
if (netif_running(netdev)) {
ibmveth_close(netdev);
pool->buff_size = value;
if ((rc = ibmveth_open(netdev)))
return rc;
rc = ibmveth_open(netdev);
if (rc)
goto unlock_err;
} else {
pool->buff_size = value;
}
}
}
rtnl_unlock();
/* kick the interrupt handler to allocate/deallocate pools */
ibmveth_interrupt(netdev->irq, netdev);
return count;
unlock_err:
rtnl_unlock();
return rc;
}

View File

@ -803,4 +803,7 @@
/* SerDes Control */
#define E1000_GEN_POLL_TIMEOUT 640
#define E1000_FEXTNVM12_PHYPD_CTRL_MASK 0x00C00000
#define E1000_FEXTNVM12_PHYPD_CTRL_P1 0x00800000
#endif /* _E1000_DEFINES_H_ */

View File

@ -285,6 +285,45 @@ static void e1000_toggle_lanphypc_pch_lpt(struct e1000_hw *hw)
}
}
/**
* e1000_reconfigure_k1_exit_timeout - reconfigure K1 exit timeout to
* align to MTP and later platform requirements.
* @hw: pointer to the HW structure
*
* Context: PHY semaphore must be held by caller.
* Return: 0 on success, negative on failure
*/
static s32 e1000_reconfigure_k1_exit_timeout(struct e1000_hw *hw)
{
u16 phy_timeout;
u32 fextnvm12;
s32 ret_val;
if (hw->mac.type < e1000_pch_mtp)
return 0;
/* Change Kumeran K1 power down state from P0s to P1 */
fextnvm12 = er32(FEXTNVM12);
fextnvm12 &= ~E1000_FEXTNVM12_PHYPD_CTRL_MASK;
fextnvm12 |= E1000_FEXTNVM12_PHYPD_CTRL_P1;
ew32(FEXTNVM12, fextnvm12);
/* Wait for the interface the settle */
usleep_range(1000, 1100);
/* Change K1 exit timeout */
ret_val = e1e_rphy_locked(hw, I217_PHY_TIMEOUTS_REG,
&phy_timeout);
if (ret_val)
return ret_val;
phy_timeout &= ~I217_PHY_TIMEOUTS_K1_EXIT_TO_MASK;
phy_timeout |= 0xF00;
return e1e_wphy_locked(hw, I217_PHY_TIMEOUTS_REG,
phy_timeout);
}
/**
* e1000_init_phy_workarounds_pchlan - PHY initialization workarounds
* @hw: pointer to the HW structure
@ -327,15 +366,22 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
* LANPHYPC Value bit to force the interconnect to PCIe mode.
*/
switch (hw->mac.type) {
case e1000_pch_mtp:
case e1000_pch_lnp:
case e1000_pch_ptp:
case e1000_pch_nvp:
/* At this point the PHY might be inaccessible so don't
* propagate the failure
*/
if (e1000_reconfigure_k1_exit_timeout(hw))
e_dbg("Failed to reconfigure K1 exit timeout\n");
fallthrough;
case e1000_pch_lpt:
case e1000_pch_spt:
case e1000_pch_cnp:
case e1000_pch_tgp:
case e1000_pch_adp:
case e1000_pch_mtp:
case e1000_pch_lnp:
case e1000_pch_ptp:
case e1000_pch_nvp:
if (e1000_phy_is_accessible_pchlan(hw))
break;
@ -419,8 +465,20 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
* the PHY is in.
*/
ret_val = hw->phy.ops.check_reset_block(hw);
if (ret_val)
if (ret_val) {
e_err("ME blocked access to PHY after reset\n");
goto out;
}
if (hw->mac.type >= e1000_pch_mtp) {
ret_val = hw->phy.ops.acquire(hw);
if (ret_val) {
e_err("Failed to reconfigure K1 exit timeout\n");
goto out;
}
ret_val = e1000_reconfigure_k1_exit_timeout(hw);
hw->phy.ops.release(hw);
}
}
out:
@ -4888,6 +4946,18 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
u16 i;
e1000_initialize_hw_bits_ich8lan(hw);
if (hw->mac.type >= e1000_pch_mtp) {
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
return ret_val;
ret_val = e1000_reconfigure_k1_exit_timeout(hw);
hw->phy.ops.release(hw);
if (ret_val) {
e_dbg("Error failed to reconfigure K1 exit timeout\n");
return ret_val;
}
}
/* Initialize identification LED */
ret_val = mac->ops.id_led_init(hw);

View File

@ -219,6 +219,10 @@
#define I217_PLL_CLOCK_GATE_REG PHY_REG(772, 28)
#define I217_PLL_CLOCK_GATE_MASK 0x07FF
/* PHY Timeouts */
#define I217_PHY_TIMEOUTS_REG PHY_REG(770, 21)
#define I217_PHY_TIMEOUTS_K1_EXIT_TO_MASK 0x0FC0
#define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in ms */
/* Inband Control */

View File

@ -87,7 +87,11 @@ destroy_wqs:
*/
static void idpf_shutdown(struct pci_dev *pdev)
{
idpf_remove(pdev);
struct idpf_adapter *adapter = pci_get_drvdata(pdev);
cancel_delayed_work_sync(&adapter->vc_event_task);
idpf_vc_core_deinit(adapter);
idpf_deinit_dflt_mbx(adapter);
if (system_state == SYSTEM_POWER_OFF)
pci_set_power_state(pdev, PCI_D3hot);

View File

@ -337,8 +337,6 @@ struct igc_adapter {
struct igc_led_classdev *leds;
};
void igc_set_queue_napi(struct igc_adapter *adapter, int q_idx,
struct napi_struct *napi);
void igc_up(struct igc_adapter *adapter);
void igc_down(struct igc_adapter *adapter);
int igc_open(struct net_device *netdev);

View File

@ -3042,7 +3042,7 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring)
* descriptors. Therefore, to be safe, we always ensure we have at least
* 4 descriptors available.
*/
while (xsk_tx_peek_desc(pool, &xdp_desc) && budget >= 4) {
while (budget >= 4 && xsk_tx_peek_desc(pool, &xdp_desc)) {
struct igc_metadata_request meta_req;
struct xsk_tx_metadata *meta = NULL;
struct igc_tx_buffer *bi;
@ -5022,8 +5022,8 @@ static int igc_sw_init(struct igc_adapter *adapter)
return 0;
}
void igc_set_queue_napi(struct igc_adapter *adapter, int vector,
struct napi_struct *napi)
static void igc_set_queue_napi(struct igc_adapter *adapter, int vector,
struct napi_struct *napi)
{
struct igc_q_vector *q_vector = adapter->q_vector[vector];

View File

@ -97,7 +97,6 @@ static int igc_xdp_enable_pool(struct igc_adapter *adapter,
napi_disable(napi);
}
igc_set_queue_napi(adapter, queue_id, NULL);
set_bit(IGC_RING_FLAG_AF_XDP_ZC, &rx_ring->flags);
set_bit(IGC_RING_FLAG_AF_XDP_ZC, &tx_ring->flags);
@ -147,7 +146,6 @@ static int igc_xdp_disable_pool(struct igc_adapter *adapter, u16 queue_id)
xsk_pool_dma_unmap(pool, IGC_RX_DMA_ATTR);
clear_bit(IGC_RING_FLAG_AF_XDP_ZC, &rx_ring->flags);
clear_bit(IGC_RING_FLAG_AF_XDP_ZC, &tx_ring->flags);
igc_set_queue_napi(adapter, queue_id, napi);
if (needs_reset) {
napi_enable(napi);

View File

@ -1453,9 +1453,11 @@ enum ixgbe_media_type ixgbe_get_media_type_e610(struct ixgbe_hw *hw)
hw->link.link_info.phy_type_low = 0;
} else {
highest_bit = fls64(le64_to_cpu(pcaps.phy_type_low));
if (highest_bit)
if (highest_bit) {
hw->link.link_info.phy_type_low =
BIT_ULL(highest_bit - 1);
hw->link.link_info.phy_type_high = 0;
}
}
}

View File

@ -1113,6 +1113,9 @@ struct mvpp2 {
/* Spinlocks for CM3 shared memory configuration */
spinlock_t mss_spinlock;
/* Spinlock for shared PRS parser memory and shadow table */
spinlock_t prs_spinlock;
};
struct mvpp2_pcpu_stats {

View File

@ -7723,8 +7723,9 @@ static int mvpp2_probe(struct platform_device *pdev)
if (mvpp2_read(priv, MVPP2_VER_ID_REG) == MVPP2_VER_PP23)
priv->hw_version = MVPP23;
/* Init mss lock */
/* Init locks for shared packet processor resources */
spin_lock_init(&priv->mss_spinlock);
spin_lock_init(&priv->prs_spinlock);
/* Initialize network controller */
err = mvpp2_init(pdev, priv);

View File

@ -23,6 +23,8 @@ static int mvpp2_prs_hw_write(struct mvpp2 *priv, struct mvpp2_prs_entry *pe)
{
int i;
lockdep_assert_held(&priv->prs_spinlock);
if (pe->index > MVPP2_PRS_TCAM_SRAM_SIZE - 1)
return -EINVAL;
@ -43,11 +45,13 @@ static int mvpp2_prs_hw_write(struct mvpp2 *priv, struct mvpp2_prs_entry *pe)
}
/* Initialize tcam entry from hw */
int mvpp2_prs_init_from_hw(struct mvpp2 *priv, struct mvpp2_prs_entry *pe,
int tid)
static int __mvpp2_prs_init_from_hw(struct mvpp2 *priv,
struct mvpp2_prs_entry *pe, int tid)
{
int i;
lockdep_assert_held(&priv->prs_spinlock);
if (tid > MVPP2_PRS_TCAM_SRAM_SIZE - 1)
return -EINVAL;
@ -73,6 +77,18 @@ int mvpp2_prs_init_from_hw(struct mvpp2 *priv, struct mvpp2_prs_entry *pe,
return 0;
}
int mvpp2_prs_init_from_hw(struct mvpp2 *priv, struct mvpp2_prs_entry *pe,
int tid)
{
int err;
spin_lock_bh(&priv->prs_spinlock);
err = __mvpp2_prs_init_from_hw(priv, pe, tid);
spin_unlock_bh(&priv->prs_spinlock);
return err;
}
/* Invalidate tcam hw entry */
static void mvpp2_prs_hw_inv(struct mvpp2 *priv, int index)
{
@ -374,7 +390,7 @@ static int mvpp2_prs_flow_find(struct mvpp2 *priv, int flow)
priv->prs_shadow[tid].lu != MVPP2_PRS_LU_FLOWS)
continue;
mvpp2_prs_init_from_hw(priv, &pe, tid);
__mvpp2_prs_init_from_hw(priv, &pe, tid);
bits = mvpp2_prs_sram_ai_get(&pe);
/* Sram store classification lookup ID in AI bits [5:0] */
@ -441,7 +457,7 @@ static void mvpp2_prs_mac_drop_all_set(struct mvpp2 *priv, int port, bool add)
if (priv->prs_shadow[MVPP2_PE_DROP_ALL].valid) {
/* Entry exist - update port only */
mvpp2_prs_init_from_hw(priv, &pe, MVPP2_PE_DROP_ALL);
__mvpp2_prs_init_from_hw(priv, &pe, MVPP2_PE_DROP_ALL);
} else {
/* Entry doesn't exist - create new */
memset(&pe, 0, sizeof(pe));
@ -469,14 +485,17 @@ static void mvpp2_prs_mac_drop_all_set(struct mvpp2 *priv, int port, bool add)
}
/* Set port to unicast or multicast promiscuous mode */
void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port,
enum mvpp2_prs_l2_cast l2_cast, bool add)
static void __mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port,
enum mvpp2_prs_l2_cast l2_cast,
bool add)
{
struct mvpp2_prs_entry pe;
unsigned char cast_match;
unsigned int ri;
int tid;
lockdep_assert_held(&priv->prs_spinlock);
if (l2_cast == MVPP2_PRS_L2_UNI_CAST) {
cast_match = MVPP2_PRS_UCAST_VAL;
tid = MVPP2_PE_MAC_UC_PROMISCUOUS;
@ -489,7 +508,7 @@ void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port,
/* promiscuous mode - Accept unknown unicast or multicast packets */
if (priv->prs_shadow[tid].valid) {
mvpp2_prs_init_from_hw(priv, &pe, tid);
__mvpp2_prs_init_from_hw(priv, &pe, tid);
} else {
memset(&pe, 0, sizeof(pe));
mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
@ -522,6 +541,14 @@ void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port,
mvpp2_prs_hw_write(priv, &pe);
}
void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port,
enum mvpp2_prs_l2_cast l2_cast, bool add)
{
spin_lock_bh(&priv->prs_spinlock);
__mvpp2_prs_mac_promisc_set(priv, port, l2_cast, add);
spin_unlock_bh(&priv->prs_spinlock);
}
/* Set entry for dsa packets */
static void mvpp2_prs_dsa_tag_set(struct mvpp2 *priv, int port, bool add,
bool tagged, bool extend)
@ -539,7 +566,7 @@ static void mvpp2_prs_dsa_tag_set(struct mvpp2 *priv, int port, bool add,
if (priv->prs_shadow[tid].valid) {
/* Entry exist - update port only */
mvpp2_prs_init_from_hw(priv, &pe, tid);
__mvpp2_prs_init_from_hw(priv, &pe, tid);
} else {
/* Entry doesn't exist - create new */
memset(&pe, 0, sizeof(pe));
@ -610,7 +637,7 @@ static void mvpp2_prs_dsa_tag_ethertype_set(struct mvpp2 *priv, int port,
if (priv->prs_shadow[tid].valid) {
/* Entry exist - update port only */
mvpp2_prs_init_from_hw(priv, &pe, tid);
__mvpp2_prs_init_from_hw(priv, &pe, tid);
} else {
/* Entry doesn't exist - create new */
memset(&pe, 0, sizeof(pe));
@ -673,7 +700,7 @@ static int mvpp2_prs_vlan_find(struct mvpp2 *priv, unsigned short tpid, int ai)
priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN)
continue;
mvpp2_prs_init_from_hw(priv, &pe, tid);
__mvpp2_prs_init_from_hw(priv, &pe, tid);
match = mvpp2_prs_tcam_data_cmp(&pe, 0, tpid);
if (!match)
continue;
@ -726,7 +753,7 @@ static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai,
priv->prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN)
continue;
mvpp2_prs_init_from_hw(priv, &pe, tid_aux);
__mvpp2_prs_init_from_hw(priv, &pe, tid_aux);
ri_bits = mvpp2_prs_sram_ri_get(&pe);
if ((ri_bits & MVPP2_PRS_RI_VLAN_MASK) ==
MVPP2_PRS_RI_VLAN_DOUBLE)
@ -760,7 +787,7 @@ static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai,
mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VLAN);
} else {
mvpp2_prs_init_from_hw(priv, &pe, tid);
__mvpp2_prs_init_from_hw(priv, &pe, tid);
}
/* Update ports' mask */
mvpp2_prs_tcam_port_map_set(&pe, port_map);
@ -800,7 +827,7 @@ static int mvpp2_prs_double_vlan_find(struct mvpp2 *priv, unsigned short tpid1,
priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN)
continue;
mvpp2_prs_init_from_hw(priv, &pe, tid);
__mvpp2_prs_init_from_hw(priv, &pe, tid);
match = mvpp2_prs_tcam_data_cmp(&pe, 0, tpid1) &&
mvpp2_prs_tcam_data_cmp(&pe, 4, tpid2);
@ -849,7 +876,7 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1,
priv->prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN)
continue;
mvpp2_prs_init_from_hw(priv, &pe, tid_aux);
__mvpp2_prs_init_from_hw(priv, &pe, tid_aux);
ri_bits = mvpp2_prs_sram_ri_get(&pe);
ri_bits &= MVPP2_PRS_RI_VLAN_MASK;
if (ri_bits == MVPP2_PRS_RI_VLAN_SINGLE ||
@ -880,7 +907,7 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1,
mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VLAN);
} else {
mvpp2_prs_init_from_hw(priv, &pe, tid);
__mvpp2_prs_init_from_hw(priv, &pe, tid);
}
/* Update ports' mask */
@ -1213,8 +1240,8 @@ static void mvpp2_prs_mac_init(struct mvpp2 *priv)
/* Create dummy entries for drop all and promiscuous modes */
mvpp2_prs_drop_fc(priv);
mvpp2_prs_mac_drop_all_set(priv, 0, false);
mvpp2_prs_mac_promisc_set(priv, 0, MVPP2_PRS_L2_UNI_CAST, false);
mvpp2_prs_mac_promisc_set(priv, 0, MVPP2_PRS_L2_MULTI_CAST, false);
__mvpp2_prs_mac_promisc_set(priv, 0, MVPP2_PRS_L2_UNI_CAST, false);
__mvpp2_prs_mac_promisc_set(priv, 0, MVPP2_PRS_L2_MULTI_CAST, false);
}
/* Set default entries for various types of dsa packets */
@ -1533,12 +1560,6 @@ static int mvpp2_prs_vlan_init(struct platform_device *pdev, struct mvpp2 *priv)
struct mvpp2_prs_entry pe;
int err;
priv->prs_double_vlans = devm_kcalloc(&pdev->dev, sizeof(bool),
MVPP2_PRS_DBL_VLANS_MAX,
GFP_KERNEL);
if (!priv->prs_double_vlans)
return -ENOMEM;
/* Double VLAN: 0x88A8, 0x8100 */
err = mvpp2_prs_double_vlan_add(priv, ETH_P_8021AD, ETH_P_8021Q,
MVPP2_PRS_PORT_MASK);
@ -1941,7 +1962,7 @@ static int mvpp2_prs_vid_range_find(struct mvpp2_port *port, u16 vid, u16 mask)
port->priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VID)
continue;
mvpp2_prs_init_from_hw(port->priv, &pe, tid);
__mvpp2_prs_init_from_hw(port->priv, &pe, tid);
mvpp2_prs_tcam_data_byte_get(&pe, 2, &byte[0], &enable[0]);
mvpp2_prs_tcam_data_byte_get(&pe, 3, &byte[1], &enable[1]);
@ -1970,6 +1991,8 @@ int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid)
memset(&pe, 0, sizeof(pe));
spin_lock_bh(&priv->prs_spinlock);
/* Scan TCAM and see if entry with this <vid,port> already exist */
tid = mvpp2_prs_vid_range_find(port, vid, mask);
@ -1988,8 +2011,10 @@ int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid)
MVPP2_PRS_VLAN_FILT_MAX_ENTRY);
/* There isn't room for a new VID filter */
if (tid < 0)
if (tid < 0) {
spin_unlock_bh(&priv->prs_spinlock);
return tid;
}
mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VID);
pe.index = tid;
@ -1997,7 +2022,7 @@ int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid)
/* Mask all ports */
mvpp2_prs_tcam_port_map_set(&pe, 0);
} else {
mvpp2_prs_init_from_hw(priv, &pe, tid);
__mvpp2_prs_init_from_hw(priv, &pe, tid);
}
/* Enable the current port */
@ -2019,6 +2044,7 @@ int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid)
mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VID);
mvpp2_prs_hw_write(priv, &pe);
spin_unlock_bh(&priv->prs_spinlock);
return 0;
}
@ -2028,15 +2054,16 @@ void mvpp2_prs_vid_entry_remove(struct mvpp2_port *port, u16 vid)
struct mvpp2 *priv = port->priv;
int tid;
/* Scan TCAM and see if entry with this <vid,port> already exist */
spin_lock_bh(&priv->prs_spinlock);
/* Invalidate TCAM entry with this <vid,port>, if it exists */
tid = mvpp2_prs_vid_range_find(port, vid, 0xfff);
if (tid >= 0) {
mvpp2_prs_hw_inv(priv, tid);
priv->prs_shadow[tid].valid = false;
}
/* No such entry */
if (tid < 0)
return;
mvpp2_prs_hw_inv(priv, tid);
priv->prs_shadow[tid].valid = false;
spin_unlock_bh(&priv->prs_spinlock);
}
/* Remove all existing VID filters on this port */
@ -2045,6 +2072,8 @@ void mvpp2_prs_vid_remove_all(struct mvpp2_port *port)
struct mvpp2 *priv = port->priv;
int tid;
spin_lock_bh(&priv->prs_spinlock);
for (tid = MVPP2_PRS_VID_PORT_FIRST(port->id);
tid <= MVPP2_PRS_VID_PORT_LAST(port->id); tid++) {
if (priv->prs_shadow[tid].valid) {
@ -2052,6 +2081,8 @@ void mvpp2_prs_vid_remove_all(struct mvpp2_port *port)
priv->prs_shadow[tid].valid = false;
}
}
spin_unlock_bh(&priv->prs_spinlock);
}
/* Remove VID filering entry for this port */
@ -2060,10 +2091,14 @@ void mvpp2_prs_vid_disable_filtering(struct mvpp2_port *port)
unsigned int tid = MVPP2_PRS_VID_PORT_DFLT(port->id);
struct mvpp2 *priv = port->priv;
spin_lock_bh(&priv->prs_spinlock);
/* Invalidate the guard entry */
mvpp2_prs_hw_inv(priv, tid);
priv->prs_shadow[tid].valid = false;
spin_unlock_bh(&priv->prs_spinlock);
}
/* Add guard entry that drops packets when no VID is matched on this port */
@ -2079,6 +2114,8 @@ void mvpp2_prs_vid_enable_filtering(struct mvpp2_port *port)
memset(&pe, 0, sizeof(pe));
spin_lock_bh(&priv->prs_spinlock);
pe.index = tid;
reg_val = mvpp2_read(priv, MVPP2_MH_REG(port->id));
@ -2111,6 +2148,8 @@ void mvpp2_prs_vid_enable_filtering(struct mvpp2_port *port)
/* Update shadow table */
mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VID);
mvpp2_prs_hw_write(priv, &pe);
spin_unlock_bh(&priv->prs_spinlock);
}
/* Parser default initialization */
@ -2118,6 +2157,20 @@ int mvpp2_prs_default_init(struct platform_device *pdev, struct mvpp2 *priv)
{
int err, index, i;
priv->prs_shadow = devm_kcalloc(&pdev->dev, MVPP2_PRS_TCAM_SRAM_SIZE,
sizeof(*priv->prs_shadow),
GFP_KERNEL);
if (!priv->prs_shadow)
return -ENOMEM;
priv->prs_double_vlans = devm_kcalloc(&pdev->dev, sizeof(bool),
MVPP2_PRS_DBL_VLANS_MAX,
GFP_KERNEL);
if (!priv->prs_double_vlans)
return -ENOMEM;
spin_lock_bh(&priv->prs_spinlock);
/* Enable tcam table */
mvpp2_write(priv, MVPP2_PRS_TCAM_CTRL_REG, MVPP2_PRS_TCAM_EN_MASK);
@ -2136,12 +2189,6 @@ int mvpp2_prs_default_init(struct platform_device *pdev, struct mvpp2 *priv)
for (index = 0; index < MVPP2_PRS_TCAM_SRAM_SIZE; index++)
mvpp2_prs_hw_inv(priv, index);
priv->prs_shadow = devm_kcalloc(&pdev->dev, MVPP2_PRS_TCAM_SRAM_SIZE,
sizeof(*priv->prs_shadow),
GFP_KERNEL);
if (!priv->prs_shadow)
return -ENOMEM;
/* Always start from lookup = 0 */
for (index = 0; index < MVPP2_MAX_PORTS; index++)
mvpp2_prs_hw_port_init(priv, index, MVPP2_PRS_LU_MH,
@ -2158,26 +2205,13 @@ int mvpp2_prs_default_init(struct platform_device *pdev, struct mvpp2 *priv)
mvpp2_prs_vid_init(priv);
err = mvpp2_prs_etype_init(priv);
if (err)
return err;
err = err ? : mvpp2_prs_vlan_init(pdev, priv);
err = err ? : mvpp2_prs_pppoe_init(priv);
err = err ? : mvpp2_prs_ip6_init(priv);
err = err ? : mvpp2_prs_ip4_init(priv);
err = mvpp2_prs_vlan_init(pdev, priv);
if (err)
return err;
err = mvpp2_prs_pppoe_init(priv);
if (err)
return err;
err = mvpp2_prs_ip6_init(priv);
if (err)
return err;
err = mvpp2_prs_ip4_init(priv);
if (err)
return err;
return 0;
spin_unlock_bh(&priv->prs_spinlock);
return err;
}
/* Compare MAC DA with tcam entry data */
@ -2217,7 +2251,7 @@ mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da,
(priv->prs_shadow[tid].udf != udf_type))
continue;
mvpp2_prs_init_from_hw(priv, &pe, tid);
__mvpp2_prs_init_from_hw(priv, &pe, tid);
entry_pmap = mvpp2_prs_tcam_port_map_get(&pe);
if (mvpp2_prs_mac_range_equals(&pe, da, mask) &&
@ -2229,7 +2263,8 @@ mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da,
}
/* Update parser's mac da entry */
int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da, bool add)
static int __mvpp2_prs_mac_da_accept(struct mvpp2_port *port,
const u8 *da, bool add)
{
unsigned char mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
struct mvpp2 *priv = port->priv;
@ -2261,7 +2296,7 @@ int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da, bool add)
/* Mask all ports */
mvpp2_prs_tcam_port_map_set(&pe, 0);
} else {
mvpp2_prs_init_from_hw(priv, &pe, tid);
__mvpp2_prs_init_from_hw(priv, &pe, tid);
}
mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
@ -2317,6 +2352,17 @@ int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da, bool add)
return 0;
}
int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da, bool add)
{
int err;
spin_lock_bh(&port->priv->prs_spinlock);
err = __mvpp2_prs_mac_da_accept(port, da, add);
spin_unlock_bh(&port->priv->prs_spinlock);
return err;
}
int mvpp2_prs_update_mac_da(struct net_device *dev, const u8 *da)
{
struct mvpp2_port *port = netdev_priv(dev);
@ -2345,6 +2391,8 @@ void mvpp2_prs_mac_del_all(struct mvpp2_port *port)
unsigned long pmap;
int index, tid;
spin_lock_bh(&priv->prs_spinlock);
for (tid = MVPP2_PE_MAC_RANGE_START;
tid <= MVPP2_PE_MAC_RANGE_END; tid++) {
unsigned char da[ETH_ALEN], da_mask[ETH_ALEN];
@ -2354,7 +2402,7 @@ void mvpp2_prs_mac_del_all(struct mvpp2_port *port)
(priv->prs_shadow[tid].udf != MVPP2_PRS_UDF_MAC_DEF))
continue;
mvpp2_prs_init_from_hw(priv, &pe, tid);
__mvpp2_prs_init_from_hw(priv, &pe, tid);
pmap = mvpp2_prs_tcam_port_map_get(&pe);
@ -2375,14 +2423,17 @@ void mvpp2_prs_mac_del_all(struct mvpp2_port *port)
continue;
/* Remove entry from TCAM */
mvpp2_prs_mac_da_accept(port, da, false);
__mvpp2_prs_mac_da_accept(port, da, false);
}
spin_unlock_bh(&priv->prs_spinlock);
}
int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type)
{
switch (type) {
case MVPP2_TAG_TYPE_EDSA:
spin_lock_bh(&priv->prs_spinlock);
/* Add port to EDSA entries */
mvpp2_prs_dsa_tag_set(priv, port, true,
MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA);
@ -2393,9 +2444,11 @@ int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type)
MVPP2_PRS_TAGGED, MVPP2_PRS_DSA);
mvpp2_prs_dsa_tag_set(priv, port, false,
MVPP2_PRS_UNTAGGED, MVPP2_PRS_DSA);
spin_unlock_bh(&priv->prs_spinlock);
break;
case MVPP2_TAG_TYPE_DSA:
spin_lock_bh(&priv->prs_spinlock);
/* Add port to DSA entries */
mvpp2_prs_dsa_tag_set(priv, port, true,
MVPP2_PRS_TAGGED, MVPP2_PRS_DSA);
@ -2406,10 +2459,12 @@ int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type)
MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA);
mvpp2_prs_dsa_tag_set(priv, port, false,
MVPP2_PRS_UNTAGGED, MVPP2_PRS_EDSA);
spin_unlock_bh(&priv->prs_spinlock);
break;
case MVPP2_TAG_TYPE_MH:
case MVPP2_TAG_TYPE_NONE:
spin_lock_bh(&priv->prs_spinlock);
/* Remove port form EDSA and DSA entries */
mvpp2_prs_dsa_tag_set(priv, port, false,
MVPP2_PRS_TAGGED, MVPP2_PRS_DSA);
@ -2419,6 +2474,7 @@ int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type)
MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA);
mvpp2_prs_dsa_tag_set(priv, port, false,
MVPP2_PRS_UNTAGGED, MVPP2_PRS_EDSA);
spin_unlock_bh(&priv->prs_spinlock);
break;
default:
@ -2437,11 +2493,15 @@ int mvpp2_prs_add_flow(struct mvpp2 *priv, int flow, u32 ri, u32 ri_mask)
memset(&pe, 0, sizeof(pe));
spin_lock_bh(&priv->prs_spinlock);
tid = mvpp2_prs_tcam_first_free(priv,
MVPP2_PE_LAST_FREE_TID,
MVPP2_PE_FIRST_FREE_TID);
if (tid < 0)
if (tid < 0) {
spin_unlock_bh(&priv->prs_spinlock);
return tid;
}
pe.index = tid;
@ -2461,6 +2521,7 @@ int mvpp2_prs_add_flow(struct mvpp2 *priv, int flow, u32 ri, u32 ri_mask)
mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
mvpp2_prs_hw_write(priv, &pe);
spin_unlock_bh(&priv->prs_spinlock);
return 0;
}
@ -2472,6 +2533,8 @@ int mvpp2_prs_def_flow(struct mvpp2_port *port)
memset(&pe, 0, sizeof(pe));
spin_lock_bh(&port->priv->prs_spinlock);
tid = mvpp2_prs_flow_find(port->priv, port->id);
/* Such entry not exist */
@ -2480,8 +2543,10 @@ int mvpp2_prs_def_flow(struct mvpp2_port *port)
tid = mvpp2_prs_tcam_first_free(port->priv,
MVPP2_PE_LAST_FREE_TID,
MVPP2_PE_FIRST_FREE_TID);
if (tid < 0)
if (tid < 0) {
spin_unlock_bh(&port->priv->prs_spinlock);
return tid;
}
pe.index = tid;
@ -2492,13 +2557,14 @@ int mvpp2_prs_def_flow(struct mvpp2_port *port)
/* Update shadow table */
mvpp2_prs_shadow_set(port->priv, pe.index, MVPP2_PRS_LU_FLOWS);
} else {
mvpp2_prs_init_from_hw(port->priv, &pe, tid);
__mvpp2_prs_init_from_hw(port->priv, &pe, tid);
}
mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
mvpp2_prs_tcam_port_map_set(&pe, (1 << port->id));
mvpp2_prs_hw_write(port->priv, &pe);
spin_unlock_bh(&port->priv->prs_spinlock);
return 0;
}
@ -2509,11 +2575,14 @@ int mvpp2_prs_hits(struct mvpp2 *priv, int index)
if (index > MVPP2_PRS_TCAM_SRAM_SIZE)
return -EINVAL;
spin_lock_bh(&priv->prs_spinlock);
mvpp2_write(priv, MVPP2_PRS_TCAM_HIT_IDX_REG, index);
val = mvpp2_read(priv, MVPP2_PRS_TCAM_HIT_CNT_REG);
val &= MVPP2_PRS_TCAM_HIT_CNT_MASK;
spin_unlock_bh(&priv->prs_spinlock);
return val;
}

View File

@ -1559,12 +1559,11 @@ handle_xdp_verdict:
break;
default:
bpf_warn_invalid_xdp_action(pfvf->netdev, prog, act);
break;
fallthrough;
case XDP_ABORTED:
if (xsk_buff)
xsk_buff_free(xsk_buff);
trace_xdp_exception(pfvf->netdev, prog, act);
break;
if (act == XDP_ABORTED)
trace_xdp_exception(pfvf->netdev, prog, act);
fallthrough;
case XDP_DROP:
cq->pool_ptrs++;
if (xsk_buff) {

View File

@ -7,6 +7,7 @@ config MLX4_EN
tristate "Mellanox Technologies 1/10/40Gbit Ethernet support"
depends on PCI && NETDEVICES && ETHERNET && INET
depends on PTP_1588_CLOCK_OPTIONAL
select PAGE_POOL
select MLX4_CORE
help
This driver supports Mellanox Technologies ConnectX Ethernet

View File

@ -450,8 +450,9 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
net_dev->hw_enc_features |= efx->type->offload_features;
net_dev->vlan_features |= NETIF_F_HW_CSUM | NETIF_F_SG |
NETIF_F_HIGHDMA | NETIF_F_ALL_TSO;
netif_set_tso_max_segs(net_dev,
ESE_EF100_DP_GZ_TSO_MAX_HDR_NUM_SEGS_DEFAULT);
nic_data = efx->nic_data;
netif_set_tso_max_size(efx->net_dev, nic_data->tso_max_payload_len);
netif_set_tso_max_segs(efx->net_dev, nic_data->tso_max_payload_num_segs);
rc = efx_ef100_init_datapath_caps(efx);
if (rc < 0)
@ -477,7 +478,6 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
/* Don't fail init if RSS setup doesn't work. */
efx_mcdi_push_default_indir_table(efx, efx->n_rx_channels);
nic_data = efx->nic_data;
rc = ef100_get_mac_address(efx, net_dev->perm_addr, CLIENT_HANDLE_SELF,
efx->type->is_vf);
if (rc)

View File

@ -887,8 +887,7 @@ static int ef100_process_design_param(struct efx_nic *efx,
case ESE_EF100_DP_GZ_TSO_MAX_HDR_NUM_SEGS:
/* We always put HDR_NUM_SEGS=1 in our TSO descriptors */
if (!reader->value) {
netif_err(efx, probe, efx->net_dev,
"TSO_MAX_HDR_NUM_SEGS < 1\n");
pci_err(efx->pci_dev, "TSO_MAX_HDR_NUM_SEGS < 1\n");
return -EOPNOTSUPP;
}
return 0;
@ -901,32 +900,28 @@ static int ef100_process_design_param(struct efx_nic *efx,
*/
if (!reader->value || reader->value > EFX_MIN_DMAQ_SIZE ||
EFX_MIN_DMAQ_SIZE % (u32)reader->value) {
netif_err(efx, probe, efx->net_dev,
"%s size granularity is %llu, can't guarantee safety\n",
reader->type == ESE_EF100_DP_GZ_RXQ_SIZE_GRANULARITY ? "RXQ" : "TXQ",
reader->value);
pci_err(efx->pci_dev,
"%s size granularity is %llu, can't guarantee safety\n",
reader->type == ESE_EF100_DP_GZ_RXQ_SIZE_GRANULARITY ? "RXQ" : "TXQ",
reader->value);
return -EOPNOTSUPP;
}
return 0;
case ESE_EF100_DP_GZ_TSO_MAX_PAYLOAD_LEN:
nic_data->tso_max_payload_len = min_t(u64, reader->value,
GSO_LEGACY_MAX_SIZE);
netif_set_tso_max_size(efx->net_dev,
nic_data->tso_max_payload_len);
return 0;
case ESE_EF100_DP_GZ_TSO_MAX_PAYLOAD_NUM_SEGS:
nic_data->tso_max_payload_num_segs = min_t(u64, reader->value, 0xffff);
netif_set_tso_max_segs(efx->net_dev,
nic_data->tso_max_payload_num_segs);
return 0;
case ESE_EF100_DP_GZ_TSO_MAX_NUM_FRAMES:
nic_data->tso_max_frames = min_t(u64, reader->value, 0xffff);
return 0;
case ESE_EF100_DP_GZ_COMPAT:
if (reader->value) {
netif_err(efx, probe, efx->net_dev,
"DP_COMPAT has unknown bits %#llx, driver not compatible with this hw\n",
reader->value);
pci_err(efx->pci_dev,
"DP_COMPAT has unknown bits %#llx, driver not compatible with this hw\n",
reader->value);
return -EOPNOTSUPP;
}
return 0;
@ -946,10 +941,10 @@ static int ef100_process_design_param(struct efx_nic *efx,
* So the value of this shouldn't matter.
*/
if (reader->value != ESE_EF100_DP_GZ_VI_STRIDES_DEFAULT)
netif_dbg(efx, probe, efx->net_dev,
"NIC has other than default VI_STRIDES (mask "
"%#llx), early probing might use wrong one\n",
reader->value);
pci_dbg(efx->pci_dev,
"NIC has other than default VI_STRIDES (mask "
"%#llx), early probing might use wrong one\n",
reader->value);
return 0;
case ESE_EF100_DP_GZ_RX_MAX_RUNT:
/* Driver doesn't look at L2_STATUS:LEN_ERR bit, so we don't
@ -961,9 +956,9 @@ static int ef100_process_design_param(struct efx_nic *efx,
/* Host interface says "Drivers should ignore design parameters
* that they do not recognise."
*/
netif_dbg(efx, probe, efx->net_dev,
"Ignoring unrecognised design parameter %u\n",
reader->type);
pci_dbg(efx->pci_dev,
"Ignoring unrecognised design parameter %u\n",
reader->type);
return 0;
}
}
@ -999,13 +994,13 @@ static int ef100_check_design_params(struct efx_nic *efx)
*/
if (reader.state != EF100_TLV_TYPE) {
if (reader.state == EF100_TLV_TYPE_CONT)
netif_err(efx, probe, efx->net_dev,
"truncated design parameter (incomplete type %u)\n",
reader.type);
pci_err(efx->pci_dev,
"truncated design parameter (incomplete type %u)\n",
reader.type);
else
netif_err(efx, probe, efx->net_dev,
"truncated design parameter %u\n",
reader.type);
pci_err(efx->pci_dev,
"truncated design parameter %u\n",
reader.type);
rc = -EIO;
}
out:

View File

@ -939,6 +939,7 @@ static int nsim_init_netdevsim(struct netdevsim *ns)
ns->netdev->netdev_ops = &nsim_netdev_ops;
ns->netdev->stat_ops = &nsim_stat_ops;
ns->netdev->queue_mgmt_ops = &nsim_queue_mgmt_ops;
netdev_lockdep_set_classes(ns->netdev);
err = nsim_udp_tunnels_info_create(ns->nsim_dev, ns->netdev);
if (err)
@ -960,6 +961,14 @@ static int nsim_init_netdevsim(struct netdevsim *ns)
if (err)
goto err_ipsec_teardown;
rtnl_unlock();
if (IS_ENABLED(CONFIG_DEBUG_NET)) {
ns->nb.notifier_call = netdev_debug_event;
if (register_netdevice_notifier_dev_net(ns->netdev, &ns->nb,
&ns->nn))
ns->nb.notifier_call = NULL;
}
return 0;
err_ipsec_teardown:
@ -1043,6 +1052,10 @@ void nsim_destroy(struct netdevsim *ns)
debugfs_remove(ns->qr_dfs);
debugfs_remove(ns->pp_dfs);
if (ns->nb.notifier_call)
unregister_netdevice_notifier_dev_net(ns->netdev, &ns->nb,
&ns->nn);
rtnl_lock();
peer = rtnl_dereference(ns->peer);
if (peer)

View File

@ -144,6 +144,9 @@ struct netdevsim {
struct nsim_ethtool ethtool;
struct netdevsim __rcu *peer;
struct notifier_block nb;
struct netdev_net_notifier nn;
};
struct netdevsim *

View File

@ -530,7 +530,8 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
netif_device_present (dev->net) &&
test_bit(EVENT_DEV_OPEN, &dev->flags) &&
!test_bit (EVENT_RX_HALT, &dev->flags) &&
!test_bit (EVENT_DEV_ASLEEP, &dev->flags)) {
!test_bit (EVENT_DEV_ASLEEP, &dev->flags) &&
!usbnet_going_away(dev)) {
switch (retval = usb_submit_urb (urb, GFP_ATOMIC)) {
case -EPIPE:
usbnet_defer_kevent (dev, EVENT_RX_HALT);
@ -551,8 +552,7 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
tasklet_schedule (&dev->bh);
break;
case 0:
if (!usbnet_going_away(dev))
__usbnet_queue_skb(&dev->rxq, skb, rx_start);
__usbnet_queue_skb(&dev->rxq, skb, rx_start);
}
} else {
netif_dbg(dev, ifdown, dev->net, "rx: stopped\n");

View File

@ -4192,7 +4192,7 @@ int dev_change_flags(struct net_device *dev, unsigned int flags,
int netif_set_alias(struct net_device *dev, const char *alias, size_t len);
int dev_set_alias(struct net_device *, const char *, size_t);
int dev_get_alias(const struct net_device *, char *, size_t);
int netif_change_net_namespace(struct net_device *dev, struct net *net,
int __dev_change_net_namespace(struct net_device *dev, struct net *net,
const char *pat, int new_ifindex,
struct netlink_ext_ack *extack);
int dev_change_net_namespace(struct net_device *dev, struct net *net,

View File

@ -667,14 +667,6 @@ static inline void ip_ipgre_mc_map(__be32 naddr, const unsigned char *broadcast,
memcpy(buf, &naddr, sizeof(naddr));
}
#if IS_MODULE(CONFIG_IPV6)
#define EXPORT_IPV6_MOD(X) EXPORT_SYMBOL(X)
#define EXPORT_IPV6_MOD_GPL(X) EXPORT_SYMBOL_GPL(X)
#else
#define EXPORT_IPV6_MOD(X)
#define EXPORT_IPV6_MOD_GPL(X)
#endif
#if IS_ENABLED(CONFIG_IPV6)
#include <linux/ipv6.h>
#endif
@ -694,6 +686,14 @@ static __inline__ void inet_reset_saddr(struct sock *sk)
#endif
#if IS_MODULE(CONFIG_IPV6)
#define EXPORT_IPV6_MOD(X) EXPORT_SYMBOL(X)
#define EXPORT_IPV6_MOD_GPL(X) EXPORT_SYMBOL_GPL(X)
#else
#define EXPORT_IPV6_MOD(X)
#define EXPORT_IPV6_MOD_GPL(X)
#endif
static inline unsigned int ipv4_addr_hash(__be32 ip)
{
return (__force unsigned int) ip;

View File

@ -98,4 +98,7 @@ static inline int netdev_lock_cmp_fn(const struct lockdep_map *a,
&qdisc_xmit_lock_key); \
}
int netdev_debug_event(struct notifier_block *nb, unsigned long event,
void *ptr);
#endif

View File

@ -6,6 +6,7 @@
#include <net/page_pool/types.h>
struct netdev_rx_queue;
struct netlink_ext_ack;
struct sk_buff;
struct memory_provider_ops {
@ -24,8 +25,13 @@ void net_mp_niov_clear_page_pool(struct net_iov *niov);
int net_mp_open_rxq(struct net_device *dev, unsigned ifq_idx,
struct pp_memory_provider_params *p);
int __net_mp_open_rxq(struct net_device *dev, unsigned int rxq_idx,
const struct pp_memory_provider_params *p,
struct netlink_ext_ack *extack);
void net_mp_close_rxq(struct net_device *dev, unsigned ifq_idx,
struct pp_memory_provider_params *old_p);
void __net_mp_close_rxq(struct net_device *dev, unsigned int rxq_idx,
const struct pp_memory_provider_params *old_p);
/**
* net_mp_netmem_place_in_cache() - give a netmem to a page pool

View File

@ -45,5 +45,5 @@ obj-$(CONFIG_BPF_SYSCALL) += bpf_sk_storage.o
obj-$(CONFIG_OF) += of_net.o
obj-$(CONFIG_NET_TEST) += net_test.o
obj-$(CONFIG_NET_DEVMEM) += devmem.o
obj-$(CONFIG_DEBUG_NET_SMALL_RTNL) += rtnl_net_debug.o
obj-$(CONFIG_DEBUG_NET) += lock_debug.o
obj-$(CONFIG_FAIL_SKB_REALLOC) += skb_fault_injection.o

View File

@ -1771,6 +1771,7 @@ void netif_disable_lro(struct net_device *dev)
netdev_unlock_ops(lower_dev);
}
}
EXPORT_IPV6_MOD(netif_disable_lro);
/**
* dev_disable_gro_hw - disable HW Generic Receive Offload on a device
@ -1858,7 +1859,9 @@ static int call_netdevice_register_net_notifiers(struct notifier_block *nb,
int err;
for_each_netdev(net, dev) {
netdev_lock_ops(dev);
err = call_netdevice_register_notifiers(nb, dev);
netdev_unlock_ops(dev);
if (err)
goto rollback;
}
@ -10284,7 +10287,9 @@ int bpf_xdp_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
goto unlock;
}
netdev_lock_ops(dev);
err = dev_xdp_attach_link(dev, &extack, link);
netdev_unlock_ops(dev);
rtnl_unlock();
if (err) {
@ -11045,7 +11050,9 @@ int register_netdevice(struct net_device *dev)
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
/* Notify protocols, that a new device appeared. */
netdev_lock_ops(dev);
ret = call_netdevice_notifiers(NETDEV_REGISTER, dev);
netdev_unlock_ops(dev);
ret = notifier_to_errno(ret);
if (ret) {
/* Expect explicit free_netdev() on failure */
@ -12057,7 +12064,7 @@ void unregister_netdev(struct net_device *dev)
}
EXPORT_SYMBOL(unregister_netdev);
int netif_change_net_namespace(struct net_device *dev, struct net *net,
int __dev_change_net_namespace(struct net_device *dev, struct net *net,
const char *pat, int new_ifindex,
struct netlink_ext_ack *extack)
{
@ -12142,11 +12149,12 @@ int netif_change_net_namespace(struct net_device *dev, struct net *net,
* And now a mini version of register_netdevice unregister_netdevice.
*/
netdev_lock_ops(dev);
/* If device is running close it first. */
netif_close(dev);
/* And unlink it from device chain */
unlist_netdevice(dev);
netdev_unlock_ops(dev);
synchronize_net();
@ -12208,11 +12216,12 @@ int netif_change_net_namespace(struct net_device *dev, struct net *net,
err = netdev_change_owner(dev, net_old, net);
WARN_ON(err);
netdev_lock_ops(dev);
/* Add the device back in the hashes */
list_netdevice(dev);
/* Notify protocols, that a new device appeared. */
call_netdevice_notifiers(NETDEV_REGISTER, dev);
netdev_unlock_ops(dev);
/*
* Prevent userspace races by waiting until the network

View File

@ -117,13 +117,7 @@ EXPORT_SYMBOL(dev_set_mac_address_user);
int dev_change_net_namespace(struct net_device *dev, struct net *net,
const char *pat)
{
int ret;
netdev_lock_ops(dev);
ret = netif_change_net_namespace(dev, net, pat, 0, NULL);
netdev_unlock_ops(dev);
return ret;
return __dev_change_net_namespace(dev, net, pat, 0, NULL);
}
EXPORT_SYMBOL_GPL(dev_change_net_namespace);

View File

@ -8,7 +8,6 @@
*/
#include <linux/dma-buf.h>
#include <linux/ethtool_netlink.h>
#include <linux/genalloc.h>
#include <linux/mm.h>
#include <linux/netdevice.h>
@ -117,21 +116,19 @@ void net_devmem_unbind_dmabuf(struct net_devmem_dmabuf_binding *binding)
struct netdev_rx_queue *rxq;
unsigned long xa_idx;
unsigned int rxq_idx;
int err;
if (binding->list.next)
list_del(&binding->list);
xa_for_each(&binding->bound_rxqs, xa_idx, rxq) {
WARN_ON(rxq->mp_params.mp_priv != binding);
rxq->mp_params.mp_priv = NULL;
rxq->mp_params.mp_ops = NULL;
const struct pp_memory_provider_params mp_params = {
.mp_priv = binding,
.mp_ops = &dmabuf_devmem_ops,
};
rxq_idx = get_netdev_rx_queue_index(rxq);
err = netdev_rx_queue_restart(binding->dev, rxq_idx);
WARN_ON(err && err != -ENETDOWN);
__net_mp_close_rxq(binding->dev, rxq_idx, &mp_params);
}
xa_erase(&net_devmem_dmabuf_bindings, binding->id);
@ -143,57 +140,28 @@ int net_devmem_bind_dmabuf_to_queue(struct net_device *dev, u32 rxq_idx,
struct net_devmem_dmabuf_binding *binding,
struct netlink_ext_ack *extack)
{
struct pp_memory_provider_params mp_params = {
.mp_priv = binding,
.mp_ops = &dmabuf_devmem_ops,
};
struct netdev_rx_queue *rxq;
u32 xa_idx;
int err;
if (rxq_idx >= dev->real_num_rx_queues) {
NL_SET_ERR_MSG(extack, "rx queue index out of range");
return -ERANGE;
}
if (dev->cfg->hds_config != ETHTOOL_TCP_DATA_SPLIT_ENABLED) {
NL_SET_ERR_MSG(extack, "tcp-data-split is disabled");
return -EINVAL;
}
if (dev->cfg->hds_thresh) {
NL_SET_ERR_MSG(extack, "hds-thresh is not zero");
return -EINVAL;
}
rxq = __netif_get_rx_queue(dev, rxq_idx);
if (rxq->mp_params.mp_ops) {
NL_SET_ERR_MSG(extack, "designated queue already memory provider bound");
return -EEXIST;
}
#ifdef CONFIG_XDP_SOCKETS
if (rxq->pool) {
NL_SET_ERR_MSG(extack, "designated queue already in use by AF_XDP");
return -EBUSY;
}
#endif
err = xa_alloc(&binding->bound_rxqs, &xa_idx, rxq, xa_limit_32b,
GFP_KERNEL);
err = __net_mp_open_rxq(dev, rxq_idx, &mp_params, extack);
if (err)
return err;
rxq->mp_params.mp_priv = binding;
rxq->mp_params.mp_ops = &dmabuf_devmem_ops;
err = netdev_rx_queue_restart(dev, rxq_idx);
rxq = __netif_get_rx_queue(dev, rxq_idx);
err = xa_alloc(&binding->bound_rxqs, &xa_idx, rxq, xa_limit_32b,
GFP_KERNEL);
if (err)
goto err_xa_erase;
goto err_close_rxq;
return 0;
err_xa_erase:
rxq->mp_params.mp_priv = NULL;
rxq->mp_params.mp_ops = NULL;
xa_erase(&binding->bound_rxqs, xa_idx);
err_close_rxq:
__net_mp_close_rxq(dev, rxq_idx, &mp_params);
return err;
}

View File

@ -165,6 +165,14 @@ static void dst_count_dec(struct dst_entry *dst)
void dst_release(struct dst_entry *dst)
{
if (dst && rcuref_put(&dst->__rcuref)) {
#ifdef CONFIG_DST_CACHE
if (dst->flags & DST_METADATA) {
struct metadata_dst *md_dst = (struct metadata_dst *)dst;
if (md_dst->type == METADATA_IP_TUNNEL)
dst_cache_reset_now(&md_dst->u.tun_info.dst_cache);
}
#endif
dst_count_dec(dst);
call_rcu_hurry(&dst->rcu_head, dst_destroy_rcu);
}

View File

@ -6,10 +6,11 @@
#include <linux/notifier.h>
#include <linux/rtnetlink.h>
#include <net/net_namespace.h>
#include <net/netdev_lock.h>
#include <net/netns/generic.h>
static int rtnl_net_debug_event(struct notifier_block *nb,
unsigned long event, void *ptr)
int netdev_debug_event(struct notifier_block *nb, unsigned long event,
void *ptr)
{
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
struct net *net = dev_net(dev);
@ -17,11 +18,13 @@ static int rtnl_net_debug_event(struct notifier_block *nb,
/* Keep enum and don't add default to trigger -Werror=switch */
switch (cmd) {
case NETDEV_REGISTER:
case NETDEV_UP:
netdev_ops_assert_locked(dev);
fallthrough;
case NETDEV_DOWN:
case NETDEV_REBOOT:
case NETDEV_CHANGE:
case NETDEV_REGISTER:
case NETDEV_UNREGISTER:
case NETDEV_CHANGEMTU:
case NETDEV_CHANGEADDR:
@ -66,6 +69,7 @@ static int rtnl_net_debug_event(struct notifier_block *nb,
return NOTIFY_DONE;
}
EXPORT_SYMBOL_NS_GPL(netdev_debug_event, "NETDEV_INTERNAL");
static int rtnl_net_debug_net_id;
@ -74,7 +78,7 @@ static int __net_init rtnl_net_debug_net_init(struct net *net)
struct notifier_block *nb;
nb = net_generic(net, rtnl_net_debug_net_id);
nb->notifier_call = rtnl_net_debug_event;
nb->notifier_call = netdev_debug_event;
return register_netdevice_notifier_net(net, nb);
}
@ -95,14 +99,14 @@ static struct pernet_operations rtnl_net_debug_net_ops __net_initdata = {
};
static struct notifier_block rtnl_net_debug_block = {
.notifier_call = rtnl_net_debug_event,
.notifier_call = netdev_debug_event,
};
static int __init rtnl_net_debug_init(void)
{
int ret;
ret = register_pernet_device(&rtnl_net_debug_net_ops);
ret = register_pernet_subsys(&rtnl_net_debug_net_ops);
if (ret)
return ret;

View File

@ -874,12 +874,6 @@ int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
goto err_unlock;
}
if (dev_xdp_prog_count(netdev)) {
NL_SET_ERR_MSG(info->extack, "unable to bind dmabuf to device with XDP program attached");
err = -EEXIST;
goto err_unlock;
}
binding = net_devmem_bind_dmabuf(netdev, dmabuf_fd, info->extack);
if (IS_ERR(binding)) {
err = PTR_ERR(binding);

View File

@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <linux/ethtool_netlink.h>
#include <linux/netdevice.h>
#include <net/netdev_lock.h>
#include <net/netdev_queues.h>
@ -86,8 +87,9 @@ err_free_new_mem:
}
EXPORT_SYMBOL_NS_GPL(netdev_rx_queue_restart, "NETDEV_INTERNAL");
static int __net_mp_open_rxq(struct net_device *dev, unsigned ifq_idx,
struct pp_memory_provider_params *p)
int __net_mp_open_rxq(struct net_device *dev, unsigned int rxq_idx,
const struct pp_memory_provider_params *p,
struct netlink_ext_ack *extack)
{
struct netdev_rx_queue *rxq;
int ret;
@ -95,16 +97,41 @@ static int __net_mp_open_rxq(struct net_device *dev, unsigned ifq_idx,
if (!netdev_need_ops_lock(dev))
return -EOPNOTSUPP;
if (ifq_idx >= dev->real_num_rx_queues)
if (rxq_idx >= dev->real_num_rx_queues)
return -EINVAL;
ifq_idx = array_index_nospec(ifq_idx, dev->real_num_rx_queues);
rxq_idx = array_index_nospec(rxq_idx, dev->real_num_rx_queues);
rxq = __netif_get_rx_queue(dev, ifq_idx);
if (rxq->mp_params.mp_ops)
if (rxq_idx >= dev->real_num_rx_queues) {
NL_SET_ERR_MSG(extack, "rx queue index out of range");
return -ERANGE;
}
if (dev->cfg->hds_config != ETHTOOL_TCP_DATA_SPLIT_ENABLED) {
NL_SET_ERR_MSG(extack, "tcp-data-split is disabled");
return -EINVAL;
}
if (dev->cfg->hds_thresh) {
NL_SET_ERR_MSG(extack, "hds-thresh is not zero");
return -EINVAL;
}
if (dev_xdp_prog_count(dev)) {
NL_SET_ERR_MSG(extack, "unable to custom memory provider to device with XDP program attached");
return -EEXIST;
}
rxq = __netif_get_rx_queue(dev, rxq_idx);
if (rxq->mp_params.mp_ops) {
NL_SET_ERR_MSG(extack, "designated queue already memory provider bound");
return -EEXIST;
}
#ifdef CONFIG_XDP_SOCKETS
if (rxq->pool) {
NL_SET_ERR_MSG(extack, "designated queue already in use by AF_XDP");
return -EBUSY;
}
#endif
rxq->mp_params = *p;
ret = netdev_rx_queue_restart(dev, ifq_idx);
ret = netdev_rx_queue_restart(dev, rxq_idx);
if (ret) {
rxq->mp_params.mp_ops = NULL;
rxq->mp_params.mp_priv = NULL;
@ -112,21 +139,22 @@ static int __net_mp_open_rxq(struct net_device *dev, unsigned ifq_idx,
return ret;
}
int net_mp_open_rxq(struct net_device *dev, unsigned ifq_idx,
int net_mp_open_rxq(struct net_device *dev, unsigned int rxq_idx,
struct pp_memory_provider_params *p)
{
int ret;
netdev_lock(dev);
ret = __net_mp_open_rxq(dev, ifq_idx, p);
ret = __net_mp_open_rxq(dev, rxq_idx, p, NULL);
netdev_unlock(dev);
return ret;
}
static void __net_mp_close_rxq(struct net_device *dev, unsigned ifq_idx,
struct pp_memory_provider_params *old_p)
void __net_mp_close_rxq(struct net_device *dev, unsigned int ifq_idx,
const struct pp_memory_provider_params *old_p)
{
struct netdev_rx_queue *rxq;
int err;
if (WARN_ON_ONCE(ifq_idx >= dev->real_num_rx_queues))
return;
@ -146,7 +174,8 @@ static void __net_mp_close_rxq(struct net_device *dev, unsigned ifq_idx,
rxq->mp_params.mp_ops = NULL;
rxq->mp_params.mp_priv = NULL;
WARN_ON(netdev_rx_queue_restart(dev, ifq_idx));
err = netdev_rx_queue_restart(dev, ifq_idx);
WARN_ON(err && err != -ENETDOWN);
}
void net_mp_close_rxq(struct net_device *dev, unsigned ifq_idx,

View File

@ -3025,8 +3025,6 @@ static int do_setlink(const struct sk_buff *skb, struct net_device *dev,
char ifname[IFNAMSIZ];
int err;
netdev_lock_ops(dev);
err = validate_linkmsg(dev, tb, extack);
if (err < 0)
goto errout;
@ -3042,14 +3040,16 @@ static int do_setlink(const struct sk_buff *skb, struct net_device *dev,
new_ifindex = nla_get_s32_default(tb[IFLA_NEW_IFINDEX], 0);
err = netif_change_net_namespace(dev, tgt_net, pat,
err = __dev_change_net_namespace(dev, tgt_net, pat,
new_ifindex, extack);
if (err)
goto errout;
return err;
status |= DO_SETLINK_MODIFIED;
}
netdev_lock_ops(dev);
if (tb[IFLA_MAP]) {
struct rtnl_link_ifmap *u_map;
struct ifmap k_map;

View File

@ -281,7 +281,7 @@ static struct in_device *inetdev_init(struct net_device *dev)
if (!in_dev->arp_parms)
goto out_kfree;
if (IPV4_DEVCONF(in_dev->cnf, FORWARDING))
dev_disable_lro(dev);
netif_disable_lro(dev);
/* Reference in_dev->dev */
netdev_hold(dev, &in_dev->dev_tracker, GFP_KERNEL);
/* Account for reference dev->ip_ptr (below) */

View File

@ -416,7 +416,7 @@ int skb_tunnel_check_pmtu(struct sk_buff *skb, struct dst_entry *encap_dst,
skb_dst_update_pmtu_no_confirm(skb, mtu);
if (!reply || skb->pkt_type == PACKET_HOST)
if (!reply)
return 0;
if (skb->protocol == htons(ETH_P_IP))
@ -451,7 +451,7 @@ static const struct nla_policy
geneve_opt_policy[LWTUNNEL_IP_OPT_GENEVE_MAX + 1] = {
[LWTUNNEL_IP_OPT_GENEVE_CLASS] = { .type = NLA_U16 },
[LWTUNNEL_IP_OPT_GENEVE_TYPE] = { .type = NLA_U8 },
[LWTUNNEL_IP_OPT_GENEVE_DATA] = { .type = NLA_BINARY, .len = 128 },
[LWTUNNEL_IP_OPT_GENEVE_DATA] = { .type = NLA_BINARY, .len = 127 },
};
static const struct nla_policy

View File

@ -1625,12 +1625,12 @@ static bool udp_skb_has_head_state(struct sk_buff *skb)
}
/* fully reclaim rmem/fwd memory allocated for skb */
static void udp_rmem_release(struct sock *sk, int size, int partial,
bool rx_queue_lock_held)
static void udp_rmem_release(struct sock *sk, unsigned int size,
int partial, bool rx_queue_lock_held)
{
struct udp_sock *up = udp_sk(sk);
struct sk_buff_head *sk_queue;
int amt;
unsigned int amt;
if (likely(partial)) {
up->forward_deficit += size;
@ -1650,10 +1650,8 @@ static void udp_rmem_release(struct sock *sk, int size, int partial,
if (!rx_queue_lock_held)
spin_lock(&sk_queue->lock);
sk_forward_alloc_add(sk, size);
amt = (sk->sk_forward_alloc - partial) & ~(PAGE_SIZE - 1);
sk_forward_alloc_add(sk, -amt);
amt = (size + sk->sk_forward_alloc - partial) & ~(PAGE_SIZE - 1);
sk_forward_alloc_add(sk, size - amt);
if (amt)
__sk_mem_reduce_allocated(sk, amt >> PAGE_SHIFT);
@ -1725,17 +1723,25 @@ static int udp_rmem_schedule(struct sock *sk, int size)
int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb)
{
struct sk_buff_head *list = &sk->sk_receive_queue;
int rmem, err = -ENOMEM;
unsigned int rmem, rcvbuf;
spinlock_t *busy = NULL;
int size, rcvbuf;
int size, err = -ENOMEM;
/* Immediately drop when the receive queue is full.
* Always allow at least one packet.
*/
rmem = atomic_read(&sk->sk_rmem_alloc);
rcvbuf = READ_ONCE(sk->sk_rcvbuf);
if (rmem > rcvbuf)
goto drop;
size = skb->truesize;
/* Immediately drop when the receive queue is full.
* Cast to unsigned int performs the boundary check for INT_MAX.
*/
if (rmem + size > rcvbuf) {
if (rcvbuf > INT_MAX >> 1)
goto drop;
/* Always allow at least one packet for small buffer. */
if (rmem > rcvbuf)
goto drop;
}
/* Under mem pressure, it might be helpful to help udp_recvmsg()
* having linear skbs :
@ -1745,10 +1751,10 @@ int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb)
*/
if (rmem > (rcvbuf >> 1)) {
skb_condense(skb);
size = skb->truesize;
busy = busylock_acquire(sk);
}
size = skb->truesize;
udp_set_dev_scratch(skb);
atomic_add(size, &sk->sk_rmem_alloc);
@ -1835,7 +1841,7 @@ EXPORT_IPV6_MOD_GPL(skb_consume_udp);
static struct sk_buff *__first_packet_length(struct sock *sk,
struct sk_buff_head *rcvq,
int *total)
unsigned int *total)
{
struct sk_buff *skb;
@ -1868,8 +1874,8 @@ static int first_packet_length(struct sock *sk)
{
struct sk_buff_head *rcvq = &udp_sk(sk)->reader_queue;
struct sk_buff_head *sk_queue = &sk->sk_receive_queue;
unsigned int total = 0;
struct sk_buff *skb;
int total = 0;
int res;
spin_lock_bh(&rcvq->lock);

View File

@ -80,6 +80,7 @@
#include <net/netlink.h>
#include <net/pkt_sched.h>
#include <net/l3mdev.h>
#include <net/netdev_lock.h>
#include <linux/if_tunnel.h>
#include <linux/rtnetlink.h>
#include <linux/netconf.h>
@ -377,6 +378,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
int err = -ENOMEM;
ASSERT_RTNL();
netdev_ops_assert_locked(dev);
if (dev->mtu < IPV6_MIN_MTU && dev != blackhole_netdev)
return ERR_PTR(-EINVAL);
@ -402,7 +404,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
return ERR_PTR(err);
}
if (ndev->cnf.forwarding)
dev_disable_lro(dev);
netif_disable_lro(dev);
/* We refer to the device */
netdev_hold(dev, &ndev->dev_tracker, GFP_KERNEL);
@ -3152,10 +3154,12 @@ int addrconf_add_ifaddr(struct net *net, void __user *arg)
rtnl_net_lock(net);
dev = __dev_get_by_index(net, ireq.ifr6_ifindex);
netdev_lock_ops(dev);
if (dev)
err = inet6_addr_add(net, dev, &cfg, 0, 0, NULL);
else
err = -ENODEV;
netdev_unlock_ops(dev);
rtnl_net_unlock(net);
return err;
}
@ -5026,9 +5030,10 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
if (!dev) {
NL_SET_ERR_MSG_MOD(extack, "Unable to find the interface");
err = -ENODEV;
goto unlock;
goto unlock_rtnl;
}
netdev_lock_ops(dev);
idev = ipv6_find_idev(dev);
if (IS_ERR(idev)) {
err = PTR_ERR(idev);
@ -5065,6 +5070,8 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
in6_ifa_put(ifa);
unlock:
netdev_unlock_ops(dev);
unlock_rtnl:
rtnl_net_unlock(net);
return err;
@ -5784,6 +5791,27 @@ static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype,
}
}
static int inet6_fill_ifla6_stats_attrs(struct sk_buff *skb,
struct inet6_dev *idev)
{
struct nlattr *nla;
nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64));
if (!nla)
goto nla_put_failure;
snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla));
nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64));
if (!nla)
goto nla_put_failure;
snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla));
return 0;
nla_put_failure:
return -EMSGSIZE;
}
static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev,
u32 ext_filter_mask)
{
@ -5806,18 +5834,10 @@ static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev,
/* XXX - MC not implemented */
if (ext_filter_mask & RTEXT_FILTER_SKIP_STATS)
return 0;
nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64));
if (!nla)
goto nla_put_failure;
snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla));
nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64));
if (!nla)
goto nla_put_failure;
snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla));
if (!(ext_filter_mask & RTEXT_FILTER_SKIP_STATS)) {
if (inet6_fill_ifla6_stats_attrs(skb, idev) < 0)
goto nla_put_failure;
}
nla = nla_reserve(skb, IFLA_INET6_TOKEN, sizeof(struct in6_addr));
if (!nla)
@ -6503,7 +6523,9 @@ static int addrconf_sysctl_addr_gen_mode(const struct ctl_table *ctl, int write,
if (idev->cnf.addr_gen_mode != new_val) {
WRITE_ONCE(idev->cnf.addr_gen_mode, new_val);
netdev_lock_ops(idev->dev);
addrconf_init_auto_addrs(idev->dev);
netdev_unlock_ops(idev->dev);
}
} else if (&net->ipv6.devconf_all->addr_gen_mode == ctl->data) {
struct net_device *dev;
@ -6515,7 +6537,9 @@ static int addrconf_sysctl_addr_gen_mode(const struct ctl_table *ctl, int write,
idev->cnf.addr_gen_mode != new_val) {
WRITE_ONCE(idev->cnf.addr_gen_mode,
new_val);
netdev_lock_ops(idev->dev);
addrconf_init_auto_addrs(idev->dev);
netdev_unlock_ops(idev->dev);
}
}
}

View File

@ -1072,8 +1072,13 @@ static int calipso_sock_getattr(struct sock *sk,
struct ipv6_opt_hdr *hop;
int opt_len, len, ret_val = -ENOMSG, offset;
unsigned char *opt;
struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk));
struct ipv6_pinfo *pinfo = inet6_sk(sk);
struct ipv6_txoptions *txopts;
if (!pinfo)
return -EAFNOSUPPORT;
txopts = txopt_get(pinfo);
if (!txopts || !txopts->hopopt)
goto done;
@ -1125,8 +1130,13 @@ static int calipso_sock_setattr(struct sock *sk,
{
int ret_val;
struct ipv6_opt_hdr *old, *new;
struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk));
struct ipv6_pinfo *pinfo = inet6_sk(sk);
struct ipv6_txoptions *txopts;
if (!pinfo)
return -EAFNOSUPPORT;
txopts = txopt_get(pinfo);
old = NULL;
if (txopts)
old = txopts->hopopt;
@ -1153,8 +1163,13 @@ static int calipso_sock_setattr(struct sock *sk,
static void calipso_sock_delattr(struct sock *sk)
{
struct ipv6_opt_hdr *new_hop;
struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk));
struct ipv6_pinfo *pinfo = inet6_sk(sk);
struct ipv6_txoptions *txopts;
if (!pinfo)
return;
txopts = txopt_get(pinfo);
if (!txopts || !txopts->hopopt)
goto done;

View File

@ -412,12 +412,37 @@ static bool rt6_check_expired(const struct rt6_info *rt)
return false;
}
static struct fib6_info *
rt6_multipath_first_sibling_rcu(const struct fib6_info *rt)
{
struct fib6_info *iter;
struct fib6_node *fn;
fn = rcu_dereference(rt->fib6_node);
if (!fn)
goto out;
iter = rcu_dereference(fn->leaf);
if (!iter)
goto out;
while (iter) {
if (iter->fib6_metric == rt->fib6_metric &&
rt6_qualify_for_ecmp(iter))
return iter;
iter = rcu_dereference(iter->fib6_next);
}
out:
return NULL;
}
void fib6_select_path(const struct net *net, struct fib6_result *res,
struct flowi6 *fl6, int oif, bool have_oif_match,
const struct sk_buff *skb, int strict)
{
struct fib6_info *match = res->f6i;
struct fib6_info *first, *match = res->f6i;
struct fib6_info *sibling;
int hash;
if (!match->nh && (!match->fib6_nsiblings || have_oif_match))
goto out;
@ -440,16 +465,25 @@ void fib6_select_path(const struct net *net, struct fib6_result *res,
return;
}
if (fl6->mp_hash <= atomic_read(&match->fib6_nh->fib_nh_upper_bound))
first = rt6_multipath_first_sibling_rcu(match);
if (!first)
goto out;
list_for_each_entry_rcu(sibling, &match->fib6_siblings,
hash = fl6->mp_hash;
if (hash <= atomic_read(&first->fib6_nh->fib_nh_upper_bound) &&
rt6_score_route(first->fib6_nh, first->fib6_flags, oif,
strict) >= 0) {
match = first;
goto out;
}
list_for_each_entry_rcu(sibling, &first->fib6_siblings,
fib6_siblings) {
const struct fib6_nh *nh = sibling->fib6_nh;
int nh_upper_bound;
nh_upper_bound = atomic_read(&nh->fib_nh_upper_bound);
if (fl6->mp_hash > nh_upper_bound)
if (hash > nh_upper_bound)
continue;
if (rt6_score_route(nh, sibling->fib6_flags, oif, strict) < 0)
break;

View File

@ -2839,11 +2839,11 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
err = nft_netdev_register_hooks(ctx->net, &hook.list);
if (err < 0)
goto err_hooks;
unregister = true;
}
}
unregister = true;
if (nla[NFTA_CHAIN_COUNTERS]) {
if (!nft_is_base_chain(chain)) {
err = -EOPNOTSUPP;

View File

@ -309,7 +309,8 @@ static bool nft_rhash_expr_needs_gc_run(const struct nft_set *set,
nft_setelem_expr_foreach(expr, elem_expr, size) {
if (expr->ops->gc &&
expr->ops->gc(read_pnet(&set->net), expr))
expr->ops->gc(read_pnet(&set->net), expr) &&
set->flags & NFT_SET_EVAL)
return true;
}

View File

@ -335,13 +335,13 @@ static int nft_tunnel_obj_erspan_init(const struct nlattr *attr,
static const struct nla_policy nft_tunnel_opts_geneve_policy[NFTA_TUNNEL_KEY_GENEVE_MAX + 1] = {
[NFTA_TUNNEL_KEY_GENEVE_CLASS] = { .type = NLA_U16 },
[NFTA_TUNNEL_KEY_GENEVE_TYPE] = { .type = NLA_U8 },
[NFTA_TUNNEL_KEY_GENEVE_DATA] = { .type = NLA_BINARY, .len = 128 },
[NFTA_TUNNEL_KEY_GENEVE_DATA] = { .type = NLA_BINARY, .len = 127 },
};
static int nft_tunnel_obj_geneve_init(const struct nlattr *attr,
struct nft_tunnel_opts *opts)
{
struct geneve_opt *opt = (struct geneve_opt *)opts->u.data + opts->len;
struct geneve_opt *opt = (struct geneve_opt *)(opts->u.data + opts->len);
struct nlattr *tb[NFTA_TUNNEL_KEY_GENEVE_MAX + 1];
int err, data_len;
@ -625,7 +625,7 @@ static int nft_tunnel_opts_dump(struct sk_buff *skb,
if (!inner)
goto failure;
while (opts->len > offset) {
opt = (struct geneve_opt *)opts->u.data + offset;
opt = (struct geneve_opt *)(opts->u.data + offset);
if (nla_put_be16(skb, NFTA_TUNNEL_KEY_GENEVE_CLASS,
opt->opt_class) ||
nla_put_u8(skb, NFTA_TUNNEL_KEY_GENEVE_TYPE,

View File

@ -947,12 +947,6 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
pskb_trim(skb, ovs_mac_header_len(key));
}
/* Need to set the pkt_type to involve the routing layer. The
* packet movement through the OVS datapath doesn't generally
* use routing, but this is needed for tunnel cases.
*/
skb->pkt_type = PACKET_OUTGOING;
if (likely(!mru ||
(skb->len <= mru + vport->dev->hard_header_len))) {
ovs_vport_send(vport, skb, ovs_key_mac_proto(key));

View File

@ -68,7 +68,7 @@ geneve_opt_policy[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX + 1] = {
[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS] = { .type = NLA_U16 },
[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE] = { .type = NLA_U8 },
[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA] = { .type = NLA_BINARY,
.len = 128 },
.len = 127 },
};
static const struct nla_policy

View File

@ -766,7 +766,7 @@ geneve_opt_policy[TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX + 1] = {
[TCA_FLOWER_KEY_ENC_OPT_GENEVE_CLASS] = { .type = NLA_U16 },
[TCA_FLOWER_KEY_ENC_OPT_GENEVE_TYPE] = { .type = NLA_U8 },
[TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA] = { .type = NLA_BINARY,
.len = 128 },
.len = 127 },
};
static const struct nla_policy

View File

@ -123,8 +123,6 @@ static int skbprio_enqueue(struct sk_buff *skb, struct Qdisc *sch,
/* Check to update highest and lowest priorities. */
if (skb_queue_empty(lp_qdisc)) {
if (q->lowest_prio == q->highest_prio) {
/* The incoming packet is the only packet in queue. */
BUG_ON(sch->q.qlen != 1);
q->lowest_prio = prio;
q->highest_prio = prio;
} else {
@ -156,7 +154,6 @@ static struct sk_buff *skbprio_dequeue(struct Qdisc *sch)
/* Update highest priority field. */
if (skb_queue_empty(hpq)) {
if (q->lowest_prio == q->highest_prio) {
BUG_ON(sch->q.qlen);
q->highest_prio = 0;
q->lowest_prio = SKBPRIO_MAX_PRIORITY - 1;
} else {

View File

@ -525,6 +525,8 @@ static int proc_sctp_do_auth(const struct ctl_table *ctl, int write,
return ret;
}
static DEFINE_MUTEX(sctp_sysctl_mutex);
static int proc_sctp_do_udp_port(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
@ -549,6 +551,7 @@ static int proc_sctp_do_udp_port(const struct ctl_table *ctl, int write,
if (new_value > max || new_value < min)
return -EINVAL;
mutex_lock(&sctp_sysctl_mutex);
net->sctp.udp_port = new_value;
sctp_udp_sock_stop(net);
if (new_value) {
@ -561,6 +564,7 @@ static int proc_sctp_do_udp_port(const struct ctl_table *ctl, int write,
lock_sock(sk);
sctp_sk(sk)->udp_port = htons(net->sctp.udp_port);
release_sock(sk);
mutex_unlock(&sctp_sysctl_mutex);
}
return ret;

View File

@ -1551,7 +1551,11 @@ static int vsock_connect(struct socket *sock, struct sockaddr *addr,
timeout = vsk->connect_timeout;
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
while (sk->sk_state != TCP_ESTABLISHED && sk->sk_err == 0) {
/* If the socket is already closing or it is in an error state, there
* is no point in waiting.
*/
while (sk->sk_state != TCP_ESTABLISHED &&
sk->sk_state != TCP_CLOSING && sk->sk_err == 0) {
if (flags & O_NONBLOCK) {
/* If we're not going to block, we schedule a timeout
* function to generate a timeout on the connection

View File

@ -27,7 +27,7 @@ def _set_flow_rule(cfg, chan):
def test_zcrx(cfg) -> None:
cfg.require_v6()
cfg.require_ipver('6')
combined_chans = _get_combined_channels(cfg)
if combined_chans < 2:
@ -40,7 +40,7 @@ def test_zcrx(cfg) -> None:
flow_rule_id = _set_flow_rule(cfg, combined_chans - 1)
rx_cmd = f"{cfg.bin_remote} -s -p 9999 -i {cfg.ifname} -q {combined_chans - 1}"
tx_cmd = f"{cfg.bin_local} -c -h {cfg.remote_v6} -p 9999 -l 12840"
tx_cmd = f"{cfg.bin_local} -c -h {cfg.remote_addr_v['6']} -p 9999 -l 12840"
with bkg(rx_cmd, host=cfg.remote, exit_wait=True):
wait_port_listen(9999, proto="tcp", host=cfg.remote)
cmd(tx_cmd)
@ -51,7 +51,7 @@ def test_zcrx(cfg) -> None:
def test_zcrx_oneshot(cfg) -> None:
cfg.require_v6()
cfg.require_ipver('6')
combined_chans = _get_combined_channels(cfg)
if combined_chans < 2:
@ -64,7 +64,7 @@ def test_zcrx_oneshot(cfg) -> None:
flow_rule_id = _set_flow_rule(cfg, combined_chans - 1)
rx_cmd = f"{cfg.bin_remote} -s -p 9999 -i {cfg.ifname} -q {combined_chans - 1} -o 4"
tx_cmd = f"{cfg.bin_local} -c -h {cfg.remote_v6} -p 9999 -l 4096 -z 16384"
tx_cmd = f"{cfg.bin_local} -c -h {cfg.remote_addr_v['6']} -p 9999 -l 4096 -z 16384"
with bkg(rx_cmd, host=cfg.remote, exit_wait=True):
wait_port_listen(9999, proto="tcp", host=cfg.remote)
cmd(tx_cmd)

View File

@ -194,15 +194,21 @@ test_remote_ip()
send_mcast_torture4()
{
ip netns exec "${SOURCE}" bash -c \
'cat /dev/urandom | head -c 1G | nc -w 1 -u 239.0.0.1 4001'
for i in `seq 10`; do
ip netns exec "${SOURCE}" bash -c \
'cat /dev/urandom | head -c 100M | nc -w 1 -u 239.0.0.1 4001'
echo -n "."
done
}
send_mcast_torture6()
{
ip netns exec "${SOURCE}" bash -c \
'cat /dev/urandom | head -c 1G | nc -w 1 -u ff0e::5:6 6001'
for i in `seq 10`; do
ip netns exec "${SOURCE}" bash -c \
'cat /dev/urandom | head -c 100M | nc -w 1 -u ff0e::5:6 6001'
echo -n "."
done
}
check_features()
@ -278,10 +284,12 @@ wait $pid || err=$?
if [ $err -eq 1 ]; then
ERR=1
fi
printf "TEST: %-50s" "IPv4 amt traffic forwarding torture"
send_mcast_torture4
printf "TEST: %-60s [ OK ]\n" "IPv4 amt traffic forwarding torture"
printf " [ OK ]\n"
printf "TEST: %-50s" "IPv6 amt traffic forwarding torture"
send_mcast_torture6
printf "TEST: %-60s [ OK ]\n" "IPv6 amt traffic forwarding torture"
printf " [ OK ]\n"
sleep 5
if [ "${ERR}" -eq 1 ]; then
echo "Some tests failed." >&2

View File

@ -222,6 +222,31 @@ setup_ns()
NS_LIST+=("${ns_list[@]}")
}
# Create netdevsim with given id and net namespace.
create_netdevsim() {
local id="$1"
local ns="$2"
modprobe netdevsim &> /dev/null
udevadm settle
echo "$id 1" | ip netns exec $ns tee /sys/bus/netdevsim/new_device >/dev/null
local dev=$(ip netns exec $ns ls /sys/bus/netdevsim/devices/netdevsim$id/net)
ip -netns $ns link set dev $dev name nsim$id
ip -netns $ns link set dev nsim$id up
echo nsim$id
}
# Remove netdevsim with given id.
cleanup_netdevsim() {
local id="$1"
if [ -d "/sys/bus/netdevsim/devices/netdevsim$id/net" ]; then
echo "$id" > /sys/bus/netdevsim/del_device
fi
}
tc_rule_stats_get()
{
local dev=$1; shift

View File

@ -7,10 +7,12 @@ set -o pipefail
DEV=dummy-dev0
DEV2=dummy-dev1
ALT_NAME=some-alt-name
NSIM_ADDR=2025
RET_CODE=0
cleanup() {
cleanup_netdevsim $NSIM_ADDR
cleanup_ns $NS $test_ns
}
@ -25,12 +27,15 @@ setup_ns NS test_ns
#
# Test basic move without a rename
# Use netdevsim because it has extra asserts for notifiers.
#
ip -netns $NS link add name $DEV type dummy || fail
ip -netns $NS link set dev $DEV netns $test_ns ||
nsim=$(create_netdevsim $NSIM_ADDR $NS)
ip -netns $NS link set dev $nsim netns $test_ns ||
fail "Can't perform a netns move"
ip -netns $test_ns link show dev $DEV >> /dev/null || fail "Device not found after move"
ip -netns $test_ns link del $DEV || fail
ip -netns $test_ns link show dev $nsim >> /dev/null ||
fail "Device not found after move"
cleanup_netdevsim $NSIM_ADDR
#
# Test move with a conflict

View File

@ -12,10 +12,10 @@ def dump_mcaddr_check(rtnl: RtnlAddrFamily) -> None:
At least the loopback interface should have this address.
"""
addresses = rtnl.getmaddrs({"ifa-family": socket.AF_INET}, dump=True)
addresses = rtnl.getmulticast({"ifa-family": socket.AF_INET}, dump=True)
all_host_multicasts = [
addr for addr in addresses if addr['ifa-multicast'] == IPV4_ALL_HOSTS_MULTICAST
addr for addr in addresses if addr['multicast'] == IPV4_ALL_HOSTS_MULTICAST
]
ksft_ge(len(all_host_multicasts), 1,

View File

@ -16,6 +16,9 @@ static void __setup_lo_intf(const char *lo_intf,
if (link_set_up(lo_intf))
test_error("Failed to bring %s up", lo_intf);
if (ip_route_add(lo_intf, TEST_FAMILY, local_addr, local_addr))
test_error("Failed to add a local route %s", lo_intf);
}
static void setup_lo_intf(const char *lo_intf)

View File

@ -305,7 +305,7 @@
"cmdUnderTest": "$TC actions add action nat ingress default 10.10.10.1 index 12",
"expExitCode": "0",
"verifyCmd": "$TC actions get action nat index 12",
"matchPattern": "action order [0-9]+: nat ingress 0.0.0.0/32 10.10.10.1 pass.*index 12 ref",
"matchPattern": "action order [0-9]+: nat ingress 0.0.0.0/0 10.10.10.1 pass.*index 12 ref",
"matchCount": "1",
"teardown": [
"$TC actions flush action nat"
@ -332,7 +332,7 @@
"cmdUnderTest": "$TC actions add action nat ingress any 10.10.10.1 index 12",
"expExitCode": "0",
"verifyCmd": "$TC actions get action nat index 12",
"matchPattern": "action order [0-9]+: nat ingress 0.0.0.0/32 10.10.10.1 pass.*index 12 ref",
"matchPattern": "action order [0-9]+: nat ingress 0.0.0.0/0 10.10.10.1 pass.*index 12 ref",
"matchCount": "1",
"teardown": [
"$TC actions flush action nat"
@ -359,7 +359,7 @@
"cmdUnderTest": "$TC actions add action nat ingress all 10.10.10.1 index 12",
"expExitCode": "0",
"verifyCmd": "$TC actions get action nat index 12",
"matchPattern": "action order [0-9]+: nat ingress 0.0.0.0/32 10.10.10.1 pass.*index 12 ref",
"matchPattern": "action order [0-9]+: nat ingress 0.0.0.0/0 10.10.10.1 pass.*index 12 ref",
"matchCount": "1",
"teardown": [
"$TC actions flush action nat"
@ -548,7 +548,7 @@
"cmdUnderTest": "$TC actions add action nat egress default 20.20.20.1 pipe index 10",
"expExitCode": "0",
"verifyCmd": "$TC actions get action nat index 10",
"matchPattern": "action order [0-9]+: nat egress 0.0.0.0/32 20.20.20.1 pipe.*index 10 ref",
"matchPattern": "action order [0-9]+: nat egress 0.0.0.0/0 20.20.20.1 pipe.*index 10 ref",
"matchCount": "1",
"teardown": [
"$TC actions flush action nat"
@ -575,7 +575,7 @@
"cmdUnderTest": "$TC actions add action nat egress any 20.20.20.1 pipe index 10",
"expExitCode": "0",
"verifyCmd": "$TC actions get action nat index 10",
"matchPattern": "action order [0-9]+: nat egress 0.0.0.0/32 20.20.20.1 pipe.*index 10 ref",
"matchPattern": "action order [0-9]+: nat egress 0.0.0.0/0 20.20.20.1 pipe.*index 10 ref",
"matchCount": "1",
"teardown": [
"$TC actions flush action nat"
@ -602,7 +602,7 @@
"cmdUnderTest": "$TC actions add action nat egress all 20.20.20.1 pipe index 10",
"expExitCode": "0",
"verifyCmd": "$TC actions get action nat index 10",
"matchPattern": "action order [0-9]+: nat egress 0.0.0.0/32 20.20.20.1 pipe.*index 10 ref",
"matchPattern": "action order [0-9]+: nat egress 0.0.0.0/0 20.20.20.1 pipe.*index 10 ref",
"matchCount": "1",
"teardown": [
"$TC actions flush action nat"
@ -629,7 +629,7 @@
"cmdUnderTest": "$TC actions add action nat egress all 20.20.20.1 pipe index 10 cookie aa1bc2d3eeff112233445566778800a1",
"expExitCode": "0",
"verifyCmd": "$TC actions get action nat index 10",
"matchPattern": "action order [0-9]+: nat egress 0.0.0.0/32 20.20.20.1 pipe.*index 10 ref.*cookie aa1bc2d3eeff112233445566778800a1",
"matchPattern": "action order [0-9]+: nat egress 0.0.0.0/0 20.20.20.1 pipe.*index 10 ref.*cookie aa1bc2d3eeff112233445566778800a1",
"matchCount": "1",
"teardown": [
"$TC actions flush action nat"

View File

@ -126,5 +126,37 @@
"$TC qdisc del dev $DUMMY root handle 1: drr",
"$IP addr del 10.10.10.10/24 dev $DUMMY"
]
}
},
{
"id": "c024",
"name": "Test TBF with SKBPRIO - catch qlen corner cases",
"category": [
"qdisc",
"tbf",
"skbprio"
],
"plugins": {
"requires": "nsPlugin"
},
"setup": [
"$IP link set dev $DUMMY up || true",
"$IP addr add 10.10.10.10/24 dev $DUMMY || true",
"$TC qdisc add dev $DUMMY handle 1: root tbf rate 100bit burst 2000 limit 1000",
"$TC qdisc add dev $DUMMY parent 1: handle 10: skbprio limit 1",
"ping -c 1 -W 0.1 -Q 0x00 -s 1400 -I $DUMMY 10.10.10.1 > /dev/null || true",
"ping -c 1 -W 0.1 -Q 0x1c -s 1400 -I $DUMMY 10.10.10.1 > /dev/null || true",
"ping -c 1 -W 0.1 -Q 0x00 -s 1400 -I $DUMMY 10.10.10.1 > /dev/null || true",
"ping -c 1 -W 0.1 -Q 0x1c -s 1400 -I $DUMMY 10.10.10.1 > /dev/null || true",
"sleep 0.5"
],
"cmdUnderTest": "$TC -s qdisc show dev $DUMMY",
"expExitCode": "0",
"verifyCmd": "$TC -s qdisc show dev $DUMMY | grep -A 5 'qdisc skbprio'",
"matchPattern": "dropped [1-9][0-9]*",
"matchCount": "1",
"teardown": [
"$TC qdisc del dev $DUMMY handle 1: root",
"$IP addr del 10.10.10.10/24 dev $DUMMY || true"
]
}
]