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
ionic_rx_filter_free(struct ionic_rx_filter * f)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
ionic_rx_filters_init(struct ionic_lif * lif)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
ionic_rx_filters_deinit(struct ionic_lif * lif)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
ionic_rx_filter_save(struct ionic_lif * lif,uint32_t flow_id,uint16_t rxq_index,struct ionic_admin_ctx * ctx)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 *
ionic_rx_filter_by_vlan(struct ionic_lif * lif,uint16_t vid)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 *
ionic_rx_filter_by_addr(struct ionic_lif * lif,const uint8_t * addr)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 }
128