DPDK patches and discussions
 help / color / Atom feed
From: alvinx.zhang@intel.com
To: qi.z.zhang@intel.com;beilei.xing@intel.com
Cc: dev@dpdk.org, Alvin Zhang <alvinx.zhang@intel.com>
Subject: [dpdk-dev] [PATCH v2] net/i40e: add checking for messages from VF
Date: Wed, 28 Aug 2019 15:13:56 +0800
Message-ID: <1566976436-173305-1-git-send-email-alvinx.zhang@intel.com> (raw)
In-Reply-To: <1566285506-63817-1-git-send-email-alvinx.zhang@intel.com>

From: Alvin Zhang <alvinx.zhang@intel.com>

If VF driver in VM continuous sending invalid messages by mailbox,
it will waste CPU cycles on PF driver and impact other VF drivers
configuration. I40E PF PMD can count the numbers of invalid and
unsupported messages from VFs, when the counter of statistics from
a VF exceed maximum limitation, PF driver will ignore all of
messages from that VF for some seconds.

Signed-off-by: Alvin Zhang <alvinx.zhang@intel.com>
---
 doc/guides/nics/i40e.rst       |  12 +++
 drivers/net/i40e/i40e_ethdev.c |  82 ++++++++++++++++++
 drivers/net/i40e/i40e_ethdev.h |  32 +++++++
 drivers/net/i40e/i40e_pf.c     | 185 ++++++++++++++++++++++++++++++++---------
 4 files changed, 270 insertions(+), 41 deletions(-)

diff --git a/doc/guides/nics/i40e.rst b/doc/guides/nics/i40e.rst
index 0884e15..5c7bdb0 100644
--- a/doc/guides/nics/i40e.rst
+++ b/doc/guides/nics/i40e.rst
@@ -185,6 +185,18 @@ Runtime Config Options
 
   -w 84:00.0,use-latest-supported-vec=1
 
+- ``Enable validation for VF message`` (default ``not enabled``)
+
+  The i40e PF PMD supports message validation which from VFs. This will count the
+  numbers of continuous invalid and unsupported messages from VFs. If the counter of
+  statistics from a VF exceed maximum limitation, PF driver will ignore all of messages
+  from that VF for some seconds. Using the ``devargs`` option ``vf_max_wrong_msg``,
+  user can specify how many continuous invalid and unsupported message that PF driver
+  could tolerate and how many seconds during which PF driver will ignore all of
+  messages from a VF, for example::
+
+  -w 84:00.0,vf_max_wrong_msg=4,6,30
+
 Vector RX Pre-conditions
 ~~~~~~~~~~~~~~~~~~~~~~~~
 For Vector RX it is assumed that the number of descriptor rings will be a power
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 4e40b7a..e17cd66 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -44,6 +44,7 @@
 #define ETH_I40E_SUPPORT_MULTI_DRIVER	"support-multi-driver"
 #define ETH_I40E_QUEUE_NUM_PER_VF_ARG	"queue-num-per-vf"
 #define ETH_I40E_USE_LATEST_VEC	"use-latest-supported-vec"
+#define ETH_I40E_MAX_VF_WRONG_MSG	"vf_max_wrong_msg"
 
 #define I40E_CLEAR_PXE_WAIT_MS     200
 
@@ -406,6 +407,7 @@ static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
 	ETH_I40E_SUPPORT_MULTI_DRIVER,
 	ETH_I40E_QUEUE_NUM_PER_VF_ARG,
 	ETH_I40E_USE_LATEST_VEC,
+	ETH_I40E_MAX_VF_WRONG_MSG,
 	NULL};
 
 static const struct rte_pci_id pci_id_i40e_map[] = {
@@ -1256,6 +1258,84 @@ static inline void i40e_config_automask(struct i40e_pf *pf)
 	return 0;
 }
 
+static int
+read_vf_msg_check_info(__rte_unused const char *key,
+			       const char *value,
+			       void *opaque)
+{
+	struct i40e_wrong_vf_msg info;
+
+	memset(&info, 0, sizeof(info));
+	/*
+	 * VF message checking function need 3 parameters, max_invalid,
+	 * max_unsupported and silence_seconds.
+	 * When continuous invalid or unsupported message statistics
+	 * from a VF exceed the limitation of 'max_invalid' or
+	 * 'max_unsupported', PF will ignore any message from that VF for
+	 * 'silence_seconds' seconds.
+	 */
+	if (sscanf(value, "%u:%u:%lu", &info.max_invalid,
+			&info.max_unsupported, &info.silence_seconds)
+			!= 3) {
+		PMD_DRV_LOG(ERR, "vf_max_wrong_msg error! format like: "
+				"vf_max_wrong_msg=4:6:60");
+		return -EINVAL;
+	}
+
+	/*
+	 * If invalid or unsupported message checking function is enabled
+	 * by setting max_invalid or max_unsupported variable to not zero,
+	 * 'slience_seconds' must be greater than zero.
+	 */
+	if ((info.max_invalid || info.max_unsupported) &&
+			!info.silence_seconds) {
+		PMD_DRV_LOG(ERR, "vf_max_wrong_msg error! last integer"
+				" must be larger than zero");
+		return -EINVAL;
+	}
+
+	memcpy(opaque, &info, sizeof(struct i40e_wrong_vf_msg));
+	return 0;
+}
+
+static int
+i40e_parse_vf_msg_check_info(struct rte_eth_dev *dev,
+		struct i40e_wrong_vf_msg *wrong_info)
+{
+	int ret = 0;
+	int kvargs_count;
+	struct rte_kvargs *kvlist;
+
+	/* reset all to zero */
+	memset(wrong_info, 0, sizeof(*wrong_info));
+
+	if (!dev->device->devargs)
+		return ret;
+
+	kvlist = rte_kvargs_parse(dev->device->devargs->args, valid_keys);
+	if (!kvlist)
+		return -EINVAL;
+
+	kvargs_count = rte_kvargs_count(kvlist, ETH_I40E_MAX_VF_WRONG_MSG);
+	if (!kvargs_count)
+		goto free_end;
+
+	if (kvargs_count > 1) {
+		PMD_DRV_LOG(ERR, "More than one argument \"%s\"!",
+				ETH_I40E_MAX_VF_WRONG_MSG);
+		ret = -EINVAL;
+		goto free_end;
+	}
+
+	if (rte_kvargs_process(kvlist, ETH_I40E_MAX_VF_WRONG_MSG,
+			read_vf_msg_check_info, wrong_info) < 0)
+		ret = -EINVAL;
+
+free_end:
+	rte_kvargs_free(kvlist);
+	return ret;
+}
+
 #define I40E_ALARM_INTERVAL 50000 /* us */
 
 static int
@@ -1328,6 +1408,8 @@ static inline void i40e_config_automask(struct i40e_pf *pf)
 		return -EIO;
 	}
 
+	/* read VF message checking function parameters */
+	i40e_parse_vf_msg_check_info(dev, &pf->wrong_vf_msg_conf);
 	/* Check if need to support multi-driver */
 	i40e_support_multi_driver(dev);
 	/* Check if users want the latest supported vec path */
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 38ac3ea..d4d98cb 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -426,6 +426,25 @@ struct i40e_pf_vf {
 	/* version of the virtchnl from VF */
 	struct virtchnl_version_info version;
 	uint32_t request_caps; /* offload caps requested from VF */
+
+	/*
+	 * Counter of message from VF
+	 * invalid_cmd_cnt, invalid command since last valid command
+	 * unsupported_cmd_cnt, unsupported command since last valid command
+	 * invalid_total, total invalid command
+	 * unsupported_total, total unsupported command
+	 * ignored_cmd_cnt, ignored command in silence
+	 */
+	uint16_t invalid_cmd_cnt;
+	uint16_t unsupported_cmd_cnt;
+	uint64_t invalid_total;
+	uint64_t unsupported_total;
+	uint64_t ignored_cmd_cnt;
+
+	/* cycle of stop ignoring VF message */
+	uint64_t silence_end_cycle;
+	/* cycle of receive last invalid or unsupported message from VF*/
+	uint64_t last_wrong_msg_cycle;
 };
 
 /*
@@ -900,6 +919,17 @@ struct i40e_rte_flow_rss_conf {
 	uint16_t queue[I40E_MAX_Q_PER_TC]; /**< Queues indices to use. */
 };
 
+struct i40e_wrong_vf_msg {
+	uint32_t max_invalid; /* maximal continuous invalid message from VF */
+	/* maximal continuous unsupported message from VF */
+	uint32_t max_unsupported;
+	/*
+	 * silence seconds when VF send much more invalid or unsupported
+	 * message
+	 */
+	uint64_t silence_seconds;
+};
+
 /*
  * Structure to store private data specific for PF instance.
  */
@@ -975,6 +1005,8 @@ struct i40e_pf {
 	struct i40e_customized_pctype customized_pctype[I40E_CUSTOMIZED_MAX];
 	/* Switch Domain Id */
 	uint16_t switch_domain_id;
+
+	struct i40e_wrong_vf_msg wrong_vf_msg_conf;
 };
 
 enum pending_msg {
diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
index b28d02e..c94fc51 100644
--- a/drivers/net/i40e/i40e_pf.c
+++ b/drivers/net/i40e/i40e_pf.c
@@ -297,7 +297,7 @@
 		i40e_pf_host_send_msg_to_vf(vf,
 					    VIRTCHNL_OP_GET_VF_RESOURCES,
 					    I40E_NOT_SUPPORTED, NULL, 0);
-		return ret;
+		return I40E_NOT_SUPPORTED;
 	}
 
 	/* only have 1 VSI by default */
@@ -488,7 +488,7 @@
 		i40e_pf_host_send_msg_to_vf(vf,
 					    VIRTCHNL_OP_CONFIG_VSI_QUEUES,
 					    I40E_NOT_SUPPORTED, NULL, 0);
-		return ret;
+		return I40E_NOT_SUPPORTED;
 	}
 
 	if (!msg || vc_vqci->num_queue_pairs > vsi->nb_qps ||
@@ -655,7 +655,7 @@
 			vf,
 			VIRTCHNL_OP_CONFIG_IRQ_MAP,
 			I40E_NOT_SUPPORTED, NULL, 0);
-		return ret;
+		return I40E_NOT_SUPPORTED;
 	}
 
 	if (msg == NULL || msglen < sizeof(struct virtchnl_irq_map_info)) {
@@ -795,7 +795,7 @@
 			vf,
 			VIRTCHNL_OP_DISABLE_QUEUES,
 			I40E_NOT_SUPPORTED, NULL, 0);
-		return ret;
+		return I40E_NOT_SUPPORTED;
 	}
 
 	if (msg == NULL || msglen != sizeof(*q_sel)) {
@@ -830,7 +830,7 @@
 			vf,
 			VIRTCHNL_OP_ADD_ETH_ADDR,
 			I40E_NOT_SUPPORTED, NULL, 0);
-		return ret;
+		return I40E_NOT_SUPPORTED;
 	}
 
 	memset(&filter, 0 , sizeof(struct i40e_mac_filter_info));
@@ -876,7 +876,7 @@
 			vf,
 			VIRTCHNL_OP_DEL_ETH_ADDR,
 			I40E_NOT_SUPPORTED, NULL, 0);
-		return ret;
+		return I40E_NOT_SUPPORTED;
 	}
 
 	if (msg == NULL || msglen <= sizeof(*addr_list)) {
@@ -917,7 +917,7 @@
 			vf,
 			VIRTCHNL_OP_ADD_VLAN,
 			I40E_NOT_SUPPORTED, NULL, 0);
-		return ret;
+		return I40E_NOT_SUPPORTED;
 	}
 
 	if (msg == NULL || msglen <= sizeof(*vlan_filter_list)) {
@@ -958,7 +958,7 @@
 			vf,
 			VIRTCHNL_OP_DEL_VLAN,
 			I40E_NOT_SUPPORTED, NULL, 0);
-		return ret;
+		return I40E_NOT_SUPPORTED;
 	}
 
 	if (msg == NULL || msglen <= sizeof(*vlan_filter_list)) {
@@ -999,7 +999,7 @@
 			vf,
 			VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
 			I40E_NOT_SUPPORTED, NULL, 0);
-		return ret;
+		return I40E_NOT_SUPPORTED;
 	}
 
 	if (msg == NULL || msglen != sizeof(*promisc)) {
@@ -1031,16 +1031,18 @@
 {
 	i40e_update_vsi_stats(vf->vsi);
 
-	if (b_op)
+	if (b_op) {
 		i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_GET_STATS,
 					    I40E_SUCCESS,
 					    (uint8_t *)&vf->vsi->eth_stats,
 					    sizeof(vf->vsi->eth_stats));
-	else
+	} else {
 		i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_GET_STATS,
 					    I40E_NOT_SUPPORTED,
 					    (uint8_t *)&vf->vsi->eth_stats,
 					    sizeof(vf->vsi->eth_stats));
+		return I40E_NOT_SUPPORTED;
+	}
 
 	return I40E_SUCCESS;
 }
@@ -1055,7 +1057,7 @@
 			vf,
 			VIRTCHNL_OP_ENABLE_VLAN_STRIPPING,
 			I40E_NOT_SUPPORTED, NULL, 0);
-		return ret;
+		return I40E_NOT_SUPPORTED;
 	}
 
 	ret = i40e_vsi_config_vlan_stripping(vf->vsi, TRUE);
@@ -1078,7 +1080,7 @@
 			vf,
 			VIRTCHNL_OP_DISABLE_VLAN_STRIPPING,
 			I40E_NOT_SUPPORTED, NULL, 0);
-		return ret;
+		return I40E_NOT_SUPPORTED;
 	}
 
 	ret = i40e_vsi_config_vlan_stripping(vf->vsi, FALSE);
@@ -1106,7 +1108,7 @@
 			vf,
 			VIRTCHNL_OP_CONFIG_RSS_LUT,
 			I40E_NOT_SUPPORTED, NULL, 0);
-		return ret;
+		return I40E_NOT_SUPPORTED;
 	}
 
 	if (!msg || msglen <= sizeof(struct virtchnl_rss_lut)) {
@@ -1247,6 +1249,7 @@
 	struct i40e_pf *pf;
 	uint32_t req_pairs = vfres->num_queue_pairs;
 	uint32_t cur_pairs = vf->vsi->nb_used_qps;
+	int ret = I40E_SUCCESS;
 
 	pf = vf->pf;
 
@@ -1256,12 +1259,14 @@
 	if (req_pairs == 0) {
 		PMD_DRV_LOG(ERR, "VF %d tried to request 0 queues. Ignoring.\n",
 			    vf->vf_idx);
+		ret = I40E_ERR_PARAM;
 	} else if (req_pairs > I40E_MAX_QP_NUM_PER_VF) {
 		PMD_DRV_LOG(ERR,
 			    "VF %d tried to request more than %d queues.\n",
 			    vf->vf_idx,
 			    I40E_MAX_QP_NUM_PER_VF);
 		vfres->num_queue_pairs = I40E_MAX_QP_NUM_PER_VF;
+		ret = I40E_ERR_PARAM;
 	} else if (req_pairs > cur_pairs + pf->qp_pool.num_free) {
 		PMD_DRV_LOG(ERR, "VF %d requested %d queues (rounded to %d) "
 			"but only %d available\n",
@@ -1277,11 +1282,12 @@
 		pf->vf_nb_qps = req_pairs;
 		i40e_pf_host_process_cmd_reset_vf(vf);
 
-		return 0;
+		return I40E_SUCCESS;
 	}
 
-	return i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_REQUEST_QUEUES, 0,
+	i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_REQUEST_QUEUES, 0,
 				(u8 *)vfres, sizeof(*vfres));
+	return ret;
 }
 
 void
@@ -1306,11 +1312,19 @@
 	}
 
 	vf = &pf->vfs[vf_id];
+
+	/* if timer not end, ignore the message and return */
+	if (rte_get_timer_cycles() < vf->silence_end_cycle) {
+		vf->ignored_cmd_cnt++;
+		return;
+	}
+
 	if (!vf->vsi) {
 		PMD_DRV_LOG(ERR, "NO VSI associated with VF found");
 		i40e_pf_host_send_msg_to_vf(vf, opcode,
 			I40E_ERR_NO_AVAILABLE_VSI, NULL, 0);
-		return;
+		ret = I40E_ERR_NO_AVAILABLE_VSI;
+		goto err_cmd;
 	}
 
 	/* perform basic checks on the msg */
@@ -1331,14 +1345,15 @@
 
 	if (ret) {
 		PMD_DRV_LOG(ERR, "Invalid message from VF %u, opcode %u, len %u",
-			    vf_id, opcode, msglen);
+				vf_id, opcode, msglen);
 		i40e_pf_host_send_msg_to_vf(vf, opcode,
-					    I40E_ERR_PARAM, NULL, 0);
-		return;
+				I40E_ERR_PARAM, NULL, 0);
+		ret = I40E_ERR_PARAM;
+		goto err_cmd;
 	}
 
 	/**
-	 * initialise structure to send to user application
+	 * initialize structure to send to user application
 	 * will return response from user in retval field
 	 */
 	ret_param.retval = RTE_PMD_I40E_MB_EVENT_PROCEED;
@@ -1373,78 +1388,84 @@
 		break;
 	case VIRTCHNL_OP_GET_VF_RESOURCES:
 		PMD_DRV_LOG(INFO, "OP_GET_VF_RESOURCES received");
-		i40e_pf_host_process_cmd_get_vf_resource(vf, msg, b_op);
+		ret = i40e_pf_host_process_cmd_get_vf_resource(vf, msg, b_op);
 		break;
 	case VIRTCHNL_OP_CONFIG_VSI_QUEUES:
 		PMD_DRV_LOG(INFO, "OP_CONFIG_VSI_QUEUES received");
-		i40e_pf_host_process_cmd_config_vsi_queues(vf, msg,
+		ret = i40e_pf_host_process_cmd_config_vsi_queues(vf, msg,
 							   msglen, b_op);
 		break;
 	case VIRTCHNL_OP_CONFIG_IRQ_MAP:
 		PMD_DRV_LOG(INFO, "OP_CONFIG_IRQ_MAP received");
-		i40e_pf_host_process_cmd_config_irq_map(vf, msg, msglen, b_op);
+		ret = i40e_pf_host_process_cmd_config_irq_map(vf, msg,
+				msglen, b_op);
 		break;
 	case VIRTCHNL_OP_ENABLE_QUEUES:
 		PMD_DRV_LOG(INFO, "OP_ENABLE_QUEUES received");
 		if (b_op) {
-			i40e_pf_host_process_cmd_enable_queues(vf, msg, msglen);
+			ret = i40e_pf_host_process_cmd_enable_queues(vf,
+					msg, msglen);
 			i40e_notify_vf_link_status(dev, vf);
 		} else {
-			i40e_pf_host_send_msg_to_vf(
-				vf, VIRTCHNL_OP_ENABLE_QUEUES,
-				I40E_NOT_SUPPORTED, NULL, 0);
+			i40e_pf_host_send_msg_to_vf(vf,
+					VIRTCHNL_OP_ENABLE_QUEUES,
+					I40E_NOT_SUPPORTED, NULL, 0);
+			ret = I40E_NOT_SUPPORTED;
 		}
 		break;
 	case VIRTCHNL_OP_DISABLE_QUEUES:
 		PMD_DRV_LOG(INFO, "OP_DISABLE_QUEUE received");
-		i40e_pf_host_process_cmd_disable_queues(vf, msg, msglen, b_op);
+		ret = i40e_pf_host_process_cmd_disable_queues(vf,
+				msg, msglen, b_op);
 		break;
 	case VIRTCHNL_OP_ADD_ETH_ADDR:
 		PMD_DRV_LOG(INFO, "OP_ADD_ETHER_ADDRESS received");
-		i40e_pf_host_process_cmd_add_ether_address(vf, msg,
+		ret = i40e_pf_host_process_cmd_add_ether_address(vf, msg,
 							   msglen, b_op);
 		break;
 	case VIRTCHNL_OP_DEL_ETH_ADDR:
 		PMD_DRV_LOG(INFO, "OP_DEL_ETHER_ADDRESS received");
-		i40e_pf_host_process_cmd_del_ether_address(vf, msg,
+		ret = i40e_pf_host_process_cmd_del_ether_address(vf, msg,
 							   msglen, b_op);
 		break;
 	case VIRTCHNL_OP_ADD_VLAN:
 		PMD_DRV_LOG(INFO, "OP_ADD_VLAN received");
-		i40e_pf_host_process_cmd_add_vlan(vf, msg, msglen, b_op);
+		ret = i40e_pf_host_process_cmd_add_vlan(vf, msg, msglen, b_op);
 		break;
 	case VIRTCHNL_OP_DEL_VLAN:
 		PMD_DRV_LOG(INFO, "OP_DEL_VLAN received");
-		i40e_pf_host_process_cmd_del_vlan(vf, msg, msglen, b_op);
+		ret = i40e_pf_host_process_cmd_del_vlan(vf, msg, msglen, b_op);
 		break;
 	case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
 		PMD_DRV_LOG(INFO, "OP_CONFIG_PROMISCUOUS_MODE received");
-		i40e_pf_host_process_cmd_config_promisc_mode(vf, msg,
+		ret = i40e_pf_host_process_cmd_config_promisc_mode(vf, msg,
 							     msglen, b_op);
 		break;
 	case VIRTCHNL_OP_GET_STATS:
 		PMD_DRV_LOG(INFO, "OP_GET_STATS received");
-		i40e_pf_host_process_cmd_get_stats(vf, b_op);
+		ret = i40e_pf_host_process_cmd_get_stats(vf, b_op);
 		break;
 	case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING:
 		PMD_DRV_LOG(INFO, "OP_ENABLE_VLAN_STRIPPING received");
-		i40e_pf_host_process_cmd_enable_vlan_strip(vf, b_op);
+		ret = i40e_pf_host_process_cmd_enable_vlan_strip(vf, b_op);
 		break;
 	case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING:
 		PMD_DRV_LOG(INFO, "OP_DISABLE_VLAN_STRIPPING received");
-		i40e_pf_host_process_cmd_disable_vlan_strip(vf, b_op);
+		ret = i40e_pf_host_process_cmd_disable_vlan_strip(vf, b_op);
 		break;
 	case VIRTCHNL_OP_CONFIG_RSS_LUT:
 		PMD_DRV_LOG(INFO, "OP_CONFIG_RSS_LUT received");
-		i40e_pf_host_process_cmd_set_rss_lut(vf, msg, msglen, b_op);
+		ret = i40e_pf_host_process_cmd_set_rss_lut(vf, msg,
+				msglen, b_op);
 		break;
 	case VIRTCHNL_OP_CONFIG_RSS_KEY:
 		PMD_DRV_LOG(INFO, "OP_CONFIG_RSS_KEY received");
-		i40e_pf_host_process_cmd_set_rss_key(vf, msg, msglen, b_op);
+		ret = i40e_pf_host_process_cmd_set_rss_key(vf, msg,
+				msglen, b_op);
 		break;
 	case VIRTCHNL_OP_REQUEST_QUEUES:
 		PMD_DRV_LOG(INFO, "OP_REQUEST_QUEUES received");
-		i40e_pf_host_process_cmd_request_queues(vf, msg);
+		ret = i40e_pf_host_process_cmd_request_queues(vf, msg);
 		break;
 
 	/* Don't add command supported below, which will
@@ -1452,10 +1473,86 @@
 	 */
 	default:
 		PMD_DRV_LOG(ERR, "%u received, not supported", opcode);
-		i40e_pf_host_send_msg_to_vf(vf, opcode, I40E_ERR_PARAM,
+		i40e_pf_host_send_msg_to_vf(vf, opcode, I40E_NOT_SUPPORTED,
 								NULL, 0);
+		ret = I40E_NOT_SUPPORTED;
 		break;
 	}
+
+err_cmd:
+	/* If the amount of invalid or unsupported message been received
+	 * from a VF exceed maximal limitation, PF will start a timer.
+	 * Before the timer timed out, PF should ignore any message from
+	 * that VF.
+	 * Once the timer timed out, PF will accept a message from the VF,
+	 * if this message is still invalid or unsupported, PF will
+	 * restart the timer and enter another loop.
+	 * If the last commond execute succeed and within 'silence_seconds'
+	 * period of time, no invalid or unsupported message been
+	 * received from same VF, the counter of 'invalid/unsupported'
+	 * message for that VF will be reset to zero.
+	 */
+	vf->silence_end_cycle = 0;
+	switch (ret) {
+	case I40E_SUCCESS:
+		if ((vf->invalid_cmd_cnt || vf->unsupported_cmd_cnt) &&
+				rte_get_timer_cycles() >=
+				vf->last_wrong_msg_cycle +
+				pf->wrong_vf_msg_conf.silence_seconds *
+				rte_get_timer_hz()) {
+			PMD_DRV_LOG(WARNING, "VF %u message, ignored %lu, "
+					"invalid %lu, unsupported %lu", vf_id,
+					vf->ignored_cmd_cnt, vf->invalid_total,
+					vf->unsupported_total);
+			vf->unsupported_cmd_cnt = 0;
+			vf->invalid_cmd_cnt = 0;
+		}
+		break;
+
+	case I40E_ERR_PARAM:
+	case I40E_ERR_NO_AVAILABLE_VSI:
+		vf->invalid_total++;
+		if (!pf->wrong_vf_msg_conf.max_invalid)
+			break;
+		vf->invalid_cmd_cnt++;
+		if (vf->invalid_cmd_cnt >
+				pf->wrong_vf_msg_conf.max_invalid) {
+			PMD_DRV_LOG(ERR, "VF %u too much continuous invalid"
+					" message(%u, maximum %u, total %lu)!",
+					vf_id, vf->invalid_cmd_cnt,
+					pf->wrong_vf_msg_conf.max_invalid,
+					vf->invalid_total);
+			vf->silence_end_cycle = rte_get_timer_cycles() +
+					pf->wrong_vf_msg_conf.silence_seconds
+					* rte_get_timer_hz();
+		}
+
+		vf->last_wrong_msg_cycle = rte_get_timer_cycles();
+		break;
+
+	case I40E_NOT_SUPPORTED:
+		vf->unsupported_total++;
+		if (!pf->wrong_vf_msg_conf.max_unsupported)
+			break;
+		vf->unsupported_cmd_cnt++;
+		if (vf->unsupported_cmd_cnt >
+				pf->wrong_vf_msg_conf.max_unsupported) {
+			PMD_DRV_LOG(ERR, "VF %u too much continuous unsupported"
+					" message(%u, maximum %u, total %lu)!",
+					vf_id, vf->unsupported_cmd_cnt,
+					pf->wrong_vf_msg_conf.max_unsupported,
+					vf->unsupported_total);
+			vf->silence_end_cycle = rte_get_timer_cycles() +
+					pf->wrong_vf_msg_conf.silence_seconds
+					* rte_get_timer_hz();
+		}
+
+		vf->last_wrong_msg_cycle = rte_get_timer_cycles();
+		break;
+	default:
+		break;
+	}
+	return;
 }
 
 int
@@ -1493,6 +1590,12 @@
 		pf->vfs[i].pf = pf;
 		pf->vfs[i].state = I40E_VF_INACTIVE;
 		pf->vfs[i].vf_idx = i;
+
+		pf->vfs[i].invalid_cmd_cnt = 0;
+		pf->vfs[i].unsupported_cmd_cnt = 0;
+		pf->vfs[i].silence_end_cycle = 0;
+		pf->vfs[i].last_wrong_msg_cycle = 0;
+
 		ret = i40e_pf_host_vf_reset(&pf->vfs[i], 0);
 		if (ret != I40E_SUCCESS)
 			goto fail;
-- 
1.8.3.1


  parent reply index

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-20  7:18 [dpdk-dev] [PATCH] " alvinx.zhang
2019-08-22  4:18 ` Ye Xiaolong
2019-08-28  7:13 ` alvinx.zhang [this message]
2019-09-09 10:01   ` [dpdk-dev] [PATCH v3] net/i40e: validate all " alvinx.zhang
2019-09-09 15:11     ` [dpdk-dev] [PATCH v4] " alvinx.zhang
2019-09-09 13:34       ` Ye Xiaolong
2019-09-10 17:12       ` alvinx.zhang
2019-09-18 15:39         ` [dpdk-dev] [PATCH v5] " alvinx.zhang
2019-09-18 21:03           ` [dpdk-dev] [PATCH v6] net/i40e: limit the number of VF messages alvinx.zhang
2019-09-20 10:22             ` [dpdk-dev] [PATCH v7] " alvinx.zhang
2019-09-20  2:20               ` Zhang, Qi Z
2019-09-23 23:52               ` Ye Xiaolong
2019-09-24 14:24               ` [dpdk-dev] [PATCH v8] " alvinx.zhang
2019-09-24  8:47                 ` Ye Xiaolong

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1566976436-173305-1-git-send-email-alvinx.zhang@intel.com \
    --to=alvinx.zhang@intel.com \
    --cc=beilei.xing@intel.com \
    --cc=dev@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

DPDK patches and discussions

Archives are clonable:
	git clone --mirror http://inbox.dpdk.org/dev/0 dev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 dev dev/ http://inbox.dpdk.org/dev \
		dev@dpdk.org
	public-inbox-index dev


Newsgroup available over NNTP:
	nntp://inbox.dpdk.org/inbox.dpdk.dev


AGPL code for this site: git clone https://public-inbox.org/ public-inbox