X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Ftap%2Ftap_flow.c;h=aab9eefe1ccdb5777585d76c36c0bf791c3f823f;hb=fbe90cdd776c3ac99c4c56d1b5318a90fcf01602;hp=65657f0a04de93c127493d390af61cfab65b54bb;hpb=d98fac4dae3634fedbb6f3d568e71a30ded81dd9;p=dpdk.git diff --git a/drivers/net/tap/tap_flow.c b/drivers/net/tap/tap_flow.c index 65657f0a04..aab9eefe1c 100644 --- a/drivers/net/tap/tap_flow.c +++ b/drivers/net/tap/tap_flow.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright 2017 6WIND S.A. - * Copyright 2017 Mellanox. + * Copyright 2017 Mellanox Technologies, Ltd */ #include @@ -123,6 +123,7 @@ enum key_status_e { }; #define ISOLATE_HANDLE 1 +#define REMOTE_PROMISCUOUS_HANDLE 2 struct rte_flow { LIST_ENTRY(rte_flow) next; /* Pointer to the next rte_flow structure */ @@ -269,13 +270,13 @@ static const struct tap_flow_items tap_flow_items[] = { .items = ITEMS(RTE_FLOW_ITEM_TYPE_IPV4, RTE_FLOW_ITEM_TYPE_IPV6), .mask = &(const struct rte_flow_item_vlan){ - .tpid = -1, /* DEI matching is not supported */ #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN .tci = 0xffef, #else .tci = 0xefff, #endif + .inner_type = -1, }, .mask_sz = sizeof(struct rte_flow_item_vlan), .default_mask = &rte_flow_item_vlan_mask, @@ -577,13 +578,19 @@ tap_flow_create_vlan(const struct rte_flow_item *item, void *data) /* use default mask if none provided */ if (!mask) mask = tap_flow_items[RTE_FLOW_ITEM_TYPE_VLAN].default_mask; - /* TC does not support tpid masking. Only accept if exact match. */ - if (mask->tpid && mask->tpid != 0xffff) + /* Outer TPID cannot be matched. */ + if (info->eth_type) return -1; /* Double-tagging not supported. */ - if (spec && mask->tpid && spec->tpid != htons(ETH_P_8021Q)) + if (info->vlan) return -1; info->vlan = 1; + if (mask->inner_type) { + /* TC does not support partial eth_type masking */ + if (mask->inner_type != RTE_BE16(0xffff)) + return -1; + info->eth_type = spec->inner_type; + } if (!flow) return 0; msg = &flow->msg; @@ -1032,6 +1039,12 @@ priv_flow_process(struct pmd_internals *pmd, }; int action = 0; /* Only one action authorized for now */ + if (attr->transfer) { + rte_flow_error_set( + error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, + NULL, "transfer is not supported"); + return -rte_errno; + } if (attr->group > MAX_GROUP) { rte_flow_error_set( error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR_GROUP, @@ -1139,6 +1152,7 @@ priv_flow_process(struct pmd_internals *pmd, else goto end; } +actions: for (; actions->type != RTE_FLOW_ACTION_TYPE_END; ++actions) { int err = 0; @@ -1213,7 +1227,7 @@ priv_flow_process(struct pmd_internals *pmd, if (err) goto exit_action_not_supported; } - if (flow && rss) + if (flow) err = rss_add_actions(flow, pmd, rss, error); } else { goto exit_action_not_supported; @@ -1221,6 +1235,16 @@ priv_flow_process(struct pmd_internals *pmd, if (err) goto exit_action_not_supported; } + /* When fate is unknown, drop traffic. */ + if (!action) { + static const struct rte_flow_action drop[] = { + { .type = RTE_FLOW_ACTION_TYPE_DROP, }, + { .type = RTE_FLOW_ACTION_TYPE_END, }, + }; + + actions = drop; + goto actions; + } end: if (flow) tap_nlattr_nested_finish(&flow->msg); /* nested TCA_OPTIONS */ @@ -1375,8 +1399,8 @@ tap_flow_create(struct rte_eth_dev *dev, } err = tap_nl_recv_ack(pmd->nlsk_fd); if (err < 0) { - RTE_LOG(ERR, PMD, - "Kernel refused TC filter rule creation (%d): %s\n", + TAP_LOG(ERR, + "Kernel refused TC filter rule creation (%d): %s", errno, strerror(errno)); rte_flow_error_set(error, EEXIST, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, @@ -1420,8 +1444,8 @@ tap_flow_create(struct rte_eth_dev *dev, } err = tap_nl_recv_ack(pmd->nlsk_fd); if (err < 0) { - RTE_LOG(ERR, PMD, - "Kernel refused TC filter rule creation (%d): %s\n", + TAP_LOG(ERR, + "Kernel refused TC filter rule creation (%d): %s", errno, strerror(errno)); rte_flow_error_set( error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE, @@ -1475,8 +1499,8 @@ tap_flow_destroy_pmd(struct pmd_internals *pmd, if (ret < 0 && errno == ENOENT) ret = 0; if (ret < 0) { - RTE_LOG(ERR, PMD, - "Kernel refused TC filter rule deletion (%d): %s\n", + TAP_LOG(ERR, + "Kernel refused TC filter rule deletion (%d): %s", errno, strerror(errno)); rte_flow_error_set( error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, @@ -1499,8 +1523,8 @@ tap_flow_destroy_pmd(struct pmd_internals *pmd, if (ret < 0 && errno == ENOENT) ret = 0; if (ret < 0) { - RTE_LOG(ERR, PMD, - "Kernel refused TC filter rule deletion (%d): %s\n", + TAP_LOG(ERR, + "Kernel refused TC filter rule deletion (%d): %s", errno, strerror(errno)); rte_flow_error_set( error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE, @@ -1664,7 +1688,7 @@ int tap_flow_implicit_create(struct pmd_internals *pmd, remote_flow = rte_malloc(__func__, sizeof(struct rte_flow), 0); if (!remote_flow) { - RTE_LOG(ERR, PMD, "Cannot allocate memory for rte_flow\n"); + TAP_LOG(ERR, "Cannot allocate memory for rte_flow"); goto fail; } msg = &remote_flow->msg; @@ -1692,29 +1716,39 @@ int tap_flow_implicit_create(struct pmd_internals *pmd, * The ISOLATE rule is always present and must have a static handle, as * the action is changed whether the feature is enabled (DROP) or * disabled (PASSTHRU). + * There is just one REMOTE_PROMISCUOUS rule in all cases. It should + * have a static handle such that adding it twice will fail with EEXIST + * with any kernel version. Remark: old kernels may falsely accept the + * same REMOTE_PROMISCUOUS rules if they had different handles. */ if (idx == TAP_ISOLATE) remote_flow->msg.t.tcm_handle = ISOLATE_HANDLE; + else if (idx == TAP_REMOTE_PROMISC) + remote_flow->msg.t.tcm_handle = REMOTE_PROMISCUOUS_HANDLE; else tap_flow_set_handle(remote_flow); if (priv_flow_process(pmd, attr, items, actions, NULL, remote_flow, implicit_rte_flows[idx].mirred)) { - RTE_LOG(ERR, PMD, "rte flow rule validation failed\n"); + TAP_LOG(ERR, "rte flow rule validation failed"); goto fail; } err = tap_nl_send(pmd->nlsk_fd, &msg->nh); if (err < 0) { - RTE_LOG(ERR, PMD, "Failure sending nl request\n"); + TAP_LOG(ERR, "Failure sending nl request"); goto fail; } err = tap_nl_recv_ack(pmd->nlsk_fd); if (err < 0) { - RTE_LOG(ERR, PMD, - "Kernel refused TC filter rule creation (%d): %s\n", + /* Silently ignore re-entering remote promiscuous rule */ + if (errno == EEXIST && idx == TAP_REMOTE_PROMISC) + goto success; + TAP_LOG(ERR, + "Kernel refused TC filter rule creation (%d): %s", errno, strerror(errno)); goto fail; } LIST_INSERT_HEAD(&pmd->implicit_flows, remote_flow, next); +success: return 0; fail: if (remote_flow) @@ -1825,8 +1859,8 @@ static int rss_enable(struct pmd_internals *pmd, sizeof(struct rss_key), MAX_RSS_KEYS); if (pmd->map_fd < 0) { - RTE_LOG(ERR, PMD, - "Failed to create BPF map (%d): %s\n", + TAP_LOG(ERR, + "Failed to create BPF map (%d): %s", errno, strerror(errno)); rte_flow_error_set( error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, @@ -1843,7 +1877,7 @@ static int rss_enable(struct pmd_internals *pmd, for (i = 0; i < pmd->dev->data->nb_rx_queues; i++) { pmd->bpf_fd[i] = tap_flow_bpf_cls_q(i); if (pmd->bpf_fd[i] < 0) { - RTE_LOG(ERR, PMD, + TAP_LOG(ERR, "Failed to load BPF section %s for queue %d", SEC_NAME_CLS_Q, i); rte_flow_error_set( @@ -1857,7 +1891,7 @@ static int rss_enable(struct pmd_internals *pmd, rss_flow = rte_malloc(__func__, sizeof(struct rte_flow), 0); if (!rss_flow) { - RTE_LOG(ERR, PMD, + TAP_LOG(ERR, "Cannot allocate memory for rte_flow"); return -1; } @@ -1900,8 +1934,8 @@ static int rss_enable(struct pmd_internals *pmd, return -1; err = tap_nl_recv_ack(pmd->nlsk_fd); if (err < 0) { - RTE_LOG(ERR, PMD, - "Kernel refused TC filter rule creation (%d): %s\n", + TAP_LOG(ERR, + "Kernel refused TC filter rule creation (%d): %s", errno, strerror(errno)); return err; } @@ -2028,11 +2062,21 @@ static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd, struct rte_flow_error *error) { /* 4096 is the maximum number of instructions for a BPF program */ - int i; + unsigned int i; int err; struct rss_key rss_entry = { .hash_fields = 0, .key_size = 0 }; + /* Check supported RSS features */ + if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT) + return rte_flow_error_set + (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "non-default RSS hash functions are not supported"); + if (rss->level) + return rte_flow_error_set + (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "a nonzero RSS encapsulation level is not supported"); + /* Get a new map key for a new RSS rule */ err = bpf_rss_key(KEY_CMD_GET, &flow->key_idx); if (err < 0) { @@ -2044,8 +2088,8 @@ static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd, } /* Update RSS map entry with queues */ - rss_entry.nb_queues = rss->num; - for (i = 0; i < rss->num; i++) + rss_entry.nb_queues = rss->queue_num; + for (i = 0; i < rss->queue_num; i++) rss_entry.queues[i] = rss->queue[i]; rss_entry.hash_fields = (1 << HASH_FIELD_IPV4_L3_L4) | (1 << HASH_FIELD_IPV6_L3_L4); @@ -2055,8 +2099,8 @@ static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd, &flow->key_idx, &rss_entry); if (err) { - RTE_LOG(ERR, PMD, - "Failed to update BPF map entry #%u (%d): %s\n", + TAP_LOG(ERR, + "Failed to update BPF map entry #%u (%d): %s", flow->key_idx, errno, strerror(errno)); rte_flow_error_set( error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, @@ -2074,8 +2118,8 @@ static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd, flow->bpf_fd[SEC_L3_L4] = tap_flow_bpf_calc_l3_l4_hash(flow->key_idx, pmd->map_fd); if (flow->bpf_fd[SEC_L3_L4] < 0) { - RTE_LOG(ERR, PMD, - "Failed to load BPF section %s (%d): %s\n", + TAP_LOG(ERR, + "Failed to load BPF section %s (%d): %s", sec_name[SEC_L3_L4], errno, strerror(errno)); rte_flow_error_set( error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, @@ -2136,9 +2180,8 @@ tap_dev_filter_ctrl(struct rte_eth_dev *dev, *(const void **)arg = &tap_flow_ops; return 0; default: - RTE_LOG(ERR, PMD, "%p: filter type (%d) not supported\n", - (void *)dev, filter_type); + TAP_LOG(ERR, "%p: filter type (%d) not supported", + dev, filter_type); } return -EINVAL; } -