dpdk/lib/acl/acl_run_scalar.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(c) 2010-2014 Intel Corporation
   3 */
   4
   5#include "acl_run.h"
   6
   7/*
   8 * Resolve priority for multiple results (scalar version).
   9 * This consists comparing the priority of the current traversal with the
  10 * running set of results for the packet.
  11 * For each result, keep a running array of the result (rule number) and
  12 * its priority for each category.
  13 */
  14static inline void
  15resolve_priority_scalar(uint64_t transition, int n,
  16        const struct rte_acl_ctx *ctx, struct parms *parms,
  17        const struct rte_acl_match_results *p, uint32_t categories)
  18{
  19        uint32_t i;
  20        int32_t *saved_priority;
  21        uint32_t *saved_results;
  22        const int32_t *priority;
  23        const uint32_t *results;
  24
  25        saved_results = parms[n].cmplt->results;
  26        saved_priority = parms[n].cmplt->priority;
  27
  28        /* results and priorities for completed trie */
  29        results = p[transition].results;
  30        priority = p[transition].priority;
  31
  32        /* if this is not the first completed trie */
  33        if (parms[n].cmplt->count != ctx->num_tries) {
  34                for (i = 0; i < categories; i += RTE_ACL_RESULTS_MULTIPLIER) {
  35
  36                        if (saved_priority[i] <= priority[i]) {
  37                                saved_priority[i] = priority[i];
  38                                saved_results[i] = results[i];
  39                        }
  40                        if (saved_priority[i + 1] <= priority[i + 1]) {
  41                                saved_priority[i + 1] = priority[i + 1];
  42                                saved_results[i + 1] = results[i + 1];
  43                        }
  44                        if (saved_priority[i + 2] <= priority[i + 2]) {
  45                                saved_priority[i + 2] = priority[i + 2];
  46                                saved_results[i + 2] = results[i + 2];
  47                        }
  48                        if (saved_priority[i + 3] <= priority[i + 3]) {
  49                                saved_priority[i + 3] = priority[i + 3];
  50                                saved_results[i + 3] = results[i + 3];
  51                        }
  52                }
  53        } else {
  54                for (i = 0; i < categories; i += RTE_ACL_RESULTS_MULTIPLIER) {
  55                        saved_priority[i] = priority[i];
  56                        saved_priority[i + 1] = priority[i + 1];
  57                        saved_priority[i + 2] = priority[i + 2];
  58                        saved_priority[i + 3] = priority[i + 3];
  59
  60                        saved_results[i] = results[i];
  61                        saved_results[i + 1] = results[i + 1];
  62                        saved_results[i + 2] = results[i + 2];
  63                        saved_results[i + 3] = results[i + 3];
  64                }
  65        }
  66}
  67
  68static inline uint32_t
  69scan_forward(uint32_t input, uint32_t max)
  70{
  71        return (input == 0) ? max : rte_bsf32(input);
  72}
  73
  74static inline uint64_t
  75scalar_transition(const uint64_t *trans_table, uint64_t transition,
  76        uint8_t input)
  77{
  78        uint32_t addr, index, ranges, x, a, b, c;
  79
  80        /* break transition into component parts */
  81        ranges = transition >> (sizeof(index) * CHAR_BIT);
  82        index = transition & ~RTE_ACL_NODE_INDEX;
  83        addr = transition ^ index;
  84
  85        if (index != RTE_ACL_NODE_DFA) {
  86                /* calc address for a QRANGE/SINGLE node */
  87                c = (uint32_t)input * SCALAR_QRANGE_MULT;
  88                a = ranges | SCALAR_QRANGE_MIN;
  89                a -= (c & SCALAR_QRANGE_MASK);
  90                b = c & SCALAR_QRANGE_MIN;
  91                a &= SCALAR_QRANGE_MIN;
  92                a ^= (ranges ^ b) & (a ^ b);
  93                x = scan_forward(a, 32) >> 3;
  94        } else {
  95                /* calc address for a DFA node */
  96                x = ranges >> (input /
  97                        RTE_ACL_DFA_GR64_SIZE * RTE_ACL_DFA_GR64_BIT);
  98                x &= UINT8_MAX;
  99                x = input - x;
 100        }
 101
 102        addr += x;
 103
 104        /* pickup next transition */
 105        transition = *(trans_table + addr);
 106        return transition;
 107}
 108
 109int
 110rte_acl_classify_scalar(const struct rte_acl_ctx *ctx, const uint8_t **data,
 111        uint32_t *results, uint32_t num, uint32_t categories)
 112{
 113        int n;
 114        uint64_t transition0, transition1;
 115        uint32_t input0, input1;
 116        struct acl_flow_data flows;
 117        uint64_t index_array[MAX_SEARCHES_SCALAR];
 118        struct completion cmplt[MAX_SEARCHES_SCALAR];
 119        struct parms parms[MAX_SEARCHES_SCALAR];
 120
 121        acl_set_flow(&flows, cmplt, RTE_DIM(cmplt), data, results, num,
 122                categories, ctx->trans_table);
 123
 124        for (n = 0; n < MAX_SEARCHES_SCALAR; n++) {
 125                cmplt[n].count = 0;
 126                index_array[n] = acl_start_next_trie(&flows, parms, n, ctx);
 127        }
 128
 129        transition0 = index_array[0];
 130        transition1 = index_array[1];
 131
 132        while ((transition0 | transition1) & RTE_ACL_NODE_MATCH) {
 133                transition0 = acl_match_check(transition0,
 134                        0, ctx, parms, &flows, resolve_priority_scalar);
 135                transition1 = acl_match_check(transition1,
 136                        1, ctx, parms, &flows, resolve_priority_scalar);
 137        }
 138
 139        while (flows.started > 0) {
 140
 141                input0 = GET_NEXT_4BYTES(parms, 0);
 142                input1 = GET_NEXT_4BYTES(parms, 1);
 143
 144                for (n = 0; n < 4; n++) {
 145
 146                        transition0 = scalar_transition(flows.trans,
 147                                transition0, (uint8_t)input0);
 148                        input0 >>= CHAR_BIT;
 149
 150                        transition1 = scalar_transition(flows.trans,
 151                                transition1, (uint8_t)input1);
 152                        input1 >>= CHAR_BIT;
 153                }
 154
 155                while ((transition0 | transition1) & RTE_ACL_NODE_MATCH) {
 156                        transition0 = acl_match_check(transition0,
 157                                0, ctx, parms, &flows, resolve_priority_scalar);
 158                        transition1 = acl_match_check(transition1,
 159                                1, ctx, parms, &flows, resolve_priority_scalar);
 160                }
 161        }
 162        return 0;
 163}
 164