diff mbox series

[net-next,01/16] bnxt_en: Support ingress rate limiting with TC-offload.

Message ID 1580029390-32760-2-git-send-email-michael.chan@broadcom.com
State Changes Requested
Delegated to: David Miller
Headers show
Series bnxt_en: Updates for net-next. | expand

Commit Message

Michael Chan Jan. 26, 2020, 9:02 a.m. UTC
From: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>

This patch enables offloading of ingress rate limiting TC-action
on a VF. The driver processes "cls_matchall" filter callbacks to
add and remove ingress rate limiting actions. The driver parses
police action parameter and sends the command to FW to configure
rate limiting for the VF.

For example, to configure rate limiting offload on a VF using OVS,
use the below command on the corresponding VF-rep port. The example
below configures min and max tx rates of 200 and 600 Mbps.

	# ovs-vsctl set interface bnxt0_pf0vf0 \
		ingress_policing_rate=600000 ingress_policing_burst=200000

Signed-off-by: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
---
 drivers/net/ethernet/broadcom/bnxt/bnxt.h     |  1 +
 drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c  | 90 +++++++++++++++++++++++++++
 drivers/net/ethernet/broadcom/bnxt/bnxt_tc.h  |  3 +
 drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c |  2 +
 4 files changed, 96 insertions(+)

Comments

Jakub Kicinski Jan. 27, 2020, 12:12 a.m. UTC | #1
On Sun, 26 Jan 2020 04:02:55 -0500, Michael Chan wrote:
> From: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
> 
> This patch enables offloading of ingress rate limiting TC-action
> on a VF. The driver processes "cls_matchall" filter callbacks to
> add and remove ingress rate limiting actions. The driver parses
> police action parameter and sends the command to FW to configure
> rate limiting for the VF.
> 
> For example, to configure rate limiting offload on a VF using OVS,
> use the below command on the corresponding VF-rep port. The example
> below configures min and max tx rates of 200 and 600 Mbps.
> 
> 	# ovs-vsctl set interface bnxt0_pf0vf0 \
> 		ingress_policing_rate=600000 ingress_policing_burst=200000
> 
> Signed-off-by: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
> Signed-off-by: Michael Chan <michael.chan@broadcom.com>

Does the device drop or back-pressure when VF goes over the rate?

> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
> index f143354..534bc9e 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
> @@ -1069,6 +1069,7 @@ struct bnxt_vf_info {
>  	u32	max_tx_rate;
>  	void	*hwrm_cmd_req_addr;
>  	dma_addr_t	hwrm_cmd_req_dma_addr;
> +	unsigned long police_id;
>  };
>  #endif
>  
> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
> index 0cc6ec5..2dfb650 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
> @@ -10,6 +10,7 @@
>  #include <linux/netdevice.h>
>  #include <linux/inetdevice.h>
>  #include <linux/if_vlan.h>
> +#include <linux/pci.h>
>  #include <net/flow_dissector.h>
>  #include <net/pkt_cls.h>
>  #include <net/tc_act/tc_gact.h>
> @@ -1983,6 +1984,95 @@ static int bnxt_tc_indr_block_event(struct notifier_block *nb,
>  	return NOTIFY_DONE;
>  }
>  
> +static inline int bnxt_tc_find_vf_by_fid(struct bnxt *bp, u16 fid)

No static inlines in C files

> +{
> +	int num_vfs = pci_num_vf(bp->pdev);
> +	int i;
> +
> +	for (i = 0; i < num_vfs; i++) {
> +		if (bp->pf.vf[i].fw_fid == fid)

return i;

> +			break;
> +	}

return -EINVAL;

> +	if (i >= num_vfs)
> +		return -EINVAL;
> +	return i;
> +}

> +static int bnxt_tc_add_matchall(struct bnxt *bp, u16 src_fid,
> +				struct tc_cls_matchall_offload *matchall_cmd)
> +{
> +	struct flow_action_entry *action;
> +	int vf_idx;
> +	s64 burst;
> +	u64 rate;
> +	int rc;
> +
> +	vf_idx = bnxt_tc_find_vf_by_fid(bp, src_fid);
> +	if (vf_idx < 0)
> +		return vf_idx;

You need to check this is the only action, check priority, check
shared, etc. Just look as one of the drivers which do this right :/

> +	action = &matchall_cmd->rule->action.entries[0];
> +	if (action->id != FLOW_ACTION_POLICE) {
> +		netdev_err(bp->dev, "%s: Unsupported matchall action: %d",
> +			   __func__, action->id);
> +		return -EOPNOTSUPP;
> +	}
> +	if (bp->pf.vf[vf_idx].police_id && bp->pf.vf[vf_idx].police_id !=
> +	    matchall_cmd->cookie) {
> +		netdev_err(bp->dev,
> +			   "%s: Policer is already configured for VF: %d",
> +			   __func__, vf_idx);
> +		return -EEXIST;
> +	}
> +
> +	rate = (u32)div_u64(action->police.rate_bytes_ps, 1024 * 1000) * 8;
> +	burst = (u32)div_u64(action->police.rate_bytes_ps *
> +			     PSCHED_NS2TICKS(action->police.burst),
> +			     PSCHED_TICKS_PER_SEC);
> +	burst = (u32)PSCHED_TICKS2NS(burst) / (1 << 20);
> +
> +	rc = bnxt_set_vf_bw(bp->dev, vf_idx, burst, rate);
> +	if (rc) {
> +		netdev_err(bp->dev,
> +			   "Error: %s: VF: %d rate: %llu burst: %llu rc: %d",
> +			   __func__, vf_idx, rate, burst, rc);
> +		return rc;
> +	}
> +
> +	bp->pf.vf[vf_idx].police_id = matchall_cmd->cookie;
> +	return 0;
> +}
> +
> +int bnxt_tc_setup_matchall(struct bnxt *bp, u16 src_fid,
> +			   struct tc_cls_matchall_offload *cls_matchall)
> +{
> +	switch (cls_matchall->command) {
> +	case TC_CLSMATCHALL_REPLACE:
> +		return bnxt_tc_add_matchall(bp, src_fid, cls_matchall);
> +	case TC_CLSMATCHALL_DESTROY:
> +		return bnxt_tc_del_matchall(bp, src_fid, cls_matchall);
> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +}
> +
>  static const struct rhashtable_params bnxt_tc_flow_ht_params = {
>  	.head_offset = offsetof(struct bnxt_tc_flow_node, node),
>  	.key_offset = offsetof(struct bnxt_tc_flow_node, cookie),
> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.h
> index 10c62b0..963788e 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.h
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.h
> @@ -220,6 +220,9 @@ int bnxt_tc_setup_flower(struct bnxt *bp, u16 src_fid,
>  int bnxt_init_tc(struct bnxt *bp);
>  void bnxt_shutdown_tc(struct bnxt *bp);
>  void bnxt_tc_flow_stats_work(struct bnxt *bp);
> +int bnxt_tc_setup_matchall(struct bnxt *bp, u16 src_fid,
> +			   struct tc_cls_matchall_offload *cls_matchall);
> +
>  

Spurious new line

>  static inline bool bnxt_tc_flower_enabled(struct bnxt *bp)
>  {
diff mbox series

Patch

diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index f143354..534bc9e 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -1069,6 +1069,7 @@  struct bnxt_vf_info {
 	u32	max_tx_rate;
 	void	*hwrm_cmd_req_addr;
 	dma_addr_t	hwrm_cmd_req_dma_addr;
+	unsigned long police_id;
 };
 #endif
 
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
index 0cc6ec5..2dfb650 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
@@ -10,6 +10,7 @@ 
 #include <linux/netdevice.h>
 #include <linux/inetdevice.h>
 #include <linux/if_vlan.h>
+#include <linux/pci.h>
 #include <net/flow_dissector.h>
 #include <net/pkt_cls.h>
 #include <net/tc_act/tc_gact.h>
@@ -1983,6 +1984,95 @@  static int bnxt_tc_indr_block_event(struct notifier_block *nb,
 	return NOTIFY_DONE;
 }
 
+static inline int bnxt_tc_find_vf_by_fid(struct bnxt *bp, u16 fid)
+{
+	int num_vfs = pci_num_vf(bp->pdev);
+	int i;
+
+	for (i = 0; i < num_vfs; i++) {
+		if (bp->pf.vf[i].fw_fid == fid)
+			break;
+	}
+	if (i >= num_vfs)
+		return -EINVAL;
+	return i;
+}
+
+static int bnxt_tc_del_matchall(struct bnxt *bp, u16 src_fid,
+				struct tc_cls_matchall_offload *matchall_cmd)
+{
+	int vf_idx;
+
+	vf_idx = bnxt_tc_find_vf_by_fid(bp, src_fid);
+	if (vf_idx < 0)
+		return vf_idx;
+
+	if (bp->pf.vf[vf_idx].police_id != matchall_cmd->cookie)
+		return -ENOENT;
+
+	bnxt_set_vf_bw(bp->dev, vf_idx, 0, 0);
+	bp->pf.vf[vf_idx].police_id = 0;
+	return 0;
+}
+
+static int bnxt_tc_add_matchall(struct bnxt *bp, u16 src_fid,
+				struct tc_cls_matchall_offload *matchall_cmd)
+{
+	struct flow_action_entry *action;
+	int vf_idx;
+	s64 burst;
+	u64 rate;
+	int rc;
+
+	vf_idx = bnxt_tc_find_vf_by_fid(bp, src_fid);
+	if (vf_idx < 0)
+		return vf_idx;
+
+	action = &matchall_cmd->rule->action.entries[0];
+	if (action->id != FLOW_ACTION_POLICE) {
+		netdev_err(bp->dev, "%s: Unsupported matchall action: %d",
+			   __func__, action->id);
+		return -EOPNOTSUPP;
+	}
+	if (bp->pf.vf[vf_idx].police_id && bp->pf.vf[vf_idx].police_id !=
+	    matchall_cmd->cookie) {
+		netdev_err(bp->dev,
+			   "%s: Policer is already configured for VF: %d",
+			   __func__, vf_idx);
+		return -EEXIST;
+	}
+
+	rate = (u32)div_u64(action->police.rate_bytes_ps, 1024 * 1000) * 8;
+	burst = (u32)div_u64(action->police.rate_bytes_ps *
+			     PSCHED_NS2TICKS(action->police.burst),
+			     PSCHED_TICKS_PER_SEC);
+	burst = (u32)PSCHED_TICKS2NS(burst) / (1 << 20);
+
+	rc = bnxt_set_vf_bw(bp->dev, vf_idx, burst, rate);
+	if (rc) {
+		netdev_err(bp->dev,
+			   "Error: %s: VF: %d rate: %llu burst: %llu rc: %d",
+			   __func__, vf_idx, rate, burst, rc);
+		return rc;
+	}
+
+	bp->pf.vf[vf_idx].police_id = matchall_cmd->cookie;
+	return 0;
+}
+
+int bnxt_tc_setup_matchall(struct bnxt *bp, u16 src_fid,
+			   struct tc_cls_matchall_offload *cls_matchall)
+{
+	switch (cls_matchall->command) {
+	case TC_CLSMATCHALL_REPLACE:
+		return bnxt_tc_add_matchall(bp, src_fid, cls_matchall);
+	case TC_CLSMATCHALL_DESTROY:
+		return bnxt_tc_del_matchall(bp, src_fid, cls_matchall);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static const struct rhashtable_params bnxt_tc_flow_ht_params = {
 	.head_offset = offsetof(struct bnxt_tc_flow_node, node),
 	.key_offset = offsetof(struct bnxt_tc_flow_node, cookie),
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.h
index 10c62b0..963788e 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.h
@@ -220,6 +220,9 @@  int bnxt_tc_setup_flower(struct bnxt *bp, u16 src_fid,
 int bnxt_init_tc(struct bnxt *bp);
 void bnxt_shutdown_tc(struct bnxt *bp);
 void bnxt_tc_flow_stats_work(struct bnxt *bp);
+int bnxt_tc_setup_matchall(struct bnxt *bp, u16 src_fid,
+			   struct tc_cls_matchall_offload *cls_matchall);
+
 
 static inline bool bnxt_tc_flower_enabled(struct bnxt *bp)
 {
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
index b010b34..b9d3dae 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
@@ -156,6 +156,8 @@  static int bnxt_vf_rep_setup_tc_block_cb(enum tc_setup_type type,
 	switch (type) {
 	case TC_SETUP_CLSFLOWER:
 		return bnxt_tc_setup_flower(bp, vf_fid, type_data);
+	case TC_SETUP_CLSMATCHALL:
+		return bnxt_tc_setup_matchall(bp, vf_fid, type_data);
 	default:
 		return -EOPNOTSUPP;
 	}