Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2018 Chelsio Communications.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "base/common.h"
7 : : #include "clip_tbl.h"
8 : :
9 : : /**
10 : : * Allocate clip entry in HW with associated IPV4/IPv6 address
11 : : */
12 : 0 : static int clip6_get_mbox(const struct rte_eth_dev *dev, const u32 *lip)
13 : : {
14 : : struct adapter *adap = ethdev2adap(dev);
15 : : struct fw_clip_cmd c;
16 : 0 : u64 hi = ((u64)lip[1]) << 32 | lip[0];
17 : 0 : u64 lo = ((u64)lip[3]) << 32 | lip[2];
18 : :
19 : : memset(&c, 0, sizeof(c));
20 : 0 : c.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_CLIP_CMD) |
21 : : F_FW_CMD_REQUEST | F_FW_CMD_WRITE);
22 : 0 : c.alloc_to_len16 = cpu_to_be32(F_FW_CLIP_CMD_ALLOC | FW_LEN16(c));
23 : 0 : c.ip_hi = hi;
24 : 0 : c.ip_lo = lo;
25 : 0 : return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, false);
26 : : }
27 : :
28 : : /**
29 : : * Delete clip entry in HW having the associated IPV4/IPV6 address
30 : : */
31 : 0 : static int clip6_release_mbox(const struct rte_eth_dev *dev, const u32 *lip)
32 : : {
33 : : struct adapter *adap = ethdev2adap(dev);
34 : : struct fw_clip_cmd c;
35 : 0 : u64 hi = ((u64)lip[1]) << 32 | lip[0];
36 : 0 : u64 lo = ((u64)lip[3]) << 32 | lip[2];
37 : :
38 : : memset(&c, 0, sizeof(c));
39 : 0 : c.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_CLIP_CMD) |
40 : : F_FW_CMD_REQUEST | F_FW_CMD_READ);
41 : 0 : c.alloc_to_len16 = cpu_to_be32(F_FW_CLIP_CMD_FREE | FW_LEN16(c));
42 : 0 : c.ip_hi = hi;
43 : 0 : c.ip_lo = lo;
44 : 0 : return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, false);
45 : : }
46 : :
47 : : /**
48 : : * cxgbe_clip_release - Release associated CLIP entry
49 : : * @ce: clip entry to release
50 : : *
51 : : * Releases ref count and frees up a clip entry from CLIP table
52 : : */
53 : 0 : void cxgbe_clip_release(struct rte_eth_dev *dev, struct clip_entry *ce)
54 : : {
55 : : int ret;
56 : :
57 : 0 : t4_os_lock(&ce->lock);
58 [ # # ]: 0 : if (rte_atomic_fetch_sub_explicit(&ce->refcnt, 1, rte_memory_order_relaxed) - 1 == 0) {
59 : 0 : ret = clip6_release_mbox(dev, ce->addr);
60 [ # # ]: 0 : if (ret)
61 : 0 : dev_debug(adap, "CLIP FW DEL CMD failed: %d", ret);
62 : : }
63 : : t4_os_unlock(&ce->lock);
64 : 0 : }
65 : :
66 : : /**
67 : : * find_or_alloc_clipe - Find/Allocate a free CLIP entry
68 : : * @c: CLIP table
69 : : * @lip: IPV4/IPV6 address to compare/add
70 : : * Returns pointer to the IPV4/IPV6 entry found/created
71 : : *
72 : : * Finds/Allocates an CLIP entry to be used for a filter rule.
73 : : */
74 : 0 : static struct clip_entry *find_or_alloc_clipe(struct clip_tbl *c,
75 : : const u32 *lip)
76 : : {
77 : : struct clip_entry *end, *e;
78 : : struct clip_entry *first_free = NULL;
79 : 0 : unsigned int clipt_size = c->clipt_size;
80 : :
81 [ # # ]: 0 : for (e = &c->cl_list[0], end = &c->cl_list[clipt_size]; e != end; ++e) {
82 [ # # ]: 0 : if (rte_atomic_load_explicit(&e->refcnt, rte_memory_order_relaxed) == 0) {
83 [ # # ]: 0 : if (!first_free)
84 : : first_free = e;
85 : : } else {
86 [ # # ]: 0 : if (memcmp(lip, e->addr, sizeof(e->addr)) == 0)
87 : 0 : goto exists;
88 : : }
89 : : }
90 : :
91 [ # # ]: 0 : if (first_free) {
92 : : e = first_free;
93 : 0 : goto exists;
94 : : }
95 : :
96 : : return NULL;
97 : :
98 : : exists:
99 : : return e;
100 : : }
101 : :
102 [ # # ]: 0 : static struct clip_entry *t4_clip_alloc(struct rte_eth_dev *dev,
103 : : u32 *lip, u8 v6)
104 : : {
105 : : struct adapter *adap = ethdev2adap(dev);
106 : 0 : struct clip_tbl *ctbl = adap->clipt;
107 : : struct clip_entry *ce;
108 : : int ret = 0;
109 : :
110 [ # # ]: 0 : if (!ctbl)
111 : : return NULL;
112 : :
113 : 0 : t4_os_write_lock(&ctbl->lock);
114 : 0 : ce = find_or_alloc_clipe(ctbl, lip);
115 [ # # ]: 0 : if (ce) {
116 : 0 : t4_os_lock(&ce->lock);
117 [ # # ]: 0 : if (rte_atomic_load_explicit(&ce->refcnt, rte_memory_order_relaxed) == 0) {
118 [ # # ]: 0 : rte_memcpy(ce->addr, lip, sizeof(ce->addr));
119 [ # # ]: 0 : if (v6) {
120 : 0 : ce->type = FILTER_TYPE_IPV6;
121 : 0 : rte_atomic_store_explicit(&ce->refcnt, 1,
122 : : rte_memory_order_relaxed);
123 : 0 : ret = clip6_get_mbox(dev, lip);
124 [ # # ]: 0 : if (ret)
125 : 0 : dev_debug(adap,
126 : : "CLIP FW ADD CMD failed: %d",
127 : : ret);
128 : : } else {
129 : 0 : ce->type = FILTER_TYPE_IPV4;
130 : : }
131 : : } else {
132 : 0 : rte_atomic_fetch_add_explicit(&ce->refcnt, 1, rte_memory_order_relaxed);
133 : : }
134 : : t4_os_unlock(&ce->lock);
135 : : }
136 : : t4_os_write_unlock(&ctbl->lock);
137 : :
138 [ # # ]: 0 : return ret ? NULL : ce;
139 : : }
140 : :
141 : : /**
142 : : * cxgbe_clip_alloc - Allocate a IPV6 CLIP entry
143 : : * @dev: rte_eth_dev pointer
144 : : * @lip: IPV6 address to add
145 : : * Returns pointer to the CLIP entry created
146 : : *
147 : : * Allocates a IPV6 CLIP entry to be used for a filter rule.
148 : : */
149 : 0 : struct clip_entry *cxgbe_clip_alloc(struct rte_eth_dev *dev, u32 *lip)
150 : : {
151 : 0 : return t4_clip_alloc(dev, lip, FILTER_TYPE_IPV6);
152 : : }
153 : :
154 : : /**
155 : : * Initialize CLIP Table
156 : : */
157 : 0 : struct clip_tbl *t4_init_clip_tbl(unsigned int clipt_start,
158 : : unsigned int clipt_end)
159 : : {
160 : : unsigned int clipt_size;
161 : : struct clip_tbl *ctbl;
162 : : unsigned int i;
163 : :
164 [ # # ]: 0 : if (clipt_start >= clipt_end)
165 : : return NULL;
166 : :
167 : 0 : clipt_size = clipt_end - clipt_start + 1;
168 : :
169 : 0 : ctbl = t4_os_alloc(sizeof(*ctbl) +
170 : : clipt_size * sizeof(struct clip_entry));
171 [ # # ]: 0 : if (!ctbl)
172 : : return NULL;
173 : :
174 : 0 : ctbl->clipt_start = clipt_start;
175 : 0 : ctbl->clipt_size = clipt_size;
176 : :
177 : : t4_os_rwlock_init(&ctbl->lock);
178 : :
179 [ # # ]: 0 : for (i = 0; i < ctbl->clipt_size; i++) {
180 : : t4_os_lock_init(&ctbl->cl_list[i].lock);
181 : 0 : ctbl->cl_list[i].refcnt = 0;
182 : : }
183 : :
184 : : return ctbl;
185 : : }
186 : :
187 : : /**
188 : : * Cleanup CLIP Table
189 : : */
190 : 0 : void t4_cleanup_clip_tbl(struct adapter *adap)
191 : : {
192 [ # # ]: 0 : if (adap->clipt)
193 : 0 : t4_os_free(adap->clipt);
194 : 0 : }
|