42200c3f7e9280d609608790bb5ea4e79a573769
[dpdk.git] / drivers / net / sfc / sfc_mae.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2019-2020 Xilinx, Inc.
4  * Copyright(c) 2019 Solarflare Communications Inc.
5  *
6  * This software was jointly developed between OKTET Labs (under contract
7  * for Solarflare) and Solarflare Communications, Inc.
8  */
9
10 #include <stdbool.h>
11
12 #include <rte_common.h>
13
14 #include "efx.h"
15
16 #include "sfc.h"
17 #include "sfc_log.h"
18
19 int
20 sfc_mae_attach(struct sfc_adapter *sa)
21 {
22         const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
23         struct sfc_mae *mae = &sa->mae;
24         efx_mae_limits_t limits;
25         int rc;
26
27         sfc_log_init(sa, "entry");
28
29         if (!encp->enc_mae_supported) {
30                 mae->status = SFC_MAE_STATUS_UNSUPPORTED;
31                 return 0;
32         }
33
34         sfc_log_init(sa, "init MAE");
35         rc = efx_mae_init(sa->nic);
36         if (rc != 0)
37                 goto fail_mae_init;
38
39         sfc_log_init(sa, "get MAE limits");
40         rc = efx_mae_get_limits(sa->nic, &limits);
41         if (rc != 0)
42                 goto fail_mae_get_limits;
43
44         mae->status = SFC_MAE_STATUS_SUPPORTED;
45         mae->nb_action_rule_prios_max = limits.eml_max_n_action_prios;
46
47         sfc_log_init(sa, "done");
48
49         return 0;
50
51 fail_mae_get_limits:
52         efx_mae_fini(sa->nic);
53
54 fail_mae_init:
55         sfc_log_init(sa, "failed %d", rc);
56
57         return rc;
58 }
59
60 void
61 sfc_mae_detach(struct sfc_adapter *sa)
62 {
63         struct sfc_mae *mae = &sa->mae;
64         enum sfc_mae_status status_prev = mae->status;
65
66         sfc_log_init(sa, "entry");
67
68         mae->nb_action_rule_prios_max = 0;
69         mae->status = SFC_MAE_STATUS_UNKNOWN;
70
71         if (status_prev != SFC_MAE_STATUS_SUPPORTED)
72                 return;
73
74         efx_mae_fini(sa->nic);
75
76         sfc_log_init(sa, "done");
77 }
78
79 void
80 sfc_mae_flow_cleanup(struct sfc_adapter *sa,
81                      struct rte_flow *flow)
82 {
83         struct sfc_flow_spec *spec;
84         struct sfc_flow_spec_mae *spec_mae;
85
86         if (flow == NULL)
87                 return;
88
89         spec = &flow->spec;
90
91         if (spec == NULL)
92                 return;
93
94         spec_mae = &spec->mae;
95
96         if (spec_mae->match_spec != NULL)
97                 efx_mae_match_spec_fini(sa->nic, spec_mae->match_spec);
98 }
99
100 static const struct sfc_flow_item sfc_flow_items[] = {
101 };
102
103 int
104 sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
105                            const struct rte_flow_item pattern[],
106                            struct sfc_flow_spec_mae *spec,
107                            struct rte_flow_error *error)
108 {
109         struct sfc_mae_parse_ctx ctx_mae;
110         struct sfc_flow_parse_ctx ctx;
111         int rc;
112
113         memset(&ctx_mae, 0, sizeof(ctx_mae));
114
115         rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION,
116                                      spec->priority,
117                                      &ctx_mae.match_spec_action);
118         if (rc != 0) {
119                 rc = rte_flow_error_set(error, rc,
120                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
121                         "Failed to initialise action rule match specification");
122                 goto fail_init_match_spec_action;
123         }
124
125         ctx.type = SFC_FLOW_PARSE_CTX_MAE;
126         ctx.mae = &ctx_mae;
127
128         rc = sfc_flow_parse_pattern(sfc_flow_items, RTE_DIM(sfc_flow_items),
129                                     pattern, &ctx, error);
130         if (rc != 0)
131                 goto fail_parse_pattern;
132
133         if (!efx_mae_match_spec_is_valid(sa->nic, ctx_mae.match_spec_action)) {
134                 rc = rte_flow_error_set(error, ENOTSUP,
135                                         RTE_FLOW_ERROR_TYPE_ITEM, NULL,
136                                         "Inconsistent pattern");
137                 goto fail_validate_match_spec_action;
138         }
139
140         spec->match_spec = ctx_mae.match_spec_action;
141
142         return 0;
143
144 fail_validate_match_spec_action:
145 fail_parse_pattern:
146         efx_mae_match_spec_fini(sa->nic, ctx_mae.match_spec_action);
147
148 fail_init_match_spec_action:
149         return rc;
150 }
151
152 static bool
153 sfc_mae_rules_class_cmp(struct sfc_adapter *sa,
154                         const efx_mae_match_spec_t *left,
155                         const efx_mae_match_spec_t *right)
156 {
157         bool have_same_class;
158         int rc;
159
160         rc = efx_mae_match_specs_class_cmp(sa->nic, left, right,
161                                            &have_same_class);
162
163         return (rc == 0) ? have_same_class : false;
164 }
165
166 static int
167 sfc_mae_action_rule_class_verify(struct sfc_adapter *sa,
168                                  struct sfc_flow_spec_mae *spec)
169 {
170         const struct rte_flow *entry;
171
172         TAILQ_FOREACH_REVERSE(entry, &sa->flow_list, sfc_flow_list, entries) {
173                 const struct sfc_flow_spec *entry_spec = &entry->spec;
174                 const struct sfc_flow_spec_mae *es_mae = &entry_spec->mae;
175                 const efx_mae_match_spec_t *left = es_mae->match_spec;
176                 const efx_mae_match_spec_t *right = spec->match_spec;
177
178                 switch (entry_spec->type) {
179                 case SFC_FLOW_SPEC_FILTER:
180                         /* Ignore VNIC-level flows */
181                         break;
182                 case SFC_FLOW_SPEC_MAE:
183                         if (sfc_mae_rules_class_cmp(sa, left, right))
184                                 return 0;
185                         break;
186                 default:
187                         SFC_ASSERT(false);
188                 }
189         }
190
191         sfc_info(sa, "for now, the HW doesn't support rule validation, and HW "
192                  "support for inner frame pattern items is not guaranteed; "
193                  "other than that, the items are valid from SW standpoint");
194         return 0;
195 }
196
197 /**
198  * Confirm that a given flow can be accepted by the FW.
199  *
200  * @param sa
201  *   Software adapter context
202  * @param flow
203  *   Flow to be verified
204  * @return
205  *   Zero on success and non-zero in the case of error.
206  *   A special value of EAGAIN indicates that the adapter is
207  *   not in started state. This state is compulsory because
208  *   it only makes sense to compare the rule class of the flow
209  *   being validated with classes of the active rules.
210  *   Such classes are wittingly supported by the FW.
211  */
212 int
213 sfc_mae_flow_verify(struct sfc_adapter *sa,
214                     struct rte_flow *flow)
215 {
216         struct sfc_flow_spec *spec = &flow->spec;
217         struct sfc_flow_spec_mae *spec_mae = &spec->mae;
218
219         SFC_ASSERT(sfc_adapter_is_locked(sa));
220
221         if (sa->state != SFC_ADAPTER_STARTED)
222                 return EAGAIN;
223
224         return sfc_mae_action_rule_class_verify(sa, spec_mae);
225 }