+ if (rc) {
+ rte_flow_error_set(error, -rc,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ act,
+ "Failed to configure VNIC");
+ goto ret;
+ }
+
+ rc = bnxt_hwrm_vnic_plcmode_cfg(bp, vnic);
+ if (rc) {
+ rte_flow_error_set(error, -rc,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ act,
+ "Failed to configure VNIC plcmode");
+ goto ret;
+ }
+
+ bp->nr_vnics++;
+
+ return 0;
+
+ret:
+ bnxt_vnic_cleanup(bp, vnic);
+ return rc;
+}
+
+static int match_vnic_rss_cfg(struct bnxt *bp,
+ struct bnxt_vnic_info *vnic,
+ const struct rte_flow_action_rss *rss)
+{
+ unsigned int match = 0, i;
+
+ if (vnic->rx_queue_cnt != rss->queue_num)
+ return -EINVAL;
+
+ for (i = 0; i < rss->queue_num; i++) {
+ if (!bp->rx_queues[rss->queue[i]]->vnic->rx_queue_cnt &&
+ !bp->rx_queues[rss->queue[i]]->rx_started)
+ return -EINVAL;
+ }
+
+ for (i = 0; i < vnic->rx_queue_cnt; i++) {
+ int j;
+
+ for (j = 0; j < vnic->rx_queue_cnt; j++) {
+ if (bp->grp_info[rss->queue[i]].fw_grp_id ==
+ vnic->fw_grp_ids[j])
+ match++;
+ }
+ }
+
+ if (match != vnic->rx_queue_cnt) {
+ PMD_DRV_LOG(ERR,
+ "VNIC queue count %d vs queues matched %d\n",
+ match, vnic->rx_queue_cnt);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void
+bnxt_update_filter_flags_en(struct bnxt_filter_info *filter,
+ struct bnxt_filter_info *filter1,
+ int use_ntuple)
+{
+ if (!use_ntuple &&
+ !(filter->valid_flags &
+ ~(BNXT_FLOW_L2_DST_VALID_FLAG |
+ BNXT_FLOW_L2_SRC_VALID_FLAG |
+ BNXT_FLOW_L2_INNER_SRC_VALID_FLAG |
+ BNXT_FLOW_L2_INNER_DST_VALID_FLAG |
+ BNXT_FLOW_L2_DROP_FLAG |
+ BNXT_FLOW_PARSE_INNER_FLAG))) {
+ filter->flags = filter1->flags;
+ filter->enables = filter1->enables;
+ filter->filter_type = HWRM_CFA_L2_FILTER;
+ memcpy(filter->l2_addr, filter1->l2_addr, RTE_ETHER_ADDR_LEN);
+ memset(filter->l2_addr_mask, 0xff, RTE_ETHER_ADDR_LEN);
+ filter->pri_hint = filter1->pri_hint;
+ filter->l2_filter_id_hint = filter1->l2_filter_id_hint;
+ }
+ filter->fw_l2_filter_id = filter1->fw_l2_filter_id;
+ filter->l2_ref_cnt = filter1->l2_ref_cnt;
+ filter->flow_id = filter1->flow_id;
+ PMD_DRV_LOG(DEBUG,
+ "l2_filter: %p fw_l2_filter_id %" PRIx64 " l2_ref_cnt %u\n",
+ filter1, filter->fw_l2_filter_id, filter->l2_ref_cnt);
+}
+
+/* Valid actions supported along with RSS are count and mark. */
+static int
+bnxt_validate_rss_action(const struct rte_flow_action actions[])
+{
+ for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+ switch (actions->type) {
+ case RTE_FLOW_ACTION_TYPE_VOID:
+ break;
+ case RTE_FLOW_ACTION_TYPE_RSS:
+ break;
+ default:
+ return -ENOTSUP;
+ }
+ }
+
+ return 0;
+}
+
+static int
+bnxt_get_vnic(struct bnxt *bp, uint32_t group)
+{
+ int vnic_id = 0;
+
+ /* For legacy NS3 based implementations,
+ * group_id will be mapped to a VNIC ID.
+ */
+ if (BNXT_STINGRAY(bp))
+ vnic_id = group;
+
+ /* Non NS3 cases, group_id will be ignored.
+ * Setting will be configured on default VNIC.
+ */
+ return vnic_id;
+}
+
+static int
+bnxt_vnic_rss_cfg_update(struct bnxt *bp,
+ struct bnxt_vnic_info *vnic,
+ const struct rte_flow_action *act,
+ struct rte_flow_error *error)
+{
+ const struct rte_flow_action_rss *rss;
+ unsigned int rss_idx, i;
+ uint16_t hash_type;
+ uint64_t types;
+ int rc;
+
+ rss = (const struct rte_flow_action_rss *)act->conf;
+
+ /* Currently only Toeplitz hash is supported. */
+ if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT &&
+ rss->func != RTE_ETH_HASH_FUNCTION_TOEPLITZ) {
+ rte_flow_error_set(error,
+ ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ act,
+ "Unsupported RSS hash function");
+ rc = -rte_errno;
+ goto ret;
+ }
+
+ /* key_len should match the hash key supported by hardware */
+ if (rss->key_len != 0 && rss->key_len != HW_HASH_KEY_SIZE) {
+ rte_flow_error_set(error,
+ EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ act,
+ "Incorrect hash key parameters");
+ rc = -rte_errno;
+ goto ret;
+ }
+
+ /* Currently RSS hash on inner and outer headers are supported.
+ * 0 => Default (innermost RSS) setting
+ * 1 => Outermost
+ */
+ if (rss->level > 1) {
+ rte_flow_error_set(error,
+ ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ act,
+ "Unsupported hash level");
+ rc = -rte_errno;
+ goto ret;
+ }
+
+ if ((rss->queue_num == 0 && rss->queue != NULL) ||
+ (rss->queue_num != 0 && rss->queue == NULL)) {
+ rte_flow_error_set(error,
+ EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ act,
+ "Invalid queue config specified");
+ rc = -rte_errno;