* [net-next V2 05/12] net/mlx5e: Vxlan, add direct delete function
From: Saeed Mahameed @ 2018-07-28 0:06 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Saeed Mahameed
In-Reply-To: <20180728000622.4123-1-saeedm@mellanox.com>
Add direct vxlan delete function to be called from vxlan_delete_work.
Needed in downstream patch.
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Reviewed-by: Or Gerlitz <ogerlitz@mellanox.com>
---
.../net/ethernet/mellanox/mlx5/core/vxlan.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
index 4b9190d677fc..baeac5922e8c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
@@ -158,18 +158,14 @@ static void mlx5e_vxlan_add_work(struct work_struct *work)
kfree(vxlan_work);
}
-static void mlx5e_vxlan_del_work(struct work_struct *work)
+static void mlx5e_vxlan_del_port(struct mlx5e_priv *priv, u16 port)
{
- struct mlx5e_vxlan_work *vxlan_work =
- container_of(work, struct mlx5e_vxlan_work, work);
- struct mlx5e_priv *priv = vxlan_work->priv;
struct mlx5e_vxlan_db *vxlan_db = &priv->vxlan;
- u16 port = vxlan_work->port;
struct mlx5e_vxlan *vxlan;
bool remove = false;
- mutex_lock(&priv->state_lock);
spin_lock_bh(&vxlan_db->lock);
+
vxlan = mlx5e_vxlan_lookup_port_locked(priv, port);
if (!vxlan)
goto out_unlock;
@@ -187,6 +183,17 @@ static void mlx5e_vxlan_del_work(struct work_struct *work)
kfree(vxlan);
vxlan_db->num_ports--;
}
+}
+
+static void mlx5e_vxlan_del_work(struct work_struct *work)
+{
+ struct mlx5e_vxlan_work *vxlan_work =
+ container_of(work, struct mlx5e_vxlan_work, work);
+ struct mlx5e_priv *priv = vxlan_work->priv;
+ u16 port = vxlan_work->port;
+
+ mutex_lock(&priv->state_lock);
+ mlx5e_vxlan_del_port(priv, port);
mutex_unlock(&priv->state_lock);
kfree(vxlan_work);
}
--
2.17.0
^ permalink raw reply related
* [net-next V2 10/12] net/mlx5e: Vxlan, add sync lock for add/del vxlan port
From: Saeed Mahameed @ 2018-07-28 0:06 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Saeed Mahameed
In-Reply-To: <20180728000622.4123-1-saeedm@mellanox.com>
Vxlan API can and will be called from different mlx5 modules, we should
not count on mlx5e private state lock only, hence we introduce a vxlan
private mutex to sync between add/del vxlan port operations.
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Reviewed-by: Or Gerlitz <ogerlitz@mellanox.com>
---
.../net/ethernet/mellanox/mlx5/core/vxlan.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
index c9a50753ab23..9a8fd762167b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
@@ -39,9 +39,10 @@
struct mlx5_vxlan {
struct mlx5_core_dev *mdev;
spinlock_t lock; /* protect vxlan table */
- int num_ports;
/* max_num_ports is usuallly 4, 16 buckets is more than enough */
DECLARE_HASHTABLE(htable, 4);
+ int num_ports;
+ struct mutex sync_lock; /* sync add/del port HW operations */
};
struct mlx5_vxlan_port {
@@ -115,17 +116,18 @@ int mlx5_vxlan_add_port(struct mlx5_vxlan *vxlan, u16 port)
return 0;
}
+ mutex_lock(&vxlan->sync_lock);
if (vxlan->num_ports >= mlx5_vxlan_max_udp_ports(vxlan->mdev)) {
mlx5_core_info(vxlan->mdev,
"UDP port (%d) not offloaded, max number of UDP ports (%d) are already offloaded\n",
port, mlx5_vxlan_max_udp_ports(vxlan->mdev));
ret = -ENOSPC;
- return ret;
+ goto unlock;
}
ret = mlx5_vxlan_core_add_port_cmd(vxlan->mdev, port);
if (ret)
- return ret;
+ goto unlock;
vxlanp = kzalloc(sizeof(*vxlanp), GFP_KERNEL);
if (!vxlanp) {
@@ -141,10 +143,14 @@ int mlx5_vxlan_add_port(struct mlx5_vxlan *vxlan, u16 port)
spin_unlock_bh(&vxlan->lock);
vxlan->num_ports++;
+ mutex_unlock(&vxlan->sync_lock);
return 0;
err_delete_port:
mlx5_vxlan_core_del_port_cmd(vxlan->mdev, port);
+
+unlock:
+ mutex_unlock(&vxlan->sync_lock);
return ret;
}
@@ -154,6 +160,8 @@ int mlx5_vxlan_del_port(struct mlx5_vxlan *vxlan, u16 port)
bool remove = false;
int ret = 0;
+ mutex_lock(&vxlan->sync_lock);
+
spin_lock_bh(&vxlan->lock);
vxlanp = mlx5_vxlan_lookup_port_locked(vxlan, port);
if (!vxlanp) {
@@ -174,6 +182,9 @@ int mlx5_vxlan_del_port(struct mlx5_vxlan *vxlan, u16 port)
kfree(vxlanp);
vxlan->num_ports--;
}
+
+ mutex_unlock(&vxlan->sync_lock);
+
return ret;
}
@@ -189,6 +200,7 @@ struct mlx5_vxlan *mlx5_vxlan_create(struct mlx5_core_dev *mdev)
return ERR_PTR(-ENOMEM);
vxlan->mdev = mdev;
+ mutex_init(&vxlan->sync_lock);
spin_lock_init(&vxlan->lock);
hash_init(vxlan->htable);
--
2.17.0
^ permalink raw reply related
* [net-next V2 09/12] net/mlx5e: Vxlan, return values for add/del port
From: Saeed Mahameed @ 2018-07-28 0:06 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Saeed Mahameed
In-Reply-To: <20180728000622.4123-1-saeedm@mellanox.com>
For a better API mlx5_vxlan_{add/del}_port can fail, make them return
error values.
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Reviewed-by: Or Gerlitz <ogerlitz@mellanox.com>
---
.../net/ethernet/mellanox/mlx5/core/vxlan.c | 28 +++++++++++++------
.../net/ethernet/mellanox/mlx5/core/vxlan.h | 4 +--
2 files changed, 21 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
index 759260f52bdd..c9a50753ab23 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
@@ -104,29 +104,34 @@ struct mlx5_vxlan_port *mlx5_vxlan_lookup_port(struct mlx5_vxlan *vxlan, u16 por
return vxlanp;
}
-void mlx5_vxlan_add_port(struct mlx5_vxlan *vxlan, u16 port)
+int mlx5_vxlan_add_port(struct mlx5_vxlan *vxlan, u16 port)
{
struct mlx5_vxlan_port *vxlanp;
+ int ret = -ENOSPC;
vxlanp = mlx5_vxlan_lookup_port(vxlan, port);
if (vxlanp) {
atomic_inc(&vxlanp->refcount);
- return;
+ return 0;
}
if (vxlan->num_ports >= mlx5_vxlan_max_udp_ports(vxlan->mdev)) {
mlx5_core_info(vxlan->mdev,
"UDP port (%d) not offloaded, max number of UDP ports (%d) are already offloaded\n",
port, mlx5_vxlan_max_udp_ports(vxlan->mdev));
- return;
+ ret = -ENOSPC;
+ return ret;
}
- if (mlx5_vxlan_core_add_port_cmd(vxlan->mdev, port))
- return;
+ ret = mlx5_vxlan_core_add_port_cmd(vxlan->mdev, port);
+ if (ret)
+ return ret;
vxlanp = kzalloc(sizeof(*vxlanp), GFP_KERNEL);
- if (!vxlanp)
+ if (!vxlanp) {
+ ret = -ENOMEM;
goto err_delete_port;
+ }
vxlanp->udp_port = port;
atomic_set(&vxlanp->refcount, 1);
@@ -136,21 +141,25 @@ void mlx5_vxlan_add_port(struct mlx5_vxlan *vxlan, u16 port)
spin_unlock_bh(&vxlan->lock);
vxlan->num_ports++;
- return;
+ return 0;
err_delete_port:
mlx5_vxlan_core_del_port_cmd(vxlan->mdev, port);
+ return ret;
}
-void mlx5_vxlan_del_port(struct mlx5_vxlan *vxlan, u16 port)
+int mlx5_vxlan_del_port(struct mlx5_vxlan *vxlan, u16 port)
{
struct mlx5_vxlan_port *vxlanp;
bool remove = false;
+ int ret = 0;
spin_lock_bh(&vxlan->lock);
vxlanp = mlx5_vxlan_lookup_port_locked(vxlan, port);
- if (!vxlanp)
+ if (!vxlanp) {
+ ret = -ENOENT;
goto out_unlock;
+ }
if (atomic_dec_and_test(&vxlanp->refcount)) {
hash_del(&vxlanp->hlist);
@@ -165,6 +174,7 @@ void mlx5_vxlan_del_port(struct mlx5_vxlan *vxlan, u16 port)
kfree(vxlanp);
vxlan->num_ports--;
}
+ return ret;
}
struct mlx5_vxlan *mlx5_vxlan_create(struct mlx5_core_dev *mdev)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.h b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.h
index 9d6327321814..fd874a30c4d0 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.h
@@ -49,8 +49,8 @@ static inline bool mlx5_vxlan_allowed(struct mlx5_vxlan *vxlan)
struct mlx5_vxlan *mlx5_vxlan_create(struct mlx5_core_dev *mdev);
void mlx5_vxlan_destroy(struct mlx5_vxlan *vxlan);
-void mlx5_vxlan_add_port(struct mlx5_vxlan *vxlan, u16 port);
-void mlx5_vxlan_del_port(struct mlx5_vxlan *vxlan, u16 port);
+int mlx5_vxlan_add_port(struct mlx5_vxlan *vxlan, u16 port);
+int mlx5_vxlan_del_port(struct mlx5_vxlan *vxlan, u16 port);
struct mlx5_vxlan_port *mlx5_vxlan_lookup_port(struct mlx5_vxlan *vxlan, u16 port);
#else
--
2.17.0
^ permalink raw reply related
* [net-next V2 06/12] net/mlx5e: Vxlan, move netdev only logic to en_main.c
From: Saeed Mahameed @ 2018-07-28 0:06 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Saeed Mahameed
In-Reply-To: <20180728000622.4123-1-saeedm@mellanox.com>
Create a direct vxlan API to add and delete vxlan ports from HW.
+void mlx5e_vxlan_add_port(struct mlx5e_priv *priv, u16 port);
+void mlx5e_vxlan_del_port(struct mlx5e_priv *priv, u16 port);
And move vxlan_add/del_work to en_main.c since they are netdev only
logic.
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Reviewed-by: Or Gerlitz <ogerlitz@mellanox.com>
---
.../net/ethernet/mellanox/mlx5/core/en_main.c | 51 +++++++++++++++++
.../net/ethernet/mellanox/mlx5/core/vxlan.c | 55 +++----------------
.../net/ethernet/mellanox/mlx5/core/vxlan.h | 16 +-----
3 files changed, 61 insertions(+), 61 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 14a201cbb0a4..7a6b78e3b5f7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3969,6 +3969,57 @@ static int mlx5e_get_vf_stats(struct net_device *dev,
}
#endif
+struct mlx5e_vxlan_work {
+ struct work_struct work;
+ struct mlx5e_priv *priv;
+ u16 port;
+};
+
+static void mlx5e_vxlan_add_work(struct work_struct *work)
+{
+ struct mlx5e_vxlan_work *vxlan_work =
+ container_of(work, struct mlx5e_vxlan_work, work);
+ struct mlx5e_priv *priv = vxlan_work->priv;
+ u16 port = vxlan_work->port;
+
+ mutex_lock(&priv->state_lock);
+ mlx5e_vxlan_add_port(priv, port);
+ mutex_unlock(&priv->state_lock);
+
+ kfree(vxlan_work);
+}
+
+static void mlx5e_vxlan_del_work(struct work_struct *work)
+{
+ struct mlx5e_vxlan_work *vxlan_work =
+ container_of(work, struct mlx5e_vxlan_work, work);
+ struct mlx5e_priv *priv = vxlan_work->priv;
+ u16 port = vxlan_work->port;
+
+ mutex_lock(&priv->state_lock);
+ mlx5e_vxlan_del_port(priv, port);
+ mutex_unlock(&priv->state_lock);
+ kfree(vxlan_work);
+}
+
+static void mlx5e_vxlan_queue_work(struct mlx5e_priv *priv, u16 port, int add)
+{
+ struct mlx5e_vxlan_work *vxlan_work;
+
+ vxlan_work = kmalloc(sizeof(*vxlan_work), GFP_ATOMIC);
+ if (!vxlan_work)
+ return;
+
+ if (add)
+ INIT_WORK(&vxlan_work->work, mlx5e_vxlan_add_work);
+ else
+ INIT_WORK(&vxlan_work->work, mlx5e_vxlan_del_work);
+
+ vxlan_work->priv = priv;
+ vxlan_work->port = port;
+ queue_work(priv->wq, &vxlan_work->work);
+}
+
static void mlx5e_add_vxlan_port(struct net_device *netdev,
struct udp_tunnel_info *ti)
{
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
index baeac5922e8c..9a8ca532a443 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
@@ -36,7 +36,11 @@
#include "mlx5_core.h"
#include "vxlan.h"
-static void mlx5e_vxlan_add_port(struct mlx5e_priv *priv, u16 port);
+struct mlx5e_vxlan {
+ struct hlist_node hlist;
+ atomic_t refcount;
+ u16 udp_port;
+};
void mlx5e_vxlan_init(struct mlx5e_priv *priv)
{
@@ -105,7 +109,7 @@ struct mlx5e_vxlan *mlx5e_vxlan_lookup_port(struct mlx5e_priv *priv, u16 port)
return vxlan;
}
-static void mlx5e_vxlan_add_port(struct mlx5e_priv *priv, u16 port)
+void mlx5e_vxlan_add_port(struct mlx5e_priv *priv, u16 port)
{
struct mlx5e_vxlan_db *vxlan_db = &priv->vxlan;
struct mlx5e_vxlan *vxlan;
@@ -144,21 +148,7 @@ static void mlx5e_vxlan_add_port(struct mlx5e_priv *priv, u16 port)
mlx5e_vxlan_core_del_port_cmd(priv->mdev, port);
}
-static void mlx5e_vxlan_add_work(struct work_struct *work)
-{
- struct mlx5e_vxlan_work *vxlan_work =
- container_of(work, struct mlx5e_vxlan_work, work);
- struct mlx5e_priv *priv = vxlan_work->priv;
- u16 port = vxlan_work->port;
-
- mutex_lock(&priv->state_lock);
- mlx5e_vxlan_add_port(priv, port);
- mutex_unlock(&priv->state_lock);
-
- kfree(vxlan_work);
-}
-
-static void mlx5e_vxlan_del_port(struct mlx5e_priv *priv, u16 port)
+void mlx5e_vxlan_del_port(struct mlx5e_priv *priv, u16 port)
{
struct mlx5e_vxlan_db *vxlan_db = &priv->vxlan;
struct mlx5e_vxlan *vxlan;
@@ -185,37 +175,6 @@ static void mlx5e_vxlan_del_port(struct mlx5e_priv *priv, u16 port)
}
}
-static void mlx5e_vxlan_del_work(struct work_struct *work)
-{
- struct mlx5e_vxlan_work *vxlan_work =
- container_of(work, struct mlx5e_vxlan_work, work);
- struct mlx5e_priv *priv = vxlan_work->priv;
- u16 port = vxlan_work->port;
-
- mutex_lock(&priv->state_lock);
- mlx5e_vxlan_del_port(priv, port);
- mutex_unlock(&priv->state_lock);
- kfree(vxlan_work);
-}
-
-void mlx5e_vxlan_queue_work(struct mlx5e_priv *priv, u16 port, int add)
-{
- struct mlx5e_vxlan_work *vxlan_work;
-
- vxlan_work = kmalloc(sizeof(*vxlan_work), GFP_ATOMIC);
- if (!vxlan_work)
- return;
-
- if (add)
- INIT_WORK(&vxlan_work->work, mlx5e_vxlan_add_work);
- else
- INIT_WORK(&vxlan_work->work, mlx5e_vxlan_del_work);
-
- vxlan_work->priv = priv;
- vxlan_work->port = port;
- queue_work(priv->wq, &vxlan_work->work);
-}
-
void mlx5e_vxlan_cleanup(struct mlx5e_priv *priv)
{
struct mlx5e_vxlan_db *vxlan_db = &priv->vxlan;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.h b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.h
index 51f19e3e5784..1a02f5b38009 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.h
@@ -35,17 +35,7 @@
#include <linux/mlx5/driver.h>
#include "en.h"
-struct mlx5e_vxlan {
- struct hlist_node hlist;
- atomic_t refcount;
- u16 udp_port;
-};
-
-struct mlx5e_vxlan_work {
- struct work_struct work;
- struct mlx5e_priv *priv;
- u16 port;
-};
+struct mlx5e_vxlan;
static inline bool mlx5e_vxlan_allowed(struct mlx5_core_dev *mdev)
{
@@ -55,8 +45,8 @@ static inline bool mlx5e_vxlan_allowed(struct mlx5_core_dev *mdev)
void mlx5e_vxlan_init(struct mlx5e_priv *priv);
void mlx5e_vxlan_cleanup(struct mlx5e_priv *priv);
-
-void mlx5e_vxlan_queue_work(struct mlx5e_priv *priv, u16 port, int add);
+void mlx5e_vxlan_add_port(struct mlx5e_priv *priv, u16 port);
+void mlx5e_vxlan_del_port(struct mlx5e_priv *priv, u16 port);
struct mlx5e_vxlan *mlx5e_vxlan_lookup_port(struct mlx5e_priv *priv, u16 port);
#endif /* __MLX5_VXLAN_H__ */
--
2.17.0
^ permalink raw reply related
* [net-next V2 04/12] net/mlx5e: Vxlan, cleanup an unused member in vxlan work
From: Saeed Mahameed @ 2018-07-28 0:06 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Gal Pressman, Saeed Mahameed
In-Reply-To: <20180728000622.4123-1-saeedm@mellanox.com>
From: Gal Pressman <galp@mellanox.com>
Cleanup the sa_family member of the vxlan work, it is unused/needed
anywhere in the code.
Signed-off-by: Gal Pressman <galp@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 4 ++--
drivers/net/ethernet/mellanox/mlx5/core/vxlan.c | 4 +---
drivers/net/ethernet/mellanox/mlx5/core/vxlan.h | 4 +---
3 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index fad947079a43..14a201cbb0a4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3980,7 +3980,7 @@ static void mlx5e_add_vxlan_port(struct net_device *netdev,
if (!mlx5e_vxlan_allowed(priv->mdev))
return;
- mlx5e_vxlan_queue_work(priv, ti->sa_family, be16_to_cpu(ti->port), 1);
+ mlx5e_vxlan_queue_work(priv, be16_to_cpu(ti->port), 1);
}
static void mlx5e_del_vxlan_port(struct net_device *netdev,
@@ -3994,7 +3994,7 @@ static void mlx5e_del_vxlan_port(struct net_device *netdev,
if (!mlx5e_vxlan_allowed(priv->mdev))
return;
- mlx5e_vxlan_queue_work(priv, ti->sa_family, be16_to_cpu(ti->port), 0);
+ mlx5e_vxlan_queue_work(priv, be16_to_cpu(ti->port), 0);
}
static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
index 3c0ea9bc20e3..4b9190d677fc 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
@@ -191,8 +191,7 @@ static void mlx5e_vxlan_del_work(struct work_struct *work)
kfree(vxlan_work);
}
-void mlx5e_vxlan_queue_work(struct mlx5e_priv *priv, sa_family_t sa_family,
- u16 port, int add)
+void mlx5e_vxlan_queue_work(struct mlx5e_priv *priv, u16 port, int add)
{
struct mlx5e_vxlan_work *vxlan_work;
@@ -207,7 +206,6 @@ void mlx5e_vxlan_queue_work(struct mlx5e_priv *priv, sa_family_t sa_family,
vxlan_work->priv = priv;
vxlan_work->port = port;
- vxlan_work->sa_family = sa_family;
queue_work(priv->wq, &vxlan_work->work);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.h b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.h
index 52c41c22235d..51f19e3e5784 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.h
@@ -44,7 +44,6 @@ struct mlx5e_vxlan {
struct mlx5e_vxlan_work {
struct work_struct work;
struct mlx5e_priv *priv;
- sa_family_t sa_family;
u16 port;
};
@@ -57,8 +56,7 @@ static inline bool mlx5e_vxlan_allowed(struct mlx5_core_dev *mdev)
void mlx5e_vxlan_init(struct mlx5e_priv *priv);
void mlx5e_vxlan_cleanup(struct mlx5e_priv *priv);
-void mlx5e_vxlan_queue_work(struct mlx5e_priv *priv, sa_family_t sa_family,
- u16 port, int add);
+void mlx5e_vxlan_queue_work(struct mlx5e_priv *priv, u16 port, int add);
struct mlx5e_vxlan *mlx5e_vxlan_lookup_port(struct mlx5e_priv *priv, u16 port);
#endif /* __MLX5_VXLAN_H__ */
--
2.17.0
^ permalink raw reply related
* [net-next V2 03/12] net/mlx5e: Vxlan, replace ports radix-tree with hash table
From: Saeed Mahameed @ 2018-07-28 0:06 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Gal Pressman, Saeed Mahameed
In-Reply-To: <20180728000622.4123-1-saeedm@mellanox.com>
From: Gal Pressman <galp@mellanox.com>
The VXLAN database is accessed in the data path for each VXLAN TX skb in
order to check whether the UDP port is being offloaded or not.
The number of elements in the database is relatively small, we can
simplify the radix-tree to a hash table and speedup the lookup process.
Measuring mlx5e_vxlan_lookup_port execution time:
Radix Tree Hash Table
--------------- ------------ ------------
Single Stream 161 ns 79 ns (51% improvement)
Multi Stream 259 ns 136 ns (47% improvement)
Measuring UDP stream packet rate, single fully utilized TX core:
Radix Tree: 498,300 PPS
Hash Table: 555,468 PPS (11% improvement)
Signed-off-by: Gal Pressman <galp@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en.h | 3 +-
.../net/ethernet/mellanox/mlx5/core/vxlan.c | 41 +++++++++++--------
.../net/ethernet/mellanox/mlx5/core/vxlan.h | 1 +
3 files changed, 28 insertions(+), 17 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index c4d4db8722f5..6878925c3abf 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -656,7 +656,8 @@ enum {
struct mlx5e_vxlan_db {
spinlock_t lock; /* protect vxlan table */
- struct radix_tree_root tree;
+ /* max_num_ports is usuallly 4, 16 buckets is more than enough */
+ DECLARE_HASHTABLE(htable, 4);
int num_ports;
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
index e3af2efe18ce..3c0ea9bc20e3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
@@ -43,7 +43,7 @@ void mlx5e_vxlan_init(struct mlx5e_priv *priv)
struct mlx5e_vxlan_db *vxlan_db = &priv->vxlan;
spin_lock_init(&vxlan_db->lock);
- INIT_RADIX_TREE(&vxlan_db->tree, GFP_ATOMIC);
+ hash_init(vxlan_db->htable);
if (mlx5e_vxlan_allowed(priv->mdev))
/* Hardware adds 4789 by default.
@@ -79,13 +79,27 @@ static int mlx5e_vxlan_core_del_port_cmd(struct mlx5_core_dev *mdev, u16 port)
return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
}
+static struct mlx5e_vxlan *mlx5e_vxlan_lookup_port_locked(struct mlx5e_priv *priv,
+ u16 port)
+{
+ struct mlx5e_vxlan_db *vxlan_db = &priv->vxlan;
+ struct mlx5e_vxlan *vxlan;
+
+ hash_for_each_possible(vxlan_db->htable, vxlan, hlist, port) {
+ if (vxlan->udp_port == port)
+ return vxlan;
+ }
+
+ return NULL;
+}
+
struct mlx5e_vxlan *mlx5e_vxlan_lookup_port(struct mlx5e_priv *priv, u16 port)
{
struct mlx5e_vxlan_db *vxlan_db = &priv->vxlan;
struct mlx5e_vxlan *vxlan;
spin_lock_bh(&vxlan_db->lock);
- vxlan = radix_tree_lookup(&vxlan_db->tree, port);
+ vxlan = mlx5e_vxlan_lookup_port_locked(priv, port);
spin_unlock_bh(&vxlan_db->lock);
return vxlan;
@@ -95,7 +109,6 @@ static void mlx5e_vxlan_add_port(struct mlx5e_priv *priv, u16 port)
{
struct mlx5e_vxlan_db *vxlan_db = &priv->vxlan;
struct mlx5e_vxlan *vxlan;
- int err;
vxlan = mlx5e_vxlan_lookup_port(priv, port);
if (vxlan) {
@@ -121,16 +134,12 @@ static void mlx5e_vxlan_add_port(struct mlx5e_priv *priv, u16 port)
atomic_set(&vxlan->refcount, 1);
spin_lock_bh(&vxlan_db->lock);
- err = radix_tree_insert(&vxlan_db->tree, vxlan->udp_port, vxlan);
+ hash_add(vxlan_db->htable, &vxlan->hlist, port);
spin_unlock_bh(&vxlan_db->lock);
- if (err)
- goto err_free;
vxlan_db->num_ports++;
return;
-err_free:
- kfree(vxlan);
err_delete_port:
mlx5e_vxlan_core_del_port_cmd(priv->mdev, port);
}
@@ -161,12 +170,12 @@ static void mlx5e_vxlan_del_work(struct work_struct *work)
mutex_lock(&priv->state_lock);
spin_lock_bh(&vxlan_db->lock);
- vxlan = radix_tree_lookup(&vxlan_db->tree, port);
+ vxlan = mlx5e_vxlan_lookup_port_locked(priv, port);
if (!vxlan)
goto out_unlock;
if (atomic_dec_and_test(&vxlan->refcount)) {
- radix_tree_delete(&vxlan_db->tree, port);
+ hash_del(&vxlan->hlist);
remove = true;
}
@@ -206,13 +215,13 @@ void mlx5e_vxlan_cleanup(struct mlx5e_priv *priv)
{
struct mlx5e_vxlan_db *vxlan_db = &priv->vxlan;
struct mlx5e_vxlan *vxlan;
- unsigned int port = 0;
+ struct hlist_node *tmp;
+ int bkt;
- /* Lockless since we are the only radix-tree consumers, wq is disabled */
- while (radix_tree_gang_lookup(&vxlan_db->tree, (void **)&vxlan, port, 1)) {
- port = vxlan->udp_port;
- radix_tree_delete(&vxlan_db->tree, port);
- mlx5e_vxlan_core_del_port_cmd(priv->mdev, port);
+ /* Lockless since we are the only hash table consumers, wq and TX are disabled */
+ hash_for_each_safe(vxlan_db->htable, bkt, tmp, vxlan, hlist) {
+ hash_del(&vxlan->hlist);
+ mlx5e_vxlan_core_del_port_cmd(priv->mdev, vxlan->udp_port);
kfree(vxlan);
}
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.h b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.h
index 5ef6ae7d568a..52c41c22235d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.h
@@ -36,6 +36,7 @@
#include "en.h"
struct mlx5e_vxlan {
+ struct hlist_node hlist;
atomic_t refcount;
u16 udp_port;
};
--
2.17.0
^ permalink raw reply related
* [net-next V2 02/12] net/mlx5e: Vxlan, check maximum number of UDP ports
From: Saeed Mahameed @ 2018-07-28 0:06 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Gal Pressman, Saeed Mahameed
In-Reply-To: <20180728000622.4123-1-saeedm@mellanox.com>
From: Gal Pressman <galp@mellanox.com>
The NIC has a limited number of offloaded VXLAN UDP ports (usually 4).
Instead of letting the firmware fail when trying to add more ports than
it can handle, let the driver check it on its own.
Signed-off-by: Gal Pressman <galp@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en.h | 1 +
drivers/net/ethernet/mellanox/mlx5/core/vxlan.c | 14 ++++++++++++++
include/linux/mlx5/mlx5_ifc.h | 4 +++-
3 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index c41cfc2a4b70..c4d4db8722f5 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -657,6 +657,7 @@ enum {
struct mlx5e_vxlan_db {
spinlock_t lock; /* protect vxlan table */
struct radix_tree_root tree;
+ int num_ports;
};
struct mlx5e_l2_rule {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
index 2f699998d13e..e3af2efe18ce 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
@@ -52,6 +52,11 @@ void mlx5e_vxlan_init(struct mlx5e_priv *priv)
mlx5e_vxlan_add_port(priv, 4789);
}
+static inline u8 mlx5e_vxlan_max_udp_ports(struct mlx5_core_dev *mdev)
+{
+ return MLX5_CAP_ETH(mdev, max_vxlan_udp_ports) ?: 4;
+}
+
static int mlx5e_vxlan_core_add_port_cmd(struct mlx5_core_dev *mdev, u16 port)
{
u32 in[MLX5_ST_SZ_DW(add_vxlan_udp_dport_in)] = {0};
@@ -98,6 +103,13 @@ static void mlx5e_vxlan_add_port(struct mlx5e_priv *priv, u16 port)
return;
}
+ if (vxlan_db->num_ports >= mlx5e_vxlan_max_udp_ports(priv->mdev)) {
+ netdev_info(priv->netdev,
+ "UDP port (%d) not offloaded, max number of UDP ports (%d) are already offloaded\n",
+ port, mlx5e_vxlan_max_udp_ports(priv->mdev));
+ return;
+ }
+
if (mlx5e_vxlan_core_add_port_cmd(priv->mdev, port))
return;
@@ -114,6 +126,7 @@ static void mlx5e_vxlan_add_port(struct mlx5e_priv *priv, u16 port)
if (err)
goto err_free;
+ vxlan_db->num_ports++;
return;
err_free:
@@ -163,6 +176,7 @@ static void mlx5e_vxlan_del_work(struct work_struct *work)
if (remove) {
mlx5e_vxlan_core_del_port_cmd(priv->mdev, port);
kfree(vxlan);
+ vxlan_db->num_ports--;
}
mutex_unlock(&priv->state_lock);
kfree(vxlan_work);
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index 22f54bedfaae..60c2308fe062 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -668,7 +668,9 @@ struct mlx5_ifc_per_protocol_networking_offload_caps_bits {
u8 swp[0x1];
u8 swp_csum[0x1];
u8 swp_lso[0x1];
- u8 reserved_at_23[0x1b];
+ u8 reserved_at_23[0xd];
+ u8 max_vxlan_udp_ports[0x8];
+ u8 reserved_at_38[0x6];
u8 max_geneve_opt_len[0x1];
u8 tunnel_stateless_geneve_rx[0x1];
--
2.17.0
^ permalink raw reply related
* [net-next V2 01/12] net/mlx5e: Vxlan, reflect 4789 UDP port default addition to software database
From: Saeed Mahameed @ 2018-07-28 0:06 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Gal Pressman, Saeed Mahameed
In-Reply-To: <20180728000622.4123-1-saeedm@mellanox.com>
From: Gal Pressman <galp@mellanox.com>
The hardware offloads 4789 UDP port (default VXLAN port) automatically.
Add it to the software database as well in order to reflect the hardware
state appropriately.
Signed-off-by: Gal Pressman <galp@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
.../net/ethernet/mellanox/mlx5/core/vxlan.c | 40 +++++++++++++------
1 file changed, 27 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
index 2f74953e4561..2f699998d13e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
@@ -36,12 +36,20 @@
#include "mlx5_core.h"
#include "vxlan.h"
+static void mlx5e_vxlan_add_port(struct mlx5e_priv *priv, u16 port);
+
void mlx5e_vxlan_init(struct mlx5e_priv *priv)
{
struct mlx5e_vxlan_db *vxlan_db = &priv->vxlan;
spin_lock_init(&vxlan_db->lock);
INIT_RADIX_TREE(&vxlan_db->tree, GFP_ATOMIC);
+
+ if (mlx5e_vxlan_allowed(priv->mdev))
+ /* Hardware adds 4789 by default.
+ * Lockless since we are the only hash table consumers, wq and TX are disabled.
+ */
+ mlx5e_vxlan_add_port(priv, 4789);
}
static int mlx5e_vxlan_core_add_port_cmd(struct mlx5_core_dev *mdev, u16 port)
@@ -78,25 +86,20 @@ struct mlx5e_vxlan *mlx5e_vxlan_lookup_port(struct mlx5e_priv *priv, u16 port)
return vxlan;
}
-static void mlx5e_vxlan_add_port(struct work_struct *work)
+static void mlx5e_vxlan_add_port(struct mlx5e_priv *priv, u16 port)
{
- struct mlx5e_vxlan_work *vxlan_work =
- container_of(work, struct mlx5e_vxlan_work, work);
- struct mlx5e_priv *priv = vxlan_work->priv;
struct mlx5e_vxlan_db *vxlan_db = &priv->vxlan;
- u16 port = vxlan_work->port;
struct mlx5e_vxlan *vxlan;
int err;
- mutex_lock(&priv->state_lock);
vxlan = mlx5e_vxlan_lookup_port(priv, port);
if (vxlan) {
atomic_inc(&vxlan->refcount);
- goto free_work;
+ return;
}
if (mlx5e_vxlan_core_add_port_cmd(priv->mdev, port))
- goto free_work;
+ return;
vxlan = kzalloc(sizeof(*vxlan), GFP_KERNEL);
if (!vxlan)
@@ -111,18 +114,29 @@ static void mlx5e_vxlan_add_port(struct work_struct *work)
if (err)
goto err_free;
- goto free_work;
+ return;
err_free:
kfree(vxlan);
err_delete_port:
mlx5e_vxlan_core_del_port_cmd(priv->mdev, port);
-free_work:
+}
+
+static void mlx5e_vxlan_add_work(struct work_struct *work)
+{
+ struct mlx5e_vxlan_work *vxlan_work =
+ container_of(work, struct mlx5e_vxlan_work, work);
+ struct mlx5e_priv *priv = vxlan_work->priv;
+ u16 port = vxlan_work->port;
+
+ mutex_lock(&priv->state_lock);
+ mlx5e_vxlan_add_port(priv, port);
mutex_unlock(&priv->state_lock);
+
kfree(vxlan_work);
}
-static void mlx5e_vxlan_del_port(struct work_struct *work)
+static void mlx5e_vxlan_del_work(struct work_struct *work)
{
struct mlx5e_vxlan_work *vxlan_work =
container_of(work, struct mlx5e_vxlan_work, work);
@@ -164,9 +178,9 @@ void mlx5e_vxlan_queue_work(struct mlx5e_priv *priv, sa_family_t sa_family,
return;
if (add)
- INIT_WORK(&vxlan_work->work, mlx5e_vxlan_add_port);
+ INIT_WORK(&vxlan_work->work, mlx5e_vxlan_add_work);
else
- INIT_WORK(&vxlan_work->work, mlx5e_vxlan_del_port);
+ INIT_WORK(&vxlan_work->work, mlx5e_vxlan_del_work);
vxlan_work->priv = priv;
vxlan_work->port = port;
--
2.17.0
^ permalink raw reply related
* [pull request][net-next V2 00/12] Mellanox, mlx5 updates 2018-07-27 (Vxlan updates)
From: Saeed Mahameed @ 2018-07-28 0:06 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Saeed Mahameed
Hi Dave,
This series from Gal and Saeed provides updates to mlx5 vxlan implementation.
For more information please see tag log below.
Please pull and let me know if there's any problem.
V1->V2:
- Drop the rw lock patch.
Thanks,
Saeed.
---
The following changes since commit 1f3ed383fb9a073ae2e408cd7a0717b04c7c3a21:
net: sched: don't dump chains only held by actions (2018-07-27 09:38:46 -0700)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux.git tags/mlx5e-updates-2018-07-27
for you to fetch changes up to a3e673660bc3fca3e9e0cbab871b2fb100e9ed64:
net/mlx5e: Issue direct lookup on vxlan ports by vport representors (2018-07-27 15:46:13 -0700)
----------------------------------------------------------------
mlx5e-updates-2018-07-27 (Vxlan updates)
This series from Gal and Saeed provides updates to mlx5 vxlan implementation.
Gal, started with three cleanups to reflect the actual hardware vxlan state
- reflect 4789 UDP port default addition to software database
- check maximum number of vxlan UDP ports
- cleanup an unused member in vxlan work
Then Gal provides performance optimization by replacing the
vxlan radix tree with a hash table.
Measuring mlx5e_vxlan_lookup_port execution time:
Radix Tree Hash Table
--------------- ------------ ------------
Single Stream 161 ns 79 ns (51% improvement)
Multi Stream 259 ns 136 ns (47% improvement)
Measuring UDP stream packet rate, single fully utilized TX core:
Radix Tree: 498,300 PPS
Hash Table: 555,468 PPS (11% improvement)
Next, from Saeed, vxlan refactoring to allow sharing the vxlan table
between different mlx5 netdevice instances like PF and VF representors,
this is done by making mlx5 vxlan interface more generic and decoupling
it from PF netdevice structures and logic, then moving it into mlx5 core
as a low level interface so it can be used by VF representors, which is
illustrated in the last patch of the serious.
-Saeed.
----------------------------------------------------------------
Gal Pressman (4):
net/mlx5e: Vxlan, reflect 4789 UDP port default addition to software database
net/mlx5e: Vxlan, check maximum number of UDP ports
net/mlx5e: Vxlan, replace ports radix-tree with hash table
net/mlx5e: Vxlan, cleanup an unused member in vxlan work
Saeed Mahameed (8):
net/mlx5e: Vxlan, add direct delete function
net/mlx5e: Vxlan, move netdev only logic to en_main.c
net/mlx5e: Vxlan, rename struct mlx5e_vxlan to mlx5_vxlan_port
net/mlx5e: Vxlan, rename from mlx5e to mlx5
net/mlx5e: Vxlan, return values for add/del port
net/mlx5e: Vxlan, add sync lock for add/del vxlan port
net/mlx5e: Vxlan, move vxlan logic to core driver
net/mlx5e: Issue direct lookup on vxlan ports by vport representors
drivers/net/ethernet/mellanox/mlx5/core/Makefile | 4 +-
drivers/net/ethernet/mellanox/mlx5/core/en.h | 6 -
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 71 ++++++-
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 14 +-
.../net/ethernet/mellanox/mlx5/core/lib/vxlan.c | 230 +++++++++++++++++++++
.../ethernet/mellanox/mlx5/core/{ => lib}/vxlan.h | 39 ++--
drivers/net/ethernet/mellanox/mlx5/core/main.c | 5 +
drivers/net/ethernet/mellanox/mlx5/core/vxlan.c | 190 -----------------
include/linux/mlx5/driver.h | 2 +
include/linux/mlx5/mlx5_ifc.h | 4 +-
10 files changed, 325 insertions(+), 240 deletions(-)
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lib/vxlan.c
rename drivers/net/ethernet/mellanox/mlx5/core/{ => lib}/vxlan.h (66%)
delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/vxlan.c
^ permalink raw reply
* Re: [V9fs-developer] [PATCH] 9p: fix multiple NULL-pointer-dereferences
From: piaojun @ 2018-07-28 0:58 UTC (permalink / raw)
To: Dominique Martinet, Tomas Bortoli
Cc: v9fs-developer, syzkaller, davem, linux-kernel, netdev
In-Reply-To: <20180727153904.GA500@nautica>
Hi Tomas & Dominique,
I could not recieve the original patch. Did the patch CC v9fs developer
maillist?
Thanks,
Jun
On 2018/7/27 23:39, Dominique Martinet wrote:
> Tomas Bortoli wrote on Fri, Jul 27, 2018:
>> Added checks to prevent GPFs from raising.
>>
>> Signed-off-by: Tomas Bortoli <tomasbortoli@gmail.com>
>> Reported-by: syzbot+1a262da37d3bead15c39@syzkaller.appspotmail.com
>
> LGTM, I'll take this. Thanks!
>
> Just a note for future patchs that have multiple versions, it's usually
> good to write in the subject [PATCH v2] (then v3 etc) so we can easily
> tell it's a new version.
> If the thread isn't too long I'd also recommend considering setting a
> reply-to to the previous patch so we can easily compare versions/write
> off old patches.
>
>> ---
>> net/9p/trans_fd.c | 5 ++++-
>> net/9p/trans_rdma.c | 3 +++
>> net/9p/trans_virtio.c | 3 +++
>> net/9p/trans_xen.c | 3 +++
>> 4 files changed, 13 insertions(+), 1 deletion(-)
>>
>> diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
>> index 964260265b13..e2ef3c782c53 100644
>> --- a/net/9p/trans_fd.c
>> +++ b/net/9p/trans_fd.c
>> @@ -945,7 +945,7 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
>> if (err < 0)
>> return err;
>>
>> - if (valid_ipaddr4(addr) < 0)
>> + if (addr == NULL || valid_ipaddr4(addr) < 0)
>> return -EINVAL;
>>
>> csocket = NULL;
>> @@ -995,6 +995,9 @@ p9_fd_create_unix(struct p9_client *client, const char *addr, char *args)
>>
>> csocket = NULL;
>>
>> + if (addr == NULL)
>> + return -EINVAL;
>> +
>> if (strlen(addr) >= UNIX_PATH_MAX) {
>> pr_err("%s (%d): address too long: %s\n",
>> __func__, task_pid_nr(current), addr);
>> diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c
>> index 2649b2ebf961..2ab4574183c9 100644
>> --- a/net/9p/trans_rdma.c
>> +++ b/net/9p/trans_rdma.c
>> @@ -645,6 +645,9 @@ rdma_create_trans(struct p9_client *client, const char *addr, char *args)
>> struct rdma_conn_param conn_param;
>> struct ib_qp_init_attr qp_attr;
>>
>> + if (addr == NULL)
>> + return -EINVAL;
>> +
>> /* Parse the transport specific mount options */
>> err = parse_opts(args, &opts);
>> if (err < 0)
>> diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
>> index 06dcd3cc6a29..8ca356eb66bb 100644
>> --- a/net/9p/trans_virtio.c
>> +++ b/net/9p/trans_virtio.c
>> @@ -654,6 +654,9 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args)
>> int ret = -ENOENT;
>> int found = 0;
>>
>> + if (devname == NULL)
>> + return -EINVAL;
>> +
>> mutex_lock(&virtio_9p_lock);
>> list_for_each_entry(chan, &virtio_chan_list, chan_list) {
>> if (!strncmp(devname, chan->tag, chan->tag_len) &&
>> diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c
>> index 2e2b8bca54f3..c2d54ac76bfd 100644
>> --- a/net/9p/trans_xen.c
>> +++ b/net/9p/trans_xen.c
>> @@ -94,6 +94,9 @@ static int p9_xen_create(struct p9_client *client, const char *addr, char *args)
>> {
>> struct xen_9pfs_front_priv *priv;
>>
>> + if (addr == NULL)
>> + return -EINVAL;
>> +
>> read_lock(&xen_9pfs_lock);
>> list_for_each_entry(priv, &xen_9pfs_devs, list) {
>> if (!strcmp(priv->tag, addr)) {
>
^ permalink raw reply
* Re: [**EXTERNAL**] Re: VRF with enslaved L3 enabled bridge
From: D'Souza, Nelson @ 2018-07-27 23:29 UTC (permalink / raw)
To: David Ahern, netdev@vger.kernel.org
In-Reply-To: <12D41EAD-1AF2-435C-9501-5D38F1FF4ADD@ciena.com>
David,
With Ubuntu 18.04.1 (kernel 4.15.0-29) pings sent out on test-vrf and br0 are successful.
# uname -rv
4.15.0-29-generic #31-Ubuntu SMP Tue Jul 17 15:39:52 UTC 2018
# ping -c 1 -I test-vrf 172.16.2.2
ping: Warning: source address might be selected on device other than test-vrf.
PING 172.16.2.2 (172.16.2.2) from 172.16.1.1 test-vrf: 56(84) bytes of data.
64 bytes from 172.16.2.2: icmp_seq=1 ttl=64 time=0.050 ms
--- 172.16.2.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.050/0.050/0.050/0.000 ms
# ping -c 1 -I br0 172.16.2.2
PING 172.16.2.2 (172.16.2.2) from 172.16.1.1 br0: 56(84) bytes of data.
64 bytes from 172.16.2.2: icmp_seq=1 ttl=64 time=0.026 ms
--- 172.16.2.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.026/0.026/0.026/0.000 ms
However, with Ubuntu 17.10.1 (kernel 4.13.0-21) pings on only test-vrf are successful. Pings on br0 are not successful.
So it seems like there maybe a change in versions after 4.13.0-21 that causes pings on br0 to pass.
Nelson
On 7/25/18, 5:35 PM, "D'Souza, Nelson" <ndsouza@ciena.com> wrote:
David,
I tried out the commands on an Ubuntu 17.10.1 VM.
The pings on test-vrf are successful, but the pings on br0 are not successful.
# uname -rv
4.13.0-21-generic #24-Ubuntu SMP Mon Dec 18 17:29:16 UTC 2017
# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 17.10
Release: 17.10
Codename: artful
# ip rule --> Note: its missing the l3mdev rule
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
Ran the configs from a bash script vrf.sh
# ./vrf.sh
+ ip netns add foo
+ ip li add veth1 type veth peer name veth2
+ ip li set veth2 netns foo
+ ip -netns foo li set lo up
+ ip -netns foo li set veth2 up
+ ip -netns foo addr add 172.16.1.2/24 dev veth2
+ ip li add test-vrf type vrf table 123
+ ip li set test-vrf up
+ ip ro add vrf test-vrf unreachable default
+ ip li add br0 type bridge
+ ip li set veth1 master br0
+ ip li set veth1 up
+ ip li set br0 up
+ ip addr add dev br0 172.16.1.1/24
+ ip li set br0 master test-vrf
+ ip -netns foo addr add 172.16.2.2/32 dev lo
+ ip ro add vrf test-vrf 172.16.2.2/32 via 172.16.1.2
# ping -I test-vrf 172.16.2.2 -c 2 <<< successful on test-vrf
ping: Warning: source address might be selected on device other than test-vrf.
PING 172.16.2.2 (172.16.2.2) from 172.16.1.1 test-vrf: 56(84) bytes of data.
64 bytes from 172.16.2.2: icmp_seq=1 ttl=64 time=0.035 ms
64 bytes from 172.16.2.2: icmp_seq=2 ttl=64 time=0.045 ms
--- 172.16.2.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1022ms
rtt min/avg/max/mdev = 0.035/0.040/0.045/0.005 ms
#ping -I br0 172.16.2.2 -c 2 <<< fails on br0
PING 172.16.2.2 (172.16.2.2) from 172.16.1.1 br0: 56(84) bytes of data.
--- 172.16.2.2 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1022ms
Please let me know if I should try a different version.
Nelson
On 7/24/18, 9:08 AM, "D'Souza, Nelson" <ndsouza@ciena.com> wrote:
It's strange that enslaving eth1 -> br0 -> test-vrf does not work, but enslaving eth1->test-vrf works fine.
Nelson
On 7/24/18, 8:58 AM, "D'Souza, Nelson" <ndsouza@ciena.com> wrote:
Thank you David, really appreciate the help. Most likely something specific to my environment.
ip vrf id, does not report anything on my system. Here's the result after running the command.
# ip vrf id
#
I'll follow up with a VM.
Nelson
On 7/24/18, 5:55 AM, "David Ahern" <dsa@cumulusnetworks.com> wrote:
On 7/23/18 7:43 PM, D'Souza, Nelson wrote:
> I copy and pasted the configs onto my device, but pings on test-vrf do not work in my setup.
> I'm essentially seeing the same issue as I reported before.
>
> In this case, pings sent out on test-vrf (host ns) are received and replied to by the loopback interface (foo ns). Although the replies are seen at the test-vrf level, they are not locally delivered to the ping application.
>
I just built v4.14.52 kernel and ran those commands - worked fine. It is
something specific to your environment. Is your shell tied to a VRF --
(ip vrf id)?
After that, I suggest you create a VM running a newer distribution of
your choice (Ubuntu 17.10 or newer, debian stretch with 4.14 kernel, or
Fedora 26 or newer) and run the commands there.
^ permalink raw reply
* [PATCH bpf] tools/bpftool: fix a percpu_array map dump problem
From: Yonghong Song @ 2018-07-27 23:11 UTC (permalink / raw)
To: ast, daniel, netdev; +Cc: kernel-team
I hit the following problem when I tried to use bpftool
to dump a percpu array.
$ sudo ./bpftool map show
61: percpu_array name stub flags 0x0
key 4B value 4B max_entries 1 memlock 4096B
...
$ sudo ./bpftool map dump id 61
bpftool: malloc.c:2406: sysmalloc: Assertion
`(old_top == initial_top (av) && old_size == 0) || \
((unsigned long) (old_size) >= MINSIZE && \
prev_inuse (old_top) && \
((unsigned long) old_end & (pagesize - 1)) == 0)'
failed.
Aborted
Further debugging revealed that this is due to
miscommunication between bpftool and kernel.
For example, for the above percpu_array with value size of 4B.
The map info returned to user space has value size of 4B.
In bpftool, the values array for lookup is allocated like:
info->value_size * get_possible_cpus() = 4 * get_possible_cpus()
In kernel (kernel/bpf/syscall.c), the values array size is
rounded up to multiple of 8.
round_up(map->value_size, 8) * num_possible_cpus()
= 8 * num_possible_cpus()
So when kernel copies the values to user buffer, the kernel will
overwrite beyond user buffer boundary.
This patch fixed the issue by allocating and stepping through
percpu map value array properly in bpftool.
Fixes: 71bb428fe2c19 ("tools: bpf: add bpftool")
Signed-off-by: Yonghong Song <yhs@fb.com>
---
tools/bpf/bpftool/map.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c
index 0ee3ba479d87..92bc55f98c4c 100644
--- a/tools/bpf/bpftool/map.c
+++ b/tools/bpf/bpftool/map.c
@@ -35,6 +35,7 @@
#include <errno.h>
#include <fcntl.h>
#include <linux/err.h>
+#include <linux/kernel.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -91,7 +92,8 @@ static bool map_is_map_of_progs(__u32 type)
static void *alloc_value(struct bpf_map_info *info)
{
if (map_is_per_cpu(info->type))
- return malloc(info->value_size * get_possible_cpus());
+ return malloc(round_up(info->value_size, 8) *
+ get_possible_cpus());
else
return malloc(info->value_size);
}
@@ -273,9 +275,10 @@ static void print_entry_json(struct bpf_map_info *info, unsigned char *key,
do_dump_btf(&d, info, key, value);
}
} else {
- unsigned int i, n;
+ unsigned int i, n, step;
n = get_possible_cpus();
+ step = round_up(info->value_size, 8);
jsonw_name(json_wtr, "key");
print_hex_data_json(key, info->key_size);
@@ -288,7 +291,7 @@ static void print_entry_json(struct bpf_map_info *info, unsigned char *key,
jsonw_int_field(json_wtr, "cpu", i);
jsonw_name(json_wtr, "value");
- print_hex_data_json(value + i * info->value_size,
+ print_hex_data_json(value + i * step,
info->value_size);
jsonw_end_object(json_wtr);
--
2.14.3
^ permalink raw reply related
* [PATCH net-next] selftests: mlxsw: qos_dscp_bridge: Fix
From: Petr Machata @ 2018-07-27 22:48 UTC (permalink / raw)
To: netdev, linux-kselftest; +Cc: jiri, idosch, shuah
There are two problems in this test case:
- When indexing in bash associative array, the subscript is interpreted as
string, not as a variable name to be expanded.
- The keys stored to t0s and t1s are not DSCP values, but priority +
base (i.e. the logical DSCP value, not the full bitfield value).
In combination these two bugs conspire to make the test just work,
except it doesn't really test anything and always passes.
Fix the above two problems in obvious manner.
Signed-off-by: Petr Machata <petrm@mellanox.com>
---
tools/testing/selftests/drivers/net/mlxsw/qos_dscp_bridge.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_bridge.sh b/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_bridge.sh
index 418319f19108..cc527660a022 100755
--- a/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_bridge.sh
+++ b/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_bridge.sh
@@ -217,13 +217,13 @@ dscp_ping_test()
for key in ${!t0s[@]}; do
local expect
- if ((key == dscp_10 || key == dscp_20)); then
+ if ((key == prio+10 || key == prio+20)); then
expect=10
else
expect=0
fi
- local delta=$((t1s[key] - t0s[key]))
+ local delta=$((t1s[$key] - t0s[$key]))
((expect == delta))
check_err $? "DSCP $key: Expected to capture $expect packets, got $delta."
done
--
2.4.11
^ permalink raw reply related
* Re: [PATCH v2 6/7] net: phy: Add support to configure clock in Broadcom iProc mdio mux
From: Andrew Lunn @ 2018-07-28 0:03 UTC (permalink / raw)
To: Arun Parameswaran
Cc: David S. Miller, Florian Fainelli, Rob Herring, Mark Rutland,
Ray Jui, Scott Branden, Catalin Marinas, Will Deacon, netdev,
devicetree, linux-arm-kernel, linux-kernel,
bcm-kernel-feedback-list
In-Reply-To: <1532726613-6483-7-git-send-email-arun.parameswaran@broadcom.com>
> static void mdio_mux_iproc_config(struct iproc_mdiomux_desc *md)
> {
> u32 val;
> + u32 divisor;
Hi Arun
Reverse Christmas tree please.
Andrew
^ permalink raw reply
* Re: [net-next 04/13] net/mlx5e: Vxlan, replace spinlock with read-write lock
From: Saeed Mahameed @ 2018-07-27 22:29 UTC (permalink / raw)
To: Stephen Hemminger
Cc: Saeed Mahameed, David S. Miller, Linux Netdev List, Gal Pressman
In-Reply-To: <20180727144800.1065a3fd@xeon-e3>
On Fri, Jul 27, 2018 at 2:48 PM, Stephen Hemminger
<stephen@networkplumber.org> wrote:
> On Fri, 27 Jul 2018 14:15:09 -0700
> Saeed Mahameed <saeedm@mellanox.com> wrote:
>
>> From: Gal Pressman <galp@mellanox.com>
>>
>> The VXLAN database is mainly used by readers in data path, and rarely
>> used by control path writers.
>> Multiple readers (threads) should not block each other and cause an
>> unnecessary contention on the lock.
>>
>> Replacing the spinlock with rwlock optimizes the common use case where
>> adding ports to the table (adding VXLAN interfaces) is quite rare, but
>> the table is accessed for each VXLAN TX skb.
>>
>> Signed-off-by: Gal Pressman <galp@mellanox.com>
>> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
>
> Did you know that for small sections a spinlock is significantly faster than
> a reader-writer lock. It turns out that reader-writer locks the reader
> creates a cache line bounce.
>
> https://www.kernel.org/doc/Documentation/locking/spinlocks.txt
>
>
> Lesson 2: reader-writer spinlocks.
>
> If your data accesses have a very natural pattern where you usually tend
> to mostly read from the shared variables, the reader-writer locks
> (rw_lock) versions of the spinlocks are sometimes useful. They allow multiple
> readers to be in the same critical region at once, but if somebody wants
> to change the variables it has to get an exclusive write lock.
>
> NOTE! reader-writer locks require more atomic memory operations than
> simple spinlocks. Unless the reader critical section is long, you
> are better off just using spinlocks.
Thanks Stephen, very usefull information !
I will drop this patch for now, I will consider using rcu lock
instead in a future patch.
^ permalink raw reply
* Re: [PATCH v1 0/4] PCI: Remove unnecessary includes of <linux/pci-aspm.h>
From: Bjorn Helgaas @ 2018-07-27 22:18 UTC (permalink / raw)
To: linux-pci
Cc: Jeff Kirsher, David S. Miller, Kalle Valo, Johannes Berg,
Emmanuel Grumbach, Luca Coelho, ath9k-devel, linuxwifi,
intel-wired-lan, netdev, linux-kernel, linux-wireless
In-Reply-To: <153254813164.92573.10755585465477668768.stgit@bhelgaas-glaptop.roam.corp.google.com>
On Wed, Jul 25, 2018 at 02:52:08PM -0500, Bjorn Helgaas wrote:
> Remove includes of <linux/pci-aspm.h> from files that don't need
> it. I'll apply all these via the PCI tree unless there's objection.
>
> ---
>
> Bjorn Helgaas (4):
> igb: Remove unnecessary include of <linux/pci-aspm.h>
> ath9k: Remove unnecessary include of <linux/pci-aspm.h>
> iwlwifi: Remove unnecessary include of <linux/pci-aspm.h>
> PCI: Remove unnecessary include of <linux/pci-aspm.h>
>
>
> drivers/net/ethernet/intel/igb/igb_main.c | 1 -
> drivers/net/wireless/ath/ath9k/pci.c | 1 -
> drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 1 -
> drivers/pci/pci-sysfs.c | 1 -
> drivers/pci/pci.c | 1 -
> drivers/pci/probe.c | 1 -
> drivers/pci/remove.c | 1 -
> 7 files changed, 7 deletions(-)
I applied these to the pci/aspm branch for v4.19.
^ permalink raw reply
* Re: [PATCH v3 net-next] net: ethernet: ti: cpsw: replace unnecessarily macroses on functions
From: Joe Perches @ 2018-07-27 23:30 UTC (permalink / raw)
To: Ivan Khoronzhuk, grygorii.strashko, davem
Cc: linux-omap, netdev, linux-kernel, andrew
In-Reply-To: <20180727225725.3843-1-ivan.khoronzhuk@linaro.org>
On Sat, 2018-07-28 at 01:57 +0300, Ivan Khoronzhuk wrote:
> Replace ugly macroses on functions.
trivia:
As cpsw_src_port_detect is only used once, and is a
very small function, it might make the code more
intelligible to just directly code it where it's used.
> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
[]
> @@ -565,40 +565,40 @@ static const struct cpsw_stats cpsw_gstrings_ch_stats[] = {
[]
> +static void cpsw_src_port_detect(struct cpsw_common *cpsw, int status,
> + struct sk_buff *skb)
> +{
> + if (!cpsw->data.dual_emac)
> + return;
> +
> + if (CPDMA_RX_SOURCE_PORT(status) == 1)
> + skb->dev = cpsw->slaves[0].ndev;
> + else if (CPDMA_RX_SOURCE_PORT(status) == 2)
> + skb->dev = cpsw->slaves[1].ndev;
> +}
[]
> @@ -801,7 +801,8 @@ static void cpsw_rx_handler(void *token, int len, int status)
> int ret = 0;
> struct cpsw_common *cpsw = ndev_to_cpsw(ndev);
>
> - cpsw_dual_emac_src_port_detect(cpsw, status, ndev, skb);
> + cpsw_src_port_detect(cpsw, status, skb);
here
> + ndev = skb->dev;
^ permalink raw reply
* [PATCH v4 bpf-next 05/14] bpf: extend bpf_prog_array to store pointers to the cgroup storage
From: Roman Gushchin @ 2018-07-27 21:52 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel-team, Roman Gushchin, Alexei Starovoitov,
Daniel Borkmann
In-Reply-To: <20180727215243.3850-1-guro@fb.com>
This patch converts bpf_prog_array from an array of prog pointers
to the array of struct bpf_prog_array_item elements.
This allows to save a cgroup storage pointer for each bpf program
efficiently attached to a cgroup.
Signed-off-by: Roman Gushchin <guro@fb.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Martin KaFai Lau <kafai@fb.com>
---
drivers/media/rc/bpf-lirc.c | 10 +++---
include/linux/bpf.h | 19 ++++++++----
kernel/bpf/cgroup.c | 21 +++++++------
kernel/bpf/core.c | 76 +++++++++++++++++++++++----------------------
4 files changed, 70 insertions(+), 56 deletions(-)
diff --git a/drivers/media/rc/bpf-lirc.c b/drivers/media/rc/bpf-lirc.c
index fcfab6635f9c..8c26df9b96c1 100644
--- a/drivers/media/rc/bpf-lirc.c
+++ b/drivers/media/rc/bpf-lirc.c
@@ -195,14 +195,16 @@ void lirc_bpf_run(struct rc_dev *rcdev, u32 sample)
*/
void lirc_bpf_free(struct rc_dev *rcdev)
{
- struct bpf_prog **progs;
+ struct bpf_prog_array_item *item;
if (!rcdev->raw->progs)
return;
- progs = rcu_dereference(rcdev->raw->progs)->progs;
- while (*progs)
- bpf_prog_put(*progs++);
+ item = rcu_dereference(rcdev->raw->progs)->items;
+ while (item->prog) {
+ bpf_prog_put(item->prog);
+ item++;
+ }
bpf_prog_array_free(rcdev->raw->progs);
}
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 9d1e4727495e..16be67888c30 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -349,9 +349,14 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
* The 'struct bpf_prog_array *' should only be replaced with xchg()
* since other cpus are walking the array of pointers in parallel.
*/
+struct bpf_prog_array_item {
+ struct bpf_prog *prog;
+ struct bpf_cgroup_storage *cgroup_storage;
+};
+
struct bpf_prog_array {
struct rcu_head rcu;
- struct bpf_prog *progs[0];
+ struct bpf_prog_array_item items[0];
};
struct bpf_prog_array *bpf_prog_array_alloc(u32 prog_cnt, gfp_t flags);
@@ -372,7 +377,8 @@ int bpf_prog_array_copy(struct bpf_prog_array __rcu *old_array,
#define __BPF_PROG_RUN_ARRAY(array, ctx, func, check_non_null) \
({ \
- struct bpf_prog **_prog, *__prog; \
+ struct bpf_prog_array_item *_item; \
+ struct bpf_prog *_prog; \
struct bpf_prog_array *_array; \
u32 _ret = 1; \
preempt_disable(); \
@@ -380,10 +386,11 @@ int bpf_prog_array_copy(struct bpf_prog_array __rcu *old_array,
_array = rcu_dereference(array); \
if (unlikely(check_non_null && !_array))\
goto _out; \
- _prog = _array->progs; \
- while ((__prog = READ_ONCE(*_prog))) { \
- _ret &= func(__prog, ctx); \
- _prog++; \
+ _item = &_array->items[0]; \
+ while ((_prog = READ_ONCE(_item->prog))) { \
+ bpf_cgroup_storage_set(_item->cgroup_storage); \
+ _ret &= func(_prog, ctx); \
+ _item++; \
} \
_out: \
rcu_read_unlock(); \
diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
index 935274c86bfe..ddfa6cc13e57 100644
--- a/kernel/bpf/cgroup.c
+++ b/kernel/bpf/cgroup.c
@@ -117,15 +117,18 @@ static int compute_effective_progs(struct cgroup *cgrp,
cnt = 0;
p = cgrp;
do {
- if (cnt == 0 || (p->bpf.flags[type] & BPF_F_ALLOW_MULTI))
- list_for_each_entry(pl,
- &p->bpf.progs[type], node) {
- if (!pl->prog)
- continue;
- progs->progs[cnt++] = pl->prog;
- }
- p = cgroup_parent(p);
- } while (p);
+ if (cnt > 0 && !(p->bpf.flags[type] & BPF_F_ALLOW_MULTI))
+ continue;
+
+ list_for_each_entry(pl, &p->bpf.progs[type], node) {
+ if (!pl->prog)
+ continue;
+
+ progs->items[cnt].prog = pl->prog;
+ progs->items[cnt].cgroup_storage = pl->storage;
+ cnt++;
+ }
+ } while ((p = cgroup_parent(p)));
rcu_assign_pointer(*array, progs);
return 0;
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 253aa8e79c7b..9abcf25ebf9f 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -1542,7 +1542,8 @@ struct bpf_prog_array *bpf_prog_array_alloc(u32 prog_cnt, gfp_t flags)
{
if (prog_cnt)
return kzalloc(sizeof(struct bpf_prog_array) +
- sizeof(struct bpf_prog *) * (prog_cnt + 1),
+ sizeof(struct bpf_prog_array_item) *
+ (prog_cnt + 1),
flags);
return &empty_prog_array.hdr;
@@ -1556,43 +1557,45 @@ void bpf_prog_array_free(struct bpf_prog_array __rcu *progs)
kfree_rcu(progs, rcu);
}
-int bpf_prog_array_length(struct bpf_prog_array __rcu *progs)
+int bpf_prog_array_length(struct bpf_prog_array __rcu *array)
{
- struct bpf_prog **prog;
+ struct bpf_prog_array_item *item;
u32 cnt = 0;
rcu_read_lock();
- prog = rcu_dereference(progs)->progs;
- for (; *prog; prog++)
- if (*prog != &dummy_bpf_prog.prog)
+ item = rcu_dereference(array)->items;
+ for (; item->prog; item++)
+ if (item->prog != &dummy_bpf_prog.prog)
cnt++;
rcu_read_unlock();
return cnt;
}
-static bool bpf_prog_array_copy_core(struct bpf_prog **prog,
+
+static bool bpf_prog_array_copy_core(struct bpf_prog_array __rcu *array,
u32 *prog_ids,
u32 request_cnt)
{
+ struct bpf_prog_array_item *item;
int i = 0;
- for (; *prog; prog++) {
- if (*prog == &dummy_bpf_prog.prog)
+ item = rcu_dereference(array)->items;
+ for (; item->prog; item++) {
+ if (item->prog == &dummy_bpf_prog.prog)
continue;
- prog_ids[i] = (*prog)->aux->id;
+ prog_ids[i] = item->prog->aux->id;
if (++i == request_cnt) {
- prog++;
+ item++;
break;
}
}
- return !!(*prog);
+ return !!(item->prog);
}
-int bpf_prog_array_copy_to_user(struct bpf_prog_array __rcu *progs,
+int bpf_prog_array_copy_to_user(struct bpf_prog_array __rcu *array,
__u32 __user *prog_ids, u32 cnt)
{
- struct bpf_prog **prog;
unsigned long err = 0;
bool nospc;
u32 *ids;
@@ -1611,8 +1614,7 @@ int bpf_prog_array_copy_to_user(struct bpf_prog_array __rcu *progs,
if (!ids)
return -ENOMEM;
rcu_read_lock();
- prog = rcu_dereference(progs)->progs;
- nospc = bpf_prog_array_copy_core(prog, ids, cnt);
+ nospc = bpf_prog_array_copy_core(array, ids, cnt);
rcu_read_unlock();
err = copy_to_user(prog_ids, ids, cnt * sizeof(u32));
kfree(ids);
@@ -1623,14 +1625,14 @@ int bpf_prog_array_copy_to_user(struct bpf_prog_array __rcu *progs,
return 0;
}
-void bpf_prog_array_delete_safe(struct bpf_prog_array __rcu *progs,
+void bpf_prog_array_delete_safe(struct bpf_prog_array __rcu *array,
struct bpf_prog *old_prog)
{
- struct bpf_prog **prog = progs->progs;
+ struct bpf_prog_array_item *item = array->items;
- for (; *prog; prog++)
- if (*prog == old_prog) {
- WRITE_ONCE(*prog, &dummy_bpf_prog.prog);
+ for (; item->prog; item++)
+ if (item->prog == old_prog) {
+ WRITE_ONCE(item->prog, &dummy_bpf_prog.prog);
break;
}
}
@@ -1641,7 +1643,7 @@ int bpf_prog_array_copy(struct bpf_prog_array __rcu *old_array,
struct bpf_prog_array **new_array)
{
int new_prog_cnt, carry_prog_cnt = 0;
- struct bpf_prog **existing_prog;
+ struct bpf_prog_array_item *existing;
struct bpf_prog_array *array;
bool found_exclude = false;
int new_prog_idx = 0;
@@ -1650,15 +1652,15 @@ int bpf_prog_array_copy(struct bpf_prog_array __rcu *old_array,
* the new array.
*/
if (old_array) {
- existing_prog = old_array->progs;
- for (; *existing_prog; existing_prog++) {
- if (*existing_prog == exclude_prog) {
+ existing = old_array->items;
+ for (; existing->prog; existing++) {
+ if (existing->prog == exclude_prog) {
found_exclude = true;
continue;
}
- if (*existing_prog != &dummy_bpf_prog.prog)
+ if (existing->prog != &dummy_bpf_prog.prog)
carry_prog_cnt++;
- if (*existing_prog == include_prog)
+ if (existing->prog == include_prog)
return -EEXIST;
}
}
@@ -1684,15 +1686,17 @@ int bpf_prog_array_copy(struct bpf_prog_array __rcu *old_array,
/* Fill in the new prog array */
if (carry_prog_cnt) {
- existing_prog = old_array->progs;
- for (; *existing_prog; existing_prog++)
- if (*existing_prog != exclude_prog &&
- *existing_prog != &dummy_bpf_prog.prog)
- array->progs[new_prog_idx++] = *existing_prog;
+ existing = old_array->items;
+ for (; existing->prog; existing++)
+ if (existing->prog != exclude_prog &&
+ existing->prog != &dummy_bpf_prog.prog) {
+ array->items[new_prog_idx++].prog =
+ existing->prog;
+ }
}
if (include_prog)
- array->progs[new_prog_idx++] = include_prog;
- array->progs[new_prog_idx] = NULL;
+ array->items[new_prog_idx++].prog = include_prog;
+ array->items[new_prog_idx].prog = NULL;
*new_array = array;
return 0;
}
@@ -1701,7 +1705,6 @@ int bpf_prog_array_copy_info(struct bpf_prog_array __rcu *array,
u32 *prog_ids, u32 request_cnt,
u32 *prog_cnt)
{
- struct bpf_prog **prog;
u32 cnt = 0;
if (array)
@@ -1714,8 +1717,7 @@ int bpf_prog_array_copy_info(struct bpf_prog_array __rcu *array,
return 0;
/* this function is called under trace/bpf_trace.c: bpf_event_mutex */
- prog = rcu_dereference_check(array, 1)->progs;
- return bpf_prog_array_copy_core(prog, prog_ids, request_cnt) ? -ENOSPC
+ return bpf_prog_array_copy_core(array, prog_ids, request_cnt) ? -ENOSPC
: 0;
}
--
2.14.4
^ permalink raw reply related
* [PATCH v4 bpf-next 04/14] bpf: allocate cgroup storage entries on attaching bpf programs
From: Roman Gushchin @ 2018-07-27 21:52 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel-team, Roman Gushchin, Alexei Starovoitov,
Daniel Borkmann
In-Reply-To: <20180727215243.3850-1-guro@fb.com>
If a bpf program is using cgroup local storage, allocate
a bpf_cgroup_storage structure automatically on attaching the program
to a cgroup and save the pointer into the corresponding bpf_prog_list
entry.
Analogically, release the cgroup local storage on detaching
of the bpf program.
Signed-off-by: Roman Gushchin <guro@fb.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Martin KaFai Lau <kafai@fb.com>
---
include/linux/bpf-cgroup.h | 1 +
kernel/bpf/cgroup.c | 35 +++++++++++++++++++++++++++++++----
2 files changed, 32 insertions(+), 4 deletions(-)
diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h
index 9a144ddbbc8f..f91b0f8ff3a9 100644
--- a/include/linux/bpf-cgroup.h
+++ b/include/linux/bpf-cgroup.h
@@ -43,6 +43,7 @@ struct bpf_cgroup_storage {
struct bpf_prog_list {
struct list_head node;
struct bpf_prog *prog;
+ struct bpf_cgroup_storage *storage;
};
struct bpf_prog_array;
diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
index badabb0b435c..935274c86bfe 100644
--- a/kernel/bpf/cgroup.c
+++ b/kernel/bpf/cgroup.c
@@ -34,6 +34,8 @@ void cgroup_bpf_put(struct cgroup *cgrp)
list_for_each_entry_safe(pl, tmp, progs, node) {
list_del(&pl->node);
bpf_prog_put(pl->prog);
+ bpf_cgroup_storage_unlink(pl->storage);
+ bpf_cgroup_storage_free(pl->storage);
kfree(pl);
static_branch_dec(&cgroup_bpf_enabled_key);
}
@@ -188,6 +190,7 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
{
struct list_head *progs = &cgrp->bpf.progs[type];
struct bpf_prog *old_prog = NULL;
+ struct bpf_cgroup_storage *storage, *old_storage = NULL;
struct cgroup_subsys_state *css;
struct bpf_prog_list *pl;
bool pl_was_allocated;
@@ -210,31 +213,47 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
if (prog_list_length(progs) >= BPF_CGROUP_MAX_PROGS)
return -E2BIG;
+ storage = bpf_cgroup_storage_alloc(prog);
+ if (IS_ERR(storage))
+ return -ENOMEM;
+
if (flags & BPF_F_ALLOW_MULTI) {
- list_for_each_entry(pl, progs, node)
- if (pl->prog == prog)
+ list_for_each_entry(pl, progs, node) {
+ if (pl->prog == prog) {
/* disallow attaching the same prog twice */
+ bpf_cgroup_storage_free(storage);
return -EINVAL;
+ }
+ }
pl = kmalloc(sizeof(*pl), GFP_KERNEL);
- if (!pl)
+ if (!pl) {
+ bpf_cgroup_storage_free(storage);
return -ENOMEM;
+ }
+
pl_was_allocated = true;
pl->prog = prog;
+ pl->storage = storage;
list_add_tail(&pl->node, progs);
} else {
if (list_empty(progs)) {
pl = kmalloc(sizeof(*pl), GFP_KERNEL);
- if (!pl)
+ if (!pl) {
+ bpf_cgroup_storage_free(storage);
return -ENOMEM;
+ }
pl_was_allocated = true;
list_add_tail(&pl->node, progs);
} else {
pl = list_first_entry(progs, typeof(*pl), node);
old_prog = pl->prog;
+ old_storage = pl->storage;
+ bpf_cgroup_storage_unlink(old_storage);
pl_was_allocated = false;
}
pl->prog = prog;
+ pl->storage = storage;
}
cgrp->bpf.flags[type] = flags;
@@ -257,10 +276,13 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
}
static_branch_inc(&cgroup_bpf_enabled_key);
+ if (old_storage)
+ bpf_cgroup_storage_free(old_storage);
if (old_prog) {
bpf_prog_put(old_prog);
static_branch_dec(&cgroup_bpf_enabled_key);
}
+ bpf_cgroup_storage_link(storage, cgrp, type);
return 0;
cleanup:
@@ -276,6 +298,9 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
/* and cleanup the prog list */
pl->prog = old_prog;
+ bpf_cgroup_storage_free(pl->storage);
+ pl->storage = old_storage;
+ bpf_cgroup_storage_link(old_storage, cgrp, type);
if (pl_was_allocated) {
list_del(&pl->node);
kfree(pl);
@@ -356,6 +381,8 @@ int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
/* now can actually delete it from this cgroup list */
list_del(&pl->node);
+ bpf_cgroup_storage_unlink(pl->storage);
+ bpf_cgroup_storage_free(pl->storage);
kfree(pl);
if (list_empty(progs))
/* last program was detached, reset flags to zero */
--
2.14.4
^ permalink raw reply related
* [PATCH v4 bpf-next 01/14] bpf: add ability to charge bpf maps memory dynamically
From: Roman Gushchin @ 2018-07-27 21:52 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel-team, Roman Gushchin, Alexei Starovoitov,
Daniel Borkmann
In-Reply-To: <20180727215243.3850-1-guro@fb.com>
This commits extends existing bpf maps memory charging API
to support dynamic charging/uncharging.
This is required to account memory used by maps,
if all entries are created dynamically after
the map initialization.
Signed-off-by: Roman Gushchin <guro@fb.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Martin KaFai Lau <kafai@fb.com>
---
include/linux/bpf.h | 2 ++
kernel/bpf/syscall.c | 58 ++++++++++++++++++++++++++++++++++++++--------------
2 files changed, 45 insertions(+), 15 deletions(-)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 5b5ad95cf339..5a4a256473c3 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -435,6 +435,8 @@ struct bpf_map * __must_check bpf_map_inc(struct bpf_map *map, bool uref);
void bpf_map_put_with_uref(struct bpf_map *map);
void bpf_map_put(struct bpf_map *map);
int bpf_map_precharge_memlock(u32 pages);
+int bpf_map_charge_memlock(struct bpf_map *map, u32 pages);
+void bpf_map_uncharge_memlock(struct bpf_map *map, u32 pages);
void *bpf_map_area_alloc(size_t size, int numa_node);
void bpf_map_area_free(void *base);
void bpf_map_init_from_attr(struct bpf_map *map, union bpf_attr *attr);
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index a31a1ba0f8ea..40119aef9ddc 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -181,32 +181,60 @@ int bpf_map_precharge_memlock(u32 pages)
return 0;
}
-static int bpf_map_charge_memlock(struct bpf_map *map)
+static int bpf_charge_memlock(struct user_struct *user, u32 pages)
{
- struct user_struct *user = get_current_user();
- unsigned long memlock_limit;
+ unsigned long memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
- memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+ if (atomic_long_add_return(pages, &user->locked_vm) > memlock_limit) {
+ atomic_long_sub(pages, &user->locked_vm);
+ return -EPERM;
+ }
+ return 0;
+}
- atomic_long_add(map->pages, &user->locked_vm);
+static void bpf_uncharge_memlock(struct user_struct *user, u32 pages)
+{
+ atomic_long_sub(pages, &user->locked_vm);
+}
+
+static int bpf_map_init_memlock(struct bpf_map *map)
+{
+ struct user_struct *user = get_current_user();
+ int ret;
- if (atomic_long_read(&user->locked_vm) > memlock_limit) {
- atomic_long_sub(map->pages, &user->locked_vm);
+ ret = bpf_charge_memlock(user, map->pages);
+ if (ret) {
free_uid(user);
- return -EPERM;
+ return ret;
}
map->user = user;
- return 0;
+ return ret;
}
-static void bpf_map_uncharge_memlock(struct bpf_map *map)
+static void bpf_map_release_memlock(struct bpf_map *map)
{
struct user_struct *user = map->user;
-
- atomic_long_sub(map->pages, &user->locked_vm);
+ atomic_long_sub(map->pages, &map->user->locked_vm);
free_uid(user);
}
+int bpf_map_charge_memlock(struct bpf_map *map, u32 pages)
+{
+ int ret;
+
+ ret = bpf_charge_memlock(map->user, pages);
+ if (ret)
+ return ret;
+ map->pages += pages;
+ return ret;
+}
+
+void bpf_map_uncharge_memlock(struct bpf_map *map, u32 pages)
+{
+ bpf_uncharge_memlock(map->user, pages);
+ map->pages -= pages;
+}
+
static int bpf_map_alloc_id(struct bpf_map *map)
{
int id;
@@ -256,7 +284,7 @@ static void bpf_map_free_deferred(struct work_struct *work)
{
struct bpf_map *map = container_of(work, struct bpf_map, work);
- bpf_map_uncharge_memlock(map);
+ bpf_map_release_memlock(map);
security_bpf_map_free(map);
/* implementation dependent freeing */
map->ops->map_free(map);
@@ -492,7 +520,7 @@ static int map_create(union bpf_attr *attr)
if (err)
goto free_map_nouncharge;
- err = bpf_map_charge_memlock(map);
+ err = bpf_map_init_memlock(map);
if (err)
goto free_map_sec;
@@ -515,7 +543,7 @@ static int map_create(union bpf_attr *attr)
return err;
free_map:
- bpf_map_uncharge_memlock(map);
+ bpf_map_release_memlock(map);
free_map_sec:
security_bpf_map_free(map);
free_map_nouncharge:
--
2.14.4
^ permalink raw reply related
* [PATCH iproute2-next] sch_cake: Make gso-splitting configurable
From: Dave Taht @ 2018-07-27 21:48 UTC (permalink / raw)
To: netdev; +Cc: Dave Taht, Toke Høiland-Jørgensen
This patch makes sch_cake's gso/gro splitting configurable
from userspace.
To disable breaking apart superpackets in sch_cake:
tc qdisc replace dev whatever root cake no-split-gso
to enable:
tc qdisc replace dev whatever root cake split-gso
Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
Signed-off-by: Dave Taht <dave.taht@gmail.com>
---
tc/q_cake.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/tc/q_cake.c b/tc/q_cake.c
index f1e232a..727d673 100644
--- a/tc/q_cake.c
+++ b/tc/q_cake.c
@@ -79,6 +79,7 @@ static void explain(void)
" dual-srchost | dual-dsthost | triple-isolate* ]\n"
" [ nat | nonat* ]\n"
" [ wash | nowash* ]\n"
+" [ split-gso* | no-split-gso ]\n"
" [ ack-filter | ack-filter-aggressive | no-ack-filter* ]\n"
" [ memlimit LIMIT ]\n"
" [ ptm | atm | noatm* ] [ overhead N | conservative | raw* ]\n"
@@ -108,6 +109,7 @@ static int cake_parse_opt(struct qdisc_util *qu, int argc, char **argv,
int nat = -1;
int atm = -1;
int mpu = 0;
+ int split_gso = -1;
while (argc > 0) {
if (strcmp(*argv, "bandwidth") == 0) {
@@ -155,6 +157,10 @@ static int cake_parse_opt(struct qdisc_util *qu, int argc, char **argv,
wash = 0;
} else if (strcmp(*argv, "wash") == 0) {
wash = 1;
+ } else if (strcmp(*argv, "split-gso") == 0) {
+ split_gso = 1;
+ } else if (strcmp(*argv, "no-split-gso") == 0) {
+ split_gso = 0;
} else if (strcmp(*argv, "flowblind") == 0) {
flowmode = CAKE_FLOW_NONE;
} else if (strcmp(*argv, "srchost") == 0) {
@@ -374,6 +380,9 @@ static int cake_parse_opt(struct qdisc_util *qu, int argc, char **argv,
addattr_l(n, 1024, TCA_CAKE_NAT, &nat, sizeof(nat));
if (wash != -1)
addattr_l(n, 1024, TCA_CAKE_WASH, &wash, sizeof(wash));
+ if (split_gso != -1)
+ addattr_l(n, 1024, TCA_CAKE_SPLIT_GSO, &split_gso,
+ sizeof(split_gso));
if (ingress != -1)
addattr_l(n, 1024, TCA_CAKE_INGRESS, &ingress, sizeof(ingress));
if (ack_filter != -1)
--
2.7.4
^ permalink raw reply related
* Re: [net-next 04/13] net/mlx5e: Vxlan, replace spinlock with read-write lock
From: Stephen Hemminger @ 2018-07-27 21:48 UTC (permalink / raw)
To: Saeed Mahameed; +Cc: David S. Miller, netdev, Gal Pressman
In-Reply-To: <20180727211518.1916-5-saeedm@mellanox.com>
On Fri, 27 Jul 2018 14:15:09 -0700
Saeed Mahameed <saeedm@mellanox.com> wrote:
> From: Gal Pressman <galp@mellanox.com>
>
> The VXLAN database is mainly used by readers in data path, and rarely
> used by control path writers.
> Multiple readers (threads) should not block each other and cause an
> unnecessary contention on the lock.
>
> Replacing the spinlock with rwlock optimizes the common use case where
> adding ports to the table (adding VXLAN interfaces) is quite rare, but
> the table is accessed for each VXLAN TX skb.
>
> Signed-off-by: Gal Pressman <galp@mellanox.com>
> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Did you know that for small sections a spinlock is significantly faster than
a reader-writer lock. It turns out that reader-writer locks the reader
creates a cache line bounce.
https://www.kernel.org/doc/Documentation/locking/spinlocks.txt
Lesson 2: reader-writer spinlocks.
If your data accesses have a very natural pattern where you usually tend
to mostly read from the shared variables, the reader-writer locks
(rw_lock) versions of the spinlocks are sometimes useful. They allow multiple
readers to be in the same critical region at once, but if somebody wants
to change the variables it has to get an exclusive write lock.
NOTE! reader-writer locks require more atomic memory operations than
simple spinlocks. Unless the reader critical section is long, you
are better off just using spinlocks.
^ permalink raw reply
* [PATCH v3 net-next] net: ethernet: ti: cpsw: replace unnecessarily macroses on functions
From: Ivan Khoronzhuk @ 2018-07-27 22:57 UTC (permalink / raw)
To: grygorii.strashko, davem
Cc: linux-omap, netdev, linux-kernel, joe, andrew, Ivan Khoronzhuk
Replace ugly macroses on functions.
Reviewed-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
---
Based on net-next/master
v2..v1:
- removed inline for cpsw_src_port_detect()
drivers/net/ethernet/ti/cpsw.c | 63 +++++++++++++++++-----------------
1 file changed, 32 insertions(+), 31 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 1b54c26c2bec..9cacfe4ad065 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -565,40 +565,40 @@ static const struct cpsw_stats cpsw_gstrings_ch_stats[] = {
(func)(slave++, ##arg); \
} while (0)
-#define cpsw_dual_emac_src_port_detect(cpsw, status, ndev, skb) \
- do { \
- if (!cpsw->data.dual_emac) \
- break; \
- if (CPDMA_RX_SOURCE_PORT(status) == 1) { \
- ndev = cpsw->slaves[0].ndev; \
- skb->dev = ndev; \
- } else if (CPDMA_RX_SOURCE_PORT(status) == 2) { \
- ndev = cpsw->slaves[1].ndev; \
- skb->dev = ndev; \
- } \
- } while (0)
-#define cpsw_add_mcast(cpsw, priv, addr) \
- do { \
- if (cpsw->data.dual_emac) { \
- struct cpsw_slave *slave = cpsw->slaves + \
- priv->emac_port; \
- int slave_port = cpsw_get_slave_port( \
- slave->slave_num); \
- cpsw_ale_add_mcast(cpsw->ale, addr, \
- 1 << slave_port | ALE_PORT_HOST, \
- ALE_VLAN, slave->port_vlan, 0); \
- } else { \
- cpsw_ale_add_mcast(cpsw->ale, addr, \
- ALE_ALL_PORTS, \
- 0, 0, 0); \
- } \
- } while (0)
-
static inline int cpsw_get_slave_port(u32 slave_num)
{
return slave_num + 1;
}
+static void cpsw_src_port_detect(struct cpsw_common *cpsw, int status,
+ struct sk_buff *skb)
+{
+ if (!cpsw->data.dual_emac)
+ return;
+
+ if (CPDMA_RX_SOURCE_PORT(status) == 1)
+ skb->dev = cpsw->slaves[0].ndev;
+ else if (CPDMA_RX_SOURCE_PORT(status) == 2)
+ skb->dev = cpsw->slaves[1].ndev;
+}
+
+static void cpsw_add_mcast(struct cpsw_priv *priv, u8 *addr)
+{
+ struct cpsw_common *cpsw = priv->cpsw;
+
+ if (cpsw->data.dual_emac) {
+ struct cpsw_slave *slave = cpsw->slaves + priv->emac_port;
+ int slave_port = cpsw_get_slave_port(slave->slave_num);
+
+ cpsw_ale_add_mcast(cpsw->ale, addr,
+ 1 << slave_port | ALE_PORT_HOST,
+ ALE_VLAN, slave->port_vlan, 0);
+ return;
+ }
+
+ cpsw_ale_add_mcast(cpsw->ale, addr, ALE_ALL_PORTS, 0, 0, 0);
+}
+
static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
{
struct cpsw_common *cpsw = ndev_to_cpsw(ndev);
@@ -706,7 +706,7 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
/* program multicast address list into ALE register */
netdev_for_each_mc_addr(ha, ndev) {
- cpsw_add_mcast(cpsw, priv, (u8 *)ha->addr);
+ cpsw_add_mcast(priv, (u8 *)ha->addr);
}
}
}
@@ -801,7 +801,8 @@ static void cpsw_rx_handler(void *token, int len, int status)
int ret = 0;
struct cpsw_common *cpsw = ndev_to_cpsw(ndev);
- cpsw_dual_emac_src_port_detect(cpsw, status, ndev, skb);
+ cpsw_src_port_detect(cpsw, status, skb);
+ ndev = skb->dev;
if (unlikely(status < 0) || unlikely(!netif_running(ndev))) {
/* In dual emac mode check for all interfaces */
--
2.17.1
^ permalink raw reply related
* [PATCH 2/2] net: socket: Fix potential spectre v1 gadget in sock_is_registered
From: Jeremy Cline @ 2018-07-27 22:43 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, linux-kernel, Josh Poimboeuf, Jeremy Cline, stable
In-Reply-To: <20180727224302.5503-1-jcline@redhat.com>
'family' can be a user-controlled value, so sanitize it after the bounds
check to avoid speculative out-of-bounds access.
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: Jeremy Cline <jcline@redhat.com>
---
net/socket.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/socket.c b/net/socket.c
index f15d5cbb3ba4..608e29ae6baf 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2672,7 +2672,8 @@ EXPORT_SYMBOL(sock_unregister);
bool sock_is_registered(int family)
{
- return family < NPROTO && rcu_access_pointer(net_families[family]);
+ return family < NPROTO &&
+ rcu_access_pointer(net_families[array_index_nospec(family, NPROTO)]);
}
static int __init sock_init(void)
--
2.17.1
^ permalink raw reply related
* [PATCH 1/2] net: socket: fix potential spectre v1 gadget in socketcall
From: Jeremy Cline @ 2018-07-27 22:43 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, linux-kernel, Josh Poimboeuf, Jeremy Cline, stable
In-Reply-To: <20180727224302.5503-1-jcline@redhat.com>
'call' is a user-controlled value, so sanitize the array index after the
bounds check to avoid speculating past the bounds of the 'nargs' array.
Found with the help of Smatch:
net/socket.c:2508 __do_sys_socketcall() warn: potential spectre issue
'nargs' [r] (local cap)
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: Jeremy Cline <jcline@redhat.com>
---
net/socket.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/socket.c b/net/socket.c
index 3015ddace71e..f15d5cbb3ba4 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -89,6 +89,7 @@
#include <linux/magic.h>
#include <linux/slab.h>
#include <linux/xattr.h>
+#include <linux/nospec.h>
#include <linux/uaccess.h>
#include <asm/unistd.h>
@@ -2504,6 +2505,7 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
if (call < 1 || call > SYS_SENDMMSG)
return -EINVAL;
+ call = array_index_nospec(call, SYS_SENDMMSG + 1);
len = nargs[call];
if (len > sizeof(a))
--
2.17.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox