forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c
....@@ -7,6 +7,201 @@
77 #include "spectrum.h"
88 #include "spectrum_mr.h"
99
10
+struct mlxsw_sp2_mr_tcam {
11
+ struct mlxsw_sp *mlxsw_sp;
12
+ struct mlxsw_sp_flow_block *flow_block;
13
+ struct mlxsw_sp_acl_ruleset *ruleset4;
14
+ struct mlxsw_sp_acl_ruleset *ruleset6;
15
+};
16
+
17
+struct mlxsw_sp2_mr_route {
18
+ struct mlxsw_sp2_mr_tcam *mr_tcam;
19
+};
20
+
21
+static struct mlxsw_sp_acl_ruleset *
22
+mlxsw_sp2_mr_tcam_proto_ruleset(struct mlxsw_sp2_mr_tcam *mr_tcam,
23
+ enum mlxsw_sp_l3proto proto)
24
+{
25
+ switch (proto) {
26
+ case MLXSW_SP_L3_PROTO_IPV4:
27
+ return mr_tcam->ruleset4;
28
+ case MLXSW_SP_L3_PROTO_IPV6:
29
+ return mr_tcam->ruleset6;
30
+ }
31
+ return NULL;
32
+}
33
+
34
+static int mlxsw_sp2_mr_tcam_bind_group(struct mlxsw_sp *mlxsw_sp,
35
+ enum mlxsw_reg_pemrbt_protocol protocol,
36
+ struct mlxsw_sp_acl_ruleset *ruleset)
37
+{
38
+ char pemrbt_pl[MLXSW_REG_PEMRBT_LEN];
39
+ u16 group_id;
40
+
41
+ group_id = mlxsw_sp_acl_ruleset_group_id(ruleset);
42
+
43
+ mlxsw_reg_pemrbt_pack(pemrbt_pl, protocol, group_id);
44
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pemrbt), pemrbt_pl);
45
+}
46
+
47
+static const enum mlxsw_afk_element mlxsw_sp2_mr_tcam_usage_ipv4[] = {
48
+ MLXSW_AFK_ELEMENT_VIRT_ROUTER_8_10,
49
+ MLXSW_AFK_ELEMENT_VIRT_ROUTER_0_7,
50
+ MLXSW_AFK_ELEMENT_SRC_IP_0_31,
51
+ MLXSW_AFK_ELEMENT_DST_IP_0_31,
52
+};
53
+
54
+static int mlxsw_sp2_mr_tcam_ipv4_init(struct mlxsw_sp2_mr_tcam *mr_tcam)
55
+{
56
+ struct mlxsw_afk_element_usage elusage;
57
+ int err;
58
+
59
+ /* Initialize IPv4 ACL group. */
60
+ mlxsw_afk_element_usage_fill(&elusage,
61
+ mlxsw_sp2_mr_tcam_usage_ipv4,
62
+ ARRAY_SIZE(mlxsw_sp2_mr_tcam_usage_ipv4));
63
+ mr_tcam->ruleset4 = mlxsw_sp_acl_ruleset_get(mr_tcam->mlxsw_sp,
64
+ mr_tcam->flow_block,
65
+ MLXSW_SP_L3_PROTO_IPV4,
66
+ MLXSW_SP_ACL_PROFILE_MR,
67
+ &elusage);
68
+
69
+ if (IS_ERR(mr_tcam->ruleset4))
70
+ return PTR_ERR(mr_tcam->ruleset4);
71
+
72
+ /* MC Router groups should be bound before routes are inserted. */
73
+ err = mlxsw_sp2_mr_tcam_bind_group(mr_tcam->mlxsw_sp,
74
+ MLXSW_REG_PEMRBT_PROTO_IPV4,
75
+ mr_tcam->ruleset4);
76
+ if (err)
77
+ goto err_bind_group;
78
+
79
+ return 0;
80
+
81
+err_bind_group:
82
+ mlxsw_sp_acl_ruleset_put(mr_tcam->mlxsw_sp, mr_tcam->ruleset4);
83
+ return err;
84
+}
85
+
86
+static void mlxsw_sp2_mr_tcam_ipv4_fini(struct mlxsw_sp2_mr_tcam *mr_tcam)
87
+{
88
+ mlxsw_sp_acl_ruleset_put(mr_tcam->mlxsw_sp, mr_tcam->ruleset4);
89
+}
90
+
91
+static const enum mlxsw_afk_element mlxsw_sp2_mr_tcam_usage_ipv6[] = {
92
+ MLXSW_AFK_ELEMENT_VIRT_ROUTER_8_10,
93
+ MLXSW_AFK_ELEMENT_VIRT_ROUTER_0_7,
94
+ MLXSW_AFK_ELEMENT_SRC_IP_96_127,
95
+ MLXSW_AFK_ELEMENT_SRC_IP_64_95,
96
+ MLXSW_AFK_ELEMENT_SRC_IP_32_63,
97
+ MLXSW_AFK_ELEMENT_SRC_IP_0_31,
98
+ MLXSW_AFK_ELEMENT_DST_IP_96_127,
99
+ MLXSW_AFK_ELEMENT_DST_IP_64_95,
100
+ MLXSW_AFK_ELEMENT_DST_IP_32_63,
101
+ MLXSW_AFK_ELEMENT_DST_IP_0_31,
102
+};
103
+
104
+static int mlxsw_sp2_mr_tcam_ipv6_init(struct mlxsw_sp2_mr_tcam *mr_tcam)
105
+{
106
+ struct mlxsw_afk_element_usage elusage;
107
+ int err;
108
+
109
+ /* Initialize IPv6 ACL group */
110
+ mlxsw_afk_element_usage_fill(&elusage,
111
+ mlxsw_sp2_mr_tcam_usage_ipv6,
112
+ ARRAY_SIZE(mlxsw_sp2_mr_tcam_usage_ipv6));
113
+ mr_tcam->ruleset6 = mlxsw_sp_acl_ruleset_get(mr_tcam->mlxsw_sp,
114
+ mr_tcam->flow_block,
115
+ MLXSW_SP_L3_PROTO_IPV6,
116
+ MLXSW_SP_ACL_PROFILE_MR,
117
+ &elusage);
118
+
119
+ if (IS_ERR(mr_tcam->ruleset6))
120
+ return PTR_ERR(mr_tcam->ruleset6);
121
+
122
+ /* MC Router groups should be bound before routes are inserted. */
123
+ err = mlxsw_sp2_mr_tcam_bind_group(mr_tcam->mlxsw_sp,
124
+ MLXSW_REG_PEMRBT_PROTO_IPV6,
125
+ mr_tcam->ruleset6);
126
+ if (err)
127
+ goto err_bind_group;
128
+
129
+ return 0;
130
+
131
+err_bind_group:
132
+ mlxsw_sp_acl_ruleset_put(mr_tcam->mlxsw_sp, mr_tcam->ruleset6);
133
+ return err;
134
+}
135
+
136
+static void mlxsw_sp2_mr_tcam_ipv6_fini(struct mlxsw_sp2_mr_tcam *mr_tcam)
137
+{
138
+ mlxsw_sp_acl_ruleset_put(mr_tcam->mlxsw_sp, mr_tcam->ruleset6);
139
+}
140
+
141
+static void
142
+mlxsw_sp2_mr_tcam_rule_parse4(struct mlxsw_sp_acl_rule_info *rulei,
143
+ struct mlxsw_sp_mr_route_key *key)
144
+{
145
+ mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_0_31,
146
+ (char *) &key->source.addr4,
147
+ (char *) &key->source_mask.addr4, 4);
148
+ mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_0_31,
149
+ (char *) &key->group.addr4,
150
+ (char *) &key->group_mask.addr4, 4);
151
+}
152
+
153
+static void
154
+mlxsw_sp2_mr_tcam_rule_parse6(struct mlxsw_sp_acl_rule_info *rulei,
155
+ struct mlxsw_sp_mr_route_key *key)
156
+{
157
+ mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_96_127,
158
+ &key->source.addr6.s6_addr[0x0],
159
+ &key->source_mask.addr6.s6_addr[0x0], 4);
160
+ mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_64_95,
161
+ &key->source.addr6.s6_addr[0x4],
162
+ &key->source_mask.addr6.s6_addr[0x4], 4);
163
+ mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_32_63,
164
+ &key->source.addr6.s6_addr[0x8],
165
+ &key->source_mask.addr6.s6_addr[0x8], 4);
166
+ mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_0_31,
167
+ &key->source.addr6.s6_addr[0xc],
168
+ &key->source_mask.addr6.s6_addr[0xc], 4);
169
+ mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_96_127,
170
+ &key->group.addr6.s6_addr[0x0],
171
+ &key->group_mask.addr6.s6_addr[0x0], 4);
172
+ mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_64_95,
173
+ &key->group.addr6.s6_addr[0x4],
174
+ &key->group_mask.addr6.s6_addr[0x4], 4);
175
+ mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_32_63,
176
+ &key->group.addr6.s6_addr[0x8],
177
+ &key->group_mask.addr6.s6_addr[0x8], 4);
178
+ mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_0_31,
179
+ &key->group.addr6.s6_addr[0xc],
180
+ &key->group_mask.addr6.s6_addr[0xc], 4);
181
+}
182
+
183
+static void
184
+mlxsw_sp2_mr_tcam_rule_parse(struct mlxsw_sp_acl_rule *rule,
185
+ struct mlxsw_sp_mr_route_key *key,
186
+ unsigned int priority)
187
+{
188
+ struct mlxsw_sp_acl_rule_info *rulei;
189
+
190
+ rulei = mlxsw_sp_acl_rule_rulei(rule);
191
+ rulei->priority = priority;
192
+ mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_VIRT_ROUTER_0_7,
193
+ key->vrid, GENMASK(7, 0));
194
+ mlxsw_sp_acl_rulei_keymask_u32(rulei,
195
+ MLXSW_AFK_ELEMENT_VIRT_ROUTER_8_10,
196
+ key->vrid >> 8, GENMASK(2, 0));
197
+ switch (key->proto) {
198
+ case MLXSW_SP_L3_PROTO_IPV4:
199
+ return mlxsw_sp2_mr_tcam_rule_parse4(rulei, key);
200
+ case MLXSW_SP_L3_PROTO_IPV6:
201
+ return mlxsw_sp2_mr_tcam_rule_parse6(rulei, key);
202
+ }
203
+}
204
+
10205 static int
11206 mlxsw_sp2_mr_tcam_route_create(struct mlxsw_sp *mlxsw_sp, void *priv,
12207 void *route_priv,
....@@ -14,7 +209,33 @@
14209 struct mlxsw_afa_block *afa_block,
15210 enum mlxsw_sp_mr_route_prio prio)
16211 {
212
+ struct mlxsw_sp2_mr_route *mr_route = route_priv;
213
+ struct mlxsw_sp2_mr_tcam *mr_tcam = priv;
214
+ struct mlxsw_sp_acl_ruleset *ruleset;
215
+ struct mlxsw_sp_acl_rule *rule;
216
+ int err;
217
+
218
+ mr_route->mr_tcam = mr_tcam;
219
+ ruleset = mlxsw_sp2_mr_tcam_proto_ruleset(mr_tcam, key->proto);
220
+ if (WARN_ON(!ruleset))
221
+ return -EINVAL;
222
+
223
+ rule = mlxsw_sp_acl_rule_create(mlxsw_sp, ruleset,
224
+ (unsigned long) route_priv, afa_block,
225
+ NULL);
226
+ if (IS_ERR(rule))
227
+ return PTR_ERR(rule);
228
+
229
+ mlxsw_sp2_mr_tcam_rule_parse(rule, key, prio);
230
+ err = mlxsw_sp_acl_rule_add(mlxsw_sp, rule);
231
+ if (err)
232
+ goto err_rule_add;
233
+
17234 return 0;
235
+
236
+err_rule_add:
237
+ mlxsw_sp_acl_rule_destroy(mlxsw_sp, rule);
238
+ return err;
18239 }
19240
20241 static void
....@@ -22,6 +243,21 @@
22243 void *route_priv,
23244 struct mlxsw_sp_mr_route_key *key)
24245 {
246
+ struct mlxsw_sp2_mr_tcam *mr_tcam = priv;
247
+ struct mlxsw_sp_acl_ruleset *ruleset;
248
+ struct mlxsw_sp_acl_rule *rule;
249
+
250
+ ruleset = mlxsw_sp2_mr_tcam_proto_ruleset(mr_tcam, key->proto);
251
+ if (WARN_ON(!ruleset))
252
+ return;
253
+
254
+ rule = mlxsw_sp_acl_rule_lookup(mlxsw_sp, ruleset,
255
+ (unsigned long) route_priv);
256
+ if (WARN_ON(!rule))
257
+ return;
258
+
259
+ mlxsw_sp_acl_rule_del(mlxsw_sp, rule);
260
+ mlxsw_sp_acl_rule_destroy(mlxsw_sp, rule);
25261 }
26262
27263 static int
....@@ -30,21 +266,64 @@
30266 struct mlxsw_sp_mr_route_key *key,
31267 struct mlxsw_afa_block *afa_block)
32268 {
33
- return 0;
269
+ struct mlxsw_sp2_mr_route *mr_route = route_priv;
270
+ struct mlxsw_sp2_mr_tcam *mr_tcam = mr_route->mr_tcam;
271
+ struct mlxsw_sp_acl_ruleset *ruleset;
272
+ struct mlxsw_sp_acl_rule *rule;
273
+
274
+ ruleset = mlxsw_sp2_mr_tcam_proto_ruleset(mr_tcam, key->proto);
275
+ if (WARN_ON(!ruleset))
276
+ return -EINVAL;
277
+
278
+ rule = mlxsw_sp_acl_rule_lookup(mlxsw_sp, ruleset,
279
+ (unsigned long) route_priv);
280
+ if (WARN_ON(!rule))
281
+ return -EINVAL;
282
+
283
+ return mlxsw_sp_acl_rule_action_replace(mlxsw_sp, rule, afa_block);
34284 }
35285
36286 static int mlxsw_sp2_mr_tcam_init(struct mlxsw_sp *mlxsw_sp, void *priv)
37287 {
288
+ struct mlxsw_sp2_mr_tcam *mr_tcam = priv;
289
+ int err;
290
+
291
+ mr_tcam->mlxsw_sp = mlxsw_sp;
292
+ mr_tcam->flow_block = mlxsw_sp_flow_block_create(mlxsw_sp, NULL);
293
+ if (!mr_tcam->flow_block)
294
+ return -ENOMEM;
295
+
296
+ err = mlxsw_sp2_mr_tcam_ipv4_init(mr_tcam);
297
+ if (err)
298
+ goto err_ipv4_init;
299
+
300
+ err = mlxsw_sp2_mr_tcam_ipv6_init(mr_tcam);
301
+ if (err)
302
+ goto err_ipv6_init;
303
+
38304 return 0;
305
+
306
+err_ipv6_init:
307
+ mlxsw_sp2_mr_tcam_ipv4_fini(mr_tcam);
308
+err_ipv4_init:
309
+ mlxsw_sp_flow_block_destroy(mr_tcam->flow_block);
310
+ return err;
39311 }
40312
41313 static void mlxsw_sp2_mr_tcam_fini(void *priv)
42314 {
315
+ struct mlxsw_sp2_mr_tcam *mr_tcam = priv;
316
+
317
+ mlxsw_sp2_mr_tcam_ipv6_fini(mr_tcam);
318
+ mlxsw_sp2_mr_tcam_ipv4_fini(mr_tcam);
319
+ mlxsw_sp_flow_block_destroy(mr_tcam->flow_block);
43320 }
44321
45322 const struct mlxsw_sp_mr_tcam_ops mlxsw_sp2_mr_tcam_ops = {
323
+ .priv_size = sizeof(struct mlxsw_sp2_mr_tcam),
46324 .init = mlxsw_sp2_mr_tcam_init,
47325 .fini = mlxsw_sp2_mr_tcam_fini,
326
+ .route_priv_size = sizeof(struct mlxsw_sp2_mr_route),
48327 .route_create = mlxsw_sp2_mr_tcam_route_create,
49328 .route_destroy = mlxsw_sp2_mr_tcam_route_destroy,
50329 .route_update = mlxsw_sp2_mr_tcam_route_update,