crypto/openssl: add RSA and mod asym operations
[dpdk.git] / lib / librte_ethdev / rte_flow.c
index 7947529..cff4b52 100644 (file)
@@ -84,7 +84,7 @@ static const struct rte_flow_desc_data rte_flow_desc_action[] = {
        MK_FLOW_ACTION(FLAG, 0),
        MK_FLOW_ACTION(QUEUE, sizeof(struct rte_flow_action_queue)),
        MK_FLOW_ACTION(DROP, 0),
-       MK_FLOW_ACTION(COUNT, 0),
+       MK_FLOW_ACTION(COUNT, sizeof(struct rte_flow_action_count)),
        MK_FLOW_ACTION(RSS, sizeof(struct rte_flow_action_rss)),
        MK_FLOW_ACTION(PF, 0),
        MK_FLOW_ACTION(VF, sizeof(struct rte_flow_action_vf)),
@@ -300,15 +300,24 @@ flow_item_spec_copy(void *buf, const struct rte_flow_item *item,
                    enum item_spec_type type)
 {
        size_t size = 0;
-       const void *item_spec =
+       const void *data =
                type == ITEM_SPEC ? item->spec :
                type == ITEM_LAST ? item->last :
                type == ITEM_MASK ? item->mask :
                NULL;
 
-       if (!item_spec)
+       if (!item->spec || !data)
                goto empty;
        switch (item->type) {
+               union {
+                       const struct rte_flow_item_raw *raw;
+               } spec;
+               union {
+                       const struct rte_flow_item_raw *raw;
+               } last;
+               union {
+                       const struct rte_flow_item_raw *raw;
+               } mask;
                union {
                        const struct rte_flow_item_raw *raw;
                } src;
@@ -318,11 +327,21 @@ flow_item_spec_copy(void *buf, const struct rte_flow_item *item,
                size_t off;
 
        case RTE_FLOW_ITEM_TYPE_RAW:
-               src.raw = item_spec;
+               spec.raw = item->spec;
+               last.raw = item->last ? item->last : item->spec;
+               mask.raw = item->mask ? item->mask : &rte_flow_item_raw_mask;
+               src.raw = data;
                dst.raw = buf;
                off = RTE_ALIGN_CEIL(sizeof(struct rte_flow_item_raw),
                                     sizeof(*src.raw->pattern));
-               size = off + src.raw->length * sizeof(*src.raw->pattern);
+               if (type == ITEM_SPEC ||
+                   (type == ITEM_MASK &&
+                    ((spec.raw->length & mask.raw->length) >=
+                     (last.raw->length & mask.raw->length))))
+                       size = spec.raw->length & mask.raw->length;
+               else
+                       size = last.raw->length & mask.raw->length;
+               size = off + size * sizeof(*src.raw->pattern);
                if (dst.raw) {
                        memcpy(dst.raw, src.raw, sizeof(*src.raw));
                        dst.raw->pattern = memcpy((uint8_t *)dst.raw + off,
@@ -333,7 +352,7 @@ flow_item_spec_copy(void *buf, const struct rte_flow_item *item,
        default:
                size = rte_flow_desc_item[item->type].size;
                if (buf)
-                       memcpy(buf, item_spec, size);
+                       memcpy(buf, data, size);
                break;
        }
 empty:
@@ -507,3 +526,110 @@ store:
        }
        return 0;
 }
+
+/**
+ * Expand RSS flows into several possible flows according to the RSS hash
+ * fields requested and the driver capabilities.
+ */
+int __rte_experimental
+rte_flow_expand_rss(struct rte_flow_expand_rss *buf, size_t size,
+                   const struct rte_flow_item *pattern, uint64_t types,
+                   const struct rte_flow_expand_node graph[],
+                   int graph_root_index)
+{
+       const int elt_n = 8;
+       const struct rte_flow_item *item;
+       const struct rte_flow_expand_node *node = &graph[graph_root_index];
+       const int *next_node;
+       const int *stack[elt_n];
+       int stack_pos = 0;
+       struct rte_flow_item flow_items[elt_n];
+       unsigned int i;
+       size_t lsize;
+       size_t user_pattern_size = 0;
+       void *addr = NULL;
+
+       lsize = offsetof(struct rte_flow_expand_rss, entry) +
+               elt_n * sizeof(buf->entry[0]);
+       if (lsize <= size) {
+               buf->entry[0].priority = 0;
+               buf->entry[0].pattern = (void *)&buf->entry[elt_n];
+               buf->entries = 0;
+               addr = buf->entry[0].pattern;
+       }
+       for (item = pattern; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+               const struct rte_flow_expand_node *next = NULL;
+
+               for (i = 0; node->next && node->next[i]; ++i) {
+                       next = &graph[node->next[i]];
+                       if (next->type == item->type)
+                               break;
+               }
+               if (next)
+                       node = next;
+               user_pattern_size += sizeof(*item);
+       }
+       user_pattern_size += sizeof(*item); /* Handle END item. */
+       lsize += user_pattern_size;
+       /* Copy the user pattern in the first entry of the buffer. */
+       if (lsize <= size) {
+               rte_memcpy(addr, pattern, user_pattern_size);
+               addr = (void *)(((uintptr_t)addr) + user_pattern_size);
+               buf->entries = 1;
+       }
+       /* Start expanding. */
+       memset(flow_items, 0, sizeof(flow_items));
+       user_pattern_size -= sizeof(*item);
+       next_node = node->next;
+       stack[stack_pos] = next_node;
+       node = next_node ? &graph[*next_node] : NULL;
+       while (node) {
+               flow_items[stack_pos].type = node->type;
+               if (node->rss_types & types) {
+                       /*
+                        * compute the number of items to copy from the
+                        * expansion and copy it.
+                        * When the stack_pos is 0, there are 1 element in it,
+                        * plus the addition END item.
+                        */
+                       int elt = stack_pos + 2;
+
+                       flow_items[stack_pos + 1].type = RTE_FLOW_ITEM_TYPE_END;
+                       lsize += elt * sizeof(*item) + user_pattern_size;
+                       if (lsize <= size) {
+                               size_t n = elt * sizeof(*item);
+
+                               buf->entry[buf->entries].priority =
+                                       stack_pos + 1;
+                               buf->entry[buf->entries].pattern = addr;
+                               buf->entries++;
+                               rte_memcpy(addr, buf->entry[0].pattern,
+                                          user_pattern_size);
+                               addr = (void *)(((uintptr_t)addr) +
+                                               user_pattern_size);
+                               rte_memcpy(addr, flow_items, n);
+                               addr = (void *)(((uintptr_t)addr) + n);
+                       }
+               }
+               /* Go deeper. */
+               if (node->next) {
+                       next_node = node->next;
+                       if (stack_pos++ == elt_n) {
+                               rte_errno = E2BIG;
+                               return -rte_errno;
+                       }
+                       stack[stack_pos] = next_node;
+               } else if (*(next_node + 1)) {
+                       /* Follow up with the next possibility. */
+                       ++next_node;
+               } else {
+                       /* Move to the next path. */
+                       if (stack_pos)
+                               next_node = stack[--stack_pos];
+                       next_node++;
+                       stack[stack_pos] = next_node;
+               }
+               node = *next_node ? &graph[*next_node] : NULL;
+       };
+       return lsize;
+}