* [RFC net-next 00/13] Get rid of switchdev_ops
From: Florian Fainelli @ 2019-02-01 22:06 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Michael Chan, David S. Miller, Derek Chickles,
Satanand Burla, Felix Manlunas, Saeed Mahameed, Leon Romanovsky,
Jiri Pirko, Ido Schimmel, Alexandre Belloni,
Microchip Linux Driver Support, Jakub Kicinski, Ioana Radulescu,
Ioana Ciornei, Greg Kroah-Hartman, Ivan Vecera, Andrew Lunn,
Vivien Didelot, Dirk van der Merwe, Francois H. Theron,
Simon Horman, Quentin Monnet, Daniel Borkmann, Eric Dumazet,
John Hurley, Edwin Peer, open list,
open list:MELLANOX MLX5 core VPI driver,
open list:NETRONOME ETHERNET DRIVERS, open list:STAGING SUBSYSTEM
Hi all,
This patch series converts SWITCHDEV_PORT_ATTR_{GET,SET} to use a
blocking notifier, similar to how SWITCHDEV_PORT_OBJ_{ADD,DEL} has been
changed recently by Petr.
This was suggested by Ido to help with a particular use case I have
where I want to be able to veto a switchdev bridge attribute from a
driver (multicast_snooping).
Please review since I may not have gotten the driver abstraction right,
especially for mlx5e and nfp since these are *hum* *hum* large drivers.
Florian Fainelli (13):
switchdev: Add SWITCHDEV_PORT_ATTR_SET, SWITCHDEV_PORT_ATTR_GET
rocker: Handle SWITCHDEV_PORT_ATTR_GET/SET
net: dsa: Handle SWITCHDEV_PORT_ATTR_GET/SET
mlxsw: spectrum_switchdev: Handle SWITCHDEV_PORT_ATTR_GET/SET
net: mscc: ocelot: Handle SWITCHDEV_PORT_ATTR_GET/SET
staging: fsl-dpaa2: ethsw: Handle SWITCHDEV_PORT_ATTR_GET/SET
bnxt: Handle SWITCHDEV_PORT_ATTR_GET event
liquidio: Handle SWITCHDEV_PORT_ATTR_GET event
mlxsw: switchx2: Handle SWITCHDEV_PORT_ATTR_GET event
net/mlx5e: Handle SWITCHDEV_PORT_ATTR_GET event
nfp: Handle SWITCHDEV_PORT_ATTR_GET event
netdevsim: Handle SWITCHDEV_PORT_ATTR_GET event
net: switchdev: Replace port attr get/set SDO with a notification
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 63 ++++++++++-
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c | 9 +-
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.h | 8 ++
.../net/ethernet/cavium/liquidio/lio_main.c | 53 ++++++++-
.../net/ethernet/cavium/liquidio/lio_vf_rep.c | 48 +++++++-
.../net/ethernet/mellanox/mlx5/core/en_main.c | 4 +-
.../net/ethernet/mellanox/mlx5/core/en_rep.c | 50 ++++++--
.../net/ethernet/mellanox/mlx5/core/en_rep.h | 2 +-
.../net/ethernet/mellanox/mlxsw/spectrum.c | 12 --
.../net/ethernet/mellanox/mlxsw/spectrum.h | 2 -
.../mellanox/mlxsw/spectrum_switchdev.c | 36 +++---
.../net/ethernet/mellanox/mlxsw/switchx2.c | 46 +++++++-
drivers/net/ethernet/mscc/ocelot.c | 30 ++++-
drivers/net/ethernet/netronome/nfp/nfp_main.c | 14 ++-
drivers/net/ethernet/netronome/nfp/nfp_net.h | 3 +
.../ethernet/netronome/nfp/nfp_net_common.c | 19 +++-
.../net/ethernet/netronome/nfp/nfp_net_repr.c | 2 -
drivers/net/ethernet/netronome/nfp/nfp_port.c | 17 ++-
drivers/net/ethernet/netronome/nfp/nfp_port.h | 5 +-
drivers/net/ethernet/rocker/rocker_main.c | 30 ++++-
drivers/net/netdevsim/netdev.c | 46 +++++++-
drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 30 ++++-
include/linux/netdevice.h | 3 -
include/net/switchdev.h | 28 ++---
net/dsa/slave.c | 30 ++++-
net/switchdev/switchdev.c | 107 ++++++------------
26 files changed, 503 insertions(+), 194 deletions(-)
--
2.17.1
^ permalink raw reply
* [RFC net-next 02/13] rocker: Handle SWITCHDEV_PORT_ATTR_GET/SET
From: Florian Fainelli @ 2019-02-01 22:06 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Michael Chan, David S. Miller, Derek Chickles,
Satanand Burla, Felix Manlunas, Saeed Mahameed, Leon Romanovsky,
Jiri Pirko, Ido Schimmel, Alexandre Belloni,
Microchip Linux Driver Support, Jakub Kicinski, Ioana Radulescu,
Ioana Ciornei, Greg Kroah-Hartman, Ivan Vecera, Andrew Lunn,
Vivien Didelot, Dirk van der Merwe, Francois H. Theron,
Simon Horman, Quentin Monnet, Daniel Borkmann, Eric Dumazet,
John Hurley, Edwin Peer, open list,
open list:MELLANOX MLX5 core VPI driver,
open list:NETRONOME ETHERNET DRIVERS, open list:STAGING SUBSYSTEM
In-Reply-To: <20190201220657.30170-1-f.fainelli@gmail.com>
Following patches will change the way we communicate getting or setting
a port's attribute and use a blocking notifier to perform those tasks.
Prepare rocker to support receiving notifier events targeting
SWITCHDEV_PORT_ATTR_GET/SET and simply translate that into the existing
rocker_port_attr_{set,get} calls.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/rocker/rocker_main.c | 24 +++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index 62a205eba9f7..f25f7b4345b8 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -2827,6 +2827,27 @@ rocker_switchdev_port_obj_event(unsigned long event, struct net_device *netdev,
return notifier_from_errno(err);
}
+static int
+rocker_switchdev_port_attr_event(unsigned long event, struct net_device *netdev,
+ struct switchdev_notifier_port_attr_info
+ *port_attr_info)
+{
+ int err = -EOPNOTSUPP;
+
+ switch (event) {
+ case SWITCHDEV_PORT_ATTR_SET:
+ err = rocker_port_attr_set(netdev, port_attr_info->attr,
+ port_attr_info->trans);
+ break;
+ case SWITCHDEV_PORT_ATTR_GET:
+ err = rocker_port_attr_get(netdev, port_attr_info->attr);
+ break;
+ }
+
+ port_attr_info->handled = true;
+ return notifier_from_errno(err);
+}
+
static int rocker_switchdev_blocking_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
@@ -2839,6 +2860,9 @@ static int rocker_switchdev_blocking_event(struct notifier_block *unused,
case SWITCHDEV_PORT_OBJ_ADD:
case SWITCHDEV_PORT_OBJ_DEL:
return rocker_switchdev_port_obj_event(event, dev, ptr);
+ case SWITCHDEV_PORT_ATTR_SET:
+ case SWITCHDEV_PORT_ATTR_GET:
+ return rocker_switchdev_port_attr_event(event, dev, ptr);
}
return NOTIFY_DONE;
--
2.17.1
^ permalink raw reply related
* [RFC net-next 03/13] net: dsa: Handle SWITCHDEV_PORT_ATTR_GET/SET
From: Florian Fainelli @ 2019-02-01 22:06 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Michael Chan, David S. Miller, Derek Chickles,
Satanand Burla, Felix Manlunas, Saeed Mahameed, Leon Romanovsky,
Jiri Pirko, Ido Schimmel, Alexandre Belloni,
Microchip Linux Driver Support, Jakub Kicinski, Ioana Radulescu,
Ioana Ciornei, Greg Kroah-Hartman, Ivan Vecera, Andrew Lunn,
Vivien Didelot, Dirk van der Merwe, Francois H. Theron,
Simon Horman, Quentin Monnet, Daniel Borkmann, Eric Dumazet,
John Hurley, Edwin Peer, open list,
open list:MELLANOX MLX5 core VPI driver,
open list:NETRONOME ETHERNET DRIVERS, open list:STAGING SUBSYSTEM
In-Reply-To: <20190201220657.30170-1-f.fainelli@gmail.com>
Following patches will change the way we communicate getting or setting
a port's attribute and use a blocking notifier to perform those tasks.
Prepare DSA to support receiving notifier events targeting
SWITCHDEV_PORT_ATTR_GET/SET and simply translate that into the existing
dsa_slave_port_attr_{set,get} calls.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
net/dsa/slave.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 91de3a663226..bc7d5092a1c7 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1549,6 +1549,27 @@ dsa_slave_switchdev_port_obj_event(unsigned long event,
return notifier_from_errno(err);
}
+static int
+dsa_slave_switchdev_port_attr_event(unsigned long event,
+ struct net_device *netdev,
+ struct switchdev_notifier_port_attr_info *port_attr_info)
+{
+ int err = -EOPNOTSUPP;
+
+ switch (event) {
+ case SWITCHDEV_PORT_ATTR_SET:
+ err = dsa_slave_port_attr_set(netdev, port_attr_info->attr,
+ port_attr_info->trans);
+ break;
+ case SWITCHDEV_PORT_ATTR_GET:
+ err = dsa_slave_port_attr_get(netdev, port_attr_info->attr);
+ break;
+ }
+
+ port_attr_info->handled = true;
+ return notifier_from_errno(err);
+}
+
static int dsa_slave_switchdev_blocking_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
@@ -1561,6 +1582,9 @@ static int dsa_slave_switchdev_blocking_event(struct notifier_block *unused,
case SWITCHDEV_PORT_OBJ_ADD: /* fall through */
case SWITCHDEV_PORT_OBJ_DEL:
return dsa_slave_switchdev_port_obj_event(event, dev, ptr);
+ case SWITCHDEV_PORT_ATTR_SET: /* fallthrough */
+ case SWITCHDEV_PORT_ATTR_GET:
+ return dsa_slave_switchdev_port_attr_event(event, dev, ptr);
}
return NOTIFY_DONE;
--
2.17.1
^ permalink raw reply related
* [RFC net-next 04/13] mlxsw: spectrum_switchdev: Handle SWITCHDEV_PORT_ATTR_GET/SET
From: Florian Fainelli @ 2019-02-01 22:06 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Michael Chan, David S. Miller, Derek Chickles,
Satanand Burla, Felix Manlunas, Saeed Mahameed, Leon Romanovsky,
Jiri Pirko, Ido Schimmel, Alexandre Belloni,
Microchip Linux Driver Support, Jakub Kicinski, Ioana Radulescu,
Ioana Ciornei, Greg Kroah-Hartman, Ivan Vecera, Andrew Lunn,
Vivien Didelot, Dirk van der Merwe, Francois H. Theron,
Simon Horman, Quentin Monnet, Daniel Borkmann, Eric Dumazet,
John Hurley, Edwin Peer, open list,
open list:MELLANOX MLX5 core VPI driver,
open list:NETRONOME ETHERNET DRIVERS, open list:STAGING SUBSYSTEM
In-Reply-To: <20190201220657.30170-1-f.fainelli@gmail.com>
Following patches will change the way we communicate getting or setting
a port's attribute and use a blocking notifier to perform those tasks.
Prepare mlxsw to support receiving notifier events targeting
SWITCHDEV_PORT_ATTR_GET/SET and simply translate that into the existing
mlxsw_sp_port_attr_{set,get} calls.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
.../mellanox/mlxsw/spectrum_switchdev.c | 23 +++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 0f4e68d31cc3..7c0df736587c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -3442,6 +3442,26 @@ mlxsw_sp_switchdev_handle_vxlan_obj_del(struct net_device *vxlan_dev,
}
}
+static int
+mlxsw_sp_switchdev_port_attr_event(unsigned long event, struct net_device *dev,
+ struct switchdev_notifier_port_attr_info *port_attr_info)
+{
+ int err = -EOPNOTSUPP;
+
+ switch (event) {
+ case SWITCHDEV_PORT_ATTR_SET:
+ err = mlxsw_sp_port_attr_set(dev, port_attr_info->attr,
+ port_attr_info->trans);
+ break;
+ case SWITCHDEV_PORT_ATTR_GET:
+ err = mlxsw_sp_port_attr_get(dev, port_attr_info->attr);
+ break;
+ }
+
+ port_attr_info->handled = true;
+ return notifier_from_errno(err);
+}
+
static int mlxsw_sp_switchdev_blocking_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
@@ -3465,6 +3485,9 @@ static int mlxsw_sp_switchdev_blocking_event(struct notifier_block *unused,
mlxsw_sp_port_dev_check,
mlxsw_sp_port_obj_del);
return notifier_from_errno(err);
+ case SWITCHDEV_PORT_ATTR_SET:
+ case SWITCHDEV_PORT_ATTR_GET:
+ return mlxsw_sp_switchdev_port_attr_event(event, dev, ptr);
}
return NOTIFY_DONE;
--
2.17.1
^ permalink raw reply related
* [RFC net-next 05/13] net: mscc: ocelot: Handle SWITCHDEV_PORT_ATTR_GET/SET
From: Florian Fainelli @ 2019-02-01 22:06 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Michael Chan, David S. Miller, Derek Chickles,
Satanand Burla, Felix Manlunas, Saeed Mahameed, Leon Romanovsky,
Jiri Pirko, Ido Schimmel, Alexandre Belloni,
Microchip Linux Driver Support, Jakub Kicinski, Ioana Radulescu,
Ioana Ciornei, Greg Kroah-Hartman, Ivan Vecera, Andrew Lunn,
Vivien Didelot, Dirk van der Merwe, Francois H. Theron,
Simon Horman, Quentin Monnet, Daniel Borkmann, Eric Dumazet,
John Hurley, Edwin Peer, open list,
open list:MELLANOX MLX5 core VPI driver,
open list:NETRONOME ETHERNET DRIVERS, open list:STAGING SUBSYSTEM
In-Reply-To: <20190201220657.30170-1-f.fainelli@gmail.com>
Following patches will change the way we communicate getting or setting
a port's attribute and use a blocking notifier to perform those tasks.
Prepare ocelot to support receiving notifier events targeting
SWITCHDEV_PORT_ATTR_GET/SET and simply translate that into the existing
ocelot_port_attr_{set,get} calls.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/mscc/ocelot.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index c6a575eb0ff5..8043347a1ed4 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1589,6 +1589,27 @@ struct notifier_block ocelot_netdevice_nb __read_mostly = {
};
EXPORT_SYMBOL(ocelot_netdevice_nb);
+static int
+ocelot_switchdev_port_attr_event(unsigned long event,
+ struct net_device *netdev,
+ struct switchdev_notifier_port_attr_info *port_attr_info)
+{
+ int err = -EOPNOTSUPP;
+
+ switch (event) {
+ case SWITCHDEV_PORT_ATTR_SET:
+ err = ocelot_port_attr_set(netdev, port_attr_info->attr,
+ port_attr_info->trans);
+ break;
+ case SWITCHDEV_PORT_ATTR_GET:
+ err = ocelot_port_attr_get(netdev, port_attr_info->attr);
+ break;
+ }
+
+ port_attr_info->handled = true;
+ return notifier_from_errno(err);
+}
+
static int ocelot_switchdev_blocking_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
@@ -1607,6 +1628,9 @@ static int ocelot_switchdev_blocking_event(struct notifier_block *unused,
ocelot_netdevice_dev_check,
ocelot_port_obj_del);
return notifier_from_errno(err);
+ case SWITCHDEV_PORT_ATTR_SET:
+ case SWITCHDEV_PORT_ATTR_GET:
+ return ocelot_switchdev_port_attr_event(event, dev, ptr);
}
return NOTIFY_DONE;
--
2.17.1
^ permalink raw reply related
* [RFC net-next 07/13] bnxt: Handle SWITCHDEV_PORT_ATTR_GET event
From: Florian Fainelli @ 2019-02-01 22:06 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Michael Chan, David S. Miller, Derek Chickles,
Satanand Burla, Felix Manlunas, Saeed Mahameed, Leon Romanovsky,
Jiri Pirko, Ido Schimmel, Alexandre Belloni,
Microchip Linux Driver Support, Jakub Kicinski, Ioana Radulescu,
Ioana Ciornei, Greg Kroah-Hartman, Ivan Vecera, Andrew Lunn,
Vivien Didelot, Dirk van der Merwe, Francois H. Theron,
Simon Horman, Quentin Monnet, Daniel Borkmann, Eric Dumazet,
John Hurley, Edwin Peer, open list,
open list:MELLANOX MLX5 core VPI driver,
open list:NETRONOME ETHERNET DRIVERS, open list:STAGING SUBSYSTEM
In-Reply-To: <20190201220657.30170-1-f.fainelli@gmail.com>
Following patches will change the way we communicate getting or setting
a port's attribute and use a blocking notifier to perform those tasks.
Prepare bnxt to support receiving notifier events targeting
SWITCHDEV_PORT_ATTR_GET and simply translate that into the existing
switchdev_ops::switchdev_port_attr_get operation.
We register a single blocking switchdev notifier for the entire driver
instance and we differentiate a PF from a VF by comparing the network
device's netdev_ops with the ones that this driver manages.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 58 ++++++++++++++++++-
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c | 4 +-
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.h | 8 +++
3 files changed, 67 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 6a512871176b..c3178ca4a004 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -10045,6 +10045,45 @@ static const struct net_device_ops bnxt_netdev_ops = {
.ndo_get_phys_port_name = bnxt_get_phys_port_name
};
+static int bnxt_swdev_port_attr_event(unsigned long event,
+ struct net_device *dev,
+ struct switchdev_notifier_port_attr_info *port_attr_info)
+{
+ int rc;
+
+ if (event != SWITCHDEV_PORT_ATTR_GET)
+ return NOTIFY_DONE;
+
+ if (bnxt_dev_is_vf_rep(dev))
+ rc = bnxt_vf_rep_port_attr_get(dev, port_attr_info->attr);
+ else
+ rc = bnxt_port_attr_get(netdev_priv(dev), port_attr_info->attr);
+
+ port_attr_info->handled = true;
+ return notifier_from_errno(rc);
+}
+
+static int bnxt_switchdev_blocking_event(struct notifier_block *nb,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+
+ if (dev->netdev_ops != &bnxt_netdev_ops &&
+ !bnxt_dev_is_vf_rep(dev))
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case SWITCHDEV_PORT_ATTR_GET:
+ return bnxt_swdev_port_attr_event(event, dev, ptr);
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block bnxt_swdev_blocking_nb = {
+ .notifier_call = bnxt_switchdev_blocking_event,
+};
+
static void bnxt_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
@@ -10817,8 +10856,24 @@ static struct pci_driver bnxt_pci_driver = {
static int __init bnxt_init(void)
{
+ int rc;
+
bnxt_debug_init();
- return pci_register_driver(&bnxt_pci_driver);
+ rc = register_switchdev_blocking_notifier(&bnxt_swdev_blocking_nb);
+ if (rc)
+ goto err_debug;
+
+ rc = pci_register_driver(&bnxt_pci_driver);
+ if (rc)
+ goto err_unreg_notifier;
+
+ return rc;
+
+err_unreg_notifier:
+ unregister_switchdev_notifier(&bnxt_swdev_blocking_nb);
+err_debug:
+ bnxt_debug_exit();
+ return rc;
}
static void __exit bnxt_exit(void)
@@ -10826,6 +10881,7 @@ static void __exit bnxt_exit(void)
pci_unregister_driver(&bnxt_pci_driver);
if (bnxt_pf_wq)
destroy_workqueue(bnxt_pf_wq);
+ unregister_switchdev_notifier(&bnxt_swdev_blocking_nb);
bnxt_debug_exit();
}
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
index 9a25c05aa571..a06f93b49dd5 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
@@ -237,8 +237,8 @@ static void bnxt_vf_rep_get_drvinfo(struct net_device *dev,
strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
}
-static int bnxt_vf_rep_port_attr_get(struct net_device *dev,
- struct switchdev_attr *attr)
+int bnxt_vf_rep_port_attr_get(struct net_device *dev,
+ struct switchdev_attr *attr)
{
struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.h
index d7287651422f..ba24ac222182 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.h
@@ -32,6 +32,8 @@ bool bnxt_dev_is_vf_rep(struct net_device *dev);
int bnxt_dl_eswitch_mode_get(struct devlink *devlink, u16 *mode);
int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode,
struct netlink_ext_ack *extack);
+int bnxt_vf_rep_port_attr_get(struct net_device *dev,
+ struct switchdev_attr *attr);
#else
@@ -61,5 +63,11 @@ static inline bool bnxt_dev_is_vf_rep(struct net_device *dev)
{
return false;
}
+
+static inline int bnxt_vf_rep_port_attr_get(struct net_device *dev,
+ struct switchdev_attr *attr)
+{
+ return -EOPNOTSUPP;
+}
#endif /* CONFIG_BNXT_SRIOV */
#endif /* BNXT_VFR_H */
--
2.17.1
^ permalink raw reply related
* [RFC net-next 08/13] liquidio: Handle SWITCHDEV_PORT_ATTR_GET event
From: Florian Fainelli @ 2019-02-01 22:06 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Michael Chan, David S. Miller, Derek Chickles,
Satanand Burla, Felix Manlunas, Saeed Mahameed, Leon Romanovsky,
Jiri Pirko, Ido Schimmel, Alexandre Belloni,
Microchip Linux Driver Support, Jakub Kicinski, Ioana Radulescu,
Ioana Ciornei, Greg Kroah-Hartman, Ivan Vecera, Andrew Lunn,
Vivien Didelot, Dirk van der Merwe, Francois H. Theron,
Simon Horman, Quentin Monnet, Daniel Borkmann, Eric Dumazet,
John Hurley, Edwin Peer, open list,
open list:MELLANOX MLX5 core VPI driver,
open list:NETRONOME ETHERNET DRIVERS, open list:STAGING SUBSYSTEM
In-Reply-To: <20190201220657.30170-1-f.fainelli@gmail.com>
Following patches will change the way we communicate getting or setting
a port's attribute and use a blocking notifier to perform those tasks.
Prepare bnxt to support receiving notifier events targeting
SWITCHDEV_PORT_ATTR_GET and simply translate that into the existing
switchdev_ops::switchdev_port_attr_get operation.
We register a single blocking switchdev notifier for the PF part of the
driver, and we register another blocking switchdev notifier, following
what was done with the existing netdevice notifier within the VF
representor driver.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
.../net/ethernet/cavium/liquidio/lio_main.c | 48 ++++++++++++++++++-
.../net/ethernet/cavium/liquidio/lio_vf_rep.c | 45 ++++++++++++++++-
2 files changed, 91 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index 3d24133e5e49..b9d48e4181fc 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -162,6 +162,8 @@ static int liquidio_set_vf_link_state(struct net_device *netdev, int vfidx,
static struct handshake handshake[MAX_OCTEON_DEVICES];
static struct completion first_stage;
+static int liquidio_switchdev_blocking_event(struct notifier_block *nb,
+ unsigned long event, void *ptr);
static void octeon_droq_bh(unsigned long pdev)
{
@@ -469,12 +471,25 @@ static struct pci_driver liquidio_pci_driver = {
#endif
};
+static struct notifier_block liquidio_blocking_nb = {
+ .notifier_call = liquidio_switchdev_blocking_event,
+};
+
/**
* \brief register PCI driver
*/
static int liquidio_init_pci(void)
{
- return pci_register_driver(&liquidio_pci_driver);
+ int rc;
+
+ rc = register_switchdev_blocking_notifier(&liquidio_blocking_nb);
+ if (rc)
+ return rc;
+ rc = pci_register_driver(&liquidio_pci_driver);
+ if (rc)
+ unregister_switchdev_blocking_notifier(&liquidio_blocking_nb);
+
+ return rc;
}
/**
@@ -483,6 +498,7 @@ static int liquidio_init_pci(void)
static void liquidio_deinit_pci(void)
{
pci_unregister_driver(&liquidio_pci_driver);
+ unregister_switchdev_blocking_notifier(&liquidio_blocking_nb);
}
/**
@@ -3261,6 +3277,36 @@ static const struct net_device_ops lionetdevops = {
.ndo_get_vf_stats = liquidio_get_vf_stats,
};
+static int lio_pf_attr_event(unsigned long event, struct net_device *dev,
+ struct switchdev_notifier_port_attr_info *port_attr_info)
+{
+ int rc;
+
+ if (event != SWITCHDEV_PORT_ATTR_GET)
+ return NOTIFY_DONE;
+
+ rc = lio_pf_switchdev_attr_get(dev, port_attr_info->attr);
+
+ port_attr_info->handled = true;
+ return notifier_from_errno(rc);
+}
+
+static int liquidio_switchdev_blocking_event(struct notifier_block *nb,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+
+ if (dev->netdev_ops != &lionetdevops)
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case SWITCHDEV_PORT_ATTR_GET:
+ return lio_pf_attr_event(event, dev, ptr);
+ }
+
+ return NOTIFY_DONE;
+}
+
/** \brief Entry point for the liquidio module
*/
static int __init liquidio_init(void)
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c
index de61060721c4..d396c004c1be 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c
@@ -468,6 +468,21 @@ static const struct switchdev_ops lio_vf_rep_switchdev_ops = {
.switchdev_port_attr_get = lio_vf_rep_attr_get,
};
+static int lio_vf_rep_swdev_port_attr_event(unsigned long event,
+ struct net_device *dev,
+ struct switchdev_notifier_port_attr_info *port_attr_info)
+{
+ int rc;
+
+ if (event != SWITCHDEV_PORT_ATTR_GET)
+ return NOTIFY_DONE;
+
+ rc = lio_vf_rep_attr_get(dev, port_attr_info->attr);
+ port_attr_info->handled = true;
+
+ return notifier_from_errno(rc);
+}
+
static void
lio_vf_rep_fetch_stats(struct work_struct *work)
{
@@ -538,7 +553,6 @@ lio_vf_rep_create(struct octeon_device *oct)
if (register_netdev(ndev)) {
dev_err(&oct->pci_dev->dev, "VF rep nerdev registration failed\n");
-
free_netdev(ndev);
goto cleanup;
}
@@ -664,20 +678,49 @@ static struct notifier_block lio_vf_rep_netdev_notifier = {
.notifier_call = lio_vf_rep_netdev_event,
};
+static int lio_vf_rep_swdev_event(struct notifier_block *nb,
+ unsigned long event, void *ptr)
+{
+ struct net_device *ndev = switchdev_notifier_info_to_dev(ptr);
+
+ if (ndev->netdev_ops != &lio_vf_rep_ndev_ops)
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case SWITCHDEV_PORT_ATTR_GET:
+ return lio_vf_rep_swdev_port_attr_event(event, ndev, ptr);
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block lio_vf_rep_swdev_nb = {
+ .notifier_call = lio_vf_rep_swdev_event,
+};
+
int
lio_vf_rep_modinit(void)
{
+ int rc;
+
if (register_netdevice_notifier(&lio_vf_rep_netdev_notifier)) {
pr_err("netdev notifier registration failed\n");
return -EFAULT;
}
+ rc = register_switchdev_blocking_notifier(&lio_vf_rep_swdev_nb);
+ if (rc) {
+ unregister_netdevice_notifier(&lio_vf_rep_netdev_notifier);
+ return rc;
+ }
+
return 0;
}
void
lio_vf_rep_modexit(void)
{
+ unregister_switchdev_blocking_notifier(&lio_vf_rep_swdev_nb);
if (unregister_netdevice_notifier(&lio_vf_rep_netdev_notifier))
pr_err("netdev notifier unregister failed\n");
}
--
2.17.1
^ permalink raw reply related
* [RFC net-next 09/13] mlxsw: switchx2: Handle SWITCHDEV_PORT_ATTR_GET event
From: Florian Fainelli @ 2019-02-01 22:06 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Michael Chan, David S. Miller, Derek Chickles,
Satanand Burla, Felix Manlunas, Saeed Mahameed, Leon Romanovsky,
Jiri Pirko, Ido Schimmel, Alexandre Belloni,
Microchip Linux Driver Support, Jakub Kicinski, Ioana Radulescu,
Ioana Ciornei, Greg Kroah-Hartman, Ivan Vecera, Andrew Lunn,
Vivien Didelot, Dirk van der Merwe, Francois H. Theron,
Simon Horman, Quentin Monnet, Daniel Borkmann, Eric Dumazet,
John Hurley, Edwin Peer, open list,
open list:MELLANOX MLX5 core VPI driver,
open list:NETRONOME ETHERNET DRIVERS, open list:STAGING SUBSYSTEM
In-Reply-To: <20190201220657.30170-1-f.fainelli@gmail.com>
Following patches will change the way we communicate getting or setting
a port's attribute and use a blocking notifier to perform those tasks.
Prepare bnxt to support receiving notifier events targeting
SWITCHDEV_PORT_ATTR_GET and simply translate that into the existing
switchdev_ops::switchdev_port_attr_get operation.
We register a single blocking switchdev notifier for the entire driver
instance and check that thet network device maps to the one that
switchx2 manages.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
.../net/ethernet/mellanox/mlxsw/switchx2.c | 43 ++++++++++++++++++-
1 file changed, 42 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
index 2d4f213e154d..82fb8f1bb6e9 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
@@ -923,6 +923,36 @@ static const struct switchdev_ops mlxsw_sx_port_switchdev_ops = {
.switchdev_port_attr_get = mlxsw_sx_port_attr_get,
};
+static int mlxsw_sx_port_attr_event(unsigned long event,
+ struct net_device *dev,
+ struct switchdev_notifier_port_attr_info *port_attr_info)
+{
+ int rc;
+
+ if (event != SWITCHDEV_PORT_ATTR_GET)
+ return NOTIFY_DONE;
+
+ rc = mlxsw_sx_port_attr_get(dev, port_attr_info->attr);
+ port_attr_info->handled = true;
+ return notifier_from_errno(rc);
+}
+
+static int mlxsw_sx_swdev_blocking_event(struct notifier_block *nb,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+
+ if (dev->netdev_ops != &mlxsw_sx_port_netdev_ops)
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case SWITCHDEV_PORT_ATTR_GET:
+ return mlxsw_sx_port_attr_event(event, dev, ptr);
+ }
+
+ return NOTIFY_DONE;
+}
+
static int mlxsw_sx_hw_id_get(struct mlxsw_sx *mlxsw_sx)
{
char spad_pl[MLXSW_REG_SPAD_LEN] = {0};
@@ -1638,6 +1668,10 @@ static void mlxsw_sx_fini(struct mlxsw_core *mlxsw_core)
mlxsw_sx_ports_remove(mlxsw_sx);
}
+static struct notifier_block mlxsw_sx_swdev_nb = {
+ .notifier_call = mlxsw_sx_swdev_blocking_event,
+};
+
static const struct mlxsw_config_profile mlxsw_sx_config_profile = {
.used_max_vepa_channels = 1,
.max_vepa_channels = 0,
@@ -1698,10 +1732,14 @@ static int __init mlxsw_sx_module_init(void)
{
int err;
- err = mlxsw_core_driver_register(&mlxsw_sx_driver);
+ err = register_switchdev_blocking_notifier(&mlxsw_sx_swdev_nb);
if (err)
return err;
+ err = mlxsw_core_driver_register(&mlxsw_sx_driver);
+ if (err)
+ goto err_unregister_notifier;
+
err = mlxsw_pci_driver_register(&mlxsw_sx_pci_driver);
if (err)
goto err_pci_driver_register;
@@ -1710,6 +1748,8 @@ static int __init mlxsw_sx_module_init(void)
err_pci_driver_register:
mlxsw_core_driver_unregister(&mlxsw_sx_driver);
+err_unregister_notifier:
+ unregister_switchdev_blocking_notifier(&mlxsw_sx_swdev_nb);
return err;
}
@@ -1717,6 +1757,7 @@ static void __exit mlxsw_sx_module_exit(void)
{
mlxsw_pci_driver_unregister(&mlxsw_sx_pci_driver);
mlxsw_core_driver_unregister(&mlxsw_sx_driver);
+ unregister_switchdev_blocking_notifier(&mlxsw_sx_swdev_nb);
}
module_init(mlxsw_sx_module_init);
--
2.17.1
^ permalink raw reply related
* [RFC net-next 10/13] net/mlx5e: Handle SWITCHDEV_PORT_ATTR_GET event
From: Florian Fainelli @ 2019-02-01 22:06 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Michael Chan, David S. Miller, Derek Chickles,
Satanand Burla, Felix Manlunas, Saeed Mahameed, Leon Romanovsky,
Jiri Pirko, Ido Schimmel, Alexandre Belloni,
Microchip Linux Driver Support, Jakub Kicinski, Ioana Radulescu,
Ioana Ciornei, Greg Kroah-Hartman, Ivan Vecera, Andrew Lunn,
Vivien Didelot, Dirk van der Merwe, Francois H. Theron,
Simon Horman, Quentin Monnet, Daniel Borkmann, Eric Dumazet,
John Hurley, Edwin Peer, open list,
open list:MELLANOX MLX5 core VPI driver,
open list:NETRONOME ETHERNET DRIVERS, open list:STAGING SUBSYSTEM
In-Reply-To: <20190201220657.30170-1-f.fainelli@gmail.com>
Following patches will change the way we communicate getting or setting
a port's attribute and use a blocking notifier to perform those tasks.
Prepare mlx5e/en_rep.c to support receiving notifier events targeting
SWITCHDEV_PORT_ATTR_GET and simply translate that into the existing
switchdev_ops::switchdev_port_attr_get operation.
We register a single blocking switchdev notifier for the entire set of
representors given that mlx5e_rep_register_vport_reps() gets called for
an Ethernet device.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
.../net/ethernet/mellanox/mlx5/core/en_main.c | 4 +-
.../net/ethernet/mellanox/mlx5/core/en_rep.c | 45 ++++++++++++++++++-
.../net/ethernet/mellanox/mlx5/core/en_rep.h | 2 +-
3 files changed, 48 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index dee0c8f3d4e9..fcfe1c9d3575 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -5036,7 +5036,9 @@ static void *mlx5e_add(struct mlx5_core_dev *mdev)
#ifdef CONFIG_MLX5_ESWITCH
if (MLX5_ESWITCH_MANAGER(mdev) &&
mlx5_eswitch_mode(mdev->priv.eswitch) == SRIOV_OFFLOADS) {
- mlx5e_rep_register_vport_reps(mdev);
+ err = mlx5e_rep_register_vport_reps(mdev);
+ if (err)
+ return NULL;
return mdev;
}
#endif
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 04736212a21c..9bac78e111c6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -1289,6 +1289,21 @@ static const struct switchdev_ops mlx5e_rep_switchdev_ops = {
.switchdev_port_attr_get = mlx5e_attr_get,
};
+static int mlx5e_rep_swdev_port_attr_event(unsigned long event,
+ struct net_device *dev,
+ struct switchdev_notifier_port_attr_info *port_attr_info)
+{
+ int rc;
+
+ if (event != SWITCHDEV_PORT_ATTR_GET)
+ return NOTIFY_DONE;
+
+ rc = mlx5e_attr_get(dev, port_attr_info->attr);
+ port_attr_info->handled = true;
+
+ return notifier_from_errno(rc);
+}
+
static const struct net_device_ops mlx5e_netdev_ops_vf_rep = {
.ndo_open = mlx5e_vf_rep_open,
.ndo_stop = mlx5e_vf_rep_close,
@@ -1321,6 +1336,22 @@ static const struct net_device_ops mlx5e_netdev_ops_uplink_rep = {
.ndo_get_vf_stats = mlx5e_get_vf_stats,
};
+static int mlx5e_rep_swdev_blocking_event(struct notifier_block *nb,
+ unsigned long event, void *ptr)
+{
+ struct net_device *netdev = switchdev_notifier_info_to_dev(ptr);
+
+ if (netdev->netdev_ops != &mlx5e_netdev_ops_vf_rep)
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case SWITCHDEV_PORT_ATTR_GET:
+ return mlx5e_rep_swdev_port_attr_event(event, netdev, ptr);
+ }
+
+ return NOTIFY_DONE;
+}
+
bool mlx5e_eswitch_rep(struct net_device *netdev)
{
if (netdev->netdev_ops == &mlx5e_netdev_ops_vf_rep ||
@@ -1798,11 +1829,20 @@ static void *mlx5e_vport_rep_get_proto_dev(struct mlx5_eswitch_rep *rep)
return rpriv->netdev;
}
-void mlx5e_rep_register_vport_reps(struct mlx5_core_dev *mdev)
+static struct notifier_block mlx5e_rep_swdev_nb = {
+ .notifier_call = mlx5e_rep_swdev_blocking_event,
+};
+
+int mlx5e_rep_register_vport_reps(struct mlx5_core_dev *mdev)
{
struct mlx5_eswitch *esw = mdev->priv.eswitch;
int total_vfs = MLX5_TOTAL_VPORTS(mdev);
int vport;
+ int rc;
+
+ rc = register_switchdev_blocking_notifier(&mlx5e_rep_swdev_nb);
+ if (rc)
+ return rc;
for (vport = 0; vport < total_vfs; vport++) {
struct mlx5_eswitch_rep_if rep_if = {};
@@ -1812,6 +1852,8 @@ void mlx5e_rep_register_vport_reps(struct mlx5_core_dev *mdev)
rep_if.get_proto_dev = mlx5e_vport_rep_get_proto_dev;
mlx5_eswitch_register_vport_rep(esw, vport, &rep_if, REP_ETH);
}
+
+ return rc;
}
void mlx5e_rep_unregister_vport_reps(struct mlx5_core_dev *mdev)
@@ -1822,4 +1864,5 @@ void mlx5e_rep_unregister_vport_reps(struct mlx5_core_dev *mdev)
for (vport = total_vfs - 1; vport >= 0; vport--)
mlx5_eswitch_unregister_vport_rep(esw, vport, REP_ETH);
+ unregister_switchdev_blocking_notifier(&mlx5e_rep_swdev_nb);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
index edd722824697..b9e0507f6100 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
@@ -162,7 +162,7 @@ struct mlx5e_rep_sq {
};
void *mlx5e_alloc_nic_rep_priv(struct mlx5_core_dev *mdev);
-void mlx5e_rep_register_vport_reps(struct mlx5_core_dev *mdev);
+int mlx5e_rep_register_vport_reps(struct mlx5_core_dev *mdev);
void mlx5e_rep_unregister_vport_reps(struct mlx5_core_dev *mdev);
bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv);
int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv);
--
2.17.1
^ permalink raw reply related
* [RFC net-next 12/13] netdevsim: Handle SWITCHDEV_PORT_ATTR_GET event
From: Florian Fainelli @ 2019-02-01 22:06 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Michael Chan, David S. Miller, Derek Chickles,
Satanand Burla, Felix Manlunas, Saeed Mahameed, Leon Romanovsky,
Jiri Pirko, Ido Schimmel, Alexandre Belloni,
Microchip Linux Driver Support, Jakub Kicinski, Ioana Radulescu,
Ioana Ciornei, Greg Kroah-Hartman, Ivan Vecera, Andrew Lunn,
Vivien Didelot, Dirk van der Merwe, Francois H. Theron,
Simon Horman, Quentin Monnet, Daniel Borkmann, Eric Dumazet,
John Hurley, Edwin Peer, open list,
open list:MELLANOX MLX5 core VPI driver,
open list:NETRONOME ETHERNET DRIVERS, open list:STAGING SUBSYSTEM
In-Reply-To: <20190201220657.30170-1-f.fainelli@gmail.com>
Following patches will change the way we communicate getting or setting
a port's attribute and use a blocking notifier to perform those tasks.
Prepare netdevsim to support receiving notifier events targeting
SWITCHDEV_PORT_ATTR_GET and simply translate that into the existing
switchdev_ops::switchdev_port_attr_get operation.
We register a single blocking switchdev notifier for the entire driver
instance.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/netdevsim/netdev.c | 43 +++++++++++++++++++++++++++++++++-
1 file changed, 42 insertions(+), 1 deletion(-)
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 8d8e2b3f263e..817d94cec90f 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -168,6 +168,20 @@ static const struct switchdev_ops nsim_switchdev_ops = {
.switchdev_port_attr_get = nsim_port_attr_get,
};
+static int nsim_switchdev_port_attr_event(unsigned long event,
+ struct net_device *dev,
+ struct switchdev_notifier_port_attr_info *port_attr_info)
+{
+ int rc;
+
+ if (event != SWITCHDEV_PORT_ATTR_GET)
+ return NOTIFY_DONE;
+
+ rc = nsim_port_attr_get(dev, port_attr_info->attr);
+ port_attr_info->handled = true;
+ return notifier_from_errno(rc);
+}
+
static int nsim_init(struct net_device *dev)
{
char sdev_ddir_name[10], sdev_link_name[32];
@@ -495,6 +509,26 @@ static const struct net_device_ops nsim_netdev_ops = {
.ndo_bpf = nsim_bpf,
};
+static int nsim_swdev_blocking_event(struct notifier_block *nb,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+
+ if (dev->netdev_ops != &nsim_netdev_ops)
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case SWITCHDEV_PORT_ATTR_GET:
+ return nsim_switchdev_port_attr_event(event, dev, ptr);
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block nsim_swdev_blocking_nb = {
+ .notifier_call = nsim_swdev_blocking_event,
+};
+
static void nsim_setup(struct net_device *dev)
{
ether_setup(dev);
@@ -583,10 +617,14 @@ static int __init nsim_module_init(void)
goto err_debugfs_destroy;
}
- err = bus_register(&nsim_bus);
+ err = register_switchdev_blocking_notifier(&nsim_swdev_blocking_nb);
if (err)
goto err_sdir_destroy;
+ err = bus_register(&nsim_bus);
+ if (err)
+ goto err_unreg_notifier;
+
err = nsim_devlink_init();
if (err)
goto err_unreg_bus;
@@ -601,6 +639,8 @@ static int __init nsim_module_init(void)
nsim_devlink_exit();
err_unreg_bus:
bus_unregister(&nsim_bus);
+err_unreg_notifier:
+ unregister_switchdev_blocking_notifier(&nsim_swdev_blocking_nb);
err_sdir_destroy:
debugfs_remove_recursive(nsim_sdev_ddir);
err_debugfs_destroy:
@@ -613,6 +653,7 @@ static void __exit nsim_module_exit(void)
rtnl_link_unregister(&nsim_link_ops);
nsim_devlink_exit();
bus_unregister(&nsim_bus);
+ unregister_switchdev_blocking_notifier(&nsim_swdev_blocking_nb);
debugfs_remove_recursive(nsim_sdev_ddir);
debugfs_remove_recursive(nsim_ddir);
}
--
2.17.1
^ permalink raw reply related
* [RFC net-next 13/13] net: switchdev: Replace port attr get/set SDO with a notification
From: Florian Fainelli @ 2019-02-01 22:06 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Michael Chan, David S. Miller, Derek Chickles,
Satanand Burla, Felix Manlunas, Saeed Mahameed, Leon Romanovsky,
Jiri Pirko, Ido Schimmel, Alexandre Belloni,
Microchip Linux Driver Support, Jakub Kicinski, Ioana Radulescu,
Ioana Ciornei, Greg Kroah-Hartman, Ivan Vecera, Andrew Lunn,
Vivien Didelot, Dirk van der Merwe, Francois H. Theron,
Simon Horman, Quentin Monnet, Daniel Borkmann, Eric Dumazet,
John Hurley, Edwin Peer, open list,
open list:MELLANOX MLX5 core VPI driver,
open list:NETRONOME ETHERNET DRIVERS, open list:STAGING SUBSYSTEM
In-Reply-To: <20190201220657.30170-1-f.fainelli@gmail.com>
Drop switchdev_ops.switchdev_port_attr_get and _set. Drop the uses of
this field from all clients, which were migrated to use switchdev
notification in the previous patches.
Add a new function switchdev_port_attr_notify() that sends the switchdev
notifications SWITCHDEV_PORT_ATTR_GET and _SET.
Update switchdev_port_attr_get() to dispatch to this new function. Drop
__switchdev_port_attr_set() and update switchdev_port_attr_set()
likewise.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 5 -
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c | 5 -
.../net/ethernet/cavium/liquidio/lio_main.c | 5 -
.../net/ethernet/cavium/liquidio/lio_vf_rep.c | 5 -
.../net/ethernet/mellanox/mlx5/core/en_rep.c | 7 --
.../net/ethernet/mellanox/mlxsw/spectrum.c | 12 --
.../net/ethernet/mellanox/mlxsw/spectrum.h | 2 -
.../mellanox/mlxsw/spectrum_switchdev.c | 13 ---
.../net/ethernet/mellanox/mlxsw/switchx2.c | 5 -
drivers/net/ethernet/mscc/ocelot.c | 6 -
.../ethernet/netronome/nfp/nfp_net_common.c | 2 -
.../net/ethernet/netronome/nfp/nfp_net_repr.c | 2 -
drivers/net/ethernet/netronome/nfp/nfp_port.c | 4 -
drivers/net/ethernet/rocker/rocker_main.c | 6 -
drivers/net/netdevsim/netdev.c | 5 -
drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 6 -
include/linux/netdevice.h | 3 -
include/net/switchdev.h | 18 ---
net/dsa/slave.c | 6 -
net/switchdev/switchdev.c | 107 ++++++------------
20 files changed, 37 insertions(+), 187 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index c3178ca4a004..78d2d76de1a7 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -10007,10 +10007,6 @@ static int bnxt_swdev_port_attr_get(struct net_device *dev,
return bnxt_port_attr_get(netdev_priv(dev), attr);
}
-static const struct switchdev_ops bnxt_switchdev_ops = {
- .switchdev_port_attr_get = bnxt_swdev_port_attr_get
-};
-
static const struct net_device_ops bnxt_netdev_ops = {
.ndo_open = bnxt_open,
.ndo_start_xmit = bnxt_start_xmit,
@@ -10439,7 +10435,6 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->netdev_ops = &bnxt_netdev_ops;
dev->watchdog_timeo = BNXT_TX_TIMEOUT;
dev->ethtool_ops = &bnxt_ethtool_ops;
- SWITCHDEV_SET_OPS(dev, &bnxt_switchdev_ops);
pci_set_drvdata(pdev, dev);
rc = bnxt_alloc_hwrm_resources(bp);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
index a06f93b49dd5..13db3bf4271f 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
@@ -248,10 +248,6 @@ int bnxt_vf_rep_port_attr_get(struct net_device *dev,
return bnxt_port_attr_get(vf_rep->bp, attr);
}
-static const struct switchdev_ops bnxt_vf_rep_switchdev_ops = {
- .switchdev_port_attr_get = bnxt_vf_rep_port_attr_get
-};
-
static const struct ethtool_ops bnxt_vf_rep_ethtool_ops = {
.get_drvinfo = bnxt_vf_rep_get_drvinfo
};
@@ -392,7 +388,6 @@ static void bnxt_vf_rep_netdev_init(struct bnxt *bp, struct bnxt_vf_rep *vf_rep,
dev->netdev_ops = &bnxt_vf_rep_netdev_ops;
dev->ethtool_ops = &bnxt_vf_rep_ethtool_ops;
- SWITCHDEV_SET_OPS(dev, &bnxt_vf_rep_switchdev_ops);
/* Just inherit all the featues of the parent PF as the VF-R
* uses the RX/TX rings of the parent PF
*/
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index b9d48e4181fc..19ebf2a3aa49 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -3222,10 +3222,6 @@ lio_pf_switchdev_attr_get(struct net_device *dev, struct switchdev_attr *attr)
return 0;
}
-static const struct switchdev_ops lio_pf_switchdev_ops = {
- .switchdev_port_attr_get = lio_pf_switchdev_attr_get,
-};
-
static int liquidio_get_vf_stats(struct net_device *netdev, int vfidx,
struct ifla_vf_stats *vf_stats)
{
@@ -3580,7 +3576,6 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
* netdev tasks.
*/
netdev->netdev_ops = &lionetdevops;
- SWITCHDEV_SET_OPS(netdev, &lio_pf_switchdev_ops);
retval = netif_set_real_num_rx_queues(netdev, num_oqueues);
if (retval) {
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c
index d396c004c1be..0aa64ffae8b6 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c
@@ -464,10 +464,6 @@ lio_vf_rep_attr_get(struct net_device *dev, struct switchdev_attr *attr)
return 0;
}
-static const struct switchdev_ops lio_vf_rep_switchdev_ops = {
- .switchdev_port_attr_get = lio_vf_rep_attr_get,
-};
-
static int lio_vf_rep_swdev_port_attr_event(unsigned long event,
struct net_device *dev,
struct switchdev_notifier_port_attr_info *port_attr_info)
@@ -539,7 +535,6 @@ lio_vf_rep_create(struct octeon_device *oct)
ndev->min_mtu = LIO_MIN_MTU_SIZE;
ndev->max_mtu = LIO_MAX_MTU_SIZE;
ndev->netdev_ops = &lio_vf_rep_ndev_ops;
- SWITCHDEV_SET_OPS(ndev, &lio_vf_rep_switchdev_ops);
vf_rep = netdev_priv(ndev);
memset(vf_rep, 0, sizeof(*vf_rep));
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 9bac78e111c6..1925ab62631c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -1285,10 +1285,6 @@ static int mlx5e_uplink_rep_set_mac(struct net_device *netdev, void *addr)
return 0;
}
-static const struct switchdev_ops mlx5e_rep_switchdev_ops = {
- .switchdev_port_attr_get = mlx5e_attr_get,
-};
-
static int mlx5e_rep_swdev_port_attr_event(unsigned long event,
struct net_device *dev,
struct switchdev_notifier_port_attr_info *port_attr_info)
@@ -1423,9 +1419,6 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev)
netdev->watchdog_timeo = 15 * HZ;
-
- netdev->switchdev_ops = &mlx5e_rep_switchdev_ops;
-
netdev->features |= NETIF_F_HW_TC | NETIF_F_NETNS_LOCAL;
netdev->hw_features |= NETIF_F_HW_TC;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index a88169738b4a..e87a5e634fc1 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -3207,7 +3207,6 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
}
mlxsw_sp_port->default_vlan = mlxsw_sp_port_vlan;
- mlxsw_sp_port_switchdev_init(mlxsw_sp_port);
mlxsw_sp->ports[local_port] = mlxsw_sp_port;
err = register_netdev(dev);
if (err) {
@@ -3224,7 +3223,6 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
err_register_netdev:
mlxsw_sp->ports[local_port] = NULL;
- mlxsw_sp_port_switchdev_fini(mlxsw_sp_port);
mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
err_port_vlan_create:
err_port_pvid_set:
@@ -3267,7 +3265,6 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
mlxsw_core_port_clear(mlxsw_sp->core, local_port, mlxsw_sp);
unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */
mlxsw_sp->ports[local_port] = NULL;
- mlxsw_sp_port_switchdev_fini(mlxsw_sp_port);
mlxsw_sp_port_vlan_flush(mlxsw_sp_port, true);
mlxsw_sp_port_nve_fini(mlxsw_sp_port);
mlxsw_sp_tc_qdisc_fini(mlxsw_sp_port);
@@ -3988,12 +3985,6 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
goto err_span_init;
}
- err = mlxsw_sp_switchdev_init(mlxsw_sp);
- if (err) {
- dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize switchdev\n");
- goto err_switchdev_init;
- }
-
err = mlxsw_sp_counter_pool_init(mlxsw_sp);
if (err) {
dev_err(mlxsw_sp->bus_info->dev, "Failed to init counter pool\n");
@@ -4064,8 +4055,6 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
err_afa_init:
mlxsw_sp_counter_pool_fini(mlxsw_sp);
err_counter_pool_init:
- mlxsw_sp_switchdev_fini(mlxsw_sp);
-err_switchdev_init:
mlxsw_sp_span_fini(mlxsw_sp);
err_span_init:
mlxsw_sp_lag_fini(mlxsw_sp);
@@ -4128,7 +4117,6 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
mlxsw_sp_nve_fini(mlxsw_sp);
mlxsw_sp_afa_fini(mlxsw_sp);
mlxsw_sp_counter_pool_fini(mlxsw_sp);
- mlxsw_sp_switchdev_fini(mlxsw_sp);
mlxsw_sp_span_fini(mlxsw_sp);
mlxsw_sp_lag_fini(mlxsw_sp);
mlxsw_sp_buffers_fini(mlxsw_sp);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 1fa5c81b209f..f81914203098 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -375,8 +375,6 @@ u32 mlxsw_sp_bytes_cells(const struct mlxsw_sp *mlxsw_sp, u32 bytes);
/* spectrum_switchdev.c */
int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp);
void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp);
-void mlxsw_sp_port_switchdev_init(struct mlxsw_sp_port *mlxsw_sp_port);
-void mlxsw_sp_port_switchdev_fini(struct mlxsw_sp_port *mlxsw_sp_port);
int mlxsw_sp_rif_fdb_op(struct mlxsw_sp *mlxsw_sp, const char *mac, u16 fid,
bool adding);
void
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 7c0df736587c..19f647c4c4df 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1962,11 +1962,6 @@ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct mlxsw_sp *mlxsw_sp,
return NULL;
}
-static const struct switchdev_ops mlxsw_sp_port_switchdev_ops = {
- .switchdev_port_attr_get = mlxsw_sp_port_attr_get,
- .switchdev_port_attr_set = mlxsw_sp_port_attr_set,
-};
-
static int
mlxsw_sp_bridge_8021q_port_join(struct mlxsw_sp_bridge_device *bridge_device,
struct mlxsw_sp_bridge_port *bridge_port,
@@ -3575,11 +3570,3 @@ void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp)
kfree(mlxsw_sp->bridge);
}
-void mlxsw_sp_port_switchdev_init(struct mlxsw_sp_port *mlxsw_sp_port)
-{
- mlxsw_sp_port->dev->switchdev_ops = &mlxsw_sp_port_switchdev_ops;
-}
-
-void mlxsw_sp_port_switchdev_fini(struct mlxsw_sp_port *mlxsw_sp_port)
-{
-}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
index 82fb8f1bb6e9..1f1aca664b73 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
@@ -919,10 +919,6 @@ static int mlxsw_sx_port_attr_get(struct net_device *dev,
return 0;
}
-static const struct switchdev_ops mlxsw_sx_port_switchdev_ops = {
- .switchdev_port_attr_get = mlxsw_sx_port_attr_get,
-};
-
static int mlxsw_sx_port_attr_event(unsigned long event,
struct net_device *dev,
struct switchdev_notifier_port_attr_info *port_attr_info)
@@ -1064,7 +1060,6 @@ static int __mlxsw_sx_port_eth_create(struct mlxsw_sx *mlxsw_sx, u8 local_port,
dev->netdev_ops = &mlxsw_sx_port_netdev_ops;
dev->ethtool_ops = &mlxsw_sx_port_ethtool_ops;
- dev->switchdev_ops = &mlxsw_sx_port_switchdev_ops;
err = mlxsw_sx_port_dev_addr_get(mlxsw_sx_port);
if (err) {
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 8043347a1ed4..1b7833ee8cc6 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1330,11 +1330,6 @@ static int ocelot_port_obj_del(struct net_device *dev,
return ret;
}
-static const struct switchdev_ops ocelot_port_switchdev_ops = {
- .switchdev_port_attr_get = ocelot_port_attr_get,
- .switchdev_port_attr_set = ocelot_port_attr_set,
-};
-
static int ocelot_port_bridge_join(struct ocelot_port *ocelot_port,
struct net_device *bridge)
{
@@ -1664,7 +1659,6 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
dev->netdev_ops = &ocelot_port_netdev_ops;
dev->ethtool_ops = &ocelot_ethtool_ops;
- dev->switchdev_ops = &ocelot_port_switchdev_ops;
dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_RXFCS;
dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index c2c5e7e3aab0..46f0f29e31cd 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -3815,8 +3815,6 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
netdev->netdev_ops = &nfp_net_netdev_ops;
netdev->watchdog_timeo = msecs_to_jiffies(5 * 1000);
- SWITCHDEV_SET_OPS(netdev, &nfp_port_switchdev_ops);
-
/* MTU range: 68 - hw-specific max */
netdev->min_mtu = ETH_MIN_MTU;
netdev->max_mtu = nn->max_mtu;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index 69d7aebda09b..eb6e95cc460e 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
@@ -336,8 +336,6 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
netdev->max_mtu = pf_netdev->max_mtu;
- SWITCHDEV_SET_OPS(netdev, &nfp_port_switchdev_ops);
-
/* Set features the lower device can support with representors */
if (repr_cap & NFP_NET_CFG_CTRL_LIVE_ADDR)
netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_port.c b/drivers/net/ethernet/netronome/nfp/nfp_port.c
index 578477242ae9..77781fc2eaa6 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_port.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_port.c
@@ -55,10 +55,6 @@ nfp_port_attr_get(struct net_device *netdev, struct switchdev_attr *attr)
return 0;
}
-const struct switchdev_ops nfp_port_switchdev_ops = {
- .switchdev_port_attr_get = nfp_port_attr_get,
-};
-
int nfp_port_switchdev_attr_event(unsigned long event,
struct net_device *netdev,
struct switchdev_notifier_port_attr_info *port_attr_info)
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index f25f7b4345b8..52082c7690ea 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -2139,11 +2139,6 @@ static int rocker_port_obj_del(struct net_device *dev,
return err;
}
-static const struct switchdev_ops rocker_port_switchdev_ops = {
- .switchdev_port_attr_get = rocker_port_attr_get,
- .switchdev_port_attr_set = rocker_port_attr_set,
-};
-
struct rocker_fib_event_work {
struct work_struct work;
union {
@@ -2597,7 +2592,6 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
rocker_port_dev_addr_init(rocker_port);
dev->netdev_ops = &rocker_port_netdev_ops;
dev->ethtool_ops = &rocker_port_ethtool_ops;
- dev->switchdev_ops = &rocker_port_switchdev_ops;
netif_tx_napi_add(dev, &rocker_port->napi_tx, rocker_port_poll_tx,
NAPI_POLL_WEIGHT);
netif_napi_add(dev, &rocker_port->napi_rx, rocker_port_poll_rx,
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 817d94cec90f..b0dca4f99018 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -164,10 +164,6 @@ nsim_port_attr_get(struct net_device *dev, struct switchdev_attr *attr)
}
}
-static const struct switchdev_ops nsim_switchdev_ops = {
- .switchdev_port_attr_get = nsim_port_attr_get,
-};
-
static int nsim_switchdev_port_attr_event(unsigned long event,
struct net_device *dev,
struct switchdev_notifier_port_attr_info *port_attr_info)
@@ -228,7 +224,6 @@ static int nsim_init(struct net_device *dev)
goto err_bpf_uninit;
SET_NETDEV_DEV(dev, &ns->dev);
- SWITCHDEV_SET_OPS(dev, &nsim_switchdev_ops);
err = nsim_devlink_setup(ns);
if (err)
diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
index b18e112d84e6..4d0eb2ed062d 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -924,11 +924,6 @@ static int swdev_port_obj_del(struct net_device *netdev,
return err;
}
-static const struct switchdev_ops ethsw_port_switchdev_ops = {
- .switchdev_port_attr_get = swdev_port_attr_get,
- .switchdev_port_attr_set = swdev_port_attr_set,
-};
-
/* For the moment, only flood setting needs to be updated */
static int port_bridge_join(struct net_device *netdev,
struct net_device *upper_dev)
@@ -1458,7 +1453,6 @@ static int ethsw_probe_port(struct ethsw_core *ethsw, u16 port_idx)
SET_NETDEV_DEV(port_netdev, dev);
port_netdev->netdev_ops = ðsw_port_ops;
port_netdev->ethtool_ops = ðsw_port_ethtool_ops;
- port_netdev->switchdev_ops = ðsw_port_switchdev_ops;
/* Set MTU limits */
port_netdev->min_mtu = ETH_MIN_MTU;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index a57b9a853aab..1176292f3d62 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1826,9 +1826,6 @@ struct net_device {
#endif
const struct net_device_ops *netdev_ops;
const struct ethtool_ops *ethtool_ops;
-#ifdef CONFIG_NET_SWITCHDEV
- const struct switchdev_ops *switchdev_ops;
-#endif
#ifdef CONFIG_NET_L3_MASTER_DEV
const struct l3mdev_ops *l3mdev_ops;
#endif
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index e62fb2693e00..61a97f2a8fb0 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -115,21 +115,6 @@ void *switchdev_trans_item_dequeue(struct switchdev_trans *trans);
typedef int switchdev_obj_dump_cb_t(struct switchdev_obj *obj);
-/**
- * struct switchdev_ops - switchdev operations
- *
- * @switchdev_port_attr_get: Get a port attribute (see switchdev_attr).
- *
- * @switchdev_port_attr_set: Set a port attribute (see switchdev_attr).
- */
-struct switchdev_ops {
- int (*switchdev_port_attr_get)(struct net_device *dev,
- struct switchdev_attr *attr);
- int (*switchdev_port_attr_set)(struct net_device *dev,
- const struct switchdev_attr *attr,
- struct switchdev_trans *trans);
-};
-
enum switchdev_notifier_type {
SWITCHDEV_FDB_ADD_TO_BRIDGE = 1,
SWITCHDEV_FDB_DEL_TO_BRIDGE,
@@ -234,7 +219,6 @@ int switchdev_handle_port_obj_del(struct net_device *dev,
int (*del_cb)(struct net_device *dev,
const struct switchdev_obj *obj));
-#define SWITCHDEV_SET_OPS(netdev, ops) ((netdev)->switchdev_ops = (ops))
#else
static inline void switchdev_deferred_process(void)
@@ -333,8 +317,6 @@ switchdev_handle_port_obj_del(struct net_device *dev,
return 0;
}
-#define SWITCHDEV_SET_OPS(netdev, ops) do {} while (0)
-
#endif
#endif /* _LINUX_SWITCHDEV_H_ */
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index bc7d5092a1c7..a11f9678610c 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1048,11 +1048,6 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
.ndo_get_stats64 = dsa_slave_get_stats64,
};
-static const struct switchdev_ops dsa_slave_switchdev_ops = {
- .switchdev_port_attr_get = dsa_slave_port_attr_get,
- .switchdev_port_attr_set = dsa_slave_port_attr_set,
-};
-
static struct device_type dsa_type = {
.name = "dsa",
};
@@ -1312,7 +1307,6 @@ int dsa_slave_create(struct dsa_port *port)
eth_hw_addr_inherit(slave_dev, master);
slave_dev->priv_flags |= IFF_NO_QUEUE;
slave_dev->netdev_ops = &dsa_slave_netdev_ops;
- slave_dev->switchdev_ops = &dsa_slave_switchdev_ops;
slave_dev->min_mtu = 0;
slave_dev->max_mtu = ETH_MAX_MTU;
SET_NETDEV_DEVTYPE(slave_dev, &dsa_type);
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index cd78253de31d..b7f1cf0c7f4c 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -174,81 +174,31 @@ static int switchdev_deferred_enqueue(struct net_device *dev,
return 0;
}
-/**
- * switchdev_port_attr_get - Get port attribute
- *
- * @dev: port device
- * @attr: attribute to get
- */
-int switchdev_port_attr_get(struct net_device *dev, struct switchdev_attr *attr)
+static int switchdev_port_attr_notify(enum switchdev_notifier_type nt,
+ struct net_device *dev,
+ struct switchdev_attr *attr,
+ struct switchdev_trans *trans)
{
- const struct switchdev_ops *ops = dev->switchdev_ops;
- struct net_device *lower_dev;
- struct list_head *iter;
- struct switchdev_attr first = {
- .id = SWITCHDEV_ATTR_ID_UNDEFINED
- };
- int err = -EOPNOTSUPP;
+ int err;
+ int rc;
- if (ops && ops->switchdev_port_attr_get)
- return ops->switchdev_port_attr_get(dev, attr);
+ struct switchdev_notifier_port_attr_info attr_info = {
+ .attr = attr,
+ .trans = trans,
+ .handled = false,
+ };
- if (attr->flags & SWITCHDEV_F_NO_RECURSE)
+ rc = call_switchdev_blocking_notifiers(nt, dev, &attr_info.info, NULL);
+ err = notifier_to_errno(rc);
+ if (err) {
+ WARN_ON(!attr_info.handled);
return err;
-
- /* Switch device port(s) may be stacked under
- * bond/team/vlan dev, so recurse down to get attr on
- * each port. Return -ENODATA if attr values don't
- * compare across ports.
- */
-
- netdev_for_each_lower_dev(dev, lower_dev, iter) {
- err = switchdev_port_attr_get(lower_dev, attr);
- if (err)
- break;
- if (first.id == SWITCHDEV_ATTR_ID_UNDEFINED)
- first = *attr;
- else if (memcmp(&first, attr, sizeof(*attr)))
- return -ENODATA;
- }
-
- return err;
-}
-EXPORT_SYMBOL_GPL(switchdev_port_attr_get);
-
-static int __switchdev_port_attr_set(struct net_device *dev,
- const struct switchdev_attr *attr,
- struct switchdev_trans *trans)
-{
- const struct switchdev_ops *ops = dev->switchdev_ops;
- struct net_device *lower_dev;
- struct list_head *iter;
- int err = -EOPNOTSUPP;
-
- if (ops && ops->switchdev_port_attr_set) {
- err = ops->switchdev_port_attr_set(dev, attr, trans);
- goto done;
- }
-
- if (attr->flags & SWITCHDEV_F_NO_RECURSE)
- goto done;
-
- /* Switch device port(s) may be stacked under
- * bond/team/vlan dev, so recurse down to set attr on
- * each port.
- */
-
- netdev_for_each_lower_dev(dev, lower_dev, iter) {
- err = __switchdev_port_attr_set(lower_dev, attr, trans);
- if (err)
- break;
}
-done:
- if (err == -EOPNOTSUPP && attr->flags & SWITCHDEV_F_SKIP_EOPNOTSUPP)
- err = 0;
+ if (!attr_info.handled)
+ return -EOPNOTSUPP;
- return err;
+ return 0;
}
static int switchdev_port_attr_set_now(struct net_device *dev,
@@ -267,7 +217,9 @@ static int switchdev_port_attr_set_now(struct net_device *dev,
*/
trans.ph_prepare = true;
- err = __switchdev_port_attr_set(dev, attr, &trans);
+ err = switchdev_port_attr_notify(SWITCHDEV_PORT_ATTR_SET,
+ dev, (struct switchdev_attr *)attr,
+ &trans);
if (err) {
/* Prepare phase failed: abort the transaction. Any
* resources reserved in the prepare phase are
@@ -286,7 +238,9 @@ static int switchdev_port_attr_set_now(struct net_device *dev,
*/
trans.ph_prepare = false;
- err = __switchdev_port_attr_set(dev, attr, &trans);
+ err = switchdev_port_attr_notify(SWITCHDEV_PORT_ATTR_SET,
+ dev, (struct switchdev_attr *)attr,
+ &trans);
WARN(err, "%s: Commit of attribute (id=%d) failed.\n",
dev->name, attr->id);
switchdev_trans_items_warn_destroy(dev, &trans);
@@ -338,6 +292,19 @@ int switchdev_port_attr_set(struct net_device *dev,
}
EXPORT_SYMBOL_GPL(switchdev_port_attr_set);
+/**
+ * switchdev_port_attr_get - Get port attribute
+ *
+ * @dev: port device
+ * @attr: attribute to get
+ */
+int switchdev_port_attr_get(struct net_device *dev, struct switchdev_attr *attr)
+{
+ return switchdev_port_attr_notify(SWITCHDEV_PORT_ATTR_GET, dev,
+ attr, NULL);
+}
+EXPORT_SYMBOL_GPL(switchdev_port_attr_get);
+
static size_t switchdev_obj_size(const struct switchdev_obj *obj)
{
switch (obj->id) {
--
2.17.1
^ permalink raw reply related
* [RFC net-next 11/13] nfp: Handle SWITCHDEV_PORT_ATTR_GET event
From: Florian Fainelli @ 2019-02-01 22:06 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Michael Chan, David S. Miller, Derek Chickles,
Satanand Burla, Felix Manlunas, Saeed Mahameed, Leon Romanovsky,
Jiri Pirko, Ido Schimmel, Alexandre Belloni,
Microchip Linux Driver Support, Jakub Kicinski, Ioana Radulescu,
Ioana Ciornei, Greg Kroah-Hartman, Ivan Vecera, Andrew Lunn,
Vivien Didelot, Dirk van der Merwe, Francois H. Theron,
Simon Horman, Quentin Monnet, Daniel Borkmann, Eric Dumazet,
John Hurley, Edwin Peer, open list,
open list:MELLANOX MLX5 core VPI driver,
open list:NETRONOME ETHERNET DRIVERS, open list:STAGING SUBSYSTEM
In-Reply-To: <20190201220657.30170-1-f.fainelli@gmail.com>
Following patches will change the way we communicate getting or setting
a port's attribute and use a blocking notifier to perform those tasks.
Prepare nfp to support receiving notifier events targeting
SWITCHDEV_PORT_ATTR_GET and simply translate that into the existing
switchdev_ops::switchdev_port_attr_get operation.
We register a single blocking switchdev notifier for the entire driver
instance and we differentiate a "net" from a "repr" by comparing the
network device's netdev_ops with the ones that this driver manages.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/netronome/nfp/nfp_main.c | 14 +++++++++++++-
drivers/net/ethernet/netronome/nfp/nfp_net.h | 3 +++
.../net/ethernet/netronome/nfp/nfp_net_common.c | 17 +++++++++++++++++
drivers/net/ethernet/netronome/nfp/nfp_port.c | 15 +++++++++++++++
drivers/net/ethernet/netronome/nfp/nfp_port.h | 5 ++++-
5 files changed, 52 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.c b/drivers/net/ethernet/netronome/nfp/nfp_main.c
index 6c10e8d119e4..50c111280cd4 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_main.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_main.c
@@ -17,6 +17,7 @@
#include <linux/vermagic.h>
#include <linux/vmalloc.h>
#include <net/devlink.h>
+#include <net/switchdev.h>
#include "nfpcore/nfp.h"
#include "nfpcore/nfp_cpp.h"
@@ -708,6 +709,10 @@ static void nfp_pci_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
}
+static struct notifier_block nfp_swdev_blocking_nb = {
+ .notifier_call = nfp_switchdev_blocking_event,
+};
+
static struct pci_driver nfp_pci_driver = {
.name = nfp_driver_name,
.id_table = nfp_pci_device_ids,
@@ -725,9 +730,13 @@ static int __init nfp_main_init(void)
nfp_net_debugfs_create();
+ err = register_switchdev_blocking_notifier(&nfp_swdev_blocking_nb);
+ if (err)
+ goto err_destroy_debugfs;
+
err = pci_register_driver(&nfp_pci_driver);
if (err < 0)
- goto err_destroy_debugfs;
+ goto err_unreg_notifier;
err = pci_register_driver(&nfp_netvf_pci_driver);
if (err)
@@ -737,6 +746,8 @@ static int __init nfp_main_init(void)
err_unreg_pf:
pci_unregister_driver(&nfp_pci_driver);
+err_unreg_notifier:
+ unregister_switchdev_blocking_notifier(&nfp_swdev_blocking_nb);
err_destroy_debugfs:
nfp_net_debugfs_destroy();
return err;
@@ -746,6 +757,7 @@ static void __exit nfp_main_exit(void)
{
pci_unregister_driver(&nfp_netvf_pci_driver);
pci_unregister_driver(&nfp_pci_driver);
+ unregister_switchdev_blocking_notifier(&nfp_swdev_blocking_nb);
nfp_net_debugfs_destroy();
}
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h
index be37c2d6151c..57f7d6d634ea 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h
@@ -915,4 +915,7 @@ static inline void nfp_net_debugfs_dir_clean(struct dentry **dir)
}
#endif /* CONFIG_NFP_DEBUG */
+int nfp_switchdev_blocking_event(struct notifier_block *nb,
+ unsigned long event, void *ptr);
+
#endif /* _NFP_NET_H_ */
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 7d2d4241498f..c2c5e7e3aab0 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -3955,3 +3955,20 @@ void nfp_net_clean(struct nfp_net *nn)
unregister_netdev(nn->dp.netdev);
nfp_net_reconfig_wait_posted(nn);
}
+
+int nfp_switchdev_blocking_event(struct notifier_block *nb,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+
+ if (!nfp_netdev_is_nfp_repr(dev) &&
+ !nfp_netdev_is_nfp_net(dev))
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case SWITCHDEV_PORT_ATTR_GET:
+ return nfp_port_switchdev_attr_event(event, dev, ptr);
+ }
+
+ return NOTIFY_DONE;
+}
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_port.c b/drivers/net/ethernet/netronome/nfp/nfp_port.c
index 86bc149ca231..578477242ae9 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_port.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_port.c
@@ -59,6 +59,21 @@ const struct switchdev_ops nfp_port_switchdev_ops = {
.switchdev_port_attr_get = nfp_port_attr_get,
};
+int nfp_port_switchdev_attr_event(unsigned long event,
+ struct net_device *netdev,
+ struct switchdev_notifier_port_attr_info *port_attr_info)
+{
+ int rc;
+
+ if (event != SWITCHDEV_PORT_ATTR_GET)
+ return NOTIFY_DONE;
+
+ rc = nfp_port_attr_get(netdev, port_attr_info->attr);
+ port_attr_info->handled = true;
+
+ return notifier_from_errno(rc);
+}
+
int nfp_port_setup_tc(struct net_device *netdev, enum tc_setup_type type,
void *type_data)
{
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_port.h b/drivers/net/ethernet/netronome/nfp/nfp_port.h
index b2479a2a49e5..35342f88f715 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_port.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_port.h
@@ -10,6 +10,7 @@ struct net_device;
struct nfp_app;
struct nfp_pf;
struct nfp_port;
+struct switchdev_notifier_port_attr_info;
/**
* enum nfp_port_type - type of port NFP can switch traffic to
@@ -90,7 +91,9 @@ struct nfp_port {
};
extern const struct ethtool_ops nfp_port_ethtool_ops;
-extern const struct switchdev_ops nfp_port_switchdev_ops;
+
+int nfp_port_switchdev_attr_event(unsigned long event, struct net_device *dev,
+ struct switchdev_notifier_port_attr_info *port_attr_info);
__printf(2, 3) u8 *nfp_pr_et(u8 *data, const char *fmt, ...);
--
2.17.1
^ permalink raw reply related
* [RFC net-next 06/13] staging: fsl-dpaa2: ethsw: Handle SWITCHDEV_PORT_ATTR_GET/SET
From: Florian Fainelli @ 2019-02-01 22:06 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Michael Chan, David S. Miller, Derek Chickles,
Satanand Burla, Felix Manlunas, Saeed Mahameed, Leon Romanovsky,
Jiri Pirko, Ido Schimmel, Alexandre Belloni,
Microchip Linux Driver Support, Jakub Kicinski, Ioana Radulescu,
Ioana Ciornei, Greg Kroah-Hartman, Ivan Vecera, Andrew Lunn,
Vivien Didelot, Dirk van der Merwe, Francois H. Theron,
Simon Horman, Quentin Monnet, Daniel Borkmann, Eric Dumazet,
John Hurley, Edwin Peer, open list,
open list:MELLANOX MLX5 core VPI driver,
open list:NETRONOME ETHERNET DRIVERS, open list:STAGING SUBSYSTEM
In-Reply-To: <20190201220657.30170-1-f.fainelli@gmail.com>
Following patches will change the way we communicate getting or setting
a port's attribute and use a blocking notifier to perform those tasks.
Prepare ethsw to support receiving notifier events targeting
SWITCHDEV_PORT_ATTR_GET/SET and simply translate that into the existing
swdev_port_attr_{set,get} calls.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
index daabaceeea52..b18e112d84e6 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -1103,6 +1103,27 @@ ethsw_switchdev_port_obj_event(unsigned long event, struct net_device *netdev,
return notifier_from_errno(err);
}
+static int
+ethsw_switchdev_port_attr_event(unsigned long event,
+ struct net_device *netdev,
+ struct switchdev_notifier_port_attr_info *port_attr_info)
+{
+ int err = -EOPNOTSUPP;
+
+ switch (event) {
+ case SWITCHDEV_PORT_ATTR_SET:
+ err = swdev_port_attr_set(netdev, port_attr_info->attr,
+ port_attr_info->trans);
+ break;
+ case SWITCHDEV_PORT_ATTR_GET:
+ err = swdev_port_attr_get(netdev, port_attr_info->attr);
+ break;
+ }
+
+ port_attr_info->handled = true;
+ return notifier_from_errno(err);
+}
+
static int port_switchdev_blocking_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
@@ -1115,6 +1136,9 @@ static int port_switchdev_blocking_event(struct notifier_block *unused,
case SWITCHDEV_PORT_OBJ_ADD: /* fall through */
case SWITCHDEV_PORT_OBJ_DEL:
return ethsw_switchdev_port_obj_event(event, dev, ptr);
+ case SWITCHDEV_PORT_ATTR_SET:
+ case SWITCHDEV_PORT_ATTR_GET:
+ return ethsw_switchdev_port_attr_event(event, dev, ptr);
}
return NOTIFY_DONE;
--
2.17.1
^ permalink raw reply related
* [RFC net-next 01/13] switchdev: Add SWITCHDEV_PORT_ATTR_SET, SWITCHDEV_PORT_ATTR_GET
From: Florian Fainelli @ 2019-02-01 22:06 UTC (permalink / raw)
To: netdev
Cc: Florian Fainelli, Michael Chan, David S. Miller, Derek Chickles,
Satanand Burla, Felix Manlunas, Saeed Mahameed, Leon Romanovsky,
Jiri Pirko, Ido Schimmel, Alexandre Belloni,
Microchip Linux Driver Support, Jakub Kicinski, Ioana Radulescu,
Ioana Ciornei, Greg Kroah-Hartman, Ivan Vecera, Andrew Lunn,
Vivien Didelot, Dirk van der Merwe, Francois H. Theron,
Simon Horman, Quentin Monnet, Daniel Borkmann, Eric Dumazet,
John Hurley, Edwin Peer, open list,
open list:MELLANOX MLX5 core VPI driver,
open list:NETRONOME ETHERNET DRIVERS, open list:STAGING SUBSYSTEM
In-Reply-To: <20190201220657.30170-1-f.fainelli@gmail.com>
In preparation for allowing switchdev enabled drivers to veto specific
attribute settings from within the context of the caller, introduce a
new switchdev notifier type for port attributes.
Suggested-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
include/net/switchdev.h | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 63843ae5dc81..e62fb2693e00 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -145,6 +145,9 @@ enum switchdev_notifier_type {
SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE,
SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE,
SWITCHDEV_VXLAN_FDB_OFFLOADED,
+
+ SWITCHDEV_PORT_ATTR_SET, /* Blocking. */
+ SWITCHDEV_PORT_ATTR_GET, /* Blocking. */
};
struct switchdev_notifier_info {
@@ -167,6 +170,13 @@ struct switchdev_notifier_port_obj_info {
bool handled;
};
+struct switchdev_notifier_port_attr_info {
+ struct switchdev_notifier_info info; /* must be first */
+ struct switchdev_attr *attr;
+ struct switchdev_trans *trans;
+ bool handled;
+};
+
static inline struct net_device *
switchdev_notifier_info_to_dev(const struct switchdev_notifier_info *info)
{
--
2.17.1
^ permalink raw reply related
* [PATCH bpf-next v3 1/3] tools/bpf: move libbpf pr_* debug print functions to headers
From: Yonghong Song @ 2019-02-01 22:06 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Magnus Karlsson, netdev
Cc: Alexei Starovoitov, Daniel Borkmann, kernel-team, Yonghong Song
In-Reply-To: <20190201220616.1802774-1-yhs@fb.com>
A global function libbpf_debug_print, which is invisible
outside the shared library, is defined to print based
on levels. The pr_warning, pr_info and pr_debug
macros are moved into the newly created header
common.h. So any .c file including common.h can
use these macros directly.
Currently btf__new and btf_ext__new API has an argument getting
__pr_debug function pointer into btf.c so the debugging information
can be printed there. This patch removed this parameter
from btf__new and btf_ext__new and directly using pr_debug in btf.c.
Another global function libbpf_dprint_level_available, also
invisible outside the shared library, can test
whether a particular level debug printing is
available or not. It is used in btf.c to
test whether DEBUG level debug printing is availabl or not,
based on which the log buffer will be allocated when loading
btf to the kernel.
Signed-off-by: Yonghong Song <yhs@fb.com>
---
tools/lib/bpf/btf.c | 97 +++++++++++++++++------------------
tools/lib/bpf/btf.h | 7 +--
tools/lib/bpf/libbpf.c | 46 ++++++++++++-----
tools/lib/bpf/libbpf.h | 6 +++
tools/lib/bpf/test_libbpf.cpp | 2 +-
tools/lib/bpf/util.h | 32 ++++++++++++
6 files changed, 120 insertions(+), 70 deletions(-)
create mode 100644 tools/lib/bpf/util.h
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index d682d3b8f7b9..159104ec31dc 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -9,8 +9,9 @@
#include <linux/btf.h>
#include "btf.h"
#include "bpf.h"
+#include "libbpf.h"
+#include "util.h"
-#define elog(fmt, ...) { if (err_log) err_log(fmt, ##__VA_ARGS__); }
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
@@ -107,54 +108,54 @@ static int btf_add_type(struct btf *btf, struct btf_type *t)
return 0;
}
-static int btf_parse_hdr(struct btf *btf, btf_print_fn_t err_log)
+static int btf_parse_hdr(struct btf *btf)
{
const struct btf_header *hdr = btf->hdr;
__u32 meta_left;
if (btf->data_size < sizeof(struct btf_header)) {
- elog("BTF header not found\n");
+ pr_debug("BTF header not found\n");
return -EINVAL;
}
if (hdr->magic != BTF_MAGIC) {
- elog("Invalid BTF magic:%x\n", hdr->magic);
+ pr_debug("Invalid BTF magic:%x\n", hdr->magic);
return -EINVAL;
}
if (hdr->version != BTF_VERSION) {
- elog("Unsupported BTF version:%u\n", hdr->version);
+ pr_debug("Unsupported BTF version:%u\n", hdr->version);
return -ENOTSUP;
}
if (hdr->flags) {
- elog("Unsupported BTF flags:%x\n", hdr->flags);
+ pr_debug("Unsupported BTF flags:%x\n", hdr->flags);
return -ENOTSUP;
}
meta_left = btf->data_size - sizeof(*hdr);
if (!meta_left) {
- elog("BTF has no data\n");
+ pr_debug("BTF has no data\n");
return -EINVAL;
}
if (meta_left < hdr->type_off) {
- elog("Invalid BTF type section offset:%u\n", hdr->type_off);
+ pr_debug("Invalid BTF type section offset:%u\n", hdr->type_off);
return -EINVAL;
}
if (meta_left < hdr->str_off) {
- elog("Invalid BTF string section offset:%u\n", hdr->str_off);
+ pr_debug("Invalid BTF string section offset:%u\n", hdr->str_off);
return -EINVAL;
}
if (hdr->type_off >= hdr->str_off) {
- elog("BTF type section offset >= string section offset. No type?\n");
+ pr_debug("BTF type section offset >= string section offset. No type?\n");
return -EINVAL;
}
if (hdr->type_off & 0x02) {
- elog("BTF type section is not aligned to 4 bytes\n");
+ pr_debug("BTF type section is not aligned to 4 bytes\n");
return -EINVAL;
}
@@ -163,7 +164,7 @@ static int btf_parse_hdr(struct btf *btf, btf_print_fn_t err_log)
return 0;
}
-static int btf_parse_str_sec(struct btf *btf, btf_print_fn_t err_log)
+static int btf_parse_str_sec(struct btf *btf)
{
const struct btf_header *hdr = btf->hdr;
const char *start = btf->nohdr_data + hdr->str_off;
@@ -171,7 +172,7 @@ static int btf_parse_str_sec(struct btf *btf, btf_print_fn_t err_log)
if (!hdr->str_len || hdr->str_len - 1 > BTF_MAX_NAME_OFFSET ||
start[0] || end[-1]) {
- elog("Invalid BTF string section\n");
+ pr_debug("Invalid BTF string section\n");
return -EINVAL;
}
@@ -180,7 +181,7 @@ static int btf_parse_str_sec(struct btf *btf, btf_print_fn_t err_log)
return 0;
}
-static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log)
+static int btf_parse_type_sec(struct btf *btf)
{
struct btf_header *hdr = btf->hdr;
void *nohdr_data = btf->nohdr_data;
@@ -219,7 +220,7 @@ static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log)
case BTF_KIND_RESTRICT:
break;
default:
- elog("Unsupported BTF_KIND:%u\n",
+ pr_debug("Unsupported BTF_KIND:%u\n",
BTF_INFO_KIND(t->info));
return -EINVAL;
}
@@ -363,7 +364,7 @@ void btf__free(struct btf *btf)
free(btf);
}
-struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log)
+struct btf *btf__new(__u8 *data, __u32 size)
{
__u32 log_buf_size = 0;
char *log_buf = NULL;
@@ -376,7 +377,7 @@ struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log)
btf->fd = -1;
- if (err_log) {
+ if (libbpf_dprint_level_available(LIBBPF_DEBUG)) {
log_buf = malloc(BPF_LOG_BUF_SIZE);
if (!log_buf) {
err = -ENOMEM;
@@ -400,21 +401,21 @@ struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log)
if (btf->fd == -1) {
err = -errno;
- elog("Error loading BTF: %s(%d)\n", strerror(errno), errno);
+ pr_debug("Error loading BTF: %s(%d)\n", strerror(errno), errno);
if (log_buf && *log_buf)
- elog("%s\n", log_buf);
+ pr_debug("%s\n", log_buf);
goto done;
}
- err = btf_parse_hdr(btf, err_log);
+ err = btf_parse_hdr(btf);
if (err)
goto done;
- err = btf_parse_str_sec(btf, err_log);
+ err = btf_parse_str_sec(btf);
if (err)
goto done;
- err = btf_parse_type_sec(btf, err_log);
+ err = btf_parse_type_sec(btf);
done:
free(log_buf);
@@ -491,7 +492,7 @@ int btf__get_from_id(__u32 id, struct btf **btf)
goto exit_free;
}
- *btf = btf__new((__u8 *)(long)btf_info.btf, btf_info.btf_size, NULL);
+ *btf = btf__new((__u8 *)(long)btf_info.btf, btf_info.btf_size);
if (IS_ERR(*btf)) {
err = PTR_ERR(*btf);
*btf = NULL;
@@ -514,8 +515,7 @@ struct btf_ext_sec_copy_param {
static int btf_ext_copy_info(struct btf_ext *btf_ext,
__u8 *data, __u32 data_size,
- struct btf_ext_sec_copy_param *ext_sec,
- btf_print_fn_t err_log)
+ struct btf_ext_sec_copy_param *ext_sec)
{
const struct btf_ext_header *hdr = (struct btf_ext_header *)data;
const struct btf_ext_info_sec *sinfo;
@@ -529,14 +529,14 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext,
data_size -= hdr->hdr_len;
if (ext_sec->off & 0x03) {
- elog(".BTF.ext %s section is not aligned to 4 bytes\n",
+ pr_debug(".BTF.ext %s section is not aligned to 4 bytes\n",
ext_sec->desc);
return -EINVAL;
}
if (data_size < ext_sec->off ||
ext_sec->len > data_size - ext_sec->off) {
- elog("%s section (off:%u len:%u) is beyond the end of the ELF section .BTF.ext\n",
+ pr_debug("%s section (off:%u len:%u) is beyond the end of the ELF section .BTF.ext\n",
ext_sec->desc, ext_sec->off, ext_sec->len);
return -EINVAL;
}
@@ -546,7 +546,7 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext,
/* At least a record size */
if (info_left < sizeof(__u32)) {
- elog(".BTF.ext %s record size not found\n", ext_sec->desc);
+ pr_debug(".BTF.ext %s record size not found\n", ext_sec->desc);
return -EINVAL;
}
@@ -554,7 +554,7 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext,
record_size = *(__u32 *)info;
if (record_size < ext_sec->min_rec_size ||
record_size & 0x03) {
- elog("%s section in .BTF.ext has invalid record size %u\n",
+ pr_debug("%s section in .BTF.ext has invalid record size %u\n",
ext_sec->desc, record_size);
return -EINVAL;
}
@@ -564,7 +564,7 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext,
/* If no records, return failure now so .BTF.ext won't be used. */
if (!info_left) {
- elog("%s section in .BTF.ext has no records", ext_sec->desc);
+ pr_debug("%s section in .BTF.ext has no records", ext_sec->desc);
return -EINVAL;
}
@@ -574,14 +574,14 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext,
__u32 num_records;
if (info_left < sec_hdrlen) {
- elog("%s section header is not found in .BTF.ext\n",
+ pr_debug("%s section header is not found in .BTF.ext\n",
ext_sec->desc);
return -EINVAL;
}
num_records = sinfo->num_info;
if (num_records == 0) {
- elog("%s section has incorrect num_records in .BTF.ext\n",
+ pr_debug("%s section has incorrect num_records in .BTF.ext\n",
ext_sec->desc);
return -EINVAL;
}
@@ -589,7 +589,7 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext,
total_record_size = sec_hdrlen +
(__u64)num_records * record_size;
if (info_left < total_record_size) {
- elog("%s section has incorrect num_records in .BTF.ext\n",
+ pr_debug("%s section has incorrect num_records in .BTF.ext\n",
ext_sec->desc);
return -EINVAL;
}
@@ -610,8 +610,7 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext,
}
static int btf_ext_copy_func_info(struct btf_ext *btf_ext,
- __u8 *data, __u32 data_size,
- btf_print_fn_t err_log)
+ __u8 *data, __u32 data_size)
{
const struct btf_ext_header *hdr = (struct btf_ext_header *)data;
struct btf_ext_sec_copy_param param = {
@@ -622,12 +621,11 @@ static int btf_ext_copy_func_info(struct btf_ext *btf_ext,
.desc = "func_info"
};
- return btf_ext_copy_info(btf_ext, data, data_size, ¶m, err_log);
+ return btf_ext_copy_info(btf_ext, data, data_size, ¶m);
}
static int btf_ext_copy_line_info(struct btf_ext *btf_ext,
- __u8 *data, __u32 data_size,
- btf_print_fn_t err_log)
+ __u8 *data, __u32 data_size)
{
const struct btf_ext_header *hdr = (struct btf_ext_header *)data;
struct btf_ext_sec_copy_param param = {
@@ -638,37 +636,36 @@ static int btf_ext_copy_line_info(struct btf_ext *btf_ext,
.desc = "line_info",
};
- return btf_ext_copy_info(btf_ext, data, data_size, ¶m, err_log);
+ return btf_ext_copy_info(btf_ext, data, data_size, ¶m);
}
-static int btf_ext_parse_hdr(__u8 *data, __u32 data_size,
- btf_print_fn_t err_log)
+static int btf_ext_parse_hdr(__u8 *data, __u32 data_size)
{
const struct btf_ext_header *hdr = (struct btf_ext_header *)data;
if (data_size < offsetof(struct btf_ext_header, func_info_off) ||
data_size < hdr->hdr_len) {
- elog("BTF.ext header not found");
+ pr_debug("BTF.ext header not found");
return -EINVAL;
}
if (hdr->magic != BTF_MAGIC) {
- elog("Invalid BTF.ext magic:%x\n", hdr->magic);
+ pr_debug("Invalid BTF.ext magic:%x\n", hdr->magic);
return -EINVAL;
}
if (hdr->version != BTF_VERSION) {
- elog("Unsupported BTF.ext version:%u\n", hdr->version);
+ pr_debug("Unsupported BTF.ext version:%u\n", hdr->version);
return -ENOTSUP;
}
if (hdr->flags) {
- elog("Unsupported BTF.ext flags:%x\n", hdr->flags);
+ pr_debug("Unsupported BTF.ext flags:%x\n", hdr->flags);
return -ENOTSUP;
}
if (data_size == hdr->hdr_len) {
- elog("BTF.ext has no data\n");
+ pr_debug("BTF.ext has no data\n");
return -EINVAL;
}
@@ -685,12 +682,12 @@ void btf_ext__free(struct btf_ext *btf_ext)
free(btf_ext);
}
-struct btf_ext *btf_ext__new(__u8 *data, __u32 size, btf_print_fn_t err_log)
+struct btf_ext *btf_ext__new(__u8 *data, __u32 size)
{
struct btf_ext *btf_ext;
int err;
- err = btf_ext_parse_hdr(data, size, err_log);
+ err = btf_ext_parse_hdr(data, size);
if (err)
return ERR_PTR(err);
@@ -698,13 +695,13 @@ struct btf_ext *btf_ext__new(__u8 *data, __u32 size, btf_print_fn_t err_log)
if (!btf_ext)
return ERR_PTR(-ENOMEM);
- err = btf_ext_copy_func_info(btf_ext, data, size, err_log);
+ err = btf_ext_copy_func_info(btf_ext, data, size);
if (err) {
btf_ext__free(btf_ext);
return ERR_PTR(err);
}
- err = btf_ext_copy_line_info(btf_ext, data, size, err_log);
+ err = btf_ext_copy_line_info(btf_ext, data, size);
if (err) {
btf_ext__free(btf_ext);
return ERR_PTR(err);
diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h
index b0610dcdae6b..b1e8e54cc21d 100644
--- a/tools/lib/bpf/btf.h
+++ b/tools/lib/bpf/btf.h
@@ -55,11 +55,8 @@ struct btf_ext_header {
__u32 line_info_len;
};
-typedef int (*btf_print_fn_t)(const char *, ...)
- __attribute__((format(printf, 1, 2)));
-
LIBBPF_API void btf__free(struct btf *btf);
-LIBBPF_API struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log);
+LIBBPF_API struct btf *btf__new(__u8 *data, __u32 size);
LIBBPF_API __s32 btf__find_by_name(const struct btf *btf,
const char *type_name);
LIBBPF_API const struct btf_type *btf__type_by_id(const struct btf *btf,
@@ -70,7 +67,7 @@ LIBBPF_API int btf__fd(const struct btf *btf);
LIBBPF_API const char *btf__name_by_offset(const struct btf *btf, __u32 offset);
LIBBPF_API int btf__get_from_id(__u32 id, struct btf **btf);
-struct btf_ext *btf_ext__new(__u8 *data, __u32 size, btf_print_fn_t err_log);
+struct btf_ext *btf_ext__new(__u8 *data, __u32 size);
void btf_ext__free(struct btf_ext *btf_ext);
int btf_ext__reloc_func_info(const struct btf *btf,
const struct btf_ext *btf_ext,
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 2ccde17957e6..1ede6b93653e 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -42,6 +42,7 @@
#include "bpf.h"
#include "btf.h"
#include "str_error.h"
+#include "util.h"
#ifndef EM_BPF
#define EM_BPF 247
@@ -69,16 +70,6 @@ static __printf(1, 2) libbpf_print_fn_t __pr_warning = __base_pr;
static __printf(1, 2) libbpf_print_fn_t __pr_info = __base_pr;
static __printf(1, 2) libbpf_print_fn_t __pr_debug;
-#define __pr(func, fmt, ...) \
-do { \
- if ((func)) \
- (func)("libbpf: " fmt, ##__VA_ARGS__); \
-} while (0)
-
-#define pr_warning(fmt, ...) __pr(__pr_warning, fmt, ##__VA_ARGS__)
-#define pr_info(fmt, ...) __pr(__pr_info, fmt, ##__VA_ARGS__)
-#define pr_debug(fmt, ...) __pr(__pr_debug, fmt, ##__VA_ARGS__)
-
void libbpf_set_print(libbpf_print_fn_t warn,
libbpf_print_fn_t info,
libbpf_print_fn_t debug)
@@ -88,6 +79,35 @@ void libbpf_set_print(libbpf_print_fn_t warn,
__pr_debug = debug;
}
+__printf(2, 3)
+void libbpf_debug_print(enum libbpf_print_level level, const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ if (level == LIBBPF_WARN) {
+ if (__pr_warning)
+ __pr_warning(format, args);
+ } else if (level == LIBBPF_INFO) {
+ if (__pr_info)
+ __pr_info(format, args);
+ } else {
+ if (__pr_debug)
+ __pr_debug(format, args);
+ }
+ va_end(args);
+}
+
+bool libbpf_dprint_level_available(enum libbpf_print_level level)
+{
+ if (level == LIBBPF_WARN)
+ return !!__pr_warning;
+ else if (level == LIBBPF_INFO)
+ return !!__pr_info;
+ else
+ return !!__pr_debug;
+}
+
#define STRERR_BUFSIZE 128
#define CHECK_ERR(action, err, out) do { \
@@ -839,8 +859,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
else if (strcmp(name, "maps") == 0)
obj->efile.maps_shndx = idx;
else if (strcmp(name, BTF_ELF_SEC) == 0) {
- obj->btf = btf__new(data->d_buf, data->d_size,
- __pr_debug);
+ obj->btf = btf__new(data->d_buf, data->d_size);
if (IS_ERR(obj->btf)) {
pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n",
BTF_ELF_SEC, PTR_ERR(obj->btf));
@@ -915,8 +934,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
BTF_EXT_ELF_SEC, BTF_ELF_SEC);
} else {
obj->btf_ext = btf_ext__new(btf_ext_data->d_buf,
- btf_ext_data->d_size,
- __pr_debug);
+ btf_ext_data->d_size);
if (IS_ERR(obj->btf_ext)) {
pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n",
BTF_EXT_ELF_SEC,
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 62ae6cb93da1..4e21971101c9 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -47,6 +47,12 @@ enum libbpf_errno {
LIBBPF_API int libbpf_strerror(int err, char *buf, size_t size);
+enum libbpf_print_level {
+ LIBBPF_WARN,
+ LIBBPF_INFO,
+ LIBBPF_DEBUG,
+};
+
/*
* __printf is defined in include/linux/compiler-gcc.h. However,
* it would be better if libbpf.h didn't depend on Linux header files.
diff --git a/tools/lib/bpf/test_libbpf.cpp b/tools/lib/bpf/test_libbpf.cpp
index abf3fc25c9fa..be67f5ea2c19 100644
--- a/tools/lib/bpf/test_libbpf.cpp
+++ b/tools/lib/bpf/test_libbpf.cpp
@@ -14,5 +14,5 @@ int main(int argc, char *argv[])
bpf_prog_get_fd_by_id(0);
/* btf.h */
- btf__new(NULL, 0, NULL);
+ btf__new(NULL, 0);
}
diff --git a/tools/lib/bpf/util.h b/tools/lib/bpf/util.h
new file mode 100644
index 000000000000..3ae80f486875
--- /dev/null
+++ b/tools/lib/bpf/util.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
+/* Copyright (c) 2019 Facebook */
+
+#ifndef __LIBBPF_COMMON_H
+#define __LIBBPF_COMMON_H
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void libbpf_debug_print(enum libbpf_print_level level,
+ const char *format, ...)
+ __attribute__((format(printf, 2, 3)));
+
+extern bool libbpf_dprint_level_available(enum libbpf_print_level level);
+
+#define __pr(level, fmt, ...) \
+do { \
+ libbpf_debug_print(level, "libbpf: " fmt, ##__VA_ARGS__); \
+} while (0)
+
+#define pr_warning(fmt, ...) __pr(LIBBPF_WARN, fmt, ##__VA_ARGS__)
+#define pr_info(fmt, ...) __pr(LIBBPF_INFO, fmt, ##__VA_ARGS__)
+#define pr_debug(fmt, ...) __pr(LIBBPF_DEBUG, fmt, ##__VA_ARGS__)
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
--
2.17.1
^ permalink raw reply related
* [PATCH bpf-next v3 2/3] tools/bpf: print out btf log at LIBBPF_WARN level
From: Yonghong Song @ 2019-02-01 22:06 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Magnus Karlsson, netdev
Cc: Alexei Starovoitov, Daniel Borkmann, kernel-team, Yonghong Song
In-Reply-To: <20190201220616.1802774-1-yhs@fb.com>
Currently, the btf log is allocated and printed out in case
of error at LIBBPF_DEBUG level.
Such logs from kernel are very important for debugging.
For example, bpf syscall BPF_PROG_LOAD command can get
verifier logs back to user space. In function load_program()
of libbpf.c, the log buffer is allocated unconditionally
and printed out at pr_warning() level.
Let us do the similar thing here for btf. Allocate buffer
unconditionally and print out error logs at pr_warning() level.
This is to reduce one global function and
optimize for common situations where pr_warning()
is activated either by default or by user supplied
debug output function.
Signed-off-by: Yonghong Song <yhs@fb.com>
---
tools/lib/bpf/btf.c | 19 +++++++++----------
tools/lib/bpf/libbpf.c | 10 ----------
tools/lib/bpf/util.h | 2 --
3 files changed, 9 insertions(+), 22 deletions(-)
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 159104ec31dc..46271bc19572 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -377,16 +377,15 @@ struct btf *btf__new(__u8 *data, __u32 size)
btf->fd = -1;
- if (libbpf_dprint_level_available(LIBBPF_DEBUG)) {
- log_buf = malloc(BPF_LOG_BUF_SIZE);
- if (!log_buf) {
- err = -ENOMEM;
- goto done;
- }
- *log_buf = 0;
- log_buf_size = BPF_LOG_BUF_SIZE;
+ log_buf = malloc(BPF_LOG_BUF_SIZE);
+ if (!log_buf) {
+ err = -ENOMEM;
+ goto done;
}
+ *log_buf = 0;
+ log_buf_size = BPF_LOG_BUF_SIZE;
+
btf->data = malloc(size);
if (!btf->data) {
err = -ENOMEM;
@@ -401,9 +400,9 @@ struct btf *btf__new(__u8 *data, __u32 size)
if (btf->fd == -1) {
err = -errno;
- pr_debug("Error loading BTF: %s(%d)\n", strerror(errno), errno);
+ pr_warning("Error loading BTF: %s(%d)\n", strerror(errno), errno);
if (log_buf && *log_buf)
- pr_debug("%s\n", log_buf);
+ pr_warning("%s\n", log_buf);
goto done;
}
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 1ede6b93653e..1b1c0b504d25 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -98,16 +98,6 @@ void libbpf_debug_print(enum libbpf_print_level level, const char *format, ...)
va_end(args);
}
-bool libbpf_dprint_level_available(enum libbpf_print_level level)
-{
- if (level == LIBBPF_WARN)
- return !!__pr_warning;
- else if (level == LIBBPF_INFO)
- return !!__pr_info;
- else
- return !!__pr_debug;
-}
-
#define STRERR_BUFSIZE 128
#define CHECK_ERR(action, err, out) do { \
diff --git a/tools/lib/bpf/util.h b/tools/lib/bpf/util.h
index 3ae80f486875..66d65b803095 100644
--- a/tools/lib/bpf/util.h
+++ b/tools/lib/bpf/util.h
@@ -14,8 +14,6 @@ extern void libbpf_debug_print(enum libbpf_print_level level,
const char *format, ...)
__attribute__((format(printf, 2, 3)));
-extern bool libbpf_dprint_level_available(enum libbpf_print_level level);
-
#define __pr(level, fmt, ...) \
do { \
libbpf_debug_print(level, "libbpf: " fmt, ##__VA_ARGS__); \
--
2.17.1
^ permalink raw reply related
* [PATCH bpf-next v3 3/3] tools/bpf: simplify libbpf API function libbpf_set_print()
From: Yonghong Song @ 2019-02-01 22:06 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Magnus Karlsson, netdev
Cc: Alexei Starovoitov, Daniel Borkmann, kernel-team, Yonghong Song
In-Reply-To: <20190201220616.1802774-1-yhs@fb.com>
Currently, the libbpf API function libbpf_set_print()
takes three function pointer parameters for warning, info
and debug printout respectively.
This patch changes the API to have just one function pointer
parameter and the function pointer has one additional
parameter "debugging level". So if in the future, if
the debug level is increased, the function signature
won't change.
Signed-off-by: Yonghong Song <yhs@fb.com>
---
tools/lib/bpf/libbpf.c | 33 +++++++----------
tools/lib/bpf/libbpf.h | 14 +++-----
tools/lib/bpf/test_libbpf.cpp | 2 +-
tools/perf/util/bpf-loader.c | 32 +++++++----------
tools/testing/selftests/bpf/test_btf.c | 7 ++--
.../testing/selftests/bpf/test_libbpf_open.c | 36 +++++++++----------
tools/testing/selftests/bpf/test_progs.c | 20 +++++++++--
7 files changed, 68 insertions(+), 76 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 1b1c0b504d25..a707bfff7200 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -54,29 +54,26 @@
#define __printf(a, b) __attribute__((format(printf, a, b)))
-__printf(1, 2)
-static int __base_pr(const char *format, ...)
+__printf(2, 3)
+static int __base_pr(enum libbpf_print_level level, const char *format, ...)
{
va_list args;
int err;
+ if (level == LIBBPF_DEBUG)
+ return 0;
+
va_start(args, format);
err = vfprintf(stderr, format, args);
va_end(args);
return err;
}
-static __printf(1, 2) libbpf_print_fn_t __pr_warning = __base_pr;
-static __printf(1, 2) libbpf_print_fn_t __pr_info = __base_pr;
-static __printf(1, 2) libbpf_print_fn_t __pr_debug;
+static __printf(2, 3) libbpf_print_fn_t __libbpf_pr = __base_pr;
-void libbpf_set_print(libbpf_print_fn_t warn,
- libbpf_print_fn_t info,
- libbpf_print_fn_t debug)
+void libbpf_set_print(libbpf_print_fn_t fn)
{
- __pr_warning = warn;
- __pr_info = info;
- __pr_debug = debug;
+ __libbpf_pr = fn;
}
__printf(2, 3)
@@ -84,17 +81,11 @@ void libbpf_debug_print(enum libbpf_print_level level, const char *format, ...)
{
va_list args;
+ if (!__libbpf_pr)
+ return;
+
va_start(args, format);
- if (level == LIBBPF_WARN) {
- if (__pr_warning)
- __pr_warning(format, args);
- } else if (level == LIBBPF_INFO) {
- if (__pr_info)
- __pr_info(format, args);
- } else {
- if (__pr_debug)
- __pr_debug(format, args);
- }
+ __libbpf_pr(level, format, args);
va_end(args);
}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 4e21971101c9..f8f27f1bb6bf 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -53,17 +53,11 @@ enum libbpf_print_level {
LIBBPF_DEBUG,
};
-/*
- * __printf is defined in include/linux/compiler-gcc.h. However,
- * it would be better if libbpf.h didn't depend on Linux header files.
- * So instead of __printf, here we use gcc attribute directly.
- */
-typedef int (*libbpf_print_fn_t)(const char *, ...)
- __attribute__((format(printf, 1, 2)));
+typedef int (*libbpf_print_fn_t)(enum libbpf_print_level level,
+ const char *, ...)
+ __attribute__((format(printf, 2, 3)));
-LIBBPF_API void libbpf_set_print(libbpf_print_fn_t warn,
- libbpf_print_fn_t info,
- libbpf_print_fn_t debug);
+LIBBPF_API void libbpf_set_print(libbpf_print_fn_t fn);
/* Hide internal to user */
struct bpf_object;
diff --git a/tools/lib/bpf/test_libbpf.cpp b/tools/lib/bpf/test_libbpf.cpp
index be67f5ea2c19..fc134873bb6d 100644
--- a/tools/lib/bpf/test_libbpf.cpp
+++ b/tools/lib/bpf/test_libbpf.cpp
@@ -8,7 +8,7 @@
int main(int argc, char *argv[])
{
/* libbpf.h */
- libbpf_set_print(NULL, NULL, NULL);
+ libbpf_set_print(NULL);
/* bpf.h */
bpf_prog_get_fd_by_id(0);
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 2f3eb6d293ee..c492f3a2acdc 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -24,21 +24,17 @@
#include "llvm-utils.h"
#include "c++/clang-c.h"
-#define DEFINE_PRINT_FN(name, level) \
-static int libbpf_##name(const char *fmt, ...) \
-{ \
- va_list args; \
- int ret; \
- \
- va_start(args, fmt); \
- ret = veprintf(level, verbose, pr_fmt(fmt), args);\
- va_end(args); \
- return ret; \
-}
+static int libbpf_perf_dprint(enum libbpf_print_level level __attribute__((unused)),
+ const char *fmt, ...)
+{
+ va_list args;
+ int ret;
-DEFINE_PRINT_FN(warning, 1)
-DEFINE_PRINT_FN(info, 1)
-DEFINE_PRINT_FN(debug, 1)
+ va_start(args, fmt);
+ ret = veprintf(1, verbose, pr_fmt(fmt), args);
+ va_end(args);
+ return ret;
+}
struct bpf_prog_priv {
bool is_tp;
@@ -59,9 +55,7 @@ bpf__prepare_load_buffer(void *obj_buf, size_t obj_buf_sz, const char *name)
struct bpf_object *obj;
if (!libbpf_initialized) {
- libbpf_set_print(libbpf_warning,
- libbpf_info,
- libbpf_debug);
+ libbpf_set_print(libbpf_perf_dprint);
libbpf_initialized = true;
}
@@ -79,9 +73,7 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source)
struct bpf_object *obj;
if (!libbpf_initialized) {
- libbpf_set_print(libbpf_warning,
- libbpf_info,
- libbpf_debug);
+ libbpf_set_print(libbpf_perf_dprint);
libbpf_initialized = true;
}
diff --git a/tools/testing/selftests/bpf/test_btf.c b/tools/testing/selftests/bpf/test_btf.c
index 179f1d8ec5bf..aebaeff5a5a0 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -54,8 +54,9 @@ static int count_result(int err)
#define __printf(a, b) __attribute__((format(printf, a, b)))
-__printf(1, 2)
-static int __base_pr(const char *format, ...)
+__printf(2, 3)
+static int __base_pr(enum libbpf_print_level level __attribute__((unused)),
+ const char *format, ...)
{
va_list args;
int err;
@@ -5650,7 +5651,7 @@ int main(int argc, char **argv)
return err;
if (args.always_log)
- libbpf_set_print(__base_pr, __base_pr, __base_pr);
+ libbpf_set_print(__base_pr);
if (args.raw_test)
err |= test_raw();
diff --git a/tools/testing/selftests/bpf/test_libbpf_open.c b/tools/testing/selftests/bpf/test_libbpf_open.c
index 8fcd1c076add..3fe258520e4b 100644
--- a/tools/testing/selftests/bpf/test_libbpf_open.c
+++ b/tools/testing/selftests/bpf/test_libbpf_open.c
@@ -34,23 +34,22 @@ static void usage(char *argv[])
printf("\n");
}
-#define DEFINE_PRINT_FN(name, enabled) \
-static int libbpf_##name(const char *fmt, ...) \
-{ \
- va_list args; \
- int ret; \
- \
- va_start(args, fmt); \
- if (enabled) { \
- fprintf(stderr, "[" #name "] "); \
- ret = vfprintf(stderr, fmt, args); \
- } \
- va_end(args); \
- return ret; \
+static bool debug = 0;
+static int libbpf_print(enum libbpf_print_level level,
+ const char *fmt, ...)
+{
+ va_list args;
+ int ret;
+
+ if (level == LIBBPF_DEBUG && !debug)
+ return 0;
+
+ va_start(args, fmt);
+ fprintf(stderr, "[%d] ", level);
+ ret = vfprintf(stderr, fmt, args);
+ va_end(args);
+ return ret;
}
-DEFINE_PRINT_FN(warning, 1)
-DEFINE_PRINT_FN(info, 1)
-DEFINE_PRINT_FN(debug, 1)
#define EXIT_FAIL_LIBBPF EXIT_FAILURE
#define EXIT_FAIL_OPTION 2
@@ -120,15 +119,14 @@ int main(int argc, char **argv)
int longindex = 0;
int opt;
- libbpf_set_print(libbpf_warning, libbpf_info, NULL);
+ libbpf_set_print(libbpf_print);
/* Parse commands line args */
while ((opt = getopt_long(argc, argv, "hDq",
long_options, &longindex)) != -1) {
switch (opt) {
case 'D':
- libbpf_set_print(libbpf_warning, libbpf_info,
- libbpf_debug);
+ debug = 1;
break;
case 'q': /* Use in scripting mode */
verbose = 0;
diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
index a08d026ac396..252cea259438 100644
--- a/tools/testing/selftests/bpf/test_progs.c
+++ b/tools/testing/selftests/bpf/test_progs.c
@@ -10,6 +10,7 @@
#include <string.h>
#include <assert.h>
#include <stdlib.h>
+#include <stdarg.h>
#include <time.h>
#include <linux/types.h>
@@ -1783,6 +1784,21 @@ static void test_task_fd_query_tp(void)
"sys_enter_read");
}
+static int libbpf_print(enum libbpf_print_level level,
+ const char *format, ...)
+{
+ va_list args;
+ int ret;
+
+ if (level == LIBBPF_DEBUG)
+ return 0;
+
+ va_start(args, format);
+ ret = vfprintf(stderr, format, args);
+ va_end(args);
+ return ret;
+}
+
static void test_reference_tracking()
{
const char *file = "./test_sk_lookup_kern.o";
@@ -1809,9 +1825,9 @@ static void test_reference_tracking()
/* Expect verifier failure if test name has 'fail' */
if (strstr(title, "fail") != NULL) {
- libbpf_set_print(NULL, NULL, NULL);
+ libbpf_set_print(NULL);
err = !bpf_program__load(prog, "GPL", 0);
- libbpf_set_print(printf, printf, NULL);
+ libbpf_set_print(libbpf_print);
} else {
err = bpf_program__load(prog, "GPL", 0);
}
--
2.17.1
^ permalink raw reply related
* [PATCH bpf-next v3 0/3] tools/bpf: changes of libbpf debug interfaces
From: Yonghong Song @ 2019-02-01 22:06 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Magnus Karlsson, netdev
Cc: Alexei Starovoitov, Daniel Borkmann, kernel-team, Yonghong Song
These are patches responding to my comments for
Magnus's patch (https://patchwork.ozlabs.org/patch/1032848/).
The goal is to make pr_* macros available to other C files
than libbpf.c, and to simplify API function libbpf_set_print().
Specifically, Patch #1 used global functions
to facilitate pr_* macros in the header files so they
are available in different C files.
Patch #2 removes the global function libbpf_dprint_level_available()
which is added in Patch 1.
Patch #3 simplified libbpf_set_print() which takes only one print
function with a debug level argument among others.
Changelogs:
v2 -> v3:
. bailed out earlier in libbpf_debug_print() if __libbpf_pr is NULL
. added missing LIBBPF_DEBUG level check in libbpf.c __base_pr().
v1 -> v2:
. Renamed global function libbpf_dprint() to libbpf_debug_print()
to be more expressive.
. Removed libbpf_dprint_level_available() as it is used only
once in btf.c and we can remove it by optimizing for common cases.
Yonghong Song (3):
tools/bpf: move libbpf pr_* debug print functions to headers
tools/bpf: print out btf log at LIBBPF_WARN level
tools/bpf: simplify libbpf API function libbpf_set_print()
tools/lib/bpf/btf.c | 110 +++++++++---------
tools/lib/bpf/btf.h | 7 +-
tools/lib/bpf/libbpf.c | 47 ++++----
tools/lib/bpf/libbpf.h | 20 ++--
tools/lib/bpf/test_libbpf.cpp | 4 +-
tools/lib/bpf/util.h | 30 +++++
tools/perf/util/bpf-loader.c | 32 ++---
tools/testing/selftests/bpf/test_btf.c | 7 +-
.../testing/selftests/bpf/test_libbpf_open.c | 36 +++---
tools/testing/selftests/bpf/test_progs.c | 20 +++-
10 files changed, 171 insertions(+), 142 deletions(-)
create mode 100644 tools/lib/bpf/util.h
--
2.17.1
^ permalink raw reply
* Re: [PATCH bpf-next v5 7/8] libbpf: Add a support for getting xdp prog id on ifindex
From: Jakub Kicinski @ 2019-02-01 21:47 UTC (permalink / raw)
To: Daniel Borkmann; +Cc: Maciej Fijalkowski, ast, netdev, brouer, john.fastabend
In-Reply-To: <5d963a81-6a22-b1c6-e2f6-b6734c6d78ff@iogearbox.net>
On Fri, 1 Feb 2019 22:43:39 +0100, Daniel Borkmann wrote:
> On 02/01/2019 01:19 AM, Maciej Fijalkowski wrote:
> > Since we have a dedicated netlink attributes for xdp setup on a
> > particular interface, it is now possible to retrieve the program id that
> > is currently attached to the interface. The use case is targeted for
> > sample xdp programs, which will store the program id just after loading
> > bpf program onto iface. On shutdown, the sample will make sure that it
> > can unload the program by querying again the iface and verifying that
> > both program id's matches.
> >
> > Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
> > Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
> [...]
> > +int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags)
> > +{
> > + struct xdp_id_md xdp_id = {};
> > + int sock, ret;
> > + __u32 nl_pid;
> > + __u32 mask;
> > +
> > + if (flags & ~XDP_FLAGS_MASK)
> > + return -EINVAL;
> > +
> > + /* Check whether the single {HW,DRV,SKB} mode is set */
> > + flags &= (XDP_FLAGS_SKB_MODE | XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE);
> > + mask = flags - 1;
> > + if (flags && flags & mask)
> > + return -EINVAL;
> > +
> > + sock = libbpf_netlink_open(&nl_pid);
> > + if (sock < 0)
> > + return sock;
> > +
> > + xdp_id.ifindex = ifindex;
> > + xdp_id.flags = flags;
> > +
> > + ret = libbpf_nl_get_link(sock, nl_pid, get_xdp_id, &xdp_id);
> > + if (!ret)
> > + *prog_id = xdp_id.id;
> > +
> > + close(sock);
> > + return ret;
> > +}
>
> Btw, is anyone going to follow-up on XDP_ATTACHED_MULTI support as well
> later on?
I haven't tested to be honest, but I think Maciek got that right -
get_xdp_id_attr() should return IFLA_XDP_PROG_ID or a mode-specific
attr based on flags. And there is a check that only flag is set.
Or do you mean retrieving all program ids with one dump?
^ permalink raw reply
* [PATCH bpf-next v6 7/8] libbpf: Add a support for getting xdp prog id on ifindex
From: Maciej Fijalkowski @ 2019-02-01 21:42 UTC (permalink / raw)
To: daniel, ast; +Cc: netdev, jakub.kicinski, brouer, john.fastabend
In-Reply-To: <20190201214230.1441-1-maciej.fijalkowski@intel.com>
Since we have a dedicated netlink attributes for xdp setup on a
particular interface, it is now possible to retrieve the program id that
is currently attached to the interface. The use case is targeted for
sample xdp programs, which will store the program id just after loading
bpf program onto iface. On shutdown, the sample will make sure that it
can unload the program by querying again the iface and verifying that
both program id's matches.
Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
tools/lib/bpf/libbpf.h | 1 +
tools/lib/bpf/libbpf.map | 1 +
tools/lib/bpf/netlink.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 87 insertions(+)
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 931be6f3408c..43c77e98df6f 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -317,6 +317,7 @@ LIBBPF_API int bpf_prog_load(const char *file, enum bpf_prog_type type,
struct bpf_object **pobj, int *prog_fd);
LIBBPF_API int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags);
+LIBBPF_API int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags);
enum bpf_perf_event_ret {
LIBBPF_PERF_EVENT_DONE = 0,
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index 43ba9bb8d24b..62c680fb13d1 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -132,4 +132,5 @@ LIBBPF_0.0.2 {
bpf_probe_prog_type;
bpf_map_lookup_elem_flags;
bpf_object__find_map_fd_by_name;
+ bpf_get_link_xdp_id;
} LIBBPF_0.0.1;
diff --git a/tools/lib/bpf/netlink.c b/tools/lib/bpf/netlink.c
index 0ce67aea8f3b..ce3ec81b71c0 100644
--- a/tools/lib/bpf/netlink.c
+++ b/tools/lib/bpf/netlink.c
@@ -21,6 +21,12 @@
typedef int (*__dump_nlmsg_t)(struct nlmsghdr *nlmsg, libbpf_dump_nlmsg_t,
void *cookie);
+struct xdp_id_md {
+ int ifindex;
+ __u32 flags;
+ __u32 id;
+};
+
int libbpf_netlink_open(__u32 *nl_pid)
{
struct sockaddr_nl sa;
@@ -196,6 +202,85 @@ static int __dump_link_nlmsg(struct nlmsghdr *nlh,
return dump_link_nlmsg(cookie, ifi, tb);
}
+static unsigned char get_xdp_id_attr(unsigned char mode, __u32 flags)
+{
+ if (mode != XDP_ATTACHED_MULTI)
+ return IFLA_XDP_PROG_ID;
+ if (flags & XDP_FLAGS_DRV_MODE)
+ return IFLA_XDP_DRV_PROG_ID;
+ if (flags & XDP_FLAGS_HW_MODE)
+ return IFLA_XDP_HW_PROG_ID;
+ if (flags & XDP_FLAGS_SKB_MODE)
+ return IFLA_XDP_SKB_PROG_ID;
+
+ return IFLA_XDP_UNSPEC;
+}
+
+static int get_xdp_id(void *cookie, void *msg, struct nlattr **tb)
+{
+ struct nlattr *xdp_tb[IFLA_XDP_MAX + 1];
+ struct xdp_id_md *xdp_id = cookie;
+ struct ifinfomsg *ifinfo = msg;
+ unsigned char mode, xdp_attr;
+ int ret;
+
+ if (xdp_id->ifindex && xdp_id->ifindex != ifinfo->ifi_index)
+ return 0;
+
+ if (!tb[IFLA_XDP])
+ return 0;
+
+ ret = libbpf_nla_parse_nested(xdp_tb, IFLA_XDP_MAX, tb[IFLA_XDP], NULL);
+ if (ret)
+ return ret;
+
+ if (!xdp_tb[IFLA_XDP_ATTACHED])
+ return 0;
+
+ mode = libbpf_nla_getattr_u8(xdp_tb[IFLA_XDP_ATTACHED]);
+ if (mode == XDP_ATTACHED_NONE)
+ return 0;
+
+ xdp_attr = get_xdp_id_attr(mode, xdp_id->flags);
+ if (!xdp_attr || !xdp_tb[xdp_attr])
+ return 0;
+
+ xdp_id->id = libbpf_nla_getattr_u32(xdp_tb[xdp_attr]);
+
+ return 0;
+}
+
+int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags)
+{
+ struct xdp_id_md xdp_id = {};
+ int sock, ret;
+ __u32 nl_pid;
+ __u32 mask;
+
+ if (flags & ~XDP_FLAGS_MASK)
+ return -EINVAL;
+
+ /* Check whether the single {HW,DRV,SKB} mode is set */
+ flags &= (XDP_FLAGS_SKB_MODE | XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE);
+ mask = flags - 1;
+ if (flags && flags & mask)
+ return -EINVAL;
+
+ sock = libbpf_netlink_open(&nl_pid);
+ if (sock < 0)
+ return sock;
+
+ xdp_id.ifindex = ifindex;
+ xdp_id.flags = flags;
+
+ ret = libbpf_nl_get_link(sock, nl_pid, get_xdp_id, &xdp_id);
+ if (!ret)
+ *prog_id = xdp_id.id;
+
+ close(sock);
+ return ret;
+}
+
int libbpf_nl_get_link(int sock, unsigned int nl_pid,
libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie)
{
--
2.16.1
^ permalink raw reply related
* [PATCH bpf-next v6 8/8] samples/bpf: Check the prog id before exiting
From: Maciej Fijalkowski @ 2019-02-01 21:42 UTC (permalink / raw)
To: daniel, ast; +Cc: netdev, jakub.kicinski, brouer, john.fastabend
In-Reply-To: <20190201214230.1441-1-maciej.fijalkowski@intel.com>
Check the program id within the signal handler on polling xdp samples
that were previously converted to libbpf usage. Avoid the situation of
unloading the program that was not attached by sample that is exiting.
Handle also the case where bpf_get_link_xdp_id didn't exit with an error
but the xdp program was not found on an interface.
Reported-by: Michal Papaj <michal.papaj@intel.com>
Reported-by: Jakub Spizewski <jakub.spizewski@intel.com>
Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
samples/bpf/xdp1_user.c | 24 ++++++++++++++++-
samples/bpf/xdp_adjust_tail_user.c | 30 +++++++++++++++++++---
samples/bpf/xdp_redirect_cpu_user.c | 35 ++++++++++++++++++++-----
samples/bpf/xdp_redirect_map_user.c | 49 ++++++++++++++++++++++++++++++++---
samples/bpf/xdp_redirect_user.c | 49 ++++++++++++++++++++++++++++++++---
samples/bpf/xdp_router_ipv4_user.c | 51 ++++++++++++++++++++++++-------------
samples/bpf/xdp_rxq_info_user.c | 33 ++++++++++++++++++++----
samples/bpf/xdp_sample_pkts_user.c | 34 +++++++++++++++++++++----
samples/bpf/xdp_tx_iptunnel_user.c | 28 +++++++++++++++++---
samples/bpf/xdpsock_user.c | 23 ++++++++++++++++-
10 files changed, 308 insertions(+), 48 deletions(-)
diff --git a/samples/bpf/xdp1_user.c b/samples/bpf/xdp1_user.c
index 505bce207165..6a64e93365e1 100644
--- a/samples/bpf/xdp1_user.c
+++ b/samples/bpf/xdp1_user.c
@@ -23,10 +23,22 @@
static int ifindex;
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
+static __u32 prog_id;
static void int_exit(int sig)
{
- bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
+ __u32 curr_prog_id = 0;
+
+ if (bpf_get_link_xdp_id(ifindex, &curr_prog_id, xdp_flags)) {
+ printf("bpf_get_link_xdp_id failed\n");
+ exit(1);
+ }
+ if (prog_id == curr_prog_id)
+ bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
+ else if (!curr_prog_id)
+ printf("couldn't find a prog id on a given interface\n");
+ else
+ printf("program on interface changed, not removing\n");
exit(0);
}
@@ -74,11 +86,14 @@ int main(int argc, char **argv)
struct bpf_prog_load_attr prog_load_attr = {
.prog_type = BPF_PROG_TYPE_XDP,
};
+ struct bpf_prog_info info = {};
+ __u32 info_len = sizeof(info);
const char *optstr = "FSN";
int prog_fd, map_fd, opt;
struct bpf_object *obj;
struct bpf_map *map;
char filename[256];
+ int err;
while ((opt = getopt(argc, argv, optstr)) != -1) {
switch (opt) {
@@ -139,6 +154,13 @@ int main(int argc, char **argv)
return 1;
}
+ err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
+ if (err) {
+ printf("can't get prog info - %s\n", strerror(errno));
+ return err;
+ }
+ prog_id = info.id;
+
poll_stats(map_fd, 2);
return 0;
diff --git a/samples/bpf/xdp_adjust_tail_user.c b/samples/bpf/xdp_adjust_tail_user.c
index 049bddf7778b..07e1b9269e49 100644
--- a/samples/bpf/xdp_adjust_tail_user.c
+++ b/samples/bpf/xdp_adjust_tail_user.c
@@ -25,11 +25,24 @@
static int ifindex = -1;
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
+static __u32 prog_id;
static void int_exit(int sig)
{
- if (ifindex > -1)
- bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
+ __u32 curr_prog_id = 0;
+
+ if (ifindex > -1) {
+ if (bpf_get_link_xdp_id(ifindex, &curr_prog_id, xdp_flags)) {
+ printf("bpf_get_link_xdp_id failed\n");
+ exit(1);
+ }
+ if (prog_id == curr_prog_id)
+ bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
+ else if (!curr_prog_id)
+ printf("couldn't find a prog id on a given iface\n");
+ else
+ printf("program on interface changed, not removing\n");
+ }
exit(0);
}
@@ -72,11 +85,14 @@ int main(int argc, char **argv)
};
unsigned char opt_flags[256] = {};
const char *optstr = "i:T:SNFh";
+ struct bpf_prog_info info = {};
+ __u32 info_len = sizeof(info);
unsigned int kill_after_s = 0;
int i, prog_fd, map_fd, opt;
struct bpf_object *obj;
struct bpf_map *map;
char filename[256];
+ int err;
for (i = 0; i < strlen(optstr); i++)
if (optstr[i] != 'h' && 'a' <= optstr[i] && optstr[i] <= 'z')
@@ -146,9 +162,15 @@ int main(int argc, char **argv)
return 1;
}
- poll_stats(map_fd, kill_after_s);
+ err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
+ if (err) {
+ printf("can't get prog info - %s\n", strerror(errno));
+ return 1;
+ }
+ prog_id = info.id;
- bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
+ poll_stats(map_fd, kill_after_s);
+ int_exit(0);
return 0;
}
diff --git a/samples/bpf/xdp_redirect_cpu_user.c b/samples/bpf/xdp_redirect_cpu_user.c
index 0224afb55845..586b294d72d3 100644
--- a/samples/bpf/xdp_redirect_cpu_user.c
+++ b/samples/bpf/xdp_redirect_cpu_user.c
@@ -32,6 +32,7 @@ static const char *__doc__ =
static int ifindex = -1;
static char ifname_buf[IF_NAMESIZE];
static char *ifname;
+static __u32 prog_id;
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int cpu_map_fd;
@@ -68,11 +69,24 @@ static const struct option long_options[] = {
static void int_exit(int sig)
{
- fprintf(stderr,
- "Interrupted: Removing XDP program on ifindex:%d device:%s\n",
- ifindex, ifname);
- if (ifindex > -1)
- bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
+ __u32 curr_prog_id = 0;
+
+ if (ifindex > -1) {
+ if (bpf_get_link_xdp_id(ifindex, &curr_prog_id, xdp_flags)) {
+ printf("bpf_get_link_xdp_id failed\n");
+ exit(EXIT_FAIL);
+ }
+ if (prog_id == curr_prog_id) {
+ fprintf(stderr,
+ "Interrupted: Removing XDP program on ifindex:%d device:%s\n",
+ ifindex, ifname);
+ bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
+ } else if (!curr_prog_id) {
+ printf("couldn't find a prog id on a given iface\n");
+ } else {
+ printf("program on interface changed, not removing\n");
+ }
+ }
exit(EXIT_OK);
}
@@ -608,6 +622,8 @@ int main(int argc, char **argv)
struct bpf_prog_load_attr prog_load_attr = {
.prog_type = BPF_PROG_TYPE_UNSPEC,
};
+ struct bpf_prog_info info = {};
+ __u32 info_len = sizeof(info);
bool use_separators = true;
bool stress_mode = false;
struct bpf_program *prog;
@@ -617,9 +633,9 @@ int main(int argc, char **argv)
int longindex = 0;
int interval = 2;
int add_cpu = -1;
+ int opt, err;
int prog_fd;
__u32 qsize;
- int opt;
/* Notice: choosing he queue size is very important with the
* ixgbe driver, because it's driver page recycling trick is
@@ -746,6 +762,13 @@ int main(int argc, char **argv)
return EXIT_FAIL_XDP;
}
+ err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
+ if (err) {
+ printf("can't get prog info - %s\n", strerror(errno));
+ return err;
+ }
+ prog_id = info.id;
+
stats_poll(interval, use_separators, prog_name, stress_mode);
return EXIT_OK;
}
diff --git a/samples/bpf/xdp_redirect_map_user.c b/samples/bpf/xdp_redirect_map_user.c
index 470e1a7e8810..327226be5a06 100644
--- a/samples/bpf/xdp_redirect_map_user.c
+++ b/samples/bpf/xdp_redirect_map_user.c
@@ -29,15 +29,41 @@
static int ifindex_in;
static int ifindex_out;
static bool ifindex_out_xdp_dummy_attached = true;
+static __u32 prog_id;
+static __u32 dummy_prog_id;
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int rxcnt_map_fd;
static void int_exit(int sig)
{
- bpf_set_link_xdp_fd(ifindex_in, -1, xdp_flags);
- if (ifindex_out_xdp_dummy_attached)
- bpf_set_link_xdp_fd(ifindex_out, -1, xdp_flags);
+ __u32 curr_prog_id = 0;
+
+ if (bpf_get_link_xdp_id(ifindex_in, &curr_prog_id, xdp_flags)) {
+ printf("bpf_get_link_xdp_id failed\n");
+ exit(1);
+ }
+ if (prog_id == curr_prog_id)
+ bpf_set_link_xdp_fd(ifindex_in, -1, xdp_flags);
+ else if (!curr_prog_id)
+ printf("couldn't find a prog id on iface IN\n");
+ else
+ printf("program on iface IN changed, not removing\n");
+
+ if (ifindex_out_xdp_dummy_attached) {
+ curr_prog_id = 0;
+ if (bpf_get_link_xdp_id(ifindex_out, &curr_prog_id,
+ xdp_flags)) {
+ printf("bpf_get_link_xdp_id failed\n");
+ exit(1);
+ }
+ if (prog_id == curr_prog_id)
+ bpf_set_link_xdp_fd(ifindex_out, -1, xdp_flags);
+ else if (!curr_prog_id)
+ printf("couldn't find a prog id on iface OUT\n");
+ else
+ printf("program on iface OUT changed, not removing\n");
+ }
exit(0);
}
@@ -82,6 +108,8 @@ int main(int argc, char **argv)
.prog_type = BPF_PROG_TYPE_XDP,
};
struct bpf_program *prog, *dummy_prog;
+ struct bpf_prog_info info = {};
+ __u32 info_len = sizeof(info);
int prog_fd, dummy_prog_fd;
const char *optstr = "FSN";
struct bpf_object *obj;
@@ -153,6 +181,13 @@ int main(int argc, char **argv)
return 1;
}
+ ret = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
+ if (ret) {
+ printf("can't get prog info - %s\n", strerror(errno));
+ return ret;
+ }
+ prog_id = info.id;
+
/* Loading dummy XDP prog on out-device */
if (bpf_set_link_xdp_fd(ifindex_out, dummy_prog_fd,
(xdp_flags | XDP_FLAGS_UPDATE_IF_NOEXIST)) < 0) {
@@ -160,6 +195,14 @@ int main(int argc, char **argv)
ifindex_out_xdp_dummy_attached = false;
}
+ memset(&info, 0, sizeof(info));
+ ret = bpf_obj_get_info_by_fd(dummy_prog_fd, &info, &info_len);
+ if (ret) {
+ printf("can't get prog info - %s\n", strerror(errno));
+ return ret;
+ }
+ dummy_prog_id = info.id;
+
signal(SIGINT, int_exit);
signal(SIGTERM, int_exit);
diff --git a/samples/bpf/xdp_redirect_user.c b/samples/bpf/xdp_redirect_user.c
index be6058cda97c..a5d8ad3129ed 100644
--- a/samples/bpf/xdp_redirect_user.c
+++ b/samples/bpf/xdp_redirect_user.c
@@ -29,15 +29,41 @@
static int ifindex_in;
static int ifindex_out;
static bool ifindex_out_xdp_dummy_attached = true;
+static __u32 prog_id;
+static __u32 dummy_prog_id;
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int rxcnt_map_fd;
static void int_exit(int sig)
{
- bpf_set_link_xdp_fd(ifindex_in, -1, xdp_flags);
- if (ifindex_out_xdp_dummy_attached)
- bpf_set_link_xdp_fd(ifindex_out, -1, xdp_flags);
+ __u32 curr_prog_id = 0;
+
+ if (bpf_get_link_xdp_id(ifindex_in, &curr_prog_id, xdp_flags)) {
+ printf("bpf_get_link_xdp_id failed\n");
+ exit(1);
+ }
+ if (prog_id == curr_prog_id)
+ bpf_set_link_xdp_fd(ifindex_in, -1, xdp_flags);
+ else if (!curr_prog_id)
+ printf("couldn't find a prog id on iface IN\n");
+ else
+ printf("program on iface IN changed, not removing\n");
+
+ if (ifindex_out_xdp_dummy_attached) {
+ curr_prog_id = 0;
+ if (bpf_get_link_xdp_id(ifindex_out, &curr_prog_id,
+ xdp_flags)) {
+ printf("bpf_get_link_xdp_id failed\n");
+ exit(1);
+ }
+ if (prog_id == curr_prog_id)
+ bpf_set_link_xdp_fd(ifindex_out, -1, xdp_flags);
+ else if (!curr_prog_id)
+ printf("couldn't find a prog id on iface OUT\n");
+ else
+ printf("program on iface OUT changed, not removing\n");
+ }
exit(0);
}
@@ -84,6 +110,8 @@ int main(int argc, char **argv)
};
struct bpf_program *prog, *dummy_prog;
int prog_fd, tx_port_map_fd, opt;
+ struct bpf_prog_info info = {};
+ __u32 info_len = sizeof(info);
const char *optstr = "FSN";
struct bpf_object *obj;
char filename[256];
@@ -154,6 +182,13 @@ int main(int argc, char **argv)
return 1;
}
+ ret = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
+ if (ret) {
+ printf("can't get prog info - %s\n", strerror(errno));
+ return ret;
+ }
+ prog_id = info.id;
+
/* Loading dummy XDP prog on out-device */
if (bpf_set_link_xdp_fd(ifindex_out, dummy_prog_fd,
(xdp_flags | XDP_FLAGS_UPDATE_IF_NOEXIST)) < 0) {
@@ -161,6 +196,14 @@ int main(int argc, char **argv)
ifindex_out_xdp_dummy_attached = false;
}
+ memset(&info, 0, sizeof(info));
+ ret = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
+ if (ret) {
+ printf("can't get prog info - %s\n", strerror(errno));
+ return ret;
+ }
+ dummy_prog_id = info.id;
+
signal(SIGINT, int_exit);
signal(SIGTERM, int_exit);
diff --git a/samples/bpf/xdp_router_ipv4_user.c b/samples/bpf/xdp_router_ipv4_user.c
index 208d6a996478..79fe7bc26ab4 100644
--- a/samples/bpf/xdp_router_ipv4_user.c
+++ b/samples/bpf/xdp_router_ipv4_user.c
@@ -30,7 +30,8 @@
int sock, sock_arp, flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int total_ifindex;
-int *ifindex_list;
+static int *ifindex_list;
+static __u32 *prog_id_list;
char buf[8192];
static int lpm_map_fd;
static int rxcnt_map_fd;
@@ -41,23 +42,34 @@ static int tx_port_map_fd;
static int get_route_table(int rtm_family);
static void int_exit(int sig)
{
+ __u32 prog_id = 0;
int i = 0;
- for (i = 0; i < total_ifindex; i++)
- bpf_set_link_xdp_fd(ifindex_list[i], -1, flags);
+ for (i = 0; i < total_ifindex; i++) {
+ if (bpf_get_link_xdp_id(ifindex_list[i], &prog_id, flags)) {
+ printf("bpf_get_link_xdp_id on iface %d failed\n",
+ ifindex_list[i]);
+ exit(1);
+ }
+ if (prog_id_list[i] == prog_id)
+ bpf_set_link_xdp_fd(ifindex_list[i], -1, flags);
+ else if (!prog_id)
+ printf("couldn't find a prog id on iface %d\n",
+ ifindex_list[i]);
+ else
+ printf("program on iface %d changed, not removing\n",
+ ifindex_list[i]);
+ prog_id = 0;
+ }
exit(0);
}
static void close_and_exit(int sig)
{
- int i = 0;
-
close(sock);
close(sock_arp);
- for (i = 0; i < total_ifindex; i++)
- bpf_set_link_xdp_fd(ifindex_list[i], -1, flags);
- exit(0);
+ int_exit(0);
}
/* Get the mac address of the interface given interface name */
@@ -186,13 +198,8 @@ static void read_route(struct nlmsghdr *nh, int nll)
route.iface_name = alloca(sizeof(char *) * IFNAMSIZ);
route.iface_name = if_indextoname(route.iface, route.iface_name);
route.mac = getmac(route.iface_name);
- if (route.mac == -1) {
- int i = 0;
-
- for (i = 0; i < total_ifindex; i++)
- bpf_set_link_xdp_fd(ifindex_list[i], -1, flags);
- exit(0);
- }
+ if (route.mac == -1)
+ int_exit(0);
assert(bpf_map_update_elem(tx_port_map_fd,
&route.iface, &route.iface, 0) == 0);
if (rtm_family == AF_INET) {
@@ -625,12 +632,14 @@ int main(int ac, char **argv)
struct bpf_prog_load_attr prog_load_attr = {
.prog_type = BPF_PROG_TYPE_XDP,
};
+ struct bpf_prog_info info = {};
+ __u32 info_len = sizeof(info);
const char *optstr = "SF";
struct bpf_object *obj;
char filename[256];
char **ifname_list;
int prog_fd, opt;
- int i = 1;
+ int err, i = 1;
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
prog_load_attr.file = filename;
@@ -687,7 +696,7 @@ int main(int ac, char **argv)
return 1;
}
- ifindex_list = (int *)malloc(total_ifindex * sizeof(int *));
+ ifindex_list = (int *)calloc(total_ifindex, sizeof(int *));
for (i = 0; i < total_ifindex; i++) {
ifindex_list[i] = if_nametoindex(ifname_list[i]);
if (!ifindex_list[i]) {
@@ -696,6 +705,7 @@ int main(int ac, char **argv)
return 1;
}
}
+ prog_id_list = (__u32 *)calloc(total_ifindex, sizeof(__u32 *));
for (i = 0; i < total_ifindex; i++) {
if (bpf_set_link_xdp_fd(ifindex_list[i], prog_fd, flags) < 0) {
printf("link set xdp fd failed\n");
@@ -706,6 +716,13 @@ int main(int ac, char **argv)
return 1;
}
+ err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
+ if (err) {
+ printf("can't get prog info - %s\n", strerror(errno));
+ return err;
+ }
+ prog_id_list[i] = info.id;
+ memset(&info, 0, sizeof(info));
printf("Attached to %d\n", ifindex_list[i]);
}
signal(SIGINT, int_exit);
diff --git a/samples/bpf/xdp_rxq_info_user.c b/samples/bpf/xdp_rxq_info_user.c
index e7a98c2a440f..1210f3b170f0 100644
--- a/samples/bpf/xdp_rxq_info_user.c
+++ b/samples/bpf/xdp_rxq_info_user.c
@@ -29,6 +29,7 @@ static const char *__doc__ = " XDP RX-queue info extract example\n\n"
static int ifindex = -1;
static char ifname_buf[IF_NAMESIZE];
static char *ifname;
+static __u32 prog_id;
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
@@ -58,11 +59,24 @@ static const struct option long_options[] = {
static void int_exit(int sig)
{
- fprintf(stderr,
- "Interrupted: Removing XDP program on ifindex:%d device:%s\n",
- ifindex, ifname);
- if (ifindex > -1)
- bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
+ __u32 curr_prog_id = 0;
+
+ if (ifindex > -1) {
+ if (bpf_get_link_xdp_id(ifindex, &curr_prog_id, xdp_flags)) {
+ printf("bpf_get_link_xdp_id failed\n");
+ exit(EXIT_FAIL);
+ }
+ if (prog_id == curr_prog_id) {
+ fprintf(stderr,
+ "Interrupted: Removing XDP program on ifindex:%d device:%s\n",
+ ifindex, ifname);
+ bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
+ } else if (!curr_prog_id) {
+ printf("couldn't find a prog id on a given iface\n");
+ } else {
+ printf("program on interface changed, not removing\n");
+ }
+ }
exit(EXIT_OK);
}
@@ -447,6 +461,8 @@ int main(int argc, char **argv)
struct bpf_prog_load_attr prog_load_attr = {
.prog_type = BPF_PROG_TYPE_XDP,
};
+ struct bpf_prog_info info = {};
+ __u32 info_len = sizeof(info);
int prog_fd, map_fd, opt, err;
bool use_separators = true;
struct config cfg = { 0 };
@@ -580,6 +596,13 @@ int main(int argc, char **argv)
return EXIT_FAIL_XDP;
}
+ err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
+ if (err) {
+ printf("can't get prog info - %s\n", strerror(errno));
+ return err;
+ }
+ prog_id = info.id;
+
stats_poll(interval, action, cfg_options);
return EXIT_OK;
}
diff --git a/samples/bpf/xdp_sample_pkts_user.c b/samples/bpf/xdp_sample_pkts_user.c
index 62f34827c775..dc66345a929a 100644
--- a/samples/bpf/xdp_sample_pkts_user.c
+++ b/samples/bpf/xdp_sample_pkts_user.c
@@ -24,25 +24,49 @@ static int pmu_fds[MAX_CPUS], if_idx;
static struct perf_event_mmap_page *headers[MAX_CPUS];
static char *if_name;
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
+static __u32 prog_id;
static int do_attach(int idx, int fd, const char *name)
{
+ struct bpf_prog_info info = {};
+ __u32 info_len = sizeof(info);
int err;
err = bpf_set_link_xdp_fd(idx, fd, xdp_flags);
- if (err < 0)
+ if (err < 0) {
printf("ERROR: failed to attach program to %s\n", name);
+ return err;
+ }
+
+ err = bpf_obj_get_info_by_fd(fd, &info, &info_len);
+ if (err) {
+ printf("can't get prog info - %s\n", strerror(errno));
+ return err;
+ }
+ prog_id = info.id;
return err;
}
static int do_detach(int idx, const char *name)
{
- int err;
+ __u32 curr_prog_id = 0;
+ int err = 0;
- err = bpf_set_link_xdp_fd(idx, -1, 0);
- if (err < 0)
- printf("ERROR: failed to detach program from %s\n", name);
+ err = bpf_get_link_xdp_id(idx, &curr_prog_id, 0);
+ if (err) {
+ printf("bpf_get_link_xdp_id failed\n");
+ return err;
+ }
+ if (prog_id == curr_prog_id) {
+ err = bpf_set_link_xdp_fd(idx, -1, 0);
+ if (err < 0)
+ printf("ERROR: failed to detach prog from %s\n", name);
+ } else if (!curr_prog_id) {
+ printf("couldn't find a prog id on a %s\n", name);
+ } else {
+ printf("program on interface changed, not removing\n");
+ }
return err;
}
diff --git a/samples/bpf/xdp_tx_iptunnel_user.c b/samples/bpf/xdp_tx_iptunnel_user.c
index e3de60930d27..4a1511eb7812 100644
--- a/samples/bpf/xdp_tx_iptunnel_user.c
+++ b/samples/bpf/xdp_tx_iptunnel_user.c
@@ -27,11 +27,24 @@
static int ifindex = -1;
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int rxcnt_map_fd;
+static __u32 prog_id;
static void int_exit(int sig)
{
- if (ifindex > -1)
- bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
+ __u32 curr_prog_id = 0;
+
+ if (ifindex > -1) {
+ if (bpf_get_link_xdp_id(ifindex, &curr_prog_id, xdp_flags)) {
+ printf("bpf_get_link_xdp_id failed\n");
+ exit(1);
+ }
+ if (prog_id == curr_prog_id)
+ bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
+ else if (!curr_prog_id)
+ printf("couldn't find a prog id on a given iface\n");
+ else
+ printf("program on interface changed, not removing\n");
+ }
exit(0);
}
@@ -148,13 +161,15 @@ int main(int argc, char **argv)
int min_port = 0, max_port = 0, vip2tnl_map_fd;
const char *optstr = "i:a:p:s:d:m:T:P:FSNh";
unsigned char opt_flags[256] = {};
+ struct bpf_prog_info info = {};
+ __u32 info_len = sizeof(info);
unsigned int kill_after_s = 0;
struct iptnl_info tnl = {};
struct bpf_object *obj;
struct vip vip = {};
char filename[256];
int opt, prog_fd;
- int i;
+ int i, err;
tnl.family = AF_UNSPEC;
vip.protocol = IPPROTO_TCP;
@@ -276,6 +291,13 @@ int main(int argc, char **argv)
return 1;
}
+ err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
+ if (err) {
+ printf("can't get prog info - %s\n", strerror(errno));
+ return err;
+ }
+ prog_id = info.id;
+
poll_stats(kill_after_s);
bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
diff --git a/samples/bpf/xdpsock_user.c b/samples/bpf/xdpsock_user.c
index 188723784768..f73055e0191f 100644
--- a/samples/bpf/xdpsock_user.c
+++ b/samples/bpf/xdpsock_user.c
@@ -76,6 +76,7 @@ static int opt_poll;
static int opt_shared_packet_buffer;
static int opt_interval = 1;
static u32 opt_xdp_bind_flags;
+static __u32 prog_id;
struct xdp_umem_uqueue {
u32 cached_prod;
@@ -631,9 +632,20 @@ static void *poller(void *arg)
static void int_exit(int sig)
{
+ __u32 curr_prog_id = 0;
+
(void)sig;
dump_stats();
- bpf_set_link_xdp_fd(opt_ifindex, -1, opt_xdp_flags);
+ if (bpf_get_link_xdp_id(opt_ifindex, &curr_prog_id, opt_xdp_flags)) {
+ printf("bpf_get_link_xdp_id failed\n");
+ exit(EXIT_FAILURE);
+ }
+ if (prog_id == curr_prog_id)
+ bpf_set_link_xdp_fd(opt_ifindex, -1, opt_xdp_flags);
+ else if (!curr_prog_id)
+ printf("couldn't find a prog id on a given interface\n");
+ else
+ printf("program on interface changed, not removing\n");
exit(EXIT_SUCCESS);
}
@@ -907,6 +919,8 @@ int main(int argc, char **argv)
.prog_type = BPF_PROG_TYPE_XDP,
};
int prog_fd, qidconf_map, xsks_map;
+ struct bpf_prog_info info = {};
+ __u32 info_len = sizeof(info);
struct bpf_object *obj;
char xdp_filename[256];
struct bpf_map *map;
@@ -953,6 +967,13 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
+ ret = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
+ if (ret) {
+ printf("can't get prog info - %s\n", strerror(errno));
+ return 1;
+ }
+ prog_id = info.id;
+
ret = bpf_map_update_elem(qidconf_map, &key, &opt_queue, 0);
if (ret) {
fprintf(stderr, "ERROR: bpf_map_update_elem qidconf\n");
--
2.16.1
^ permalink raw reply related
* [PATCH bpf-next v6 6/8] samples/bpf: Add a "force" flag to XDP samples
From: Maciej Fijalkowski @ 2019-02-01 21:42 UTC (permalink / raw)
To: daniel, ast; +Cc: netdev, jakub.kicinski, brouer, john.fastabend
In-Reply-To: <20190201214230.1441-1-maciej.fijalkowski@intel.com>
Make xdp samples consistent with iproute2 behavior and set the
XDP_FLAGS_UPDATE_IF_NOEXIST by default when setting the xdp program on
interface. Provide an option for user to force the program loading,
which as a result will not include the mentioned flag in
bpf_set_link_xdp_fd call.
Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Acked-by: John Fastabend <john.fastabend@gmail.com>
---
samples/bpf/xdp1_user.c | 10 +++++---
samples/bpf/xdp_adjust_tail_user.c | 8 ++++--
samples/bpf/xdp_redirect_cpu_user.c | 8 ++++--
samples/bpf/xdp_redirect_map_user.c | 10 +++++---
samples/bpf/xdp_redirect_user.c | 10 +++++---
samples/bpf/xdp_router_ipv4_user.c | 50 +++++++++++++++++++++++++++----------
samples/bpf/xdp_rxq_info_user.c | 8 ++++--
samples/bpf/xdp_sample_pkts_user.c | 40 +++++++++++++++++++++++------
samples/bpf/xdp_tx_iptunnel_user.c | 8 ++++--
samples/bpf/xdpsock_user.c | 7 ++++--
10 files changed, 119 insertions(+), 40 deletions(-)
diff --git a/samples/bpf/xdp1_user.c b/samples/bpf/xdp1_user.c
index 8bfda95c77ad..505bce207165 100644
--- a/samples/bpf/xdp1_user.c
+++ b/samples/bpf/xdp1_user.c
@@ -22,7 +22,7 @@
#include "bpf/libbpf.h"
static int ifindex;
-static __u32 xdp_flags;
+static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static void int_exit(int sig)
{
@@ -63,7 +63,8 @@ static void usage(const char *prog)
"usage: %s [OPTS] IFACE\n\n"
"OPTS:\n"
" -S use skb-mode\n"
- " -N enforce native mode\n",
+ " -N enforce native mode\n"
+ " -F force loading prog\n",
prog);
}
@@ -73,7 +74,7 @@ int main(int argc, char **argv)
struct bpf_prog_load_attr prog_load_attr = {
.prog_type = BPF_PROG_TYPE_XDP,
};
- const char *optstr = "SN";
+ const char *optstr = "FSN";
int prog_fd, map_fd, opt;
struct bpf_object *obj;
struct bpf_map *map;
@@ -87,6 +88,9 @@ int main(int argc, char **argv)
case 'N':
xdp_flags |= XDP_FLAGS_DRV_MODE;
break;
+ case 'F':
+ xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
+ break;
default:
usage(basename(argv[0]));
return 1;
diff --git a/samples/bpf/xdp_adjust_tail_user.c b/samples/bpf/xdp_adjust_tail_user.c
index 3042ce37dae8..049bddf7778b 100644
--- a/samples/bpf/xdp_adjust_tail_user.c
+++ b/samples/bpf/xdp_adjust_tail_user.c
@@ -24,7 +24,7 @@
#define STATS_INTERVAL_S 2U
static int ifindex = -1;
-static __u32 xdp_flags;
+static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static void int_exit(int sig)
{
@@ -60,6 +60,7 @@ static void usage(const char *cmd)
printf(" -T <stop-after-X-seconds> Default: 0 (forever)\n");
printf(" -S use skb-mode\n");
printf(" -N enforce native mode\n");
+ printf(" -F force loading prog\n");
printf(" -h Display this help\n");
}
@@ -70,8 +71,8 @@ int main(int argc, char **argv)
.prog_type = BPF_PROG_TYPE_XDP,
};
unsigned char opt_flags[256] = {};
+ const char *optstr = "i:T:SNFh";
unsigned int kill_after_s = 0;
- const char *optstr = "i:T:SNh";
int i, prog_fd, map_fd, opt;
struct bpf_object *obj;
struct bpf_map *map;
@@ -96,6 +97,9 @@ int main(int argc, char **argv)
case 'N':
xdp_flags |= XDP_FLAGS_DRV_MODE;
break;
+ case 'F':
+ xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
+ break;
default:
usage(argv[0]);
return 1;
diff --git a/samples/bpf/xdp_redirect_cpu_user.c b/samples/bpf/xdp_redirect_cpu_user.c
index 8645ddc2da0e..0224afb55845 100644
--- a/samples/bpf/xdp_redirect_cpu_user.c
+++ b/samples/bpf/xdp_redirect_cpu_user.c
@@ -33,7 +33,7 @@ static int ifindex = -1;
static char ifname_buf[IF_NAMESIZE];
static char *ifname;
-static __u32 xdp_flags;
+static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int cpu_map_fd;
static int rx_cnt_map_fd;
static int redirect_err_cnt_map_fd;
@@ -62,6 +62,7 @@ static const struct option long_options[] = {
{"cpu", required_argument, NULL, 'c' },
{"stress-mode", no_argument, NULL, 'x' },
{"no-separators", no_argument, NULL, 'z' },
+ {"force", no_argument, NULL, 'F' },
{0, 0, NULL, 0 }
};
@@ -651,7 +652,7 @@ int main(int argc, char **argv)
mark_cpus_unavailable();
/* Parse commands line args */
- while ((opt = getopt_long(argc, argv, "hSd:",
+ while ((opt = getopt_long(argc, argv, "hSd:s:p:q:c:xzF",
long_options, &longindex)) != -1) {
switch (opt) {
case 'd':
@@ -700,6 +701,9 @@ int main(int argc, char **argv)
case 'q':
qsize = atoi(optarg);
break;
+ case 'F':
+ xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
+ break;
case 'h':
error:
default:
diff --git a/samples/bpf/xdp_redirect_map_user.c b/samples/bpf/xdp_redirect_map_user.c
index 60d46eea225b..470e1a7e8810 100644
--- a/samples/bpf/xdp_redirect_map_user.c
+++ b/samples/bpf/xdp_redirect_map_user.c
@@ -30,7 +30,7 @@ static int ifindex_in;
static int ifindex_out;
static bool ifindex_out_xdp_dummy_attached = true;
-static __u32 xdp_flags;
+static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int rxcnt_map_fd;
static void int_exit(int sig)
@@ -70,7 +70,8 @@ static void usage(const char *prog)
"usage: %s [OPTS] IFINDEX_IN IFINDEX_OUT\n\n"
"OPTS:\n"
" -S use skb-mode\n"
- " -N enforce native mode\n",
+ " -N enforce native mode\n"
+ " -F force loading prog\n",
prog);
}
@@ -82,7 +83,7 @@ int main(int argc, char **argv)
};
struct bpf_program *prog, *dummy_prog;
int prog_fd, dummy_prog_fd;
- const char *optstr = "SN";
+ const char *optstr = "FSN";
struct bpf_object *obj;
int ret, opt, key = 0;
char filename[256];
@@ -96,6 +97,9 @@ int main(int argc, char **argv)
case 'N':
xdp_flags |= XDP_FLAGS_DRV_MODE;
break;
+ case 'F':
+ xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
+ break;
default:
usage(basename(argv[0]));
return 1;
diff --git a/samples/bpf/xdp_redirect_user.c b/samples/bpf/xdp_redirect_user.c
index 93404820df68..be6058cda97c 100644
--- a/samples/bpf/xdp_redirect_user.c
+++ b/samples/bpf/xdp_redirect_user.c
@@ -30,7 +30,7 @@ static int ifindex_in;
static int ifindex_out;
static bool ifindex_out_xdp_dummy_attached = true;
-static __u32 xdp_flags;
+static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int rxcnt_map_fd;
static void int_exit(int sig)
@@ -70,7 +70,8 @@ static void usage(const char *prog)
"usage: %s [OPTS] IFINDEX_IN IFINDEX_OUT\n\n"
"OPTS:\n"
" -S use skb-mode\n"
- " -N enforce native mode\n",
+ " -N enforce native mode\n"
+ " -F force loading prog\n",
prog);
}
@@ -83,7 +84,7 @@ int main(int argc, char **argv)
};
struct bpf_program *prog, *dummy_prog;
int prog_fd, tx_port_map_fd, opt;
- const char *optstr = "SN";
+ const char *optstr = "FSN";
struct bpf_object *obj;
char filename[256];
int dummy_prog_fd;
@@ -97,6 +98,9 @@ int main(int argc, char **argv)
case 'N':
xdp_flags |= XDP_FLAGS_DRV_MODE;
break;
+ case 'F':
+ xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
+ break;
default:
usage(basename(argv[0]));
return 1;
diff --git a/samples/bpf/xdp_router_ipv4_user.c b/samples/bpf/xdp_router_ipv4_user.c
index c63c6beec7d6..208d6a996478 100644
--- a/samples/bpf/xdp_router_ipv4_user.c
+++ b/samples/bpf/xdp_router_ipv4_user.c
@@ -26,8 +26,9 @@
#include "bpf_util.h"
#include "bpf/libbpf.h"
#include <sys/resource.h>
+#include <libgen.h>
-int sock, sock_arp, flags = 0;
+int sock, sock_arp, flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int total_ifindex;
int *ifindex_list;
char buf[8192];
@@ -608,33 +609,56 @@ static int monitor_route(void)
return ret;
}
+static void usage(const char *prog)
+{
+ fprintf(stderr,
+ "%s: %s [OPTS] interface name list\n\n"
+ "OPTS:\n"
+ " -S use skb-mode\n"
+ " -F force loading prog\n",
+ __func__, prog);
+}
+
int main(int ac, char **argv)
{
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
struct bpf_prog_load_attr prog_load_attr = {
.prog_type = BPF_PROG_TYPE_XDP,
};
+ const char *optstr = "SF";
struct bpf_object *obj;
char filename[256];
char **ifname_list;
- int prog_fd;
+ int prog_fd, opt;
int i = 1;
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
prog_load_attr.file = filename;
- if (ac < 2) {
- printf("usage: %s [-S] Interface name list\n", argv[0]);
- return 1;
+ total_ifindex = ac - 1;
+ ifname_list = (argv + 1);
+
+ while ((opt = getopt(ac, argv, optstr)) != -1) {
+ switch (opt) {
+ case 'S':
+ flags |= XDP_FLAGS_SKB_MODE;
+ total_ifindex--;
+ ifname_list++;
+ break;
+ case 'F':
+ flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
+ total_ifindex--;
+ ifname_list++;
+ break;
+ default:
+ usage(basename(argv[0]));
+ return 1;
+ }
}
- if (!strcmp(argv[1], "-S")) {
- flags = XDP_FLAGS_SKB_MODE;
- total_ifindex = ac - 2;
- ifname_list = (argv + 2);
- } else {
- flags = 0;
- total_ifindex = ac - 1;
- ifname_list = (argv + 1);
+
+ if (optind == ac) {
+ usage(basename(argv[0]));
+ return 1;
}
if (setrlimit(RLIMIT_MEMLOCK, &r)) {
diff --git a/samples/bpf/xdp_rxq_info_user.c b/samples/bpf/xdp_rxq_info_user.c
index ef26f882f92f..e7a98c2a440f 100644
--- a/samples/bpf/xdp_rxq_info_user.c
+++ b/samples/bpf/xdp_rxq_info_user.c
@@ -30,7 +30,7 @@ static int ifindex = -1;
static char ifname_buf[IF_NAMESIZE];
static char *ifname;
-static __u32 xdp_flags;
+static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static struct bpf_map *stats_global_map;
static struct bpf_map *rx_queue_index_map;
@@ -52,6 +52,7 @@ static const struct option long_options[] = {
{"action", required_argument, NULL, 'a' },
{"readmem", no_argument, NULL, 'r' },
{"swapmac", no_argument, NULL, 'm' },
+ {"force", no_argument, NULL, 'F' },
{0, 0, NULL, 0 }
};
@@ -487,7 +488,7 @@ int main(int argc, char **argv)
}
/* Parse commands line args */
- while ((opt = getopt_long(argc, argv, "hSd:",
+ while ((opt = getopt_long(argc, argv, "FhSrmzd:s:a:",
long_options, &longindex)) != -1) {
switch (opt) {
case 'd':
@@ -524,6 +525,9 @@ int main(int argc, char **argv)
case 'm':
cfg_options |= SWAP_MAC;
break;
+ case 'F':
+ xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
+ break;
case 'h':
error:
default:
diff --git a/samples/bpf/xdp_sample_pkts_user.c b/samples/bpf/xdp_sample_pkts_user.c
index 5f5828ee0761..62f34827c775 100644
--- a/samples/bpf/xdp_sample_pkts_user.c
+++ b/samples/bpf/xdp_sample_pkts_user.c
@@ -13,6 +13,8 @@
#include <libbpf.h>
#include <bpf/bpf.h>
#include <sys/resource.h>
+#include <libgen.h>
+#include <linux/if_link.h>
#include "perf-sys.h"
#include "trace_helpers.h"
@@ -21,12 +23,13 @@
static int pmu_fds[MAX_CPUS], if_idx;
static struct perf_event_mmap_page *headers[MAX_CPUS];
static char *if_name;
+static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int do_attach(int idx, int fd, const char *name)
{
int err;
- err = bpf_set_link_xdp_fd(idx, fd, 0);
+ err = bpf_set_link_xdp_fd(idx, fd, xdp_flags);
if (err < 0)
printf("ERROR: failed to attach program to %s\n", name);
@@ -98,21 +101,42 @@ static void sig_handler(int signo)
exit(0);
}
+static void usage(const char *prog)
+{
+ fprintf(stderr,
+ "%s: %s [OPTS] <ifname|ifindex>\n\n"
+ "OPTS:\n"
+ " -F force loading prog\n",
+ __func__, prog);
+}
+
int main(int argc, char **argv)
{
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
struct bpf_prog_load_attr prog_load_attr = {
.prog_type = BPF_PROG_TYPE_XDP,
};
+ const char *optstr = "F";
+ int prog_fd, map_fd, opt;
struct bpf_object *obj;
struct bpf_map *map;
- int prog_fd, map_fd;
char filename[256];
int ret, err, i;
int numcpus;
- if (argc < 2) {
- printf("Usage: %s <ifname>\n", argv[0]);
+ while ((opt = getopt(argc, argv, optstr)) != -1) {
+ switch (opt) {
+ case 'F':
+ xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
+ break;
+ default:
+ usage(basename(argv[0]));
+ return 1;
+ }
+ }
+
+ if (optind == argc) {
+ usage(basename(argv[0]));
return 1;
}
@@ -143,16 +167,16 @@ int main(int argc, char **argv)
}
map_fd = bpf_map__fd(map);
- if_idx = if_nametoindex(argv[1]);
+ if_idx = if_nametoindex(argv[optind]);
if (!if_idx)
- if_idx = strtoul(argv[1], NULL, 0);
+ if_idx = strtoul(argv[optind], NULL, 0);
if (!if_idx) {
fprintf(stderr, "Invalid ifname\n");
return 1;
}
- if_name = argv[1];
- err = do_attach(if_idx, prog_fd, argv[1]);
+ if_name = argv[optind];
+ err = do_attach(if_idx, prog_fd, if_name);
if (err)
return err;
diff --git a/samples/bpf/xdp_tx_iptunnel_user.c b/samples/bpf/xdp_tx_iptunnel_user.c
index 5093d8220da5..e3de60930d27 100644
--- a/samples/bpf/xdp_tx_iptunnel_user.c
+++ b/samples/bpf/xdp_tx_iptunnel_user.c
@@ -25,7 +25,7 @@
#define STATS_INTERVAL_S 2U
static int ifindex = -1;
-static __u32 xdp_flags = 0;
+static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int rxcnt_map_fd;
static void int_exit(int sig)
@@ -83,6 +83,7 @@ static void usage(const char *cmd)
printf(" -P <IP-Protocol> Default is TCP\n");
printf(" -S use skb-mode\n");
printf(" -N enforce native mode\n");
+ printf(" -F Force loading the XDP prog\n");
printf(" -h Display this help\n");
}
@@ -145,7 +146,7 @@ int main(int argc, char **argv)
};
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
int min_port = 0, max_port = 0, vip2tnl_map_fd;
- const char *optstr = "i:a:p:s:d:m:T:P:SNh";
+ const char *optstr = "i:a:p:s:d:m:T:P:FSNh";
unsigned char opt_flags[256] = {};
unsigned int kill_after_s = 0;
struct iptnl_info tnl = {};
@@ -217,6 +218,9 @@ int main(int argc, char **argv)
case 'N':
xdp_flags |= XDP_FLAGS_DRV_MODE;
break;
+ case 'F':
+ xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
+ break;
default:
usage(argv[0]);
return 1;
diff --git a/samples/bpf/xdpsock_user.c b/samples/bpf/xdpsock_user.c
index 57ecadc58403..188723784768 100644
--- a/samples/bpf/xdpsock_user.c
+++ b/samples/bpf/xdpsock_user.c
@@ -68,7 +68,7 @@ enum benchmark_type {
};
static enum benchmark_type opt_bench = BENCH_RXDROP;
-static u32 opt_xdp_flags;
+static u32 opt_xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static const char *opt_if = "";
static int opt_ifindex;
static int opt_queue;
@@ -682,7 +682,7 @@ static void parse_command_line(int argc, char **argv)
opterr = 0;
for (;;) {
- c = getopt_long(argc, argv, "rtli:q:psSNn:cz", long_options,
+ c = getopt_long(argc, argv, "Frtli:q:psSNn:cz", long_options,
&option_index);
if (c == -1)
break;
@@ -725,6 +725,9 @@ static void parse_command_line(int argc, char **argv)
case 'c':
opt_xdp_bind_flags |= XDP_COPY;
break;
+ case 'F':
+ opt_xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
+ break;
default:
usage(basename(argv[0]));
}
--
2.16.1
^ permalink raw reply related
* [PATCH bpf-next v6 3/8] samples/bpf: Convert XDP samples to libbpf usage
From: Maciej Fijalkowski @ 2019-02-01 21:42 UTC (permalink / raw)
To: daniel, ast; +Cc: netdev, jakub.kicinski, brouer, john.fastabend
In-Reply-To: <20190201214230.1441-1-maciej.fijalkowski@intel.com>
Some of XDP samples that are attaching the bpf program to the interface
via libbpf's bpf_set_link_xdp_fd are still using the bpf_load.c for
loading and manipulating the ebpf program and maps. Convert them to do
this through libbpf usage and remove bpf_load from the picture.
While at it remove what looks like debug leftover in
xdp_redirect_map_user.c
In xdp_redirect_cpu, change the way that the program to be loaded onto
interface is chosen - user now needs to pass the program's section name
instead of the relative number. In case of typo print out the section
names to choose from.
Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Acked-by: Jesper Dangaard Brouer <brouer@redhat.com>
---
samples/bpf/Makefile | 8 +-
samples/bpf/xdp_redirect_cpu_user.c | 145 +++++++++++++++++++++++++-----------
samples/bpf/xdp_redirect_map_user.c | 47 ++++++++----
samples/bpf/xdp_redirect_user.c | 44 ++++++++---
samples/bpf/xdp_router_ipv4_user.c | 75 +++++++++++++------
samples/bpf/xdp_tx_iptunnel_user.c | 37 ++++++---
6 files changed, 253 insertions(+), 103 deletions(-)
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index db1a91dfa702..a0ef7eddd0b3 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -87,18 +87,18 @@ test_cgrp2_sock2-objs := bpf_load.o test_cgrp2_sock2.o
xdp1-objs := xdp1_user.o
# reuse xdp1 source intentionally
xdp2-objs := xdp1_user.o
-xdp_router_ipv4-objs := bpf_load.o xdp_router_ipv4_user.o
+xdp_router_ipv4-objs := xdp_router_ipv4_user.o
test_current_task_under_cgroup-objs := bpf_load.o $(CGROUP_HELPERS) \
test_current_task_under_cgroup_user.o
trace_event-objs := bpf_load.o trace_event_user.o $(TRACE_HELPERS)
sampleip-objs := bpf_load.o sampleip_user.o $(TRACE_HELPERS)
tc_l2_redirect-objs := bpf_load.o tc_l2_redirect_user.o
lwt_len_hist-objs := bpf_load.o lwt_len_hist_user.o
-xdp_tx_iptunnel-objs := bpf_load.o xdp_tx_iptunnel_user.o
+xdp_tx_iptunnel-objs := xdp_tx_iptunnel_user.o
test_map_in_map-objs := bpf_load.o test_map_in_map_user.o
per_socket_stats_example-objs := cookie_uid_helper_example.o
-xdp_redirect-objs := bpf_load.o xdp_redirect_user.o
-xdp_redirect_map-objs := bpf_load.o xdp_redirect_map_user.o
+xdp_redirect-objs := xdp_redirect_user.o
+xdp_redirect_map-objs := xdp_redirect_map_user.o
xdp_redirect_cpu-objs := bpf_load.o xdp_redirect_cpu_user.o
xdp_monitor-objs := bpf_load.o xdp_monitor_user.o
xdp_rxq_info-objs := xdp_rxq_info_user.o
diff --git a/samples/bpf/xdp_redirect_cpu_user.c b/samples/bpf/xdp_redirect_cpu_user.c
index f141e752ca0a..8645ddc2da0e 100644
--- a/samples/bpf/xdp_redirect_cpu_user.c
+++ b/samples/bpf/xdp_redirect_cpu_user.c
@@ -24,12 +24,8 @@ static const char *__doc__ =
/* How many xdp_progs are defined in _kern.c */
#define MAX_PROG 6
-/* Wanted to get rid of bpf_load.h and fake-"libbpf.h" (and instead
- * use bpf/libbpf.h), but cannot as (currently) needed for XDP
- * attaching to a device via bpf_set_link_xdp_fd()
- */
#include <bpf/bpf.h>
-#include "bpf_load.h"
+#include "bpf/libbpf.h"
#include "bpf_util.h"
@@ -38,6 +34,15 @@ static char ifname_buf[IF_NAMESIZE];
static char *ifname;
static __u32 xdp_flags;
+static int cpu_map_fd;
+static int rx_cnt_map_fd;
+static int redirect_err_cnt_map_fd;
+static int cpumap_enqueue_cnt_map_fd;
+static int cpumap_kthread_cnt_map_fd;
+static int cpus_available_map_fd;
+static int cpus_count_map_fd;
+static int cpus_iterator_map_fd;
+static int exception_cnt_map_fd;
/* Exit return codes */
#define EXIT_OK 0
@@ -52,7 +57,7 @@ static const struct option long_options[] = {
{"dev", required_argument, NULL, 'd' },
{"skb-mode", no_argument, NULL, 'S' },
{"sec", required_argument, NULL, 's' },
- {"prognum", required_argument, NULL, 'p' },
+ {"progname", required_argument, NULL, 'p' },
{"qsize", required_argument, NULL, 'q' },
{"cpu", required_argument, NULL, 'c' },
{"stress-mode", no_argument, NULL, 'x' },
@@ -70,7 +75,17 @@ static void int_exit(int sig)
exit(EXIT_OK);
}
-static void usage(char *argv[])
+static void print_avail_progs(struct bpf_object *obj)
+{
+ struct bpf_program *pos;
+
+ bpf_object__for_each_program(pos, obj) {
+ if (bpf_program__is_xdp(pos))
+ printf(" %s\n", bpf_program__title(pos, false));
+ }
+}
+
+static void usage(char *argv[], struct bpf_object *obj)
{
int i;
@@ -88,6 +103,8 @@ static void usage(char *argv[])
long_options[i].val);
printf("\n");
}
+ printf("\n Programs to be used for --progname:\n");
+ print_avail_progs(obj);
printf("\n");
}
@@ -262,7 +279,7 @@ static __u64 calc_errs_pps(struct datarec *r,
static void stats_print(struct stats_record *stats_rec,
struct stats_record *stats_prev,
- int prog_num)
+ char *prog_name)
{
unsigned int nr_cpus = bpf_num_possible_cpus();
double pps = 0, drop = 0, err = 0;
@@ -272,7 +289,7 @@ static void stats_print(struct stats_record *stats_rec,
int i;
/* Header */
- printf("Running XDP/eBPF prog_num:%d\n", prog_num);
+ printf("Running XDP/eBPF prog_name:%s\n", prog_name);
printf("%-15s %-7s %-14s %-11s %-9s\n",
"XDP-cpumap", "CPU:to", "pps", "drop-pps", "extra-info");
@@ -423,20 +440,20 @@ static void stats_collect(struct stats_record *rec)
{
int fd, i;
- fd = map_fd[1]; /* map: rx_cnt */
+ fd = rx_cnt_map_fd;
map_collect_percpu(fd, 0, &rec->rx_cnt);
- fd = map_fd[2]; /* map: redirect_err_cnt */
+ fd = redirect_err_cnt_map_fd;
map_collect_percpu(fd, 1, &rec->redir_err);
- fd = map_fd[3]; /* map: cpumap_enqueue_cnt */
+ fd = cpumap_enqueue_cnt_map_fd;
for (i = 0; i < MAX_CPUS; i++)
map_collect_percpu(fd, i, &rec->enq[i]);
- fd = map_fd[4]; /* map: cpumap_kthread_cnt */
+ fd = cpumap_kthread_cnt_map_fd;
map_collect_percpu(fd, 0, &rec->kthread);
- fd = map_fd[8]; /* map: exception_cnt */
+ fd = exception_cnt_map_fd;
map_collect_percpu(fd, 0, &rec->exception);
}
@@ -461,7 +478,7 @@ static int create_cpu_entry(__u32 cpu, __u32 queue_size,
/* Add a CPU entry to cpumap, as this allocate a cpu entry in
* the kernel for the cpu.
*/
- ret = bpf_map_update_elem(map_fd[0], &cpu, &queue_size, 0);
+ ret = bpf_map_update_elem(cpu_map_fd, &cpu, &queue_size, 0);
if (ret) {
fprintf(stderr, "Create CPU entry failed (err:%d)\n", ret);
exit(EXIT_FAIL_BPF);
@@ -470,23 +487,22 @@ static int create_cpu_entry(__u32 cpu, __u32 queue_size,
/* Inform bpf_prog's that a new CPU is available to select
* from via some control maps.
*/
- /* map_fd[5] = cpus_available */
- ret = bpf_map_update_elem(map_fd[5], &avail_idx, &cpu, 0);
+ ret = bpf_map_update_elem(cpus_available_map_fd, &avail_idx, &cpu, 0);
if (ret) {
fprintf(stderr, "Add to avail CPUs failed\n");
exit(EXIT_FAIL_BPF);
}
/* When not replacing/updating existing entry, bump the count */
- /* map_fd[6] = cpus_count */
- ret = bpf_map_lookup_elem(map_fd[6], &key, &curr_cpus_count);
+ ret = bpf_map_lookup_elem(cpus_count_map_fd, &key, &curr_cpus_count);
if (ret) {
fprintf(stderr, "Failed reading curr cpus_count\n");
exit(EXIT_FAIL_BPF);
}
if (new) {
curr_cpus_count++;
- ret = bpf_map_update_elem(map_fd[6], &key, &curr_cpus_count, 0);
+ ret = bpf_map_update_elem(cpus_count_map_fd, &key,
+ &curr_cpus_count, 0);
if (ret) {
fprintf(stderr, "Failed write curr cpus_count\n");
exit(EXIT_FAIL_BPF);
@@ -509,8 +525,8 @@ static void mark_cpus_unavailable(void)
int ret, i;
for (i = 0; i < MAX_CPUS; i++) {
- /* map_fd[5] = cpus_available */
- ret = bpf_map_update_elem(map_fd[5], &i, &invalid_cpu, 0);
+ ret = bpf_map_update_elem(cpus_available_map_fd, &i,
+ &invalid_cpu, 0);
if (ret) {
fprintf(stderr, "Failed marking CPU unavailable\n");
exit(EXIT_FAIL_BPF);
@@ -530,7 +546,7 @@ static void stress_cpumap(void)
create_cpu_entry(1, 16000, 0, false);
}
-static void stats_poll(int interval, bool use_separators, int prog_num,
+static void stats_poll(int interval, bool use_separators, char *prog_name,
bool stress_mode)
{
struct stats_record *record, *prev;
@@ -546,7 +562,7 @@ static void stats_poll(int interval, bool use_separators, int prog_num,
while (1) {
swap(&prev, &record);
stats_collect(record);
- stats_print(record, prev, prog_num);
+ stats_print(record, prev, prog_name);
sleep(interval);
if (stress_mode)
stress_cpumap();
@@ -556,17 +572,51 @@ static void stats_poll(int interval, bool use_separators, int prog_num,
free_stats_record(prev);
}
+static int init_map_fds(struct bpf_object *obj)
+{
+ cpu_map_fd = bpf_object__find_map_fd_by_name(obj, "cpu_map");
+ rx_cnt_map_fd = bpf_object__find_map_fd_by_name(obj, "rx_cnt");
+ redirect_err_cnt_map_fd =
+ bpf_object__find_map_fd_by_name(obj, "redirect_err_cnt");
+ cpumap_enqueue_cnt_map_fd =
+ bpf_object__find_map_fd_by_name(obj, "cpumap_enqueue_cnt");
+ cpumap_kthread_cnt_map_fd =
+ bpf_object__find_map_fd_by_name(obj, "cpumap_kthread_cnt");
+ cpus_available_map_fd =
+ bpf_object__find_map_fd_by_name(obj, "cpus_available");
+ cpus_count_map_fd = bpf_object__find_map_fd_by_name(obj, "cpus_count");
+ cpus_iterator_map_fd =
+ bpf_object__find_map_fd_by_name(obj, "cpus_iterator");
+ exception_cnt_map_fd =
+ bpf_object__find_map_fd_by_name(obj, "exception_cnt");
+
+ if (cpu_map_fd < 0 || rx_cnt_map_fd < 0 ||
+ redirect_err_cnt_map_fd < 0 || cpumap_enqueue_cnt_map_fd < 0 ||
+ cpumap_kthread_cnt_map_fd < 0 || cpus_available_map_fd < 0 ||
+ cpus_count_map_fd < 0 || cpus_iterator_map_fd < 0 ||
+ exception_cnt_map_fd < 0)
+ return -ENOENT;
+
+ return 0;
+}
+
int main(int argc, char **argv)
{
struct rlimit r = {10 * 1024 * 1024, RLIM_INFINITY};
+ char *prog_name = "xdp_cpu_map5_lb_hash_ip_pairs";
+ struct bpf_prog_load_attr prog_load_attr = {
+ .prog_type = BPF_PROG_TYPE_UNSPEC,
+ };
bool use_separators = true;
bool stress_mode = false;
+ struct bpf_program *prog;
+ struct bpf_object *obj;
char filename[256];
int added_cpus = 0;
int longindex = 0;
int interval = 2;
- int prog_num = 5;
int add_cpu = -1;
+ int prog_fd;
__u32 qsize;
int opt;
@@ -579,22 +629,25 @@ int main(int argc, char **argv)
qsize = 128+64;
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
+ prog_load_attr.file = filename;
if (setrlimit(RLIMIT_MEMLOCK, &r)) {
perror("setrlimit(RLIMIT_MEMLOCK)");
return 1;
}
- if (load_bpf_file(filename)) {
- fprintf(stderr, "ERR in load_bpf_file(): %s", bpf_log_buf);
+ if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
return EXIT_FAIL;
- }
- if (!prog_fd[0]) {
- fprintf(stderr, "ERR: load_bpf_file: %s\n", strerror(errno));
+ if (prog_fd < 0) {
+ fprintf(stderr, "ERR: bpf_prog_load_xattr: %s\n",
+ strerror(errno));
+ return EXIT_FAIL;
+ }
+ if (init_map_fds(obj) < 0) {
+ fprintf(stderr, "bpf_object__find_map_fd_by_name failed\n");
return EXIT_FAIL;
}
-
mark_cpus_unavailable();
/* Parse commands line args */
@@ -630,13 +683,7 @@ int main(int argc, char **argv)
break;
case 'p':
/* Selecting eBPF prog to load */
- prog_num = atoi(optarg);
- if (prog_num < 0 || prog_num >= MAX_PROG) {
- fprintf(stderr,
- "--prognum too large err(%d):%s\n",
- errno, strerror(errno));
- goto error;
- }
+ prog_name = optarg;
break;
case 'c':
/* Add multiple CPUs */
@@ -656,21 +703,21 @@ int main(int argc, char **argv)
case 'h':
error:
default:
- usage(argv);
+ usage(argv, obj);
return EXIT_FAIL_OPTION;
}
}
/* Required option */
if (ifindex == -1) {
fprintf(stderr, "ERR: required option --dev missing\n");
- usage(argv);
+ usage(argv, obj);
return EXIT_FAIL_OPTION;
}
/* Required option */
if (add_cpu == -1) {
fprintf(stderr, "ERR: required option --cpu missing\n");
fprintf(stderr, " Specify multiple --cpu option to add more\n");
- usage(argv);
+ usage(argv, obj);
return EXIT_FAIL_OPTION;
}
@@ -678,11 +725,23 @@ int main(int argc, char **argv)
signal(SIGINT, int_exit);
signal(SIGTERM, int_exit);
- if (bpf_set_link_xdp_fd(ifindex, prog_fd[prog_num], xdp_flags) < 0) {
+ prog = bpf_object__find_program_by_title(obj, prog_name);
+ if (!prog) {
+ fprintf(stderr, "bpf_object__find_program_by_title failed\n");
+ return EXIT_FAIL;
+ }
+
+ prog_fd = bpf_program__fd(prog);
+ if (prog_fd < 0) {
+ fprintf(stderr, "bpf_program__fd failed\n");
+ return EXIT_FAIL;
+ }
+
+ if (bpf_set_link_xdp_fd(ifindex, prog_fd, xdp_flags) < 0) {
fprintf(stderr, "link set xdp fd failed\n");
return EXIT_FAIL_XDP;
}
- stats_poll(interval, use_separators, prog_num, stress_mode);
+ stats_poll(interval, use_separators, prog_name, stress_mode);
return EXIT_OK;
}
diff --git a/samples/bpf/xdp_redirect_map_user.c b/samples/bpf/xdp_redirect_map_user.c
index 4445e76854b5..60d46eea225b 100644
--- a/samples/bpf/xdp_redirect_map_user.c
+++ b/samples/bpf/xdp_redirect_map_user.c
@@ -22,15 +22,16 @@
#include <libgen.h>
#include <sys/resource.h>
-#include "bpf_load.h"
#include "bpf_util.h"
#include <bpf/bpf.h>
+#include "bpf/libbpf.h"
static int ifindex_in;
static int ifindex_out;
static bool ifindex_out_xdp_dummy_attached = true;
static __u32 xdp_flags;
+static int rxcnt_map_fd;
static void int_exit(int sig)
{
@@ -53,7 +54,7 @@ static void poll_stats(int interval, int ifindex)
int i;
sleep(interval);
- assert(bpf_map_lookup_elem(map_fd[1], &key, values) == 0);
+ assert(bpf_map_lookup_elem(rxcnt_map_fd, &key, values) == 0);
for (i = 0; i < nr_cpus; i++)
sum += (values[i] - prev[i]);
if (sum)
@@ -76,9 +77,16 @@ static void usage(const char *prog)
int main(int argc, char **argv)
{
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
+ struct bpf_prog_load_attr prog_load_attr = {
+ .prog_type = BPF_PROG_TYPE_XDP,
+ };
+ struct bpf_program *prog, *dummy_prog;
+ int prog_fd, dummy_prog_fd;
const char *optstr = "SN";
- char filename[256];
+ struct bpf_object *obj;
int ret, opt, key = 0;
+ char filename[256];
+ int tx_port_map_fd;
while ((opt = getopt(argc, argv, optstr)) != -1) {
switch (opt) {
@@ -109,24 +117,40 @@ int main(int argc, char **argv)
printf("input: %d output: %d\n", ifindex_in, ifindex_out);
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
+ prog_load_attr.file = filename;
+
+ if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
+ return 1;
- if (load_bpf_file(filename)) {
- printf("%s", bpf_log_buf);
+ prog = bpf_program__next(NULL, obj);
+ dummy_prog = bpf_program__next(prog, obj);
+ if (!prog || !dummy_prog) {
+ printf("finding a prog in obj file failed\n");
+ return 1;
+ }
+ /* bpf_prog_load_xattr gives us the pointer to first prog's fd,
+ * so we're missing only the fd for dummy prog
+ */
+ dummy_prog_fd = bpf_program__fd(dummy_prog);
+ if (prog_fd < 0 || dummy_prog_fd < 0) {
+ printf("bpf_prog_load_xattr: %s\n", strerror(errno));
return 1;
}
- if (!prog_fd[0]) {
- printf("load_bpf_file: %s\n", strerror(errno));
+ tx_port_map_fd = bpf_object__find_map_fd_by_name(obj, "tx_port");
+ rxcnt_map_fd = bpf_object__find_map_fd_by_name(obj, "rxcnt");
+ if (tx_port_map_fd < 0 || rxcnt_map_fd < 0) {
+ printf("bpf_object__find_map_fd_by_name failed\n");
return 1;
}
- if (bpf_set_link_xdp_fd(ifindex_in, prog_fd[0], xdp_flags) < 0) {
+ if (bpf_set_link_xdp_fd(ifindex_in, prog_fd, xdp_flags) < 0) {
printf("ERROR: link set xdp fd failed on %d\n", ifindex_in);
return 1;
}
/* Loading dummy XDP prog on out-device */
- if (bpf_set_link_xdp_fd(ifindex_out, prog_fd[1],
+ if (bpf_set_link_xdp_fd(ifindex_out, dummy_prog_fd,
(xdp_flags | XDP_FLAGS_UPDATE_IF_NOEXIST)) < 0) {
printf("WARN: link set xdp fd failed on %d\n", ifindex_out);
ifindex_out_xdp_dummy_attached = false;
@@ -135,11 +159,8 @@ int main(int argc, char **argv)
signal(SIGINT, int_exit);
signal(SIGTERM, int_exit);
- printf("map[0] (vports) = %i, map[1] (map) = %i, map[2] (count) = %i\n",
- map_fd[0], map_fd[1], map_fd[2]);
-
/* populate virtual to physical port map */
- ret = bpf_map_update_elem(map_fd[0], &key, &ifindex_out, 0);
+ ret = bpf_map_update_elem(tx_port_map_fd, &key, &ifindex_out, 0);
if (ret) {
perror("bpf_update_elem");
goto out;
diff --git a/samples/bpf/xdp_redirect_user.c b/samples/bpf/xdp_redirect_user.c
index 81a69e36cb78..93404820df68 100644
--- a/samples/bpf/xdp_redirect_user.c
+++ b/samples/bpf/xdp_redirect_user.c
@@ -22,15 +22,16 @@
#include <libgen.h>
#include <sys/resource.h>
-#include "bpf_load.h"
#include "bpf_util.h"
#include <bpf/bpf.h>
+#include "bpf/libbpf.h"
static int ifindex_in;
static int ifindex_out;
static bool ifindex_out_xdp_dummy_attached = true;
static __u32 xdp_flags;
+static int rxcnt_map_fd;
static void int_exit(int sig)
{
@@ -53,7 +54,7 @@ static void poll_stats(int interval, int ifindex)
int i;
sleep(interval);
- assert(bpf_map_lookup_elem(map_fd[1], &key, values) == 0);
+ assert(bpf_map_lookup_elem(rxcnt_map_fd, &key, values) == 0);
for (i = 0; i < nr_cpus; i++)
sum += (values[i] - prev[i]);
if (sum)
@@ -77,9 +78,16 @@ static void usage(const char *prog)
int main(int argc, char **argv)
{
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
+ struct bpf_prog_load_attr prog_load_attr = {
+ .prog_type = BPF_PROG_TYPE_XDP,
+ };
+ struct bpf_program *prog, *dummy_prog;
+ int prog_fd, tx_port_map_fd, opt;
const char *optstr = "SN";
+ struct bpf_object *obj;
char filename[256];
- int ret, opt, key = 0;
+ int dummy_prog_fd;
+ int ret, key = 0;
while ((opt = getopt(argc, argv, optstr)) != -1) {
switch (opt) {
@@ -110,24 +118,40 @@ int main(int argc, char **argv)
printf("input: %d output: %d\n", ifindex_in, ifindex_out);
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
+ prog_load_attr.file = filename;
- if (load_bpf_file(filename)) {
- printf("%s", bpf_log_buf);
+ if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
+ return 1;
+
+ prog = bpf_program__next(NULL, obj);
+ dummy_prog = bpf_program__next(prog, obj);
+ if (!prog || !dummy_prog) {
+ printf("finding a prog in obj file failed\n");
+ return 1;
+ }
+ /* bpf_prog_load_xattr gives us the pointer to first prog's fd,
+ * so we're missing only the fd for dummy prog
+ */
+ dummy_prog_fd = bpf_program__fd(dummy_prog);
+ if (prog_fd < 0 || dummy_prog_fd < 0) {
+ printf("bpf_prog_load_xattr: %s\n", strerror(errno));
return 1;
}
- if (!prog_fd[0]) {
- printf("load_bpf_file: %s\n", strerror(errno));
+ tx_port_map_fd = bpf_object__find_map_fd_by_name(obj, "tx_port");
+ rxcnt_map_fd = bpf_object__find_map_fd_by_name(obj, "rxcnt");
+ if (tx_port_map_fd < 0 || rxcnt_map_fd < 0) {
+ printf("bpf_object__find_map_fd_by_name failed\n");
return 1;
}
- if (bpf_set_link_xdp_fd(ifindex_in, prog_fd[0], xdp_flags) < 0) {
+ if (bpf_set_link_xdp_fd(ifindex_in, prog_fd, xdp_flags) < 0) {
printf("ERROR: link set xdp fd failed on %d\n", ifindex_in);
return 1;
}
/* Loading dummy XDP prog on out-device */
- if (bpf_set_link_xdp_fd(ifindex_out, prog_fd[1],
+ if (bpf_set_link_xdp_fd(ifindex_out, dummy_prog_fd,
(xdp_flags | XDP_FLAGS_UPDATE_IF_NOEXIST)) < 0) {
printf("WARN: link set xdp fd failed on %d\n", ifindex_out);
ifindex_out_xdp_dummy_attached = false;
@@ -137,7 +161,7 @@ int main(int argc, char **argv)
signal(SIGTERM, int_exit);
/* bpf redirect port */
- ret = bpf_map_update_elem(map_fd[0], &key, &ifindex_out, 0);
+ ret = bpf_map_update_elem(tx_port_map_fd, &key, &ifindex_out, 0);
if (ret) {
perror("bpf_update_elem");
goto out;
diff --git a/samples/bpf/xdp_router_ipv4_user.c b/samples/bpf/xdp_router_ipv4_user.c
index b2b4dfa776c8..cea2306f5ab7 100644
--- a/samples/bpf/xdp_router_ipv4_user.c
+++ b/samples/bpf/xdp_router_ipv4_user.c
@@ -15,7 +15,6 @@
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
-#include "bpf_load.h"
#include <bpf/bpf.h>
#include <arpa/inet.h>
#include <fcntl.h>
@@ -25,11 +24,17 @@
#include <sys/ioctl.h>
#include <sys/syscall.h>
#include "bpf_util.h"
+#include "bpf/libbpf.h"
int sock, sock_arp, flags = 0;
static int total_ifindex;
int *ifindex_list;
char buf[8192];
+static int lpm_map_fd;
+static int rxcnt_map_fd;
+static int arp_table_map_fd;
+static int exact_match_map_fd;
+static int tx_port_map_fd;
static int get_route_table(int rtm_family);
static void int_exit(int sig)
@@ -186,7 +191,8 @@ static void read_route(struct nlmsghdr *nh, int nll)
bpf_set_link_xdp_fd(ifindex_list[i], -1, flags);
exit(0);
}
- assert(bpf_map_update_elem(map_fd[4], &route.iface, &route.iface, 0) == 0);
+ assert(bpf_map_update_elem(tx_port_map_fd,
+ &route.iface, &route.iface, 0) == 0);
if (rtm_family == AF_INET) {
struct trie_value {
__u8 prefix[4];
@@ -207,11 +213,16 @@ static void read_route(struct nlmsghdr *nh, int nll)
direct_entry.arp.dst = 0;
if (route.dst_len == 32) {
if (nh->nlmsg_type == RTM_DELROUTE) {
- assert(bpf_map_delete_elem(map_fd[3], &route.dst) == 0);
+ assert(bpf_map_delete_elem(exact_match_map_fd,
+ &route.dst) == 0);
} else {
- if (bpf_map_lookup_elem(map_fd[2], &route.dst, &direct_entry.arp.mac) == 0)
+ if (bpf_map_lookup_elem(arp_table_map_fd,
+ &route.dst,
+ &direct_entry.arp.mac) == 0)
direct_entry.arp.dst = route.dst;
- assert(bpf_map_update_elem(map_fd[3], &route.dst, &direct_entry, 0) == 0);
+ assert(bpf_map_update_elem(exact_match_map_fd,
+ &route.dst,
+ &direct_entry, 0) == 0);
}
}
for (i = 0; i < 4; i++)
@@ -225,7 +236,7 @@ static void read_route(struct nlmsghdr *nh, int nll)
route.gw, route.dst_len,
route.metric,
route.iface_name);
- if (bpf_map_lookup_elem(map_fd[0], prefix_key,
+ if (bpf_map_lookup_elem(lpm_map_fd, prefix_key,
prefix_value) < 0) {
for (i = 0; i < 4; i++)
prefix_value->prefix[i] = prefix_key->data[i];
@@ -234,7 +245,7 @@ static void read_route(struct nlmsghdr *nh, int nll)
prefix_value->gw = route.gw;
prefix_value->metric = route.metric;
- assert(bpf_map_update_elem(map_fd[0],
+ assert(bpf_map_update_elem(lpm_map_fd,
prefix_key,
prefix_value, 0
) == 0);
@@ -247,7 +258,7 @@ static void read_route(struct nlmsghdr *nh, int nll)
prefix_key->data[2],
prefix_key->data[3],
prefix_key->prefixlen);
- assert(bpf_map_delete_elem(map_fd[0],
+ assert(bpf_map_delete_elem(lpm_map_fd,
prefix_key
) == 0);
/* Rereading the route table to check if
@@ -275,8 +286,7 @@ static void read_route(struct nlmsghdr *nh, int nll)
prefix_value->ifindex = route.iface;
prefix_value->gw = route.gw;
prefix_value->metric = route.metric;
- assert(bpf_map_update_elem(
- map_fd[0],
+ assert(bpf_map_update_elem(lpm_map_fd,
prefix_key,
prefix_value,
0) == 0);
@@ -401,7 +411,8 @@ static void read_arp(struct nlmsghdr *nh, int nll)
arp_entry.mac = atol(mac);
printf("%x\t\t%llx\n", arp_entry.dst, arp_entry.mac);
if (ndm_family == AF_INET) {
- if (bpf_map_lookup_elem(map_fd[3], &arp_entry.dst,
+ if (bpf_map_lookup_elem(exact_match_map_fd,
+ &arp_entry.dst,
&direct_entry) == 0) {
if (nh->nlmsg_type == RTM_DELNEIGH) {
direct_entry.arp.dst = 0;
@@ -410,16 +421,17 @@ static void read_arp(struct nlmsghdr *nh, int nll)
direct_entry.arp.dst = arp_entry.dst;
direct_entry.arp.mac = arp_entry.mac;
}
- assert(bpf_map_update_elem(map_fd[3],
+ assert(bpf_map_update_elem(exact_match_map_fd,
&arp_entry.dst,
&direct_entry, 0
) == 0);
memset(&direct_entry, 0, sizeof(direct_entry));
}
if (nh->nlmsg_type == RTM_DELNEIGH) {
- assert(bpf_map_delete_elem(map_fd[2], &arp_entry.dst) == 0);
+ assert(bpf_map_delete_elem(arp_table_map_fd,
+ &arp_entry.dst) == 0);
} else if (nh->nlmsg_type == RTM_NEWNEIGH) {
- assert(bpf_map_update_elem(map_fd[2],
+ assert(bpf_map_update_elem(arp_table_map_fd,
&arp_entry.dst,
&arp_entry.mac, 0
) == 0);
@@ -553,7 +565,8 @@ static int monitor_route(void)
for (key = 0; key < nr_keys; key++) {
__u64 sum = 0;
- assert(bpf_map_lookup_elem(map_fd[1], &key, values) == 0);
+ assert(bpf_map_lookup_elem(rxcnt_map_fd,
+ &key, values) == 0);
for (i = 0; i < nr_cpus; i++)
sum += (values[i] - prev[key][i]);
if (sum)
@@ -596,11 +609,18 @@ static int monitor_route(void)
int main(int ac, char **argv)
{
+ struct bpf_prog_load_attr prog_load_attr = {
+ .prog_type = BPF_PROG_TYPE_XDP,
+ };
+ struct bpf_object *obj;
char filename[256];
char **ifname_list;
+ int prog_fd;
int i = 1;
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
+ prog_load_attr.file = filename;
+
if (ac < 2) {
printf("usage: %s [-S] Interface name list\n", argv[0]);
return 1;
@@ -614,15 +634,28 @@ int main(int ac, char **argv)
total_ifindex = ac - 1;
ifname_list = (argv + 1);
}
- if (load_bpf_file(filename)) {
- printf("%s", bpf_log_buf);
+
+ if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
return 1;
- }
+
printf("\n**************loading bpf file*********************\n\n\n");
- if (!prog_fd[0]) {
- printf("load_bpf_file: %s\n", strerror(errno));
+ if (!prog_fd) {
+ printf("bpf_prog_load_xattr: %s\n", strerror(errno));
return 1;
}
+
+ lpm_map_fd = bpf_object__find_map_fd_by_name(obj, "lpm_map");
+ rxcnt_map_fd = bpf_object__find_map_fd_by_name(obj, "rxcnt");
+ arp_table_map_fd = bpf_object__find_map_fd_by_name(obj, "arp_table");
+ exact_match_map_fd = bpf_object__find_map_fd_by_name(obj,
+ "exact_match");
+ tx_port_map_fd = bpf_object__find_map_fd_by_name(obj, "tx_port");
+ if (lpm_map_fd < 0 || rxcnt_map_fd < 0 || arp_table_map_fd < 0 ||
+ exact_match_map_fd < 0 || tx_port_map_fd < 0) {
+ printf("bpf_object__find_map_fd_by_name failed\n");
+ return 1;
+ }
+
ifindex_list = (int *)malloc(total_ifindex * sizeof(int *));
for (i = 0; i < total_ifindex; i++) {
ifindex_list[i] = if_nametoindex(ifname_list[i]);
@@ -633,7 +666,7 @@ int main(int ac, char **argv)
}
}
for (i = 0; i < total_ifindex; i++) {
- if (bpf_set_link_xdp_fd(ifindex_list[i], prog_fd[0], flags) < 0) {
+ if (bpf_set_link_xdp_fd(ifindex_list[i], prog_fd, flags) < 0) {
printf("link set xdp fd failed\n");
int recovery_index = i;
diff --git a/samples/bpf/xdp_tx_iptunnel_user.c b/samples/bpf/xdp_tx_iptunnel_user.c
index a4ccc33adac0..5093d8220da5 100644
--- a/samples/bpf/xdp_tx_iptunnel_user.c
+++ b/samples/bpf/xdp_tx_iptunnel_user.c
@@ -17,7 +17,7 @@
#include <netinet/ether.h>
#include <unistd.h>
#include <time.h>
-#include "bpf_load.h"
+#include "bpf/libbpf.h"
#include <bpf/bpf.h>
#include "bpf_util.h"
#include "xdp_tx_iptunnel_common.h"
@@ -26,6 +26,7 @@
static int ifindex = -1;
static __u32 xdp_flags = 0;
+static int rxcnt_map_fd;
static void int_exit(int sig)
{
@@ -53,7 +54,8 @@ static void poll_stats(unsigned int kill_after_s)
for (proto = 0; proto < nr_protos; proto++) {
__u64 sum = 0;
- assert(bpf_map_lookup_elem(map_fd[0], &proto, values) == 0);
+ assert(bpf_map_lookup_elem(rxcnt_map_fd, &proto,
+ values) == 0);
for (i = 0; i < nr_cpus; i++)
sum += (values[i] - prev[proto][i]);
@@ -138,15 +140,19 @@ static int parse_ports(const char *port_str, int *min_port, int *max_port)
int main(int argc, char **argv)
{
+ struct bpf_prog_load_attr prog_load_attr = {
+ .prog_type = BPF_PROG_TYPE_XDP,
+ };
+ struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
+ int min_port = 0, max_port = 0, vip2tnl_map_fd;
+ const char *optstr = "i:a:p:s:d:m:T:P:SNh";
unsigned char opt_flags[256] = {};
unsigned int kill_after_s = 0;
- const char *optstr = "i:a:p:s:d:m:T:P:SNh";
- int min_port = 0, max_port = 0;
struct iptnl_info tnl = {};
- struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
+ struct bpf_object *obj;
struct vip vip = {};
char filename[256];
- int opt;
+ int opt, prog_fd;
int i;
tnl.family = AF_UNSPEC;
@@ -232,29 +238,36 @@ int main(int argc, char **argv)
}
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
+ prog_load_attr.file = filename;
- if (load_bpf_file(filename)) {
- printf("%s", bpf_log_buf);
+ if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
return 1;
- }
- if (!prog_fd[0]) {
+ if (!prog_fd) {
printf("load_bpf_file: %s\n", strerror(errno));
return 1;
}
+ rxcnt_map_fd = bpf_object__find_map_fd_by_name(obj, "rxcnt");
+ vip2tnl_map_fd = bpf_object__find_map_fd_by_name(obj, "vip2tnl");
+ if (vip2tnl_map_fd < 0 || rxcnt_map_fd < 0) {
+ printf("bpf_object__find_map_fd_by_name failed\n");
+ return 1;
+ }
+
signal(SIGINT, int_exit);
signal(SIGTERM, int_exit);
while (min_port <= max_port) {
vip.dport = htons(min_port++);
- if (bpf_map_update_elem(map_fd[1], &vip, &tnl, BPF_NOEXIST)) {
+ if (bpf_map_update_elem(vip2tnl_map_fd, &vip, &tnl,
+ BPF_NOEXIST)) {
perror("bpf_map_update_elem(&vip2tnl)");
return 1;
}
}
- if (bpf_set_link_xdp_fd(ifindex, prog_fd[0], xdp_flags) < 0) {
+ if (bpf_set_link_xdp_fd(ifindex, prog_fd, xdp_flags) < 0) {
printf("link set xdp fd failed\n");
return 1;
}
--
2.16.1
^ permalink raw reply related
* [PATCH bpf-next v6 5/8] xdp: Provide extack messages when prog attachment failed
From: Maciej Fijalkowski @ 2019-02-01 21:42 UTC (permalink / raw)
To: daniel, ast; +Cc: netdev, jakub.kicinski, brouer, john.fastabend
In-Reply-To: <20190201214230.1441-1-maciej.fijalkowski@intel.com>
In order to provide more meaningful messages to user when the process of
loading xdp program onto network interface failed, let's add extack
messages within dev_change_xdp_fd.
Suggested-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Acked-by: Jesper Dangaard Brouer <brouer@redhat.com>
---
net/core/dev.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 8e276e0192a1..bfa4be42afff 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -7983,8 +7983,10 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
query = flags & XDP_FLAGS_HW_MODE ? XDP_QUERY_PROG_HW : XDP_QUERY_PROG;
bpf_op = bpf_chk = ops->ndo_bpf;
- if (!bpf_op && (flags & (XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE)))
+ if (!bpf_op && (flags & (XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE))) {
+ NL_SET_ERR_MSG(extack, "underlying driver does not support XDP in native mode");
return -EOPNOTSUPP;
+ }
if (!bpf_op || (flags & XDP_FLAGS_SKB_MODE))
bpf_op = generic_xdp_install;
if (bpf_op == bpf_chk)
@@ -7992,11 +7994,15 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
if (fd >= 0) {
if (__dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG) ||
- __dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG_HW))
+ __dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG_HW)) {
+ NL_SET_ERR_MSG(extack, "native and generic XDP can't be active at the same time");
return -EEXIST;
+ }
if ((flags & XDP_FLAGS_UPDATE_IF_NOEXIST) &&
- __dev_xdp_query(dev, bpf_op, query))
+ __dev_xdp_query(dev, bpf_op, query)) {
+ NL_SET_ERR_MSG(extack, "XDP program already attached");
return -EBUSY;
+ }
prog = bpf_prog_get_type_dev(fd, BPF_PROG_TYPE_XDP,
bpf_op == ops->ndo_bpf);
--
2.16.1
^ permalink raw reply related
* [PATCH bpf-next v6 4/8] samples/bpf: Extend RLIMIT_MEMLOCK for xdp_{sample_pkts, router_ipv4}
From: Maciej Fijalkowski @ 2019-02-01 21:42 UTC (permalink / raw)
To: daniel, ast; +Cc: netdev, jakub.kicinski, brouer, john.fastabend
In-Reply-To: <20190201214230.1441-1-maciej.fijalkowski@intel.com>
There is a common problem with xdp samples that happens when user wants
to run a particular sample and some bpf program is already loaded. The
default 64kb RLIMIT_MEMLOCK resource limit will cause a following error
(assuming that xdp sample that is failing was converted to libbpf
usage):
libbpf: Error in bpf_object__probe_name():Operation not permitted(1).
Couldn't load basic 'r0 = 0' BPF program.
libbpf: failed to load object './xdp_sample_pkts_kern.o'
Fix it in xdp_sample_pkts and xdp_router_ipv4 by setting RLIMIT_MEMLOCK
to RLIM_INFINITY.
Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Acked-by: Jesper Dangaard Brouer <brouer@redhat.com>
Acked-by: John Fastabend <john.fastabend@gmail.com>
---
samples/bpf/xdp_router_ipv4_user.c | 7 +++++++
samples/bpf/xdp_sample_pkts_user.c | 7 +++++++
2 files changed, 14 insertions(+)
diff --git a/samples/bpf/xdp_router_ipv4_user.c b/samples/bpf/xdp_router_ipv4_user.c
index cea2306f5ab7..c63c6beec7d6 100644
--- a/samples/bpf/xdp_router_ipv4_user.c
+++ b/samples/bpf/xdp_router_ipv4_user.c
@@ -25,6 +25,7 @@
#include <sys/syscall.h>
#include "bpf_util.h"
#include "bpf/libbpf.h"
+#include <sys/resource.h>
int sock, sock_arp, flags = 0;
static int total_ifindex;
@@ -609,6 +610,7 @@ static int monitor_route(void)
int main(int ac, char **argv)
{
+ struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
struct bpf_prog_load_attr prog_load_attr = {
.prog_type = BPF_PROG_TYPE_XDP,
};
@@ -635,6 +637,11 @@ int main(int ac, char **argv)
ifname_list = (argv + 1);
}
+ if (setrlimit(RLIMIT_MEMLOCK, &r)) {
+ perror("setrlimit(RLIMIT_MEMLOCK)");
+ return 1;
+ }
+
if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
return 1;
diff --git a/samples/bpf/xdp_sample_pkts_user.c b/samples/bpf/xdp_sample_pkts_user.c
index 8dd87c1eb560..5f5828ee0761 100644
--- a/samples/bpf/xdp_sample_pkts_user.c
+++ b/samples/bpf/xdp_sample_pkts_user.c
@@ -12,6 +12,7 @@
#include <signal.h>
#include <libbpf.h>
#include <bpf/bpf.h>
+#include <sys/resource.h>
#include "perf-sys.h"
#include "trace_helpers.h"
@@ -99,6 +100,7 @@ static void sig_handler(int signo)
int main(int argc, char **argv)
{
+ struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
struct bpf_prog_load_attr prog_load_attr = {
.prog_type = BPF_PROG_TYPE_XDP,
};
@@ -114,6 +116,11 @@ int main(int argc, char **argv)
return 1;
}
+ if (setrlimit(RLIMIT_MEMLOCK, &r)) {
+ perror("setrlimit(RLIMIT_MEMLOCK)");
+ return 1;
+ }
+
numcpus = get_nprocs();
if (numcpus > MAX_CPUS)
numcpus = MAX_CPUS;
--
2.16.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox