Skip to contentSkip to conversation

IB/cma: Honor traffic class from lower netdevice for RoCE

PATCH In review Leon Romanovsky 3 participants 3 messages Oct 2, 2019 – Oct 8, 2019 InfiniBand

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 IB/cma: Honor traffic class from lower netdevice for RoCE

From: Parav Pandit <[email protected]>

When macvlan netdevice is used for RoCE, consider the tos->prio->tc mapping as SL using its lower netdevice.
1. If lower netdevice is VLAN netdevice, consider such VLAN netdevice and it's parent netdevice for mapping
2. If lower netdevice is not a VLAN netdevice, consider tc mapping directly from such lower netdevice

---
 drivers/infiniband/core/cma.c | 59 +++++++++++++++++++++++++++++------
 1 file changed, 50 insertions(+), 9 deletions(-)
drivers/infiniband/core/cma.c +50 -9
index 0e3cf3461999..18b5ad8c7d5f 100644
@@ -2827,22 +2827,63 @@ static int cma_resolve_iw_route(struct rdma_id_private *id_priv)
 	return 0;
 }
 
-static int iboe_tos_to_sl(struct net_device *ndev, int tos)
+static int get_vlan_ndev_tc(struct net_device *vlan_ndev, int prio)
 {
-	int prio;
 	struct net_device *dev;
 
-	prio = rt_tos2priority(tos);
-	dev = is_vlan_dev(ndev) ? vlan_dev_real_dev(ndev) : ndev;
+	dev = vlan_dev_real_dev(vlan_ndev);
 	if (dev->num_tc)
 		return netdev_get_prio_tc_map(dev, prio);
 
-#if IS_ENABLED(CONFIG_VLAN_8021Q)
+	return (vlan_dev_get_egress_qos_mask(vlan_ndev, prio) &
+		VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+}
+
+struct iboe_prio_tc_map {
+	int input_prio;
+	int output_tc;
+	bool found;
+};
+
+static int get_lower_vlan_dev_tc(struct net_device *dev, void *data)
+{
+	struct iboe_prio_tc_map *map = data;
+
+	if (is_vlan_dev(dev))
+		map->output_tc = get_vlan_ndev_tc(dev, map->input_prio);
+	else if (dev->num_tc)
+		map->output_tc = netdev_get_prio_tc_map(dev, map->input_prio);
+	else
+		map->output_tc = 0;
+	/* We are interested only in first level VLAN device, so always
+	 * return 1 to stop iterating over next level devices.
+	 */
+	map->found = true;
+	return 1;
+}
+
+static int iboe_tos_to_sl(struct net_device *ndev, int tos)
+{
+	struct iboe_prio_tc_map prio_tc_map = {};
+	int prio = rt_tos2priority(tos);
+
+	/* If VLAN device, get it directly from the VLAN netdev */
 	if (is_vlan_dev(ndev))
-		return (vlan_dev_get_egress_qos_mask(ndev, prio) &
-			VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
-#endif
-	return 0;
+		return get_vlan_ndev_tc(ndev, prio);
+
+	prio_tc_map.input_prio = prio;
+	netdev_walk_all_lower_dev_rcu(ndev,
+				      get_lower_vlan_dev_tc,
+				      &prio_tc_map);
+	/* If map is found from lower device, use it; Otherwise
+	 * continue with the current netdevice to get priority to tc map.
+	 */
+	if (prio_tc_map.found)
+		return prio_tc_map.output_tc;
+	else if (ndev->num_tc)
+		return netdev_get_prio_tc_map(ndev, prio);
+	else
+		return 0;
 }
 
 static int cma_resolve_iboe_route(struct rdma_id_private *id_priv)
Signature · 1 line
2.20.1
#1 lore raw
Quoted 68 lines · Leon Romanovsky

From: Parav Pandit <[email protected]>

When macvlan netdevice is used for RoCE, consider the tos->prio->tc mapping as SL using its lower netdevice.
1. If lower netdevice is VLAN netdevice, consider such VLAN netdevice and it's parent netdevice for mapping
2. If lower netdevice is not a VLAN netdevice, consider tc mapping directly from such lower netdevice

 drivers/infiniband/core/cma.c | 59 +++++++++++++++++++++++++++++------
 1 file changed, 50 insertions(+), 9 deletions(-)
drivers/infiniband/core/cma.c +36 -5
index 0e3cf3461999..18b5ad8c7d5f 100644
+++ b/drivers/infiniband/core/cma.c
@@ -2827,22 +2827,63 @@ static int cma_resolve_iw_route(struct rdma_id_private *id_priv)
 	return 0;
 }
 
-static int iboe_tos_to_sl(struct net_device *ndev, int tos)
+static int get_vlan_ndev_tc(struct net_device *vlan_ndev, int prio)
 {
-	int prio;
 	struct net_device *dev;
 
-	prio = rt_tos2priority(tos);
-	dev = is_vlan_dev(ndev) ? vlan_dev_real_dev(ndev) : ndev;
+	dev = vlan_dev_real_dev(vlan_ndev);
 	if (dev->num_tc)
 		return netdev_get_prio_tc_map(dev, prio);
 
-#if IS_ENABLED(CONFIG_VLAN_8021Q)
+	return (vlan_dev_get_egress_qos_mask(vlan_ndev, prio) &
+		VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+}
+
+struct iboe_prio_tc_map {
+	int input_prio;
+	int output_tc;
+	bool found;
+};
+
+static int get_lower_vlan_dev_tc(struct net_device *dev, void *data)
+{
+	struct iboe_prio_tc_map *map = data;
+
+	if (is_vlan_dev(dev))
+		map->output_tc = get_vlan_ndev_tc(dev, map->input_prio);
+	else if (dev->num_tc)
+		map->output_tc = netdev_get_prio_tc_map(dev, map->input_prio);
+	else
+		map->output_tc = 0;
+	/* We are interested only in first level VLAN device, so always
+	 * return 1 to stop iterating over next level devices.
+	 */
+	map->found = true;
+	return 1;
+}
+
+static int iboe_tos_to_sl(struct net_device *ndev, int tos)
+{
+	struct iboe_prio_tc_map prio_tc_map = {};
+	int prio = rt_tos2priority(tos);
+
+	/* If VLAN device, get it directly from the VLAN netdev */
 	if (is_vlan_dev(ndev))

drivers/infiniband/core/cma.c static int cma_resolve_iw_route(struct rdma_id_private *id_priv) · line 2877

Quoted 10 lines
drivers/infiniband/core/cma.c +6 -4
-		return (vlan_dev_get_egress_qos_mask(ndev, prio) &
-			VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
-#endif
-	return 0;
+		return get_vlan_ndev_tc(ndev, prio);
+
+	prio_tc_map.input_prio = prio;
+	netdev_walk_all_lower_dev_rcu(ndev,
+				      get_lower_vlan_dev_tc,
+				      &prio_tc_map);

Kinda looks like you have to hold rcu before calling this?

Jason

#2 lore raw
Quoted 86 lines

-----Original Message-----
From: Jason Gunthorpe <[email protected]>
Sent: Tuesday, October 8, 2019 2:10 PM
To: Leon Romanovsky <[email protected]>
Cc: Doug Ledford <[email protected]>; Parav Pandit <[email protected]>; RDMA mailing list <[email protected]>; Leon Romanovsky <[email protected]>
Subject: Re: [PATCH rdma-next] IB/cma: Honor traffic class from lower netdevice for RoCE

Review static int cma_resolve_iw_route(struct

Quoted 18 lines · Leon Romanovsky

From: Parav Pandit <[email protected]>

When macvlan netdevice is used for RoCE, consider the tos->prio->tc mapping as SL using its lower netdevice.
1. If lower netdevice is VLAN netdevice, consider such VLAN netdevice and it's parent netdevice for mapping 2. If lower netdevice is not a VLAN netdevice, consider tc mapping directly from such lower netdevice

drivers/infiniband/core/cma.c | 59 +++++++++++++++++++++++++++++------

 1 file changed, 50 insertions(+), 9 deletions(-)
(quoted diff) +0 -0

b/drivers/infiniband/core/cma.c index 0e3cf3461999..18b5ad8c7d5f 100644
+++ b/drivers/infiniband/core/cma.c

(quoted diff) +0 -0
@@ -2827,22 +2827,63 @@ static int cma_resolve_iw_route(struct

rdma_id_private *id_priv)

Quoted 53 lines
drivers/infiniband/core/cma.c +33 -9
 	return 0;
 }
 
-static int iboe_tos_to_sl(struct net_device *ndev, int tos)
+static int get_vlan_ndev_tc(struct net_device *vlan_ndev, int prio)
 {
-	int prio;
 	struct net_device *dev;
 
-	prio = rt_tos2priority(tos);
-	dev = is_vlan_dev(ndev) ? vlan_dev_real_dev(ndev) : ndev;
+	dev = vlan_dev_real_dev(vlan_ndev);
 	if (dev->num_tc)
 		return netdev_get_prio_tc_map(dev, prio);
 
-#if IS_ENABLED(CONFIG_VLAN_8021Q)
+	return (vlan_dev_get_egress_qos_mask(vlan_ndev, prio) &
+		VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; }
+
+struct iboe_prio_tc_map {
+	int input_prio;
+	int output_tc;
+	bool found;
+};
+
+static int get_lower_vlan_dev_tc(struct net_device *dev, void *data)
+{
+	struct iboe_prio_tc_map *map = data;
+
+	if (is_vlan_dev(dev))
+		map->output_tc = get_vlan_ndev_tc(dev, map->input_prio);
+	else if (dev->num_tc)
+		map->output_tc = netdev_get_prio_tc_map(dev, map-
 input_prio);
+	else
+		map->output_tc = 0;
+	/* We are interested only in first level VLAN device, so always
+	 * return 1 to stop iterating over next level devices.
+	 */
+	map->found = true;
+	return 1;
+}
+
+static int iboe_tos_to_sl(struct net_device *ndev, int tos) {
+	struct iboe_prio_tc_map prio_tc_map = {};
+	int prio = rt_tos2priority(tos);
+
+	/* If VLAN device, get it directly from the VLAN netdev */
 	if (is_vlan_dev(ndev))
-		return (vlan_dev_get_egress_qos_mask(ndev, prio) &
-			VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
-#endif
-	return 0;
Quoted 9 lines

drivers/infiniband/core/cma.c static int cma_resolve_iw_route(struct rdma_id_private *id_priv) · line 2877

Quoted 6 lines
drivers/infiniband/core/cma.c +6 -0
+		return get_vlan_ndev_tc(ndev, prio);
+
+	prio_tc_map.input_prio = prio;
+	netdev_walk_all_lower_dev_rcu(ndev,
+				      get_lower_vlan_dev_tc,
+				      &prio_tc_map);

Kinda looks like you have to hold rcu before calling this?

Oh yes, my bad.
rcu lock unlock calls are missing around netdev_walk_all_lower_dev_rcu(). Will respin through Leon's tree.

Quoted 1 line

Jason