f75b81a27caed2be6e3c930bcb6fb6f53ccbe24e
[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
7 #include <rte_malloc.h>
8
9 #include "ionic_lif.h"
10 #include "ionic_rx_filter.h"
11
12 void
13 ionic_rx_filter_free(struct ionic_rx_filter *f)
14 {
15         LIST_REMOVE(f, by_id);
16         LIST_REMOVE(f, by_hash);
17         rte_free(f);
18 }
19
20 int
21 ionic_rx_filter_del(struct ionic_lif *lif, struct ionic_rx_filter *f)
22 {
23         struct ionic_admin_ctx ctx = {
24                 .pending_work = true,
25                 .cmd.rx_filter_del = {
26                         .opcode = IONIC_CMD_RX_FILTER_DEL,
27                         .filter_id = f->filter_id,
28                 },
29         };
30
31         return ionic_adminq_post(lif, &ctx);
32 }
33
34 int
35 ionic_rx_filters_init(struct ionic_lif *lif)
36 {
37         uint32_t i;
38
39         rte_spinlock_init(&lif->rx_filters.lock);
40
41         for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
42                 LIST_INIT(&lif->rx_filters.by_hash[i]);
43                 LIST_INIT(&lif->rx_filters.by_id[i]);
44         }
45
46         return 0;
47 }
48
49 void
50 ionic_rx_filters_deinit(struct ionic_lif *lif)
51 {
52         struct ionic_rx_filter *f;
53         uint32_t i;
54
55         for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
56                 while (!LIST_EMPTY(&lif->rx_filters.by_id[i])) {
57                         f = LIST_FIRST(&lif->rx_filters.by_id[i]);
58                         ionic_rx_filter_free(f);
59                 }
60         }
61 }
62
63 int
64 ionic_rx_filter_save(struct ionic_lif *lif, uint32_t flow_id,
65                 uint16_t rxq_index, struct ionic_admin_ctx *ctx)
66 {
67         struct ionic_rx_filter *f;
68         uint32_t key;
69
70         f = rte_zmalloc("ionic", sizeof(*f), 0);
71
72         if (!f)
73                 return -ENOMEM;
74
75         f->flow_id = flow_id;
76         f->filter_id = ctx->comp.rx_filter_add.filter_id;
77         f->rxq_index = rxq_index;
78         memcpy(&f->cmd, &ctx->cmd, sizeof(f->cmd));
79
80         switch (f->cmd.match) {
81         case IONIC_RX_FILTER_MATCH_VLAN:
82                 key = f->cmd.vlan.vlan & IONIC_RX_FILTER_HLISTS_MASK;
83                 break;
84         case IONIC_RX_FILTER_MATCH_MAC:
85                 memcpy(&key, f->cmd.mac.addr, sizeof(key));
86                 key &= IONIC_RX_FILTER_HLISTS_MASK;
87                 break;
88         case IONIC_RX_FILTER_MATCH_MAC_VLAN:
89                 key = f->cmd.mac_vlan.vlan & IONIC_RX_FILTER_HLISTS_MASK;
90                 break;
91         default:
92                 return -EINVAL;
93         }
94
95         rte_spinlock_lock(&lif->rx_filters.lock);
96
97         LIST_INSERT_HEAD(&lif->rx_filters.by_hash[key], f, by_hash);
98
99         key = f->filter_id & IONIC_RX_FILTER_HLISTS_MASK;
100
101         LIST_INSERT_HEAD(&lif->rx_filters.by_id[key], f, by_id);
102
103         rte_spinlock_unlock(&lif->rx_filters.lock);
104
105         return 0;
106 }
107
108 struct ionic_rx_filter *
109 ionic_rx_filter_by_vlan(struct ionic_lif *lif, uint16_t vid)
110 {
111         uint32_t key = vid & IONIC_RX_FILTER_HLISTS_MASK;
112         struct ionic_rx_filter *f;
113
114         LIST_FOREACH(f, &lif->rx_filters.by_hash[key], by_hash) {
115                 if (f->cmd.match != IONIC_RX_FILTER_MATCH_VLAN)
116                         continue;
117                 if (f->cmd.vlan.vlan == vid)
118                         return f;
119         }
120
121         return NULL;
122 }
123
124 struct ionic_rx_filter *
125 ionic_rx_filter_by_addr(struct ionic_lif *lif, const uint8_t *addr)
126 {
127         const uint32_t key = *(const uint32_t *)addr &
128                 IONIC_RX_FILTER_HLISTS_MASK;
129         struct ionic_rx_filter *f;
130
131         LIST_FOREACH(f, &lif->rx_filters.by_hash[key], by_hash) {
132                 if (f->cmd.match != IONIC_RX_FILTER_MATCH_MAC)
133                         continue;
134                 if (memcmp(addr, f->cmd.mac.addr, RTE_ETHER_ADDR_LEN) == 0)
135                         return f;
136         }
137
138         return NULL;
139 }