net/mlx5: fix flow mark with sampling and metering
[dpdk.git] / drivers / net / ionic / ionic_rx_filter.c
1 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2  * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
3  */
4
5 #include <errno.h>
6 #include <stdbool.h>
7
8 #include <rte_malloc.h>
9
10 #include "ionic.h"
11 #include "ionic_lif.h"
12 #include "ionic_rx_filter.h"
13
14 void
15 ionic_rx_filter_free(struct ionic_rx_filter *f)
16 {
17         LIST_REMOVE(f, by_id);
18         LIST_REMOVE(f, by_hash);
19         rte_free(f);
20 }
21
22 int
23 ionic_rx_filters_init(struct ionic_lif *lif)
24 {
25         uint32_t i;
26
27         rte_spinlock_init(&lif->rx_filters.lock);
28
29         for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
30                 LIST_INIT(&lif->rx_filters.by_hash[i]);
31                 LIST_INIT(&lif->rx_filters.by_id[i]);
32         }
33
34         return 0;
35 }
36
37 void
38 ionic_rx_filters_deinit(struct ionic_lif *lif)
39 {
40         struct ionic_rx_filter *f;
41         uint32_t i;
42
43         for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
44                 while (!LIST_EMPTY(&lif->rx_filters.by_id[i])) {
45                         f = LIST_FIRST(&lif->rx_filters.by_id[i]);
46                         ionic_rx_filter_free(f);
47                 }
48         }
49 }
50
51 int
52 ionic_rx_filter_save(struct ionic_lif *lif, uint32_t flow_id,
53                 uint16_t rxq_index, struct ionic_admin_ctx *ctx)
54 {
55         struct ionic_rx_filter *f;
56         uint32_t key;
57
58         f = rte_zmalloc("ionic", sizeof(*f), 0);
59
60         if (!f)
61                 return -ENOMEM;
62
63         f->flow_id = flow_id;
64         f->filter_id = rte_le_to_cpu_32(ctx->comp.rx_filter_add.filter_id);
65         f->rxq_index = rxq_index;
66         f->match = rte_le_to_cpu_16(f->cmd.match);
67         memcpy(&f->cmd, &ctx->cmd, sizeof(f->cmd));
68
69         switch (f->match) {
70         case IONIC_RX_FILTER_MATCH_VLAN:
71                 key = rte_le_to_cpu_16(f->cmd.vlan.vlan);
72                 break;
73         case IONIC_RX_FILTER_MATCH_MAC:
74                 memcpy(&key, f->cmd.mac.addr, sizeof(key));
75                 break;
76         default:
77                 return -EINVAL;
78         }
79
80         key &= IONIC_RX_FILTER_HLISTS_MASK;
81
82         rte_spinlock_lock(&lif->rx_filters.lock);
83
84         LIST_INSERT_HEAD(&lif->rx_filters.by_hash[key], f, by_hash);
85
86         key = f->filter_id & IONIC_RX_FILTER_HLISTS_MASK;
87
88         LIST_INSERT_HEAD(&lif->rx_filters.by_id[key], f, by_id);
89
90         rte_spinlock_unlock(&lif->rx_filters.lock);
91
92         return 0;
93 }
94
95 struct ionic_rx_filter *
96 ionic_rx_filter_by_vlan(struct ionic_lif *lif, uint16_t vid)
97 {
98         uint32_t key = vid & IONIC_RX_FILTER_HLISTS_MASK;
99         struct ionic_rx_filter *f;
100         __le16 vid_le = rte_cpu_to_le_16(vid);
101
102         LIST_FOREACH(f, &lif->rx_filters.by_hash[key], by_hash) {
103                 if (f->match != IONIC_RX_FILTER_MATCH_VLAN)
104                         continue;
105                 if (f->cmd.vlan.vlan == vid_le)
106                         return f;
107         }
108
109         return NULL;
110 }
111
112 struct ionic_rx_filter *
113 ionic_rx_filter_by_addr(struct ionic_lif *lif, const uint8_t *addr)
114 {
115         const uint32_t key = *(const uint32_t *)addr &
116                 IONIC_RX_FILTER_HLISTS_MASK;
117         struct ionic_rx_filter *f;
118
119         LIST_FOREACH(f, &lif->rx_filters.by_hash[key], by_hash) {
120                 if (f->match != IONIC_RX_FILTER_MATCH_MAC)
121                         continue;
122                 if (memcmp(addr, f->cmd.mac.addr, RTE_ETHER_ADDR_LEN) == 0)
123                         return f;
124         }
125
126         return NULL;
127 }