* [patch net-next 4/5] dsa: set devlink port attrs for dsa ports
From: Jiri Pirko @ 2018-05-18 7:29 UTC (permalink / raw)
To: netdev
Cc: davem, idosch, jakub.kicinski, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, saeedm, simon.horman,
pieter.jansenvanvuuren, john.hurley, dirk.vandermerwe,
alexander.h.duyck, ogerlitz, dsahern, vijaya.guvva,
satananda.burla, raghu.vatsavayi, felix.manlunas, gospo,
sathya.perla, vasundhara-v.volam, tariqt, eranbe,
jeffrey.t.kirsher, roopa
In-Reply-To: <20180518072904.29523-1-jiri@resnulli.us>
From: Jiri Pirko <jiri@mellanox.com>
Set the attrs and allow to expose port flavour to user via devlink.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
RFC->v1:
- added missing break pointed out by Andrew
---
net/dsa/dsa2.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index adf50fbc4c13..00126cda4319 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -270,7 +270,28 @@ static int dsa_port_setup(struct dsa_port *dp)
case DSA_PORT_TYPE_UNUSED:
break;
case DSA_PORT_TYPE_CPU:
+ /* dp->index is used now as port_number. However
+ * CPU ports should have separate numbering
+ * independent from front panel port numbers.
+ */
+ devlink_port_attrs_set(&dp->devlink_port,
+ DEVLINK_PORT_FLAVOUR_CPU,
+ dp->index, false, 0);
+ err = dsa_port_link_register_of(dp);
+ if (err) {
+ dev_err(ds->dev, "failed to setup link for port %d.%d\n",
+ ds->index, dp->index);
+ return err;
+ }
+ break;
case DSA_PORT_TYPE_DSA:
+ /* dp->index is used now as port_number. However
+ * DSA ports should have separate numbering
+ * independent from front panel port numbers.
+ */
+ devlink_port_attrs_set(&dp->devlink_port,
+ DEVLINK_PORT_FLAVOUR_DSA,
+ dp->index, false, 0);
err = dsa_port_link_register_of(dp);
if (err) {
dev_err(ds->dev, "failed to setup link for port %d.%d\n",
@@ -279,6 +300,9 @@ static int dsa_port_setup(struct dsa_port *dp)
}
break;
case DSA_PORT_TYPE_USER:
+ devlink_port_attrs_set(&dp->devlink_port,
+ DEVLINK_PORT_FLAVOUR_PHYSICAL,
+ dp->index, false, 0);
err = dsa_slave_create(dp);
if (err)
dev_err(ds->dev, "failed to create slave for port %d.%d\n",
--
2.14.3
^ permalink raw reply related
* [patch net-next 3/5] devlink: introduce a helper to generate physical port names
From: Jiri Pirko @ 2018-05-18 7:29 UTC (permalink / raw)
To: netdev
Cc: davem, idosch, jakub.kicinski, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, saeedm, simon.horman,
pieter.jansenvanvuuren, john.hurley, dirk.vandermerwe,
alexander.h.duyck, ogerlitz, dsahern, vijaya.guvva,
satananda.burla, raghu.vatsavayi, felix.manlunas, gospo,
sathya.perla, vasundhara-v.volam, tariqt, eranbe,
jeffrey.t.kirsher, roopa
In-Reply-To: <20180518072904.29523-1-jiri@resnulli.us>
From: Jiri Pirko <jiri@mellanox.com>
Each driver implements physical port name generation by itself. However
as devlink has all needed info, it can easily do the job for all its
users. So implement this helper in devlink.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
RFC->v1:
- rebased
---
include/net/devlink.h | 9 +++++++++
net/core/devlink.c | 33 +++++++++++++++++++++++++++++++++
2 files changed, 42 insertions(+)
diff --git a/include/net/devlink.h b/include/net/devlink.h
index 6eae15cf0f57..9686a1aa4ec9 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -378,6 +378,8 @@ void devlink_port_attrs_set(struct devlink_port *devlink_port,
enum devlink_port_flavour flavour,
u32 port_number, bool split,
u32 split_subport_number);
+int devlink_port_get_phys_port_name(struct devlink_port *devlink_port,
+ char *name, size_t len);
int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
u32 size, u16 ingress_pools_count,
u16 egress_pools_count, u16 ingress_tc_count,
@@ -482,6 +484,13 @@ static inline void devlink_port_attrs_set(struct devlink_port *devlink_port,
{
}
+static inline int
+devlink_port_get_phys_port_name(struct devlink_port *devlink_port,
+ char *name, size_t len)
+{
+ return -EOPNOTSUPP;
+}
+
static inline int devlink_sb_register(struct devlink *devlink,
unsigned int sb_index, u32 size,
u16 ingress_pools_count,
diff --git a/net/core/devlink.c b/net/core/devlink.c
index af90d237cbc2..5c8a40e1a01e 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -3016,6 +3016,39 @@ void devlink_port_attrs_set(struct devlink_port *devlink_port,
}
EXPORT_SYMBOL_GPL(devlink_port_attrs_set);
+int devlink_port_get_phys_port_name(struct devlink_port *devlink_port,
+ char *name, size_t len)
+{
+ struct devlink_port_attrs *attrs = &devlink_port->attrs;
+ int n = 0;
+
+ if (!attrs->set)
+ return -EOPNOTSUPP;
+
+ switch (attrs->flavour) {
+ case DEVLINK_PORT_FLAVOUR_PHYSICAL:
+ if (!attrs->split)
+ n = snprintf(name, len, "p%u", attrs->port_number);
+ else
+ n = snprintf(name, len, "p%us%u", attrs->port_number,
+ attrs->split_subport_number);
+ break;
+ case DEVLINK_PORT_FLAVOUR_CPU:
+ case DEVLINK_PORT_FLAVOUR_DSA:
+ /* As CPU and DSA ports do not have a netdevice associated
+ * case should not ever happen.
+ */
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ if (n >= len)
+ return -EINVAL;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(devlink_port_get_phys_port_name);
+
int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
u32 size, u16 ingress_pools_count,
u16 egress_pools_count, u16 ingress_tc_count,
--
2.14.3
^ permalink raw reply related
* [patch net-next 2/5] devlink: extend attrs_set for setting port flavours
From: Jiri Pirko @ 2018-05-18 7:29 UTC (permalink / raw)
To: netdev
Cc: davem, idosch, jakub.kicinski, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, saeedm, simon.horman,
pieter.jansenvanvuuren, john.hurley, dirk.vandermerwe,
alexander.h.duyck, ogerlitz, dsahern, vijaya.guvva,
satananda.burla, raghu.vatsavayi, felix.manlunas, gospo,
sathya.perla, vasundhara-v.volam, tariqt, eranbe,
jeffrey.t.kirsher, roopa
In-Reply-To: <20180518072904.29523-1-jiri@resnulli.us>
From: Jiri Pirko <jiri@mellanox.com>
Devlink ports can have specific flavour according to the purpose of use.
This patch extend attrs_set so the driver can say which flavour port
has. Initial flavours are:
physical, cpu, dsa
User can query this to see right away what is the purpose of each port.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
RFC->v1:
- rebased
- removed pf/vf reps flavours
---
drivers/net/ethernet/mellanox/mlxsw/core.c | 4 ++--
drivers/net/ethernet/netronome/nfp/nfp_devlink.c | 5 +++--
include/net/devlink.h | 3 +++
include/uapi/linux/devlink.h | 11 +++++++++++
net/core/devlink.c | 5 +++++
5 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
index 958769689ca2..a720aa11bcc0 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -1722,8 +1722,8 @@ void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port,
struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
mlxsw_core_port->port_driver_priv = port_driver_priv;
- devlink_port_attrs_set(devlink_port, port_number,
- split, split_port_subnumber);
+ devlink_port_attrs_set(devlink_port, DEVLINK_PORT_FLAVOUR_PHYSICAL,
+ port_number, split, split_port_subnumber);
devlink_port_type_eth_set(devlink_port, dev);
}
EXPORT_SYMBOL(mlxsw_core_port_eth_set);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
index d7a768ff3112..b1e67cf4257a 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
@@ -175,8 +175,9 @@ int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port)
return ret;
devlink_port_type_eth_set(&port->dl_port, port->netdev);
- devlink_port_attrs_set(&port->dl_port, eth_port.label_port,
- eth_port.is_split, eth_port.label_subport);
+ devlink_port_attrs_set(&port->dl_port, DEVLINK_PORT_FLAVOUR_PHYSICAL,
+ eth_port.label_port, eth_port.is_split,
+ eth_port.label_subport);
devlink = priv_to_devlink(app->pf);
diff --git a/include/net/devlink.h b/include/net/devlink.h
index d6ca92266709..6eae15cf0f57 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -37,6 +37,7 @@ struct devlink {
struct devlink_port_attrs {
bool set;
+ enum devlink_port_flavour flavour;
u32 port_number; /* same value as "split group" */
bool split;
u32 split_subport_number;
@@ -374,6 +375,7 @@ void devlink_port_type_ib_set(struct devlink_port *devlink_port,
struct ib_device *ibdev);
void devlink_port_type_clear(struct devlink_port *devlink_port);
void devlink_port_attrs_set(struct devlink_port *devlink_port,
+ enum devlink_port_flavour flavour,
u32 port_number, bool split,
u32 split_subport_number);
int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
@@ -474,6 +476,7 @@ static inline void devlink_port_type_clear(struct devlink_port *devlink_port)
}
static inline void devlink_port_attrs_set(struct devlink_port *devlink_port,
+ enum devlink_port_flavour flavour,
u32 port_number, bool split,
u32 split_subport_number)
{
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 15b031a5ee7a..75cb5450c851 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -132,6 +132,16 @@ enum devlink_eswitch_encap_mode {
DEVLINK_ESWITCH_ENCAP_MODE_BASIC,
};
+enum devlink_port_flavour {
+ DEVLINK_PORT_FLAVOUR_PHYSICAL, /* Any kind of a port physically
+ * facing the user.
+ */
+ DEVLINK_PORT_FLAVOUR_CPU, /* CPU port */
+ DEVLINK_PORT_FLAVOUR_DSA, /* Distributed switch architecture
+ * interconnect port.
+ */
+};
+
enum devlink_attr {
/* don't change the order or add anything between, this is ABI! */
DEVLINK_ATTR_UNSPEC,
@@ -224,6 +234,7 @@ enum devlink_attr {
DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID, /* u64 */
DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS,/* u64 */
+ DEVLINK_ATTR_PORT_FLAVOUR, /* u16 */
DEVLINK_ATTR_PORT_NUMBER, /* u32 */
DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER, /* u32 */
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 8fde7d2df9b0..af90d237cbc2 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -460,6 +460,8 @@ static int devlink_nl_port_attrs_put(struct sk_buff *msg,
if (!attrs->set)
return 0;
+ if (nla_put_u16(msg, DEVLINK_ATTR_PORT_FLAVOUR, attrs->flavour))
+ return -EMSGSIZE;
if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER, attrs->port_number))
return -EMSGSIZE;
if (!attrs->split)
@@ -2991,6 +2993,7 @@ EXPORT_SYMBOL_GPL(devlink_port_type_clear);
* devlink_port_attrs_set - Set port attributes
*
* @devlink_port: devlink port
+ * @flavour: flavour of the port
* @port_number: number of the port that is facing user, for example
* the front panel port number
* @split: indicates if this is split port
@@ -2998,12 +3001,14 @@ EXPORT_SYMBOL_GPL(devlink_port_type_clear);
* of subport.
*/
void devlink_port_attrs_set(struct devlink_port *devlink_port,
+ enum devlink_port_flavour flavour,
u32 port_number, bool split,
u32 split_subport_number)
{
struct devlink_port_attrs *attrs = &devlink_port->attrs;
attrs->set = true;
+ attrs->flavour = flavour;
attrs->port_number = port_number;
attrs->split = split;
attrs->split_subport_number = split_subport_number;
--
2.14.3
^ permalink raw reply related
* [patch net-next 1/5] devlink: introduce devlink_port_attrs_set
From: Jiri Pirko @ 2018-05-18 7:29 UTC (permalink / raw)
To: netdev
Cc: davem, idosch, jakub.kicinski, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, saeedm, simon.horman,
pieter.jansenvanvuuren, john.hurley, dirk.vandermerwe,
alexander.h.duyck, ogerlitz, dsahern, vijaya.guvva,
satananda.burla, raghu.vatsavayi, felix.manlunas, gospo,
sathya.perla, vasundhara-v.volam, tariqt, eranbe,
jeffrey.t.kirsher, roopa
In-Reply-To: <20180518072904.29523-1-jiri@resnulli.us>
From: Jiri Pirko <jiri@mellanox.com>
Change existing setter for split port information into more generic
attrs setter. Alongside with that, allow to set port number and subport
number for split ports.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
RFC->v1:
- Reduced the nfp change just to simply use newly created attr_set func
---
drivers/net/ethernet/mellanox/mlxsw/core.c | 7 ++--
drivers/net/ethernet/mellanox/mlxsw/core.h | 3 +-
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 4 +--
drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 2 +-
drivers/net/ethernet/netronome/nfp/nfp_devlink.c | 4 +--
include/net/devlink.h | 20 +++++++----
include/uapi/linux/devlink.h | 3 ++
net/core/devlink.c | 46 ++++++++++++++++++------
8 files changed, 64 insertions(+), 25 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
index e13ac3b8dff7..958769689ca2 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -1714,15 +1714,16 @@ EXPORT_SYMBOL(mlxsw_core_port_fini);
void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port,
void *port_driver_priv, struct net_device *dev,
- bool split, u32 split_group)
+ u32 port_number, bool split,
+ u32 split_port_subnumber)
{
struct mlxsw_core_port *mlxsw_core_port =
&mlxsw_core->ports[local_port];
struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
mlxsw_core_port->port_driver_priv = port_driver_priv;
- if (split)
- devlink_port_split_set(devlink_port, split_group);
+ devlink_port_attrs_set(devlink_port, port_number,
+ split, split_port_subnumber);
devlink_port_type_eth_set(devlink_port, dev);
}
EXPORT_SYMBOL(mlxsw_core_port_eth_set);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h
index 092d39399f3c..e65287c15afd 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.h
@@ -201,7 +201,8 @@ int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port);
void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port);
void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port,
void *port_driver_priv, struct net_device *dev,
- bool split, u32 split_group);
+ u32 port_number, bool split,
+ u32 split_port_subnumber);
void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u8 local_port,
void *port_driver_priv);
void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 94132f6cec61..96f6d8af1fd8 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -2927,8 +2927,8 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
}
mlxsw_core_port_eth_set(mlxsw_sp->core, mlxsw_sp_port->local_port,
- mlxsw_sp_port, dev, mlxsw_sp_port->split,
- module);
+ mlxsw_sp_port, dev, module + 1,
+ mlxsw_sp_port->split, lane / width);
mlxsw_core_schedule_dw(&mlxsw_sp_port->periodic_hw_stats.update_dw, 0);
return 0;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
index a655c5850aa6..551e05067b1e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
@@ -1149,7 +1149,7 @@ static int __mlxsw_sx_port_eth_create(struct mlxsw_sx *mlxsw_sx, u8 local_port,
}
mlxsw_core_port_eth_set(mlxsw_sx->core, mlxsw_sx_port->local_port,
- mlxsw_sx_port, dev, false, 0);
+ mlxsw_sx_port, dev, module + 1, false, 0);
mlxsw_sx->ports[local_port] = mlxsw_sx_port;
return 0;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
index eb0fc614673d..d7a768ff3112 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
@@ -175,8 +175,8 @@ int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port)
return ret;
devlink_port_type_eth_set(&port->dl_port, port->netdev);
- if (eth_port.is_split)
- devlink_port_split_set(&port->dl_port, eth_port.label_port);
+ devlink_port_attrs_set(&port->dl_port, eth_port.label_port,
+ eth_port.is_split, eth_port.label_subport);
devlink = priv_to_devlink(app->pf);
diff --git a/include/net/devlink.h b/include/net/devlink.h
index 2e4f71e16e95..d6ca92266709 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -35,6 +35,13 @@ struct devlink {
char priv[0] __aligned(NETDEV_ALIGN);
};
+struct devlink_port_attrs {
+ bool set;
+ u32 port_number; /* same value as "split group" */
+ bool split;
+ u32 split_subport_number;
+};
+
struct devlink_port {
struct list_head list;
struct devlink *devlink;
@@ -43,8 +50,7 @@ struct devlink_port {
enum devlink_port_type type;
enum devlink_port_type desired_type;
void *type_dev;
- bool split;
- u32 split_group;
+ struct devlink_port_attrs attrs;
};
struct devlink_sb_pool_info {
@@ -367,8 +373,9 @@ void devlink_port_type_eth_set(struct devlink_port *devlink_port,
void devlink_port_type_ib_set(struct devlink_port *devlink_port,
struct ib_device *ibdev);
void devlink_port_type_clear(struct devlink_port *devlink_port);
-void devlink_port_split_set(struct devlink_port *devlink_port,
- u32 split_group);
+void devlink_port_attrs_set(struct devlink_port *devlink_port,
+ u32 port_number, bool split,
+ u32 split_subport_number);
int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
u32 size, u16 ingress_pools_count,
u16 egress_pools_count, u16 ingress_tc_count,
@@ -466,8 +473,9 @@ static inline void devlink_port_type_clear(struct devlink_port *devlink_port)
{
}
-static inline void devlink_port_split_set(struct devlink_port *devlink_port,
- u32 split_group)
+static inline void devlink_port_attrs_set(struct devlink_port *devlink_port,
+ u32 port_number, bool split,
+ u32 split_subport_number)
{
}
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 1df65a4c2044..15b031a5ee7a 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -224,6 +224,9 @@ enum devlink_attr {
DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID, /* u64 */
DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS,/* u64 */
+ DEVLINK_ATTR_PORT_NUMBER, /* u32 */
+ DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER, /* u32 */
+
/* add new attributes above here, update the policy in devlink.c */
__DEVLINK_ATTR_MAX,
diff --git a/net/core/devlink.c b/net/core/devlink.c
index ad1317376798..8fde7d2df9b0 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -453,6 +453,25 @@ static void devlink_notify(struct devlink *devlink, enum devlink_command cmd)
msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
}
+static int devlink_nl_port_attrs_put(struct sk_buff *msg,
+ struct devlink_port *devlink_port)
+{
+ struct devlink_port_attrs *attrs = &devlink_port->attrs;
+
+ if (!attrs->set)
+ return 0;
+ if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER, attrs->port_number))
+ return -EMSGSIZE;
+ if (!attrs->split)
+ return 0;
+ if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP, attrs->port_number))
+ return -EMSGSIZE;
+ if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER,
+ attrs->split_subport_number))
+ return -EMSGSIZE;
+ return 0;
+}
+
static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
struct devlink_port *devlink_port,
enum devlink_command cmd, u32 portid,
@@ -492,9 +511,7 @@ static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
ibdev->name))
goto nla_put_failure;
}
- if (devlink_port->split &&
- nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP,
- devlink_port->split_group))
+ if (devlink_nl_port_attrs_put(msg, devlink_port))
goto nla_put_failure;
genlmsg_end(msg, hdr);
@@ -2971,19 +2988,28 @@ void devlink_port_type_clear(struct devlink_port *devlink_port)
EXPORT_SYMBOL_GPL(devlink_port_type_clear);
/**
- * devlink_port_split_set - Set port is split
+ * devlink_port_attrs_set - Set port attributes
*
* @devlink_port: devlink port
- * @split_group: split group - identifies group split port is part of
+ * @port_number: number of the port that is facing user, for example
+ * the front panel port number
+ * @split: indicates if this is split port
+ * @split_subport_number: if the port is split, this is the number
+ * of subport.
*/
-void devlink_port_split_set(struct devlink_port *devlink_port,
- u32 split_group)
+void devlink_port_attrs_set(struct devlink_port *devlink_port,
+ u32 port_number, bool split,
+ u32 split_subport_number)
{
- devlink_port->split = true;
- devlink_port->split_group = split_group;
+ struct devlink_port_attrs *attrs = &devlink_port->attrs;
+
+ attrs->set = true;
+ attrs->port_number = port_number;
+ attrs->split = split;
+ attrs->split_subport_number = split_subport_number;
devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
}
-EXPORT_SYMBOL_GPL(devlink_port_split_set);
+EXPORT_SYMBOL_GPL(devlink_port_attrs_set);
int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
u32 size, u16 ingress_pools_count,
--
2.14.3
^ permalink raw reply related
* [patch net-next 0/5] devlink: introduce port flavours and common phys_port_name generation
From: Jiri Pirko @ 2018-05-18 7:28 UTC (permalink / raw)
To: netdev
Cc: davem, idosch, jakub.kicinski, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, saeedm, simon.horman,
pieter.jansenvanvuuren, john.hurley, dirk.vandermerwe,
alexander.h.duyck, ogerlitz, dsahern, vijaya.guvva,
satananda.burla, raghu.vatsavayi, felix.manlunas, gospo,
sathya.perla, vasundhara-v.volam, tariqt, eranbe,
jeffrey.t.kirsher, roopa
From: Jiri Pirko <jiri@mellanox.com>
This patchset resolves 2 issues we have right now:
1) There are many netdevices / ports in the system, for port, pf, vf
represenatation but the user has no way to see which is which
2) The ndo_get_phys_port_name is implemented in each driver separatelly,
which may lead to inconsistent names between drivers.
This patchset introduces port flavours which should address the first
problem. In this initial patchset, I focus on DSA and their port
flavours. As a follow-up, I plan to add PF and VF representor flavours.
However, that needs additional dependencies in drivers (nfp, mlx5).
The common phys_port_name generation is used by mlxsw. An example output
for mlxsw looks like this:
# devlink port
...
pci/0000:03:00.0/59: type eth netdev enp3s0np4 flavour physical number 4
pci/0000:03:00.0/61: type eth netdev enp3s0np1 flavour physical number 1
pci/0000:03:00.0/63: type eth netdev enp3s0np2 flavour physical number 2
pci/0000:03:00.0/49: type eth netdev enp3s0np8s0 flavour physical number 8 split_group 8 subport 0
pci/0000:03:00.0/50: type eth netdev enp3s0np8s1 flavour physical number 8 split_group 8 subport 1
pci/0000:03:00.0/51: type eth netdev enp3s0np8s2 flavour physical number 8 split_group 8 subport 2
pci/0000:03:00.0/52: type eth netdev enp3s0np8s3 flavour physical number 8 split_group 8 subport 3
As you can see, the netdev names are generated according to the flavour
and port number. In case the port is split, the split subnumber is also
included.
An example output for dsa_loop testing module looks like this:
# devlink port
mdio_bus/fixed-0:1f/0: type eth netdev lan1 flavour physical number 0
mdio_bus/fixed-0:1f/1: type eth netdev lan2 flavour physical number 1
mdio_bus/fixed-0:1f/2: type eth netdev lan3 flavour physical number 2
mdio_bus/fixed-0:1f/3: type eth netdev lan4 flavour physical number 3
mdio_bus/fixed-0:1f/4: type notset
mdio_bus/fixed-0:1f/5: type notset flavour cpu number 5
mdio_bus/fixed-0:1f/6: type notset
mdio_bus/fixed-0:1f/7: type notset
mdio_bus/fixed-0:1f/8: type notset
mdio_bus/fixed-0:1f/9: type notset
mdio_bus/fixed-0:1f/10: type notset
mdio_bus/fixed-0:1f/11: type notset
---
RFC->v1:
-removed nfp patches, removed DSA patch that used name generation helper
-patch 1:
- Reduced the nfp change just to simply use newly created attr_set func
-patch 2:
- rebased
- removed pf/vf reps flavours
-patch 3:
- rebased
-patch 4:
- added missing break pointed out by Andrew
Jiri Pirko (5):
devlink: introduce devlink_port_attrs_set
devlink: extend attrs_set for setting port flavours
devlink: introduce a helper to generate physical port names
dsa: set devlink port attrs for dsa ports
mlxsw: use devlink helper to generate physical port name
drivers/net/ethernet/mellanox/mlxsw/core.c | 18 ++++-
drivers/net/ethernet/mellanox/mlxsw/core.h | 5 +-
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 21 ++----
drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 11 ++-
drivers/net/ethernet/netronome/nfp/nfp_devlink.c | 5 +-
include/net/devlink.h | 32 +++++++--
include/uapi/linux/devlink.h | 14 ++++
net/core/devlink.c | 86 +++++++++++++++++++++---
net/dsa/dsa2.c | 24 +++++++
9 files changed, 170 insertions(+), 46 deletions(-)
--
2.14.3
^ permalink raw reply
* [PATCH bpf-next 5/5] selftests/bpf: test_sockmap, print additional test options
From: Prashant Bhole @ 2018-05-18 7:17 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, John Fastabend
Cc: Prashant Bhole, David S . Miller, Shuah Khan, netdev
In-Reply-To: <20180518071753.4768-1-bhole_prashant_q7@lab.ntt.co.jp>
Print values of test options like apply, cork, start, end so that
individual failed tests can be identified for manual run
Signed-off-by: Prashant Bhole <bhole_prashant_q7@lab.ntt.co.jp>
---
tools/testing/selftests/bpf/test_sockmap.c | 28 +++++++++++++++++++---------
1 file changed, 19 insertions(+), 9 deletions(-)
diff --git a/tools/testing/selftests/bpf/test_sockmap.c b/tools/testing/selftests/bpf/test_sockmap.c
index e8faf4596dac..7970d48c4acb 100644
--- a/tools/testing/selftests/bpf/test_sockmap.c
+++ b/tools/testing/selftests/bpf/test_sockmap.c
@@ -869,6 +869,8 @@ static char *test_to_str(int test)
#define OPTSTRING 60
static void test_options(char *options)
{
+ char tstr[OPTSTRING];
+
memset(options, 0, OPTSTRING);
if (txmsg_pass)
@@ -881,14 +883,22 @@ static void test_options(char *options)
strncat(options, "redir_noisy,", OPTSTRING);
if (txmsg_drop)
strncat(options, "drop,", OPTSTRING);
- if (txmsg_apply)
- strncat(options, "apply,", OPTSTRING);
- if (txmsg_cork)
- strncat(options, "cork,", OPTSTRING);
- if (txmsg_start)
- strncat(options, "start,", OPTSTRING);
- if (txmsg_end)
- strncat(options, "end,", OPTSTRING);
+ if (txmsg_apply) {
+ snprintf(tstr, OPTSTRING, "apply %d,", txmsg_apply);
+ strncat(options, tstr, OPTSTRING);
+ }
+ if (txmsg_cork) {
+ snprintf(tstr, OPTSTRING, "cork %d,", txmsg_cork);
+ strncat(options, tstr, OPTSTRING);
+ }
+ if (txmsg_start) {
+ snprintf(tstr, OPTSTRING, "start %d,", txmsg_start);
+ strncat(options, tstr, OPTSTRING);
+ }
+ if (txmsg_end) {
+ snprintf(tstr, OPTSTRING, "end %d,", txmsg_end);
+ strncat(options, tstr, OPTSTRING);
+ }
if (txmsg_ingress)
strncat(options, "ingress,", OPTSTRING);
if (txmsg_skb)
@@ -897,7 +907,7 @@ static void test_options(char *options)
static int __test_exec(int cgrp, int test, struct sockmap_options *opt)
{
- char *options = calloc(60, sizeof(char));
+ char *options = calloc(OPTSTRING, sizeof(char));
int err;
if (test == SENDPAGE)
--
2.14.3
^ permalink raw reply related
* [PATCH bpf-next 4/5] selftests/bpf: test_sockmap, fix data verification
From: Prashant Bhole @ 2018-05-18 7:17 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, John Fastabend
Cc: Prashant Bhole, David S . Miller, Shuah Khan, netdev
In-Reply-To: <20180518071753.4768-1-bhole_prashant_q7@lab.ntt.co.jp>
When data verification is enabled, some tests fail because verification is done
incorrectly. Following changes fix it.
- Identify the size of data block to be verified
- Reset verification counter when data block size is reached
- Fixed the value printed in case of verification failure
Fixes: 16962b2404ac ("bpf: sockmap, add selftests")
Signed-off-by: Prashant Bhole <bhole_prashant_q7@lab.ntt.co.jp>
---
tools/testing/selftests/bpf/test_sockmap.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/bpf/test_sockmap.c b/tools/testing/selftests/bpf/test_sockmap.c
index f79397513362..e8faf4596dac 100644
--- a/tools/testing/selftests/bpf/test_sockmap.c
+++ b/tools/testing/selftests/bpf/test_sockmap.c
@@ -337,8 +337,15 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
int fd_flags = O_NONBLOCK;
struct timeval timeout;
float total_bytes;
+ int bytes_cnt = 0;
+ int chunk_sz;
fd_set w;
+ if (opt->sendpage)
+ chunk_sz = iov_length * cnt;
+ else
+ chunk_sz = iov_length * iov_count;
+
fcntl(fd, fd_flags);
total_bytes = (float)iov_count * (float)iov_length * (float)cnt;
err = clock_gettime(CLOCK_MONOTONIC, &s->start);
@@ -388,9 +395,14 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
errno = -EIO;
fprintf(stderr,
"detected data corruption @iov[%i]:%i %02x != %02x, %02x ?= %02x\n",
- i, j, d[j], k - 1, d[j+1], k + 1);
+ i, j, d[j], k - 1, d[j+1], k);
goto out_errno;
}
+ bytes_cnt++;
+ if (bytes_cnt == chunk_sz) {
+ k = 0;
+ bytes_cnt = 0;
+ }
recv--;
}
}
--
2.14.3
^ permalink raw reply related
* [PATCH bpf-next 3/5] selftests/bpf: test_sockmap, fix test timeout
From: Prashant Bhole @ 2018-05-18 7:17 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, John Fastabend
Cc: Prashant Bhole, David S . Miller, Shuah Khan, netdev
In-Reply-To: <20180518071753.4768-1-bhole_prashant_q7@lab.ntt.co.jp>
In order to reduce runtime of tests, recently timout for select() call
was reduced from 1sec to 10usec. This was causing many tests failures.
It was caught with failure handling commits in this series.
Restoring the timeout from 10usec to 1sec
Fixes: a18fda1a62c3 ("bpf: reduce runtime of test_sockmap tests")
Signed-off-by: Prashant Bhole <bhole_prashant_q7@lab.ntt.co.jp>
---
tools/testing/selftests/bpf/test_sockmap.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/bpf/test_sockmap.c b/tools/testing/selftests/bpf/test_sockmap.c
index 8a81ea0e9fb6..f79397513362 100644
--- a/tools/testing/selftests/bpf/test_sockmap.c
+++ b/tools/testing/selftests/bpf/test_sockmap.c
@@ -345,8 +345,8 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
if (err < 0)
perror("recv start time: ");
while (s->bytes_recvd < total_bytes) {
- timeout.tv_sec = 0;
- timeout.tv_usec = 10;
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
/* FD sets */
FD_ZERO(&w);
--
2.14.3
^ permalink raw reply related
* [PATCH bpf-next 2/5] selftests/bpf: test_sockmap, join cgroup in selftest mode
From: Prashant Bhole @ 2018-05-18 7:17 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, John Fastabend
Cc: Prashant Bhole, David S . Miller, Shuah Khan, netdev
In-Reply-To: <20180518071753.4768-1-bhole_prashant_q7@lab.ntt.co.jp>
In case of selftest mode, temporary cgroup environment is created but
cgroup is not joined. It causes test failures. Fixed by joining the
cgroup
Fixes: 16962b2404ac ("bpf: sockmap, add selftests")
Signed-off-by: Prashant Bhole <bhole_prashant_q7@lab.ntt.co.jp>
---
tools/testing/selftests/bpf/test_sockmap.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/tools/testing/selftests/bpf/test_sockmap.c b/tools/testing/selftests/bpf/test_sockmap.c
index 34feb74c95c4..8a81ea0e9fb6 100644
--- a/tools/testing/selftests/bpf/test_sockmap.c
+++ b/tools/testing/selftests/bpf/test_sockmap.c
@@ -1342,6 +1342,11 @@ static int __test_suite(char *bpf_file)
return cg_fd;
}
+ if (join_cgroup(CG_PATH)) {
+ fprintf(stderr, "ERROR: failed to join cgroup\n");
+ return -EINVAL;
+ }
+
/* Tests basic commands and APIs with range of iov values */
txmsg_start = txmsg_end = 0;
err = test_txmsg(cg_fd);
--
2.14.3
^ permalink raw reply related
* [PATCH bpf-next 1/5] selftests/bpf: test_sockmap, check test failure
From: Prashant Bhole @ 2018-05-18 7:17 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, John Fastabend
Cc: Prashant Bhole, David S . Miller, Shuah Khan, netdev
In-Reply-To: <20180518071753.4768-1-bhole_prashant_q7@lab.ntt.co.jp>
Test failures are not identified because exit code of RX/TX threads
is not checked. Also threads are not returning correct exit code.
- Return exit code from threads depending on test execution status
- In main thread, check the exit code of RX/TX threads
Fixes: 16962b2404ac ("bpf: sockmap, add selftests")
Signed-off-by: Prashant Bhole <bhole_prashant_q7@lab.ntt.co.jp>
---
tools/testing/selftests/bpf/test_sockmap.c | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/tools/testing/selftests/bpf/test_sockmap.c b/tools/testing/selftests/bpf/test_sockmap.c
index eb17fae458e6..34feb74c95c4 100644
--- a/tools/testing/selftests/bpf/test_sockmap.c
+++ b/tools/testing/selftests/bpf/test_sockmap.c
@@ -429,8 +429,8 @@ static int sendmsg_test(struct sockmap_options *opt)
struct msg_stats s = {0};
int iov_count = opt->iov_count;
int iov_buf = opt->iov_length;
+ int rx_status, tx_status;
int cnt = opt->rate;
- int status;
errno = 0;
@@ -442,7 +442,7 @@ static int sendmsg_test(struct sockmap_options *opt)
rxpid = fork();
if (rxpid == 0) {
if (opt->drop_expected)
- exit(1);
+ exit(0);
if (opt->sendpage)
iov_count = 1;
@@ -463,7 +463,7 @@ static int sendmsg_test(struct sockmap_options *opt)
"rx_sendmsg: TX: %zuB %fB/s %fGB/s RX: %zuB %fB/s %fGB/s\n",
s.bytes_sent, sent_Bps, sent_Bps/giga,
s.bytes_recvd, recvd_Bps, recvd_Bps/giga);
- exit(1);
+ exit(err ? 1 : 0);
} else if (rxpid == -1) {
perror("msg_loop_rx: ");
return errno;
@@ -491,14 +491,27 @@ static int sendmsg_test(struct sockmap_options *opt)
"tx_sendmsg: TX: %zuB %fB/s %f GB/s RX: %zuB %fB/s %fGB/s\n",
s.bytes_sent, sent_Bps, sent_Bps/giga,
s.bytes_recvd, recvd_Bps, recvd_Bps/giga);
- exit(1);
+ exit(err ? 1 : 0);
} else if (txpid == -1) {
perror("msg_loop_tx: ");
return errno;
}
- assert(waitpid(rxpid, &status, 0) == rxpid);
- assert(waitpid(txpid, &status, 0) == txpid);
+ assert(waitpid(rxpid, &rx_status, 0) == rxpid);
+ assert(waitpid(txpid, &tx_status, 0) == txpid);
+ if (WIFEXITED(rx_status)) {
+ err = WEXITSTATUS(rx_status);
+ if (err) {
+ fprintf(stderr, "rx thread exited with err %d. ", err);
+ goto out;
+ }
+ }
+ if (WIFEXITED(tx_status)) {
+ err = WEXITSTATUS(tx_status);
+ if (err)
+ fprintf(stderr, "tx thread exited with err %d. ", err);
+ }
+out:
return err;
}
--
2.14.3
^ permalink raw reply related
* [PATCH bpf-next 0/5] fix test_sockmap
From: Prashant Bhole @ 2018-05-18 7:17 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, John Fastabend
Cc: Prashant Bhole, David S . Miller, Shuah Khan, netdev
This series fixes bugs in test_sockmap code. They weren't caught
previously because failure in RX/TX thread was not notified to the
main thread.
Also fixed data verification logic and slightly improved test output
such that parameters values (cork, apply, start, end) of failed test
can be easily seen.
Note: Even after fixing above problems there are issues with tests
which set cork parameter. Tests fail (RX thread timeout) when cork
value is non-zero and overall data sent by TX thread isn't multiples
of cork value.
Prashant Bhole (5):
selftests/bpf: test_sockmap, check test failure
selftests/bpf: test_sockmap, join cgroup in selftest mode
selftests/bpf: test_sockmap, fix test timeout
selftests/bpf: test_sockmap, fix data verification
selftests/bpf: test_sockmap, print additional test options
tools/testing/selftests/bpf/test_sockmap.c | 76 +++++++++++++++++++++++-------
1 file changed, 58 insertions(+), 18 deletions(-)
--
2.14.3
^ permalink raw reply
* Re: [PATCH bpf-next v2 1/7] perf/core: add perf_get_event() to return perf_event given a struct file
From: Peter Zijlstra @ 2018-05-18 7:18 UTC (permalink / raw)
To: Yonghong Song; +Cc: ast, daniel, netdev, kernel-team
In-Reply-To: <20180518053253.2908444-1-yhs@fb.com>
On Thu, May 17, 2018 at 10:32:53PM -0700, Yonghong Song wrote:
> A new extern function, perf_get_event(), is added to return a perf event
> given a struct file. This function will be used in later patches.
Can't you do a narrower interface? Like return the prog. I'm not too
keen on random !perf code frobbing around inside the event.
^ permalink raw reply
* Re: [patch net-next RFC 04/12] dsa: set devlink port attrs for dsa ports
From: Jiri Pirko @ 2018-05-18 6:55 UTC (permalink / raw)
To: Andrew Lunn
Cc: Florian Fainelli, netdev, davem, idosch, jakub.kicinski, mlxsw,
vivien.didelot, michael.chan, ganeshgr, saeedm, simon.horman,
pieter.jansenvanvuuren, john.hurley, dirk.vandermerwe,
alexander.h.duyck, ogerlitz, dsahern, vijaya.guvva,
satananda.burla, raghu.vatsavayi, felix.manlunas, gospo,
sathya.perla, vasundhara-v.volam, tariqt, eranbe,
jeffrey.t.kirsher
In-Reply-To: <20180517224017.GA3943@lunn.ch>
Fri, May 18, 2018 at 12:40:17AM CEST, andrew@lunn.ch wrote:
>On Thu, May 17, 2018 at 03:06:36PM -0700, Florian Fainelli wrote:
>> On 05/17/2018 02:08 PM, Andrew Lunn wrote:
>> > On Thu, May 17, 2018 at 10:48:55PM +0200, Jiri Pirko wrote:
>> >> Thu, May 17, 2018 at 09:14:32PM CEST, f.fainelli@gmail.com wrote:
>> >>> On 05/17/2018 10:39 AM, Jiri Pirko wrote:
>> >>>>>> That is compiled inside "fixed_phy", isn't it?
>> >>>>>
>> >>>>> It matches what CONFIG_FIXED_PHY is, so if it's built-in it also becomes
>> >>>>> built-in, if is modular, it is also modular, this was fixed with
>> >>>>> 40013ff20b1beed31184935fc0aea6a859d4d4ef ("net: dsa: Fix functional
>> >>>>> dsa-loop dependency on FIXED_PHY")
>> >>>>
>> >>>> Now I have it compiled as module, and after modprobe dsa_loop I see:
>> >>>> [ 1168.129202] libphy: Fixed MDIO Bus: probed
>> >>>> [ 1168.222716] dsa-loop fixed-0:1f: DSA mockup driver: 0x1f
>> >>>>
>> >>>> This messages I did not see when I had fixed_phy compiled as buildin.
>> >>>>
>> >>>> But I still see no netdevs :/
>> >>>
>> >>> The platform data assumes there is a network device named "eth0" as the
>> >>
>> >> Oups, I missed, I created dummy device and modprobed again. Now I see:
>> >>
>> >> $ sudo devlink port
>> >> mdio_bus/fixed-0:1f/0: type eth netdev lan1
>> >> mdio_bus/fixed-0:1f/1: type eth netdev lan2
>> >> mdio_bus/fixed-0:1f/2: type eth netdev lan3
>> >> mdio_bus/fixed-0:1f/3: type eth netdev lan4
>> >> mdio_bus/fixed-0:1f/4: type notset
>> >> mdio_bus/fixed-0:1f/5: type notset
>> >> mdio_bus/fixed-0:1f/6: type notset
>> >> mdio_bus/fixed-0:1f/7: type notset
>> >> mdio_bus/fixed-0:1f/8: type notset
>> >> mdio_bus/fixed-0:1f/9: type notset
>> >> mdio_bus/fixed-0:1f/10: type notset
>> >> mdio_bus/fixed-0:1f/11: type notset
>> >>
>> >> I wonder why there are ports 4-11
>> >
>> > Hi Jiri
>> >
>> > ds = dsa_switch_alloc(&mdiodev->dev, DSA_MAX_PORTS);
>> >
>> > It is allocating a switch with 12 ports. However only 4 of them have
>> > names. So the core only creates slave devices for those 4.
>> >
>> > This is a useful test. Real hardware often has unused ports. A WiFi AP
>> > with a 7 port switch which only uses 6 ports is often seen.
>>
>> The following patch should fix this:
>>
>>
>> diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
>> index adf50fbc4c13..a06c29ec91f0 100644
>> --- a/net/dsa/dsa2.c
>> +++ b/net/dsa/dsa2.c
>> @@ -262,13 +262,14 @@ static int dsa_port_setup(struct dsa_port *dp)
>>
>> memset(&dp->devlink_port, 0, sizeof(dp->devlink_port));
>>
>> + if (dp->type == DSA_PORT_TYPE_UNUSED)
>> + return 0;
>> +
>> err = devlink_port_register(ds->devlink, &dp->devlink_port,
>> dp->index);
>
>Hi Florian, Jiri
>
>Maybe it is better to add a devlink port type unused?
The output with my patchset looks like this now:
salt:~/iproute2$ sudo devlink/devlink port
mdio_bus/fixed-0:1f/0: type eth netdev lan1 flavour physical number 0
mdio_bus/fixed-0:1f/1: type eth netdev lan2 flavour physical number 1
mdio_bus/fixed-0:1f/2: type eth netdev lan3 flavour physical number 2
mdio_bus/fixed-0:1f/3: type eth netdev lan4 flavour physical number 3
mdio_bus/fixed-0:1f/4: type notset
mdio_bus/fixed-0:1f/5: type notset flavour cpu number 5
mdio_bus/fixed-0:1f/6: type notset
mdio_bus/fixed-0:1f/7: type notset
mdio_bus/fixed-0:1f/8: type notset
mdio_bus/fixed-0:1f/9: type notset
mdio_bus/fixed-0:1f/10: type notset
mdio_bus/fixed-0:1f/11: type notset
^ permalink raw reply
* [PATCH net-next 2/2] net: mscc: ocelot: add VLAN filtering
From: Alexandre Belloni @ 2018-05-18 6:41 UTC (permalink / raw)
To: David S . Miller
Cc: Allan Nielsen, razvan.stefanescu, po.liu, Thomas Petazzoni,
Andrew Lunn, Florian Fainelli, netdev, linux-kernel,
Antoine Tenart, Alexandre Belloni
In-Reply-To: <20180518064106.10122-1-alexandre.belloni@bootlin.com>
From: Antoine Tenart <antoine.tenart@bootlin.com>
Add hardware VLAN filtering offloading on ocelot.
Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
drivers/net/ethernet/mscc/ocelot.c | 285 ++++++++++++++++++++++++++++-
1 file changed, 283 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index f22f5467001e..84a7687455a5 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -148,12 +148,191 @@ static inline int ocelot_vlant_wait_for_completion(struct ocelot *ocelot)
return 0;
}
+static int ocelot_vlant_set_mask(struct ocelot *ocelot, u16 vid, u32 mask)
+{
+ /* Select the VID to configure */
+ ocelot_write(ocelot, ANA_TABLES_VLANTIDX_V_INDEX(vid),
+ ANA_TABLES_VLANTIDX);
+ /* Set the vlan port members mask and issue a write command */
+ ocelot_write(ocelot, ANA_TABLES_VLANACCESS_VLAN_PORT_MASK(mask) |
+ ANA_TABLES_VLANACCESS_CMD_WRITE,
+ ANA_TABLES_VLANACCESS);
+
+ return ocelot_vlant_wait_for_completion(ocelot);
+}
+
+static void ocelot_vlan_mode(struct ocelot_port *port,
+ netdev_features_t features)
+{
+ struct ocelot *ocelot = port->ocelot;
+ u8 p = port->chip_port;
+ u32 val;
+
+ /* Filtering */
+ val = ocelot_read(ocelot, ANA_VLANMASK);
+ if (features & NETIF_F_HW_VLAN_CTAG_FILTER)
+ val |= BIT(p);
+ else
+ val &= ~BIT(p);
+ ocelot_write(ocelot, val, ANA_VLANMASK);
+}
+
+static void ocelot_vlan_port_apply(struct ocelot *ocelot,
+ struct ocelot_port *port)
+{
+ u32 val;
+
+ /* Ingress clasification (ANA_PORT_VLAN_CFG) */
+ /* Default vlan to clasify for untagged frames (may be zero) */
+ val = ANA_PORT_VLAN_CFG_VLAN_VID(port->pvid);
+ if (port->vlan_aware)
+ val |= ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
+ ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1);
+
+ ocelot_rmw_gix(ocelot, val,
+ ANA_PORT_VLAN_CFG_VLAN_VID_M |
+ ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
+ ANA_PORT_VLAN_CFG_VLAN_POP_CNT_M,
+ ANA_PORT_VLAN_CFG, port->chip_port);
+
+ /* Drop frames with multicast source address */
+ val = ANA_PORT_DROP_CFG_DROP_MC_SMAC_ENA;
+ if (port->vlan_aware && !port->vid)
+ /* If port is vlan-aware and tagged, drop untagged and priority
+ * tagged frames.
+ */
+ val |= ANA_PORT_DROP_CFG_DROP_UNTAGGED_ENA |
+ ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA |
+ ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA;
+ ocelot_write_gix(ocelot, val, ANA_PORT_DROP_CFG, port->chip_port);
+
+ /* Egress configuration (REW_TAG_CFG): VLAN tag type to 8021Q. */
+ val = REW_TAG_CFG_TAG_TPID_CFG(0);
+
+ if (port->vlan_aware) {
+ if (port->vid)
+ /* Tag all frames except when VID == DEFAULT_VLAN */
+ val |= REW_TAG_CFG_TAG_CFG(1);
+ else
+ /* Tag all frames */
+ val |= REW_TAG_CFG_TAG_CFG(3);
+ }
+ ocelot_rmw_gix(ocelot, val,
+ REW_TAG_CFG_TAG_TPID_CFG_M |
+ REW_TAG_CFG_TAG_CFG_M,
+ REW_TAG_CFG, port->chip_port);
+
+ /* Set default VLAN and tag type to 8021Q. */
+ val = REW_PORT_VLAN_CFG_PORT_TPID(ETH_P_8021Q) |
+ REW_PORT_VLAN_CFG_PORT_VID(port->vid);
+ ocelot_rmw_gix(ocelot, val,
+ REW_PORT_VLAN_CFG_PORT_TPID_M |
+ REW_PORT_VLAN_CFG_PORT_VID_M,
+ REW_PORT_VLAN_CFG, port->chip_port);
+}
+
+static int ocelot_vlan_vid_add(struct net_device *dev, u16 vid, bool pvid,
+ bool untagged)
+{
+ struct ocelot_port *port = netdev_priv(dev);
+ struct ocelot *ocelot = port->ocelot;
+ int ret;
+
+ /* Add the port MAC address to with the right VLAN information */
+ ocelot_mact_learn(ocelot, PGID_CPU, dev->dev_addr, vid,
+ ENTRYTYPE_LOCKED);
+
+ /* Make the port a member of the VLAN */
+ ocelot->vlan_mask[vid] |= BIT(port->chip_port);
+ ret = ocelot_vlant_set_mask(ocelot, vid, ocelot->vlan_mask[vid]);
+ if (ret)
+ return ret;
+
+ /* Default ingress vlan classification */
+ if (pvid)
+ port->pvid = vid;
+
+ /* Untagged egress vlan clasification */
+ if (untagged)
+ port->vid = vid;
+
+ ocelot_vlan_port_apply(ocelot, port);
+
+ return 0;
+}
+
+static int ocelot_vlan_vid_del(struct net_device *dev, u16 vid)
+{
+ struct ocelot_port *port = netdev_priv(dev);
+ struct ocelot *ocelot = port->ocelot;
+ int ret;
+
+ /* 8021q removes VID 0 on module unload for all interfaces
+ * with VLAN filtering feature. We need to keep it to receive
+ * untagged traffic.
+ */
+ if (vid == 0)
+ return 0;
+
+ /* Del the port MAC address to with the right VLAN information */
+ ocelot_mact_forget(ocelot, dev->dev_addr, vid);
+
+ /* Stop the port from being a member of the vlan */
+ ocelot->vlan_mask[vid] &= ~BIT(port->chip_port);
+ ret = ocelot_vlant_set_mask(ocelot, vid, ocelot->vlan_mask[vid]);
+ if (ret)
+ return ret;
+
+ /* Ingress */
+ if (port->pvid == vid)
+ port->pvid = 0;
+
+ /* Egress */
+ if (port->vid == vid)
+ port->vid = 0;
+
+ ocelot_vlan_port_apply(ocelot, port);
+
+ return 0;
+}
+
static void ocelot_vlan_init(struct ocelot *ocelot)
{
+ u16 port, vid;
+
/* Clear VLAN table, by default all ports are members of all VLANs */
ocelot_write(ocelot, ANA_TABLES_VLANACCESS_CMD_INIT,
ANA_TABLES_VLANACCESS);
ocelot_vlant_wait_for_completion(ocelot);
+
+ /* Configure the port VLAN memberships */
+ for (vid = 1; vid < VLAN_N_VID; vid++) {
+ ocelot->vlan_mask[vid] = 0;
+ ocelot_vlant_set_mask(ocelot, vid, ocelot->vlan_mask[vid]);
+ }
+
+ /* Because VLAN filtering is enabled, we need VID 0 to get untagged
+ * traffic. It is added automatically if 8021q module is loaded, but
+ * we can't rely on it since module may be not loaded.
+ */
+ ocelot->vlan_mask[0] = GENMASK(ocelot->num_phys_ports - 1, 0);
+ ocelot_vlant_set_mask(ocelot, 0, ocelot->vlan_mask[0]);
+
+ /* Configure the CPU port to be VLAN aware */
+ ocelot_write_gix(ocelot, ANA_PORT_VLAN_CFG_VLAN_VID(0) |
+ ANA_PORT_VLAN_CFG_VLAN_AWARE_ENA |
+ ANA_PORT_VLAN_CFG_VLAN_POP_CNT(1),
+ ANA_PORT_VLAN_CFG, ocelot->num_phys_ports);
+
+ /* Set vlan ingress filter mask to all ports but the CPU port by
+ * default.
+ */
+ ocelot_write(ocelot, GENMASK(9, 0), ANA_VLANMASK);
+
+ for (port = 0; port < ocelot->num_phys_ports; port++) {
+ ocelot_write_gix(ocelot, 0, REW_PORT_VLAN_CFG, port);
+ ocelot_write_gix(ocelot, 0, REW_TAG_CFG, port);
+ }
}
/* Watermark encode
@@ -538,6 +717,20 @@ static int ocelot_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
struct ocelot_port *port = netdev_priv(dev);
struct ocelot *ocelot = port->ocelot;
+ if (!vid) {
+ if (!port->vlan_aware)
+ /* If the bridge is not VLAN aware and no VID was
+ * provided, set it to pvid to ensure the MAC entry
+ * matches incoming untagged packets
+ */
+ vid = port->pvid;
+ else
+ /* If the bridge is VLAN aware a VID must be provided as
+ * otherwise the learnt entry wouldn't match any frame.
+ */
+ return -EINVAL;
+ }
+
return ocelot_mact_learn(ocelot, port->chip_port, addr, vid,
ENTRYTYPE_NORMAL);
}
@@ -689,6 +882,30 @@ static int ocelot_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
return ret;
}
+static int ocelot_vlan_rx_add_vid(struct net_device *dev, __be16 proto,
+ u16 vid)
+{
+ return ocelot_vlan_vid_add(dev, vid, false, true);
+}
+
+static int ocelot_vlan_rx_kill_vid(struct net_device *dev, __be16 proto,
+ u16 vid)
+{
+ return ocelot_vlan_vid_del(dev, vid);
+}
+
+static int ocelot_set_features(struct net_device *dev,
+ netdev_features_t features)
+{
+ struct ocelot_port *port = netdev_priv(dev);
+ netdev_features_t changed = dev->features ^ features;
+
+ if (changed & NETIF_F_HW_VLAN_CTAG_FILTER)
+ ocelot_vlan_mode(port, features);
+
+ return 0;
+}
+
static const struct net_device_ops ocelot_port_netdev_ops = {
.ndo_open = ocelot_port_open,
.ndo_stop = ocelot_port_stop,
@@ -700,6 +917,9 @@ static const struct net_device_ops ocelot_port_netdev_ops = {
.ndo_fdb_add = ocelot_fdb_add,
.ndo_fdb_del = ocelot_fdb_del,
.ndo_fdb_dump = ocelot_fdb_dump,
+ .ndo_vlan_rx_add_vid = ocelot_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = ocelot_vlan_rx_kill_vid,
+ .ndo_set_features = ocelot_set_features,
};
static void ocelot_get_strings(struct net_device *netdev, u32 sset, u8 *data)
@@ -946,6 +1166,10 @@ static int ocelot_port_attr_set(struct net_device *dev,
case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
ocelot_port_attr_ageing_set(ocelot_port, attr->u.ageing_time);
break;
+ case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
+ ocelot_port->vlan_aware = attr->u.vlan_filtering;
+ ocelot_vlan_port_apply(ocelot_port->ocelot, ocelot_port);
+ break;
case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED:
ocelot_port_attr_mc_set(ocelot_port, !attr->u.mc_disabled);
break;
@@ -957,6 +1181,40 @@ static int ocelot_port_attr_set(struct net_device *dev,
return err;
}
+static int ocelot_port_obj_add_vlan(struct net_device *dev,
+ const struct switchdev_obj_port_vlan *vlan,
+ struct switchdev_trans *trans)
+{
+ int ret;
+ u16 vid;
+
+ for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
+ ret = ocelot_vlan_vid_add(dev, vid,
+ vlan->flags & BRIDGE_VLAN_INFO_PVID,
+ vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ocelot_port_vlan_del_vlan(struct net_device *dev,
+ const struct switchdev_obj_port_vlan *vlan)
+{
+ int ret;
+ u16 vid;
+
+ for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
+ ret = ocelot_vlan_vid_del(dev, vid);
+
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static struct ocelot_multicast *ocelot_multicast_get(struct ocelot *ocelot,
const unsigned char *addr,
u16 vid)
@@ -983,7 +1241,7 @@ static int ocelot_port_obj_add_mdb(struct net_device *dev,
bool new = false;
if (!vid)
- vid = 1;
+ vid = port->pvid;
mc = ocelot_multicast_get(ocelot, mdb->addr, vid);
if (!mc) {
@@ -1024,7 +1282,7 @@ static int ocelot_port_obj_del_mdb(struct net_device *dev,
u16 vid = mdb->vid;
if (!vid)
- vid = 1;
+ vid = port->pvid;
mc = ocelot_multicast_get(ocelot, mdb->addr, vid);
if (!mc)
@@ -1056,6 +1314,11 @@ static int ocelot_port_obj_add(struct net_device *dev,
int ret = 0;
switch (obj->id) {
+ case SWITCHDEV_OBJ_ID_PORT_VLAN:
+ ret = ocelot_port_obj_add_vlan(dev,
+ SWITCHDEV_OBJ_PORT_VLAN(obj),
+ trans);
+ break;
case SWITCHDEV_OBJ_ID_PORT_MDB:
ret = ocelot_port_obj_add_mdb(dev, SWITCHDEV_OBJ_PORT_MDB(obj),
trans);
@@ -1073,6 +1336,10 @@ static int ocelot_port_obj_del(struct net_device *dev,
int ret = 0;
switch (obj->id) {
+ case SWITCHDEV_OBJ_ID_PORT_VLAN:
+ ret = ocelot_port_vlan_del_vlan(dev,
+ SWITCHDEV_OBJ_PORT_VLAN(obj));
+ break;
case SWITCHDEV_OBJ_ID_PORT_MDB:
ret = ocelot_port_obj_del_mdb(dev, SWITCHDEV_OBJ_PORT_MDB(obj));
break;
@@ -1118,6 +1385,11 @@ static void ocelot_port_bridge_leave(struct ocelot_port *ocelot_port,
if (!ocelot->bridge_mask)
ocelot->hw_bridge_dev = NULL;
+
+ /* Clear bridge vlan settings before calling ocelot_vlan_port_apply */
+ ocelot_port->vlan_aware = 0;
+ ocelot_port->pvid = 0;
+ ocelot_port->vid = 0;
}
static void ocelot_set_aggr_pgids(struct ocelot *ocelot)
@@ -1276,6 +1548,9 @@ static int ocelot_netdevice_port_event(struct net_device *dev,
else
ocelot_port_bridge_leave(ocelot_port,
info->upper_dev);
+
+ ocelot_vlan_port_apply(ocelot_port->ocelot,
+ ocelot_port);
}
if (netif_is_lag_master(info->upper_dev)) {
if (info->linking)
@@ -1347,6 +1622,9 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
dev->ethtool_ops = &ocelot_ethtool_ops;
dev->switchdev_ops = &ocelot_port_switchdev_ops;
+ dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+ dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+
memcpy(dev->dev_addr, ocelot->base_mac, ETH_ALEN);
dev->dev_addr[ETH_ALEN - 1] += port;
ocelot_mact_learn(ocelot, PGID_CPU, dev->dev_addr, ocelot_port->pvid,
@@ -1358,6 +1636,9 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
goto err_register_netdev;
}
+ /* Basic L2 initialization */
+ ocelot_vlan_port_apply(ocelot, ocelot_port);
+
return 0;
err_register_netdev:
--
2.17.0
^ permalink raw reply related
* [PATCH net-next 1/2] net: mscc: ocelot: add bonding support
From: Alexandre Belloni @ 2018-05-18 6:41 UTC (permalink / raw)
To: David S . Miller
Cc: Allan Nielsen, razvan.stefanescu, po.liu, Thomas Petazzoni,
Andrew Lunn, Florian Fainelli, netdev, linux-kernel,
Alexandre Belloni
In-Reply-To: <20180518064106.10122-1-alexandre.belloni@bootlin.com>
Add link aggregation hardware offload support for Ocelot.
ocelot_get_link_ksettings() is not great but it does work until the driver
is reworked to switch to phylink.
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
drivers/net/ethernet/mscc/ocelot.c | 177 +++++++++++++++++++++++++++++
drivers/net/ethernet/mscc/ocelot.h | 2 +-
2 files changed, 178 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index c8c74aa548d9..f22f5467001e 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -775,10 +775,43 @@ static int ocelot_get_sset_count(struct net_device *dev, int sset)
return ocelot->num_stats;
}
+static int ocelot_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *ks)
+{
+ ethtool_link_ksettings_zero_link_mode(ks, supported);
+ ethtool_link_ksettings_zero_link_mode(ks, advertising);
+
+ ethtool_link_ksettings_add_link_mode(ks, supported, 10baseT_Half);
+ ethtool_link_ksettings_add_link_mode(ks, supported, 10baseT_Full);
+ ethtool_link_ksettings_add_link_mode(ks, supported, 100baseT_Half);
+ ethtool_link_ksettings_add_link_mode(ks, supported, 100baseT_Full);
+ ethtool_link_ksettings_add_link_mode(ks, supported, 1000baseT_Half);
+ ethtool_link_ksettings_add_link_mode(ks, supported, 1000baseT_Full);
+ ethtool_link_ksettings_add_link_mode(ks, supported, 2500baseT_Full);
+ ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
+
+ if (!dev->phydev)
+ return 0;
+
+ ethtool_link_ksettings_add_link_mode(ks, advertising, 10baseT_Full);
+ ethtool_link_ksettings_add_link_mode(ks, advertising, 100baseT_Full);
+ ethtool_link_ksettings_add_link_mode(ks, advertising, 1000baseT_Full);
+ ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg);
+
+ if (!dev->phydev->link)
+ return 0;
+
+ ks->base.speed = dev->phydev->speed;
+ ks->base.duplex = DUPLEX_FULL;
+
+ return 0;
+}
+
static const struct ethtool_ops ocelot_ethtool_ops = {
.get_strings = ocelot_get_strings,
.get_ethtool_stats = ocelot_get_ethtool_stats,
.get_sset_count = ocelot_get_sset_count,
+ .get_link_ksettings = ocelot_get_link_ksettings,
};
static int ocelot_port_attr_get(struct net_device *dev,
@@ -1087,6 +1120,137 @@ static void ocelot_port_bridge_leave(struct ocelot_port *ocelot_port,
ocelot->hw_bridge_dev = NULL;
}
+static void ocelot_set_aggr_pgids(struct ocelot *ocelot)
+{
+ int i, port, lag;
+
+ /* Reset destination and aggregation PGIDS */
+ for (port = 0; port < ocelot->num_phys_ports; port++)
+ ocelot_write_rix(ocelot, BIT(port), ANA_PGID_PGID, port);
+
+ for (i = PGID_AGGR; i < PGID_SRC; i++)
+ ocelot_write_rix(ocelot, GENMASK(ocelot->num_phys_ports - 1, 0),
+ ANA_PGID_PGID, i);
+
+ /* Now, set PGIDs for each LAG */
+ for (lag = 0; lag < ocelot->num_phys_ports; lag++) {
+ unsigned long bond_mask;
+ int aggr_count = 0;
+ u8 aggr_idx[16];
+
+ bond_mask = ocelot->lags[lag];
+ if (!bond_mask)
+ continue;
+
+ for_each_set_bit(port, &bond_mask, ocelot->num_phys_ports) {
+ // Destination mask
+ ocelot_write_rix(ocelot, bond_mask,
+ ANA_PGID_PGID, port);
+ aggr_idx[aggr_count] = port;
+ aggr_count++;
+ }
+
+ for (i = PGID_AGGR; i < PGID_SRC; i++) {
+ u32 ac;
+
+ ac = ocelot_read_rix(ocelot, ANA_PGID_PGID, i);
+ ac &= ~bond_mask;
+ ac |= BIT(aggr_idx[i % aggr_count]);
+ ocelot_write_rix(ocelot, ac, ANA_PGID_PGID, i);
+ }
+ }
+}
+
+static void ocelot_setup_lag(struct ocelot *ocelot, int lag)
+{
+ unsigned long bond_mask = ocelot->lags[lag];
+ unsigned int p;
+
+ for_each_set_bit(p, &bond_mask, ocelot->num_phys_ports) {
+ u32 port_cfg = ocelot_read_gix(ocelot, ANA_PORT_PORT_CFG, p);
+
+ port_cfg &= ~ANA_PORT_PORT_CFG_PORTID_VAL_M;
+
+ /* Use lag port as logical port for port i */
+ ocelot_write_gix(ocelot, port_cfg |
+ ANA_PORT_PORT_CFG_PORTID_VAL(lag),
+ ANA_PORT_PORT_CFG, p);
+ }
+}
+
+static int ocelot_port_lag_join(struct ocelot_port *ocelot_port,
+ struct net_device *bond)
+{
+ struct ocelot *ocelot = ocelot_port->ocelot;
+ int p = ocelot_port->chip_port;
+ int lag, lp;
+ struct net_device *ndev;
+ u32 bond_mask = 0;
+
+ rcu_read_lock();
+ for_each_netdev_in_bond_rcu(bond, ndev) {
+ struct ocelot_port *port = netdev_priv(ndev);
+
+ bond_mask |= BIT(port->chip_port);
+ }
+ rcu_read_unlock();
+
+ lp = __ffs(bond_mask);
+
+ /* If the new port is the lowest one, use it as the logical port from
+ * now on
+ */
+ if (p == lp) {
+ lag = p;
+ ocelot->lags[p] = bond_mask;
+ bond_mask &= ~BIT(p);
+ if (bond_mask) {
+ lp = __ffs(bond_mask);
+ ocelot->lags[lp] = 0;
+ }
+ } else {
+ lag = lp;
+ ocelot->lags[lp] |= BIT(p);
+ }
+
+ ocelot_setup_lag(ocelot, lag);
+ ocelot_set_aggr_pgids(ocelot);
+
+ return 0;
+}
+
+static void ocelot_port_lag_leave(struct ocelot_port *ocelot_port,
+ struct net_device *bond)
+{
+ struct ocelot *ocelot = ocelot_port->ocelot;
+ int p = ocelot_port->chip_port;
+ u32 port_cfg;
+ int i;
+
+ /* Remove port from any lag */
+ for (i = 0; i < ocelot->num_phys_ports; i++)
+ ocelot->lags[i] &= ~BIT(ocelot_port->chip_port);
+
+ /* if it was the logical port of the lag, move the lag config to the
+ * next port
+ */
+ if (ocelot->lags[p]) {
+ int n = __ffs(ocelot->lags[p]);
+
+ ocelot->lags[n] = ocelot->lags[p];
+ ocelot->lags[p] = 0;
+
+ ocelot_setup_lag(ocelot, n);
+ }
+
+ port_cfg = ocelot_read_gix(ocelot, ANA_PORT_PORT_CFG, p);
+ port_cfg &= ~ANA_PORT_PORT_CFG_PORTID_VAL_M;
+ ocelot_write_gix(ocelot, port_cfg | ANA_PORT_PORT_CFG_PORTID_VAL(p),
+ ANA_PORT_PORT_CFG, p);
+
+ ocelot_set_aggr_pgids(ocelot);
+}
+
/* Checks if the net_device instance given to us originate from our driver. */
static bool ocelot_netdevice_dev_check(const struct net_device *dev)
{
@@ -1113,6 +1277,14 @@ static int ocelot_netdevice_port_event(struct net_device *dev,
ocelot_port_bridge_leave(ocelot_port,
info->upper_dev);
}
+ if (netif_is_lag_master(info->upper_dev)) {
+ if (info->linking)
+ err = ocelot_port_lag_join(ocelot_port,
+ info->upper_dev);
+ else
+ ocelot_port_lag_leave(ocelot_port,
+ info->upper_dev);
+ }
break;
default:
break;
@@ -1200,6 +1372,11 @@ int ocelot_init(struct ocelot *ocelot)
int i, cpu = ocelot->num_phys_ports;
char queue_name[32];
+ ocelot->lags = devm_kcalloc(ocelot->dev, ocelot->num_phys_ports,
+ sizeof(u32), GFP_KERNEL);
+ if (!ocelot->lags)
+ return -ENOMEM;
+
ocelot->stats = devm_kcalloc(ocelot->dev,
ocelot->num_phys_ports * ocelot->num_stats,
sizeof(u64), GFP_KERNEL);
diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
index 097bd12a10d4..616bec30dfa3 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -493,7 +493,7 @@ struct ocelot {
u8 num_cpu_ports;
struct ocelot_port **ports;
- u16 lags[16];
+ u32 *lags;
/* Keep track of the vlan port masks */
u32 vlan_mask[VLAN_N_VID];
--
2.17.0
^ permalink raw reply related
* [PATCH net-next 0/2] net: mscc; ocelot: add more features
From: Alexandre Belloni @ 2018-05-18 6:41 UTC (permalink / raw)
To: David S . Miller
Cc: Allan Nielsen, razvan.stefanescu, po.liu, Thomas Petazzoni,
Andrew Lunn, Florian Fainelli, netdev, linux-kernel,
Alexandre Belloni
Hi,
This series adds link aggregation and VLAN filtering hardware offload
support to the ocelot driver.
PTP is also on the list of features but it will probably not be
submitted this cycle.
Alexandre Belloni (1):
net: mscc: ocelot: add bonding support
Antoine Tenart (1):
net: mscc: ocelot: add VLAN filtering
drivers/net/ethernet/mscc/ocelot.c | 462 ++++++++++++++++++++++++++++-
drivers/net/ethernet/mscc/ocelot.h | 2 +-
2 files changed, 461 insertions(+), 3 deletions(-)
--
2.17.0
^ permalink raw reply
* Re: [patch net-next RFC 04/12] dsa: set devlink port attrs for dsa ports
From: Jiri Pirko @ 2018-05-18 6:37 UTC (permalink / raw)
To: Andrew Lunn
Cc: Florian Fainelli, netdev, davem, idosch, jakub.kicinski, mlxsw,
vivien.didelot, michael.chan, ganeshgr, saeedm, simon.horman,
pieter.jansenvanvuuren, john.hurley, dirk.vandermerwe,
alexander.h.duyck, ogerlitz, dsahern, vijaya.guvva,
satananda.burla, raghu.vatsavayi, felix.manlunas, gospo,
sathya.perla, vasundhara-v.volam, tariqt, eranbe,
jeffrey.t.kirsher
In-Reply-To: <20180518014137.GB6069@lunn.ch>
Fri, May 18, 2018 at 03:41:37AM CEST, andrew@lunn.ch wrote:
>> >>> ds = dsa_switch_alloc(&mdiodev->dev, DSA_MAX_PORTS);
>> >>>
>> >>> It is allocating a switch with 12 ports. However only 4 of them have
>> >>> names. So the core only creates slave devices for those 4.
>> >>>
>> >>> This is a useful test. Real hardware often has unused ports. A WiFi AP
>> >>> with a 7 port switch which only uses 6 ports is often seen.
>> >>
>> >> The following patch should fix this:
>> >>
>> >>
>> >> diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
>> >> index adf50fbc4c13..a06c29ec91f0 100644
>> >> --- a/net/dsa/dsa2.c
>> >> +++ b/net/dsa/dsa2.c
>> >> @@ -262,13 +262,14 @@ static int dsa_port_setup(struct dsa_port *dp)
>> >>
>> >> memset(&dp->devlink_port, 0, sizeof(dp->devlink_port));
>> >>
>> >> + if (dp->type == DSA_PORT_TYPE_UNUSED)
>> >> + return 0;
>> >> +
>> >> err = devlink_port_register(ds->devlink, &dp->devlink_port,
>> >> dp->index);
>> >
>> > Hi Florian, Jiri
>> >
>> > Maybe it is better to add a devlink port type unused?
>>
>> The port does not exist on the switch, so it should not even be
>> registered IMHO.
>
>Hi Florian
>
>The ports do exist, when you called dsa_switch_alloc() you said the
>switch has 12 ports.
What benefit does it have to register unused ports? What is a usecase
for them. Like Florian, I also think they should not be registered.
>
> Andrew
^ permalink raw reply
* Re: Request for -stable inclusion: time stamping fix for nfp
From: Greg KH @ 2018-05-18 6:36 UTC (permalink / raw)
To: Willy Tarreau; +Cc: David Miller, g.nault, jakub.kicinski, netdev
In-Reply-To: <20180517183202.GB25475@1wt.eu>
On Thu, May 17, 2018 at 08:32:02PM +0200, Willy Tarreau wrote:
> Adding Greg here.
>
> Greg, apparently a backport of 46f1c52e66db is needed in 4.9 according
> to the thread below. It was merged in 4.13 so 4.14 already has it.
Thanks for the notice, now queued up.
greg k-h
^ permalink raw reply
* [PATCH bpf-next v2 1/7] perf/core: add perf_get_event() to return perf_event given a struct file
From: Yonghong Song @ 2018-05-18 5:32 UTC (permalink / raw)
To: peterz, ast, daniel, netdev; +Cc: kernel-team
A new extern function, perf_get_event(), is added to return a perf event
given a struct file. This function will be used in later patches.
Signed-off-by: Yonghong Song <yhs@fb.com>
---
include/linux/perf_event.h | 5 +++++
kernel/events/core.c | 8 ++++++++
2 files changed, 13 insertions(+)
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index e71e99e..b5c1ad3 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -868,6 +868,7 @@ extern void perf_event_exit_task(struct task_struct *child);
extern void perf_event_free_task(struct task_struct *task);
extern void perf_event_delayed_put(struct task_struct *task);
extern struct file *perf_event_get(unsigned int fd);
+extern struct perf_event *perf_get_event(struct file *file);
extern const struct perf_event_attr *perf_event_attrs(struct perf_event *event);
extern void perf_event_print_debug(void);
extern void perf_pmu_disable(struct pmu *pmu);
@@ -1289,6 +1290,10 @@ static inline void perf_event_exit_task(struct task_struct *child) { }
static inline void perf_event_free_task(struct task_struct *task) { }
static inline void perf_event_delayed_put(struct task_struct *task) { }
static inline struct file *perf_event_get(unsigned int fd) { return ERR_PTR(-EINVAL); }
+static inline struct perf_event *perf_get_event(struct file *file)
+{
+ return ERR_PTR(-EINVAL);
+}
static inline const struct perf_event_attr *perf_event_attrs(struct perf_event *event)
{
return ERR_PTR(-EINVAL);
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 67612ce..1e3cddb 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -11212,6 +11212,14 @@ struct file *perf_event_get(unsigned int fd)
return file;
}
+struct perf_event *perf_get_event(struct file *file)
+{
+ if (file->f_op != &perf_fops)
+ return ERR_PTR(-EINVAL);
+
+ return file->private_data;
+}
+
const struct perf_event_attr *perf_event_attrs(struct perf_event *event)
{
if (!event)
--
2.9.5
^ permalink raw reply related
* Re: [PATCH v3 1/2] media: rc: introduce BPF_PROG_RAWIR_EVENT
From: Y Song @ 2018-05-18 5:31 UTC (permalink / raw)
To: Sean Young
Cc: linux-media, linux-kernel, Alexei Starovoitov,
Mauro Carvalho Chehab, Daniel Borkmann, netdev, Matthias Reichl,
Devin Heitmueller
In-Reply-To: <20180517214534.2ipc4q3ru7ykdklf@gofer.mess.org>
On Thu, May 17, 2018 at 2:45 PM, Sean Young <sean@mess.org> wrote:
> Hi,
>
> Again thanks for a thoughtful review. This will definitely will improve
> the code.
>
> On Thu, May 17, 2018 at 10:02:52AM -0700, Y Song wrote:
>> On Wed, May 16, 2018 at 2:04 PM, Sean Young <sean@mess.org> wrote:
>> > Add support for BPF_PROG_RAWIR_EVENT. This type of BPF program can call
>> > rc_keydown() to reported decoded IR scancodes, or rc_repeat() to report
>> > that the last key should be repeated.
>> >
>> > The bpf program can be attached to using the bpf(BPF_PROG_ATTACH) syscall;
>> > the target_fd must be the /dev/lircN device.
>> >
>> > Signed-off-by: Sean Young <sean@mess.org>
>> > ---
>> > drivers/media/rc/Kconfig | 13 ++
>> > drivers/media/rc/Makefile | 1 +
>> > drivers/media/rc/bpf-rawir-event.c | 363 +++++++++++++++++++++++++++++
>> > drivers/media/rc/lirc_dev.c | 24 ++
>> > drivers/media/rc/rc-core-priv.h | 24 ++
>> > drivers/media/rc/rc-ir-raw.c | 14 +-
>> > include/linux/bpf_rcdev.h | 30 +++
>> > include/linux/bpf_types.h | 3 +
>> > include/uapi/linux/bpf.h | 55 ++++-
>> > kernel/bpf/syscall.c | 7 +
>> > 10 files changed, 531 insertions(+), 3 deletions(-)
>> > create mode 100644 drivers/media/rc/bpf-rawir-event.c
>> > create mode 100644 include/linux/bpf_rcdev.h
>> >
>> > diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
>> > index eb2c3b6eca7f..2172d65b0213 100644
>> > --- a/drivers/media/rc/Kconfig
>> > +++ b/drivers/media/rc/Kconfig
>> > @@ -25,6 +25,19 @@ config LIRC
>> > passes raw IR to and from userspace, which is needed for
>> > IR transmitting (aka "blasting") and for the lirc daemon.
>> >
>> > +config BPF_RAWIR_EVENT
>> > + bool "Support for eBPF programs attached to lirc devices"
>> > + depends on BPF_SYSCALL
>> > + depends on RC_CORE=y
>> > + depends on LIRC
>> > + help
>> > + Allow attaching eBPF programs to a lirc device using the bpf(2)
>> > + syscall command BPF_PROG_ATTACH. This is supported for raw IR
>> > + receivers.
>> > +
>> > + These eBPF programs can be used to decode IR into scancodes, for
>> > + IR protocols not supported by the kernel decoders.
>> > +
>> > menuconfig RC_DECODERS
>> > bool "Remote controller decoders"
>> > depends on RC_CORE
>> > diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
>> > index 2e1c87066f6c..74907823bef8 100644
>> > --- a/drivers/media/rc/Makefile
>> > +++ b/drivers/media/rc/Makefile
>> > @@ -5,6 +5,7 @@ obj-y += keymaps/
>> > obj-$(CONFIG_RC_CORE) += rc-core.o
>> > rc-core-y := rc-main.o rc-ir-raw.o
>> > rc-core-$(CONFIG_LIRC) += lirc_dev.o
>> > +rc-core-$(CONFIG_BPF_RAWIR_EVENT) += bpf-rawir-event.o
>> > obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o
>> > obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
>> > obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
>> > diff --git a/drivers/media/rc/bpf-rawir-event.c b/drivers/media/rc/bpf-rawir-event.c
>> > new file mode 100644
>> > index 000000000000..7cb48b8d87b5
>> > --- /dev/null
>> > +++ b/drivers/media/rc/bpf-rawir-event.c
>> > @@ -0,0 +1,363 @@
>> > +// SPDX-License-Identifier: GPL-2.0
>> > +// bpf-rawir-event.c - handles bpf
>> > +//
>> > +// Copyright (C) 2018 Sean Young <sean@mess.org>
>> > +
>> > +#include <linux/bpf.h>
>> > +#include <linux/filter.h>
>> > +#include <linux/bpf_rcdev.h>
>> > +#include "rc-core-priv.h"
>> > +
>> > +/*
>> > + * BPF interface for raw IR
>> > + */
>> > +const struct bpf_prog_ops rawir_event_prog_ops = {
>> > +};
>> > +
>> > +BPF_CALL_1(bpf_rc_repeat, struct bpf_rawir_event*, event)
>> > +{
>> > + struct ir_raw_event_ctrl *ctrl;
>> > +
>> > + ctrl = container_of(event, struct ir_raw_event_ctrl, bpf_rawir_event);
>> > +
>> > + rc_repeat(ctrl->dev);
>> > +
>> > + return 0;
>> > +}
>> > +
>> > +static const struct bpf_func_proto rc_repeat_proto = {
>> > + .func = bpf_rc_repeat,
>> > + .gpl_only = true, /* rc_repeat is EXPORT_SYMBOL_GPL */
>> > + .ret_type = RET_INTEGER,
>> > + .arg1_type = ARG_PTR_TO_CTX,
>> > +};
>> > +
>> > +BPF_CALL_4(bpf_rc_keydown, struct bpf_rawir_event*, event, u32, protocol,
>> > + u32, scancode, u32, toggle)
>> > +{
>> > + struct ir_raw_event_ctrl *ctrl;
>> > +
>> > + ctrl = container_of(event, struct ir_raw_event_ctrl, bpf_rawir_event);
>> > +
>> > + rc_keydown(ctrl->dev, protocol, scancode, toggle != 0);
>> > +
>> > + return 0;
>> > +}
>> > +
>> > +static const struct bpf_func_proto rc_keydown_proto = {
>> > + .func = bpf_rc_keydown,
>> > + .gpl_only = true, /* rc_keydown is EXPORT_SYMBOL_GPL */
>> > + .ret_type = RET_INTEGER,
>> > + .arg1_type = ARG_PTR_TO_CTX,
>> > + .arg2_type = ARG_ANYTHING,
>> > + .arg3_type = ARG_ANYTHING,
>> > + .arg4_type = ARG_ANYTHING,
>> > +};
>> > +
>> > +static const struct bpf_func_proto *
>> > +rawir_event_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
>> > +{
>> > + switch (func_id) {
>> > + case BPF_FUNC_rc_repeat:
>> > + return &rc_repeat_proto;
>> > + case BPF_FUNC_rc_keydown:
>> > + return &rc_keydown_proto;
>> > + case BPF_FUNC_map_lookup_elem:
>> > + return &bpf_map_lookup_elem_proto;
>> > + case BPF_FUNC_map_update_elem:
>> > + return &bpf_map_update_elem_proto;
>> > + case BPF_FUNC_map_delete_elem:
>> > + return &bpf_map_delete_elem_proto;
>> > + case BPF_FUNC_ktime_get_ns:
>> > + return &bpf_ktime_get_ns_proto;
>> > + case BPF_FUNC_tail_call:
>> > + return &bpf_tail_call_proto;
>> > + case BPF_FUNC_get_prandom_u32:
>> > + return &bpf_get_prandom_u32_proto;
>> > + case BPF_FUNC_trace_printk:
>> > + if (capable(CAP_SYS_ADMIN))
>> > + return bpf_get_trace_printk_proto();
>> > + /* fall through */
>> > + default:
>> > + return NULL;
>> > + }
>> > +}
>> > +
>> > +static bool rawir_event_is_valid_access(int off, int size,
>> > + enum bpf_access_type type,
>> > + const struct bpf_prog *prog,
>> > + struct bpf_insn_access_aux *info)
>> > +{
>> > + /* struct bpf_rawir_event has two u32 fields */
>> > + if (type == BPF_WRITE)
>> > + return false;
>> > +
>> > + if (size != sizeof(__u32))
>> > + return false;
>> > +
>> > + if (!(off == offsetof(struct bpf_rawir_event, duration) ||
>> > + off == offsetof(struct bpf_rawir_event, type)))
>> > + return false;
>> > +
>> > + return true;
>> > +}
>> > +
>> > +const struct bpf_verifier_ops rawir_event_verifier_ops = {
>> > + .get_func_proto = rawir_event_func_proto,
>> > + .is_valid_access = rawir_event_is_valid_access
>> > +};
>> > +
>> > +#define BPF_MAX_PROGS 64
>> > +
>> > +static int rc_dev_bpf_attach(struct rc_dev *rcdev, struct bpf_prog *prog)
>> > +{
>> > + struct ir_raw_event_ctrl *raw;
>> > + struct bpf_prog_list *pl;
>> > + int ret, size;
>> > +
>> > + if (rcdev->driver_type != RC_DRIVER_IR_RAW)
>> > + return -EINVAL;
>> > +
>> > + ret = mutex_lock_interruptible(&ir_raw_handler_lock);
>> > + if (ret)
>> > + return ret;
>> > +
>> > + raw = rcdev->raw;
>> > + if (!raw) {
>> > + ret = -ENODEV;
>> > + goto out;
>> > + }
>> > +
>> > + size = 0;
>> > + list_for_each_entry(pl, &raw->progs, node) {
>> > + if (pl->prog == prog) {
>> > + ret = -EEXIST;
>> > + goto out;
>> > + }
>> > +
>> > + size++;
>> > + }
>> > +
>> > + if (size >= BPF_MAX_PROGS) {
>> > + ret = -E2BIG;
>> > + goto out;
>> > + }
>> > +
>> > + pl = kmalloc(sizeof(*pl), GFP_KERNEL);
>> > + if (!pl) {
>> > + ret = -ENOMEM;
>> > + goto out;
>> > + }
>> > +
>> > + pl->prog = prog;
>> > + list_add(&pl->node, &raw->progs);
>> > +out:
>> > + mutex_unlock(&ir_raw_handler_lock);
>> > + return ret;
>> > +}
>> > +
>> > +static int rc_dev_bpf_detach(struct rc_dev *rcdev, struct bpf_prog *prog)
>> > +{
>> > + struct ir_raw_event_ctrl *raw;
>> > + struct bpf_prog_list *pl, *tmp;
>> > + int ret;
>> > +
>> > + if (rcdev->driver_type != RC_DRIVER_IR_RAW)
>> > + return -EINVAL;
>> > +
>> > + ret = mutex_lock_interruptible(&ir_raw_handler_lock);
>> > + if (ret)
>> > + return ret;
>> > +
>> > + raw = rcdev->raw;
>> > + if (!raw) {
>> > + ret = -ENODEV;
>> > + goto out;
>> > + }
>> > +
>> > + ret = -ENOENT;
>> > +
>> > + list_for_each_entry_safe(pl, tmp, &raw->progs, node) {
>> > + if (pl->prog == prog) {
>> > + list_del(&pl->node);
>> > + kfree(pl);
>> > + bpf_prog_put(prog);
>> > + ret = 0;
>> > + goto out;
>> > + }
>> > + }
>> > +out:
>> > + mutex_unlock(&ir_raw_handler_lock);
>> > + return ret;
>> > +}
>> > +
>> > +void rc_dev_bpf_init(struct rc_dev *rcdev)
>> > +{
>> > + INIT_LIST_HEAD(&rcdev->raw->progs);
>> > +}
>> > +
>> > +void rc_dev_bpf_run(struct rc_dev *rcdev, struct ir_raw_event ev)
>> > +{
>> > + struct ir_raw_event_ctrl *raw = rcdev->raw;
>> > + struct bpf_prog_list *pl;
>> > +
>> > + if (list_empty(&raw->progs))
>> > + return;
>> > +
>> > + if (unlikely(ev.carrier_report)) {
>> > + raw->bpf_rawir_event.carrier = ev.carrier;
>> > + raw->bpf_rawir_event.type = BPF_RAWIR_EVENT_CARRIER;
>> > + } else {
>> > + raw->bpf_rawir_event.duration = ev.duration;
>> > +
>> > + if (ev.pulse)
>> > + raw->bpf_rawir_event.type = BPF_RAWIR_EVENT_PULSE;
>> > + else if (ev.timeout)
>> > + raw->bpf_rawir_event.type = BPF_RAWIR_EVENT_TIMEOUT;
>> > + else if (ev.reset)
>> > + raw->bpf_rawir_event.type = BPF_RAWIR_EVENT_RESET;
>> > + else
>> > + raw->bpf_rawir_event.type = BPF_RAWIR_EVENT_SPACE;
>> > + }
>> > +
>> > + list_for_each_entry(pl, &raw->progs, node)
>> > + BPF_PROG_RUN(pl->prog, &raw->bpf_rawir_event);
>>
>> Is the raw->progs protected by locks? It is possible that attaching/detaching
>> could manipulate raw->progs at the same time? In perf/cgroup prog array
>> case, the prog array run is protected by rcu and the dummy prog idea is
>> to avoid the prog is skipped by reshuffling.
>
> Yes, it is. The caller takes the appropriate lock. These functions could do
> with some comments.
>
>> Also, the original idea about using prog array is the least overhead since you
>> want to BPF programs to execute as soon as possible.
>
> Now, for our purposes the we're not bothered by a few milliseconds delay,
> so I would pick whatever uses less cpu/memory overall. There is some overhead
> in using rcu but the array is nice since it uses less memory than the
> double-linked list, and less cache misses.
>
> So I wanted bpf_prog_detach() to return -ENOENT if the prog was not in the list,
> however bpf_prog_array_copy() and bpf_prog_array_delete_safe() do not return
> anything useful for that.
>
> Maybe I should look at adding a count-delta return to bpf_prog_array_copy(),
> and a bool return to bpf_prog_array_delete_safe(). Or I could scan the array
> an extra time to see if it is present. Any other ideas?
The detaching is not performance critical. Either of these methods is fine.
A bool return to bpf_prog_array_delete_safe() seems easy to make a change.
>
> Also, BPF_F_OVERRIDE is not relevant for this but possibly BPF_F_ALLOW_MULTI
> could invoke the same behaviour as for cgroups. What do you think?
Looks like you already allow multiple programs attaching to the same device?
So by default you already implied supporting BPF_F_ALLOW_MULTI, but you
just did not specify it. I think this is fine. perf event also
supports program array
by default and users do not need to specify flags.
Or I misunderstood your question?
^ permalink raw reply
* [RFC PATCH net-next] tcp: tcp_rack_reo_wnd() can be static
From: kbuild test robot @ 2018-05-18 5:14 UTC (permalink / raw)
To: Yuchung Cheng
Cc: kbuild-all, netdev, Neal Cardwell, Eric Dumazet,
Soheil Hassas Yeganeh, Priyaranjan Jha, Alexey Kuznetsov,
Hideaki YOSHIFUJI, linux-kernel
In-Reply-To: <201805181300.JN7KwXNm%fengguang.wu@intel.com>
Fixes: 20b654dfe1be ("tcp: support DUPACK threshold in RACK")
Signed-off-by: kbuild test robot <fengguang.wu@intel.com>
---
tcp_recovery.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv4/tcp_recovery.c b/net/ipv4/tcp_recovery.c
index 30cbfb6..71593e4 100644
--- a/net/ipv4/tcp_recovery.c
+++ b/net/ipv4/tcp_recovery.c
@@ -21,7 +21,7 @@ static bool tcp_rack_sent_after(u64 t1, u64 t2, u32 seq1, u32 seq2)
return t1 > t2 || (t1 == t2 && after(seq1, seq2));
}
-u32 tcp_rack_reo_wnd(const struct sock *sk)
+static u32 tcp_rack_reo_wnd(const struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
^ permalink raw reply related
* [net-next:master 1200/1233] net/ipv4/tcp_recovery.c:24:5: sparse: symbol 'tcp_rack_reo_wnd' was not declared. Should it be static?
From: kbuild test robot @ 2018-05-18 5:14 UTC (permalink / raw)
To: Yuchung Cheng
Cc: kbuild-all, netdev, Neal Cardwell, Eric Dumazet,
Soheil Hassas Yeganeh, Priyaranjan Jha, Alexey Kuznetsov,
Hideaki YOSHIFUJI, linux-kernel
tree: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git master
head: 538e2de104cfb4ef1acb35af42427bff42adbe4d
commit: 20b654dfe1beaca60ab51894ff405a049248433d [1200/1233] tcp: support DUPACK threshold in RACK
reproduce:
# apt-get install sparse
git checkout 20b654dfe1beaca60ab51894ff405a049248433d
make ARCH=x86_64 allmodconfig
make C=1 CF=-D__CHECK_ENDIAN__
sparse warnings: (new ones prefixed by >>)
net/ipv4/tcp_recovery.c:46:16: sparse: expression using sizeof(void)
net/ipv4/tcp_recovery.c:46:16: sparse: expression using sizeof(void)
>> net/ipv4/tcp_recovery.c:24:5: sparse: symbol 'tcp_rack_reo_wnd' was not declared. Should it be static?
include/net/tcp.h:738:16: sparse: expression using sizeof(void)
net/ipv4/tcp_recovery.c:102:40: sparse: expression using sizeof(void)
net/ipv4/tcp_recovery.c:102:40: sparse: expression using sizeof(void)
include/net/tcp.h:738:16: sparse: expression using sizeof(void)
net/ipv4/tcp_recovery.c:210:42: sparse: expression using sizeof(void)
Please review and possibly fold the followup patch.
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
^ permalink raw reply
* [PATCH bpf-next v2 0/7] bpf: implement BPF_TASK_FD_QUERY
From: Yonghong Song @ 2018-05-18 5:03 UTC (permalink / raw)
To: peterz, ast, daniel, netdev; +Cc: kernel-team
Currently, suppose a userspace application has loaded a bpf program
and attached it to a tracepoint/kprobe/uprobe, and a bpf
introspection tool, e.g., bpftool, wants to show which bpf program
is attached to which tracepoint/kprobe/uprobe. Such attachment
information will be really useful to understand the overall bpf
deployment in the system.
There is a name field (16 bytes) for each program, which could
be used to encode the attachment point. There are some drawbacks
for this approaches. First, bpftool user (e.g., an admin) may not
really understand the association between the name and the
attachment point. Second, if one program is attached to multiple
places, encoding a proper name which can imply all these
attachments becomes difficult.
This patch introduces a new bpf subcommand BPF_TASK_FD_QUERY.
Given a pid and fd, this command will return bpf related information
to user space. Right now it only supports tracepoint/kprobe/uprobe
perf event fd's. For such a fd, BPF_TASK_FD_QUERY will return
. prog_id
. tracepoint name, or
. k[ret]probe funcname + offset or kernel addr, or
. u[ret]probe filename + offset
to the userspace.
The user can use "bpftool prog" to find more information about
bpf program itself with prog_id.
Patch #1 adds function perf_get_event() in kernel/events/core.c.
Patch #2 implements the bpf subcommand BPF_TASK_FD_QUERY.
Patch #3 syncs tools bpf.h header and also add bpf_task_fd_query()
in the libbpf library for samples/selftests/bpftool to use.
Patch #4 adds ksym_get_addr() utility function.
Patch #5 add a test in samples/bpf for querying k[ret]probes and
u[ret]probes.
Patch #6 add a test in tools/testing/selftests/bpf for querying
raw_tracepoint and tracepoint.
Patch #7 add a new subcommand "perf" to bpftool.
Changelogs:
v1 -> v2:
. changed bpf subcommand name from BPF_PERF_EVENT_QUERY
to BPF_TASK_FD_QUERY.
. fixed various "bpftool perf" issues and added documentation
and auto-completion.
Yonghong Song (7):
perf/core: add perf_get_event() to return perf_event given a struct
file
bpf: introduce bpf subcommand BPF_TASK_FD_QUERY
tools/bpf: sync kernel header bpf.h and add bpf_trace_event_query in
libbpf
tools/bpf: add ksym_get_addr() in trace_helpers
samples/bpf: add a samples/bpf test for BPF_TASK_FD_QUERY
tools/bpf: add two BPF_TASK_FD_QUERY tests in test_progs
tools/bpftool: add perf subcommand
include/linux/perf_event.h | 5 +
include/linux/trace_events.h | 15 +
include/uapi/linux/bpf.h | 27 ++
kernel/bpf/syscall.c | 124 ++++++++
kernel/events/core.c | 8 +
kernel/trace/bpf_trace.c | 48 +++
kernel/trace/trace_kprobe.c | 29 ++
kernel/trace/trace_uprobe.c | 22 ++
samples/bpf/Makefile | 4 +
samples/bpf/task_fd_query_kern.c | 19 ++
samples/bpf/task_fd_query_user.c | 379 +++++++++++++++++++++++
tools/bpf/bpftool/Documentation/bpftool-perf.rst | 81 +++++
tools/bpf/bpftool/Documentation/bpftool.rst | 5 +-
tools/bpf/bpftool/bash-completion/bpftool | 9 +
tools/bpf/bpftool/main.c | 3 +-
tools/bpf/bpftool/main.h | 1 +
tools/bpf/bpftool/perf.c | 200 ++++++++++++
tools/include/uapi/linux/bpf.h | 27 ++
tools/lib/bpf/bpf.c | 24 ++
tools/lib/bpf/bpf.h | 3 +
tools/testing/selftests/bpf/test_progs.c | 133 ++++++++
tools/testing/selftests/bpf/trace_helpers.c | 12 +
tools/testing/selftests/bpf/trace_helpers.h | 1 +
23 files changed, 1177 insertions(+), 2 deletions(-)
create mode 100644 samples/bpf/task_fd_query_kern.c
create mode 100644 samples/bpf/task_fd_query_user.c
create mode 100644 tools/bpf/bpftool/Documentation/bpftool-perf.rst
create mode 100644 tools/bpf/bpftool/perf.c
--
2.9.5
^ permalink raw reply
* [PATCH bpf-next v2 7/7] tools/bpftool: add perf subcommand
From: Yonghong Song @ 2018-05-18 5:03 UTC (permalink / raw)
To: peterz, ast, daniel, netdev; +Cc: kernel-team
In-Reply-To: <20180518050310.2814608-1-yhs@fb.com>
The new command "bpftool perf [show | list]" will traverse
all processes under /proc, and if any fd is associated
with a perf event, it will print out related perf event
information. Documentation is also added.
Below is an example to show the results using bcc commands.
Running the following 4 bcc commands:
kprobe: trace.py '__x64_sys_nanosleep'
kretprobe: trace.py 'r::__x64_sys_nanosleep'
tracepoint: trace.py 't:syscalls:sys_enter_nanosleep'
uprobe: trace.py 'p:/home/yhs/a.out:main'
The bpftool command line and result:
$ bpftool perf
pid 21711 fd 5: prog_id 5 kprobe func __x64_sys_write offset 0
pid 21765 fd 5: prog_id 7 kretprobe func __x64_sys_nanosleep offset 0
pid 21767 fd 5: prog_id 8 tracepoint sys_enter_nanosleep
pid 21800 fd 5: prog_id 9 uprobe filename /home/yhs/a.out offset 1159
$ bpftool -j perf
{"pid":21711,"fd":5,"prog_id":5,"attach_info":"kprobe","func":"__x64_sys_write","offset":0}, \
{"pid":21765,"fd":5,"prog_id":7,"attach_info":"kretprobe","func":"__x64_sys_nanosleep","offset":0}, \
{"pid":21767,"fd":5,"prog_id":8,"attach_info":"tracepoint","tracepoint":"sys_enter_nanosleep"}, \
{"pid":21800,"fd":5,"prog_id":9,"attach_info":"uprobe","filename":"/home/yhs/a.out","offset":1159}
$ bpftool prog
5: kprobe name probe___x64_sys tag e495a0c82f2c7a8d gpl
loaded_at 2018-05-15T04:46:37-0700 uid 0
xlated 200B not jited memlock 4096B map_ids 4
7: kprobe name probe___x64_sys tag f2fdee479a503abf gpl
loaded_at 2018-05-15T04:48:32-0700 uid 0
xlated 200B not jited memlock 4096B map_ids 7
8: tracepoint name tracepoint__sys tag 5390badef2395fcf gpl
loaded_at 2018-05-15T04:48:48-0700 uid 0
xlated 200B not jited memlock 4096B map_ids 8
9: kprobe name probe_main_1 tag 0a87bdc2e2953b6d gpl
loaded_at 2018-05-15T04:49:52-0700 uid 0
xlated 200B not jited memlock 4096B map_ids 9
$ ps ax | grep "python ./trace.py"
21711 pts/0 T 0:03 python ./trace.py __x64_sys_write
21765 pts/0 S+ 0:00 python ./trace.py r::__x64_sys_nanosleep
21767 pts/2 S+ 0:00 python ./trace.py t:syscalls:sys_enter_nanosleep
21800 pts/3 S+ 0:00 python ./trace.py p:/home/yhs/a.out:main
22374 pts/1 S+ 0:00 grep --color=auto python ./trace.py
Signed-off-by: Yonghong Song <yhs@fb.com>
---
tools/bpf/bpftool/Documentation/bpftool-perf.rst | 81 +++++++++
tools/bpf/bpftool/Documentation/bpftool.rst | 5 +-
tools/bpf/bpftool/bash-completion/bpftool | 9 +
tools/bpf/bpftool/main.c | 3 +-
tools/bpf/bpftool/main.h | 1 +
tools/bpf/bpftool/perf.c | 200 +++++++++++++++++++++++
6 files changed, 297 insertions(+), 2 deletions(-)
create mode 100644 tools/bpf/bpftool/Documentation/bpftool-perf.rst
create mode 100644 tools/bpf/bpftool/perf.c
diff --git a/tools/bpf/bpftool/Documentation/bpftool-perf.rst b/tools/bpf/bpftool/Documentation/bpftool-perf.rst
new file mode 100644
index 0000000..3e65375
--- /dev/null
+++ b/tools/bpf/bpftool/Documentation/bpftool-perf.rst
@@ -0,0 +1,81 @@
+================
+bpftool-perf
+================
+-------------------------------------------------------------------------------
+tool for inspection of perf related bpf prog attachments
+-------------------------------------------------------------------------------
+
+:Manual section: 8
+
+SYNOPSIS
+========
+
+ **bpftool** [*OPTIONS*] **perf** *COMMAND*
+
+ *OPTIONS* := { [{ **-j** | **--json** }] [{ **-p** | **--pretty** }] }
+
+ *COMMANDS* :=
+ { **show** | **list** | **help** }
+
+PERF COMMANDS
+=============
+
+| **bpftool** **perf { show | list }**
+| **bpftool** **perf help**
+
+DESCRIPTION
+===========
+ **bpftool perf { show | list }**
+ List all raw_tracepoint, tracepoint, kprobe attachment in the system.
+
+ Output will start with process id and file descriptor in that process,
+ followed by bpf program id, attachment information, and attachment point.
+ The attachment point for raw_tracepoint/tracepoint is the trace probe name.
+ The attachment point for k[ret]probe is either symbol name and offset,
+ or a kernel virtual address.
+ The attachment point for u[ret]probe is the file name and the file offset.
+
+ **bpftool perf help**
+ Print short help message.
+
+OPTIONS
+=======
+ -h, --help
+ Print short generic help message (similar to **bpftool help**).
+
+ -v, --version
+ Print version number (similar to **bpftool version**).
+
+ -j, --json
+ Generate JSON output. For commands that cannot produce JSON, this
+ option has no effect.
+
+ -p, --pretty
+ Generate human-readable JSON output. Implies **-j**.
+
+EXAMPLES
+========
+
+| **# bpftool perf**
+
+::
+
+ pid 21711 fd 5: prog_id 5 kprobe func __x64_sys_write offset 0
+ pid 21765 fd 5: prog_id 7 kretprobe func __x64_sys_nanosleep offset 0
+ pid 21767 fd 5: prog_id 8 tracepoint sys_enter_nanosleep
+ pid 21800 fd 5: prog_id 9 uprobe filename /home/yhs/a.out offset 1159
+
+|
+| **# bpftool -j perf**
+
+::
+
+ [{"pid":21711,"fd":5,"prog_id":5,"attach_info":"kprobe","func":"__x64_sys_write","offset":0}, \
+ {"pid":21765,"fd":5,"prog_id":7,"attach_info":"kretprobe","func":"__x64_sys_nanosleep","offset":0}, \
+ {"pid":21767,"fd":5,"prog_id":8,"attach_info":"tracepoint","tracepoint":"sys_enter_nanosleep"}, \
+ {"pid":21800,"fd":5,"prog_id":9,"attach_info":"uprobe","filename":"/home/yhs/a.out","offset":1159}]
+
+
+SEE ALSO
+========
+ **bpftool**\ (8), **bpftool-prog**\ (8), **bpftool-map**\ (8)
diff --git a/tools/bpf/bpftool/Documentation/bpftool.rst b/tools/bpf/bpftool/Documentation/bpftool.rst
index 564cb0d..b6f5d56 100644
--- a/tools/bpf/bpftool/Documentation/bpftool.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool.rst
@@ -16,7 +16,7 @@ SYNOPSIS
**bpftool** **version**
- *OBJECT* := { **map** | **program** | **cgroup** }
+ *OBJECT* := { **map** | **program** | **cgroup** | **perf** }
*OPTIONS* := { { **-V** | **--version** } | { **-h** | **--help** }
| { **-j** | **--json** } [{ **-p** | **--pretty** }] }
@@ -30,6 +30,8 @@ SYNOPSIS
*CGROUP-COMMANDS* := { **show** | **list** | **attach** | **detach** | **help** }
+ *PERF-COMMANDS* := { **show** | **list** | **help** }
+
DESCRIPTION
===========
*bpftool* allows for inspection and simple modification of BPF objects
@@ -56,3 +58,4 @@ OPTIONS
SEE ALSO
========
**bpftool-map**\ (8), **bpftool-prog**\ (8), **bpftool-cgroup**\ (8)
+ **bpftool-perf**\ (8)
diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool
index b301c9b..3680ad4 100644
--- a/tools/bpf/bpftool/bash-completion/bpftool
+++ b/tools/bpf/bpftool/bash-completion/bpftool
@@ -448,6 +448,15 @@ _bpftool()
;;
esac
;;
+ cgroup)
+ case $command in
+ *)
+ [[ $prev == $object ]] && \
+ COMPREPLY=( $( compgen -W 'help \
+ show list' -- "$cur" ) )
+ ;;
+ esac
+ ;;
esac
} &&
complete -F _bpftool bpftool
diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
index 1ec852d..eea7f14 100644
--- a/tools/bpf/bpftool/main.c
+++ b/tools/bpf/bpftool/main.c
@@ -87,7 +87,7 @@ static int do_help(int argc, char **argv)
" %s batch file FILE\n"
" %s version\n"
"\n"
- " OBJECT := { prog | map | cgroup }\n"
+ " OBJECT := { prog | map | cgroup | perf }\n"
" " HELP_SPEC_OPTIONS "\n"
"",
bin_name, bin_name, bin_name);
@@ -216,6 +216,7 @@ static const struct cmd cmds[] = {
{ "prog", do_prog },
{ "map", do_map },
{ "cgroup", do_cgroup },
+ { "perf", do_perf },
{ "version", do_version },
{ 0 }
};
diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
index 6173cd9..63fdb31 100644
--- a/tools/bpf/bpftool/main.h
+++ b/tools/bpf/bpftool/main.h
@@ -119,6 +119,7 @@ int do_prog(int argc, char **arg);
int do_map(int argc, char **arg);
int do_event_pipe(int argc, char **argv);
int do_cgroup(int argc, char **arg);
+int do_perf(int argc, char **arg);
int prog_parse_fd(int *argc, char ***argv);
int map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len);
diff --git a/tools/bpf/bpftool/perf.c b/tools/bpf/bpftool/perf.c
new file mode 100644
index 0000000..baa4bbe
--- /dev/null
+++ b/tools/bpf/bpftool/perf.c
@@ -0,0 +1,200 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (C) 2018 Facebook
+// Author: Yonghong Song <yhs@fb.com>
+
+#define _GNU_SOURCE
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <ftw.h>
+
+#include <bpf.h>
+
+#include "main.h"
+
+static void print_perf_json(int pid, int fd, __u32 prog_id, __u32 attach_info,
+ char *buf, __u64 probe_offset, __u64 probe_addr)
+{
+ jsonw_start_object(json_wtr);
+ jsonw_int_field(json_wtr, "pid", pid);
+ jsonw_int_field(json_wtr, "fd", fd);
+ jsonw_uint_field(json_wtr, "prog_id", prog_id);
+ switch (attach_info) {
+ case BPF_ATTACH_RAW_TRACEPOINT:
+ jsonw_string_field(json_wtr, "attach_info", "raw_tracepoint");
+ jsonw_string_field(json_wtr, "tracepoint", buf);
+ break;
+ case BPF_ATTACH_TRACEPOINT:
+ jsonw_string_field(json_wtr, "attach_info", "tracepoint");
+ jsonw_string_field(json_wtr, "tracepoint", buf);
+ break;
+ case BPF_ATTACH_KPROBE:
+ jsonw_string_field(json_wtr, "attach_info", "kprobe");
+ if (buf[0] != '\0') {
+ jsonw_string_field(json_wtr, "func", buf);
+ jsonw_lluint_field(json_wtr, "offset", probe_offset);
+ } else {
+ jsonw_lluint_field(json_wtr, "addr", probe_addr);
+ }
+ break;
+ case BPF_ATTACH_KRETPROBE:
+ jsonw_string_field(json_wtr, "attach_info", "kretprobe");
+ if (buf[0] != '\0') {
+ jsonw_string_field(json_wtr, "func", buf);
+ jsonw_lluint_field(json_wtr, "offset", probe_offset);
+ } else {
+ jsonw_lluint_field(json_wtr, "addr", probe_addr);
+ }
+ break;
+ case BPF_ATTACH_UPROBE:
+ jsonw_string_field(json_wtr, "attach_info", "uprobe");
+ jsonw_string_field(json_wtr, "filename", buf);
+ jsonw_lluint_field(json_wtr, "offset", probe_offset);
+ break;
+ case BPF_ATTACH_URETPROBE:
+ jsonw_string_field(json_wtr, "attach_info", "uretprobe");
+ jsonw_string_field(json_wtr, "filename", buf);
+ jsonw_lluint_field(json_wtr, "offset", probe_offset);
+ break;
+ }
+ jsonw_end_object(json_wtr);
+}
+
+static void print_perf_plain(int pid, int fd, __u32 prog_id, __u32 attach_info,
+ char *buf, __u64 probe_offset, __u64 probe_addr)
+{
+ printf("pid %d fd %d: prog_id %u ", pid, fd, prog_id);
+ switch (attach_info) {
+ case BPF_ATTACH_RAW_TRACEPOINT:
+ printf("raw_tracepoint %s\n", buf);
+ break;
+ case BPF_ATTACH_TRACEPOINT:
+ printf("tracepoint %s\n", buf);
+ break;
+ case BPF_ATTACH_KPROBE:
+ if (buf[0] != '\0')
+ printf("kprobe func %s offset %llu\n", buf,
+ probe_offset);
+ else
+ printf("kprobe addr %llu\n", probe_addr);
+ break;
+ case BPF_ATTACH_KRETPROBE:
+ if (buf[0] != '\0')
+ printf("kretprobe func %s offset %llu\n", buf,
+ probe_offset);
+ else
+ printf("kretprobe addr %llu\n", probe_addr);
+ break;
+ case BPF_ATTACH_UPROBE:
+ printf("uprobe filename %s offset %llu\n", buf, probe_offset);
+ break;
+ case BPF_ATTACH_URETPROBE:
+ printf("uretprobe filename %s offset %llu\n", buf,
+ probe_offset);
+ break;
+ }
+}
+
+static int show_proc(const char *fpath, const struct stat *sb,
+ int tflag, struct FTW *ftwbuf)
+{
+ __u64 probe_offset, probe_addr;
+ __u32 prog_id, attach_info;
+ int err, pid = 0, fd = 0;
+ const char *pch;
+ char buf[4096];
+
+ /* prefix always /proc */
+ pch = fpath + 5;
+ if (*pch == '\0')
+ return 0;
+
+ /* pid should be all numbers */
+ pch++;
+ while (isdigit(*pch)) {
+ pid = pid * 10 + *pch - '0';
+ pch++;
+ }
+ if (*pch == '\0')
+ return 0;
+ if (*pch != '/')
+ return FTW_SKIP_SUBTREE;
+
+ /* check /proc/<pid>/fd directory */
+ pch++;
+ if (strncmp(pch, "fd", 2))
+ return FTW_SKIP_SUBTREE;
+ pch += 2;
+ if (*pch == '\0')
+ return 0;
+ if (*pch != '/')
+ return FTW_SKIP_SUBTREE;
+
+ /* check /proc/<pid>/fd/<fd_num> */
+ pch++;
+ while (isdigit(*pch)) {
+ fd = fd * 10 + *pch - '0';
+ pch++;
+ }
+ if (*pch != '\0')
+ return FTW_SKIP_SUBTREE;
+
+ /* query (pid, fd) for potential perf events */
+ err = bpf_task_fd_query(pid, fd, 0, buf, sizeof(buf), &prog_id,
+ &attach_info, &probe_offset, &probe_addr);
+ if (err < 0)
+ return 0;
+
+ if (json_output)
+ print_perf_json(pid, fd, prog_id, attach_info, buf, probe_offset,
+ probe_addr);
+ else
+ print_perf_plain(pid, fd, prog_id, attach_info, buf, probe_offset,
+ probe_addr);
+
+ return 0;
+}
+
+static int do_show(int argc, char **argv)
+{
+ int err = 0, nopenfd = 16;
+ int flags = FTW_ACTIONRETVAL | FTW_PHYS;
+
+ if (json_output)
+ jsonw_start_array(json_wtr);
+ if (nftw("/proc", show_proc, nopenfd, flags) == -1) {
+ p_err("%s", strerror(errno));
+ err = -1;
+ }
+ if (json_output)
+ jsonw_end_array(json_wtr);
+
+ return err;
+}
+
+static int do_help(int argc, char **argv)
+{
+ fprintf(stderr,
+ "Usage: %s %s { show | list | help }\n"
+ "",
+ bin_name, argv[-2]);
+
+ return 0;
+}
+
+static const struct cmd cmds[] = {
+ { "show", do_show },
+ { "list", do_show },
+ { "help", do_help },
+ { 0 }
+};
+
+int do_perf(int argc, char **argv)
+{
+ return cmd_select(cmds, argc, argv, do_help);
+}
--
2.9.5
^ permalink raw reply related
* [PATCH bpf-next v2 3/7] tools/bpf: sync kernel header bpf.h and add bpf_trace_event_query in libbpf
From: Yonghong Song @ 2018-05-18 5:03 UTC (permalink / raw)
To: peterz, ast, daniel, netdev; +Cc: kernel-team
In-Reply-To: <20180518050310.2814608-1-yhs@fb.com>
Sync kernel header bpf.h to tools/include/uapi/linux/bpf.h and
implement bpf_trace_event_query() in libbpf. The test programs
in samples/bpf and tools/testing/selftests/bpf, and later bpftool
will use this libbpf function to query kernel.
Signed-off-by: Yonghong Song <yhs@fb.com>
---
tools/include/uapi/linux/bpf.h | 27 +++++++++++++++++++++++++++
tools/lib/bpf/bpf.c | 24 ++++++++++++++++++++++++
tools/lib/bpf/bpf.h | 3 +++
3 files changed, 54 insertions(+)
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index d94d333..6a22ad4 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -97,6 +97,7 @@ enum bpf_cmd {
BPF_RAW_TRACEPOINT_OPEN,
BPF_BTF_LOAD,
BPF_BTF_GET_FD_BY_ID,
+ BPF_TASK_FD_QUERY,
};
enum bpf_map_type {
@@ -379,6 +380,22 @@ union bpf_attr {
__u32 btf_log_size;
__u32 btf_log_level;
};
+
+ struct {
+ int pid; /* input: pid */
+ int fd; /* input: fd */
+ __u32 flags; /* input: flags */
+ __u32 buf_len; /* input: buf len */
+ __aligned_u64 buf; /* input/output:
+ * tp_name for tracepoint
+ * symbol for kprobe
+ * filename for uprobe
+ */
+ __u32 prog_id; /* output: prod_id */
+ __u32 attach_info; /* output: BPF_ATTACH_* */
+ __u64 probe_offset; /* output: probe_offset */
+ __u64 probe_addr; /* output: probe_addr */
+ } task_fd_query;
} __attribute__((aligned(8)));
/* The description below is an attempt at providing documentation to eBPF
@@ -2450,4 +2467,14 @@ struct bpf_fib_lookup {
__u8 dmac[6]; /* ETH_ALEN */
};
+/* used by <task, fd> based query */
+enum {
+ BPF_ATTACH_RAW_TRACEPOINT, /* tp name */
+ BPF_ATTACH_TRACEPOINT, /* tp name */
+ BPF_ATTACH_KPROBE, /* (symbol + offset) or addr */
+ BPF_ATTACH_KRETPROBE, /* (symbol + offset) or addr */
+ BPF_ATTACH_UPROBE, /* filename + offset */
+ BPF_ATTACH_URETPROBE, /* filename + offset */
+};
+
#endif /* _UAPI__LINUX_BPF_H__ */
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 6a8a000..da3f336 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -643,3 +643,27 @@ int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size,
return fd;
}
+
+int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 buf_len,
+ __u32 *prog_id, __u32 *attach_info,
+ __u64 *probe_offset, __u64 *probe_addr)
+{
+ union bpf_attr attr = {};
+ int err;
+
+ attr.task_fd_query.pid = pid;
+ attr.task_fd_query.fd = fd;
+ attr.task_fd_query.flags = flags;
+ attr.task_fd_query.buf = ptr_to_u64(buf);
+ attr.task_fd_query.buf_len = buf_len;
+
+ err = sys_bpf(BPF_TASK_FD_QUERY, &attr, sizeof(attr));
+ if (!err) {
+ *prog_id = attr.task_fd_query.prog_id;
+ *attach_info = attr.task_fd_query.attach_info;
+ *probe_offset = attr.task_fd_query.probe_offset;
+ *probe_addr = attr.task_fd_query.probe_addr;
+ }
+
+ return err;
+}
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 15bff77..9adfde6 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -107,4 +107,7 @@ int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
int bpf_raw_tracepoint_open(const char *name, int prog_fd);
int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size,
bool do_log);
+int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 buf_len,
+ __u32 *prog_id, __u32 *prog_info,
+ __u64 *probe_offset, __u64 *probe_addr);
#endif
--
2.9.5
^ 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