]> Git Repo - J-linux.git/blob - drivers/infiniband/hw/mlx5/macsec.c
Merge tag 'kbuild-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy...
[J-linux.git] / drivers / infiniband / hw / mlx5 / macsec.c
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. */
3
4 #include "macsec.h"
5 #include <linux/mlx5/macsec.h>
6
7 struct mlx5_reserved_gids {
8         int macsec_index;
9         const struct ib_gid_attr *physical_gid;
10 };
11
12 struct mlx5_roce_gids {
13         struct list_head roce_gid_list_entry;
14         u16 gid_idx;
15         union {
16                 struct sockaddr_in  sockaddr_in;
17                 struct sockaddr_in6 sockaddr_in6;
18         } addr;
19 };
20
21 struct mlx5_macsec_device {
22         struct list_head macsec_devices_list_entry;
23         void *macdev;
24         struct list_head macsec_roce_gids;
25         struct list_head tx_rules_list;
26         struct list_head rx_rules_list;
27 };
28
29 static void cleanup_macsec_device(struct mlx5_macsec_device *macsec_device)
30 {
31         if (!list_empty(&macsec_device->tx_rules_list) ||
32             !list_empty(&macsec_device->rx_rules_list) ||
33             !list_empty(&macsec_device->macsec_roce_gids))
34                 return;
35
36         list_del(&macsec_device->macsec_devices_list_entry);
37         kfree(macsec_device);
38 }
39
40 static struct mlx5_macsec_device *get_macsec_device(void *macdev,
41                                                     struct list_head *macsec_devices_list)
42 {
43         struct mlx5_macsec_device *iter, *macsec_device = NULL;
44
45         list_for_each_entry(iter, macsec_devices_list, macsec_devices_list_entry) {
46                 if (iter->macdev == macdev) {
47                         macsec_device = iter;
48                         break;
49                 }
50         }
51
52         if (macsec_device)
53                 return macsec_device;
54
55         macsec_device = kzalloc(sizeof(*macsec_device), GFP_KERNEL);
56         if (!macsec_device)
57                 return NULL;
58
59         macsec_device->macdev = macdev;
60         INIT_LIST_HEAD(&macsec_device->tx_rules_list);
61         INIT_LIST_HEAD(&macsec_device->rx_rules_list);
62         INIT_LIST_HEAD(&macsec_device->macsec_roce_gids);
63         list_add(&macsec_device->macsec_devices_list_entry, macsec_devices_list);
64
65         return macsec_device;
66 }
67
68 static void mlx5_macsec_del_roce_gid(struct mlx5_macsec_device *macsec_device, u16 gid_idx)
69 {
70         struct mlx5_roce_gids *current_gid, *next_gid;
71
72         list_for_each_entry_safe(current_gid, next_gid, &macsec_device->macsec_roce_gids,
73                                  roce_gid_list_entry)
74                 if (current_gid->gid_idx == gid_idx) {
75                         list_del(&current_gid->roce_gid_list_entry);
76                         kfree(current_gid);
77                 }
78 }
79
80 static void mlx5_macsec_save_roce_gid(struct mlx5_macsec_device *macsec_device,
81                                       const struct sockaddr *addr, u16 gid_idx)
82 {
83         struct mlx5_roce_gids *roce_gids;
84
85         roce_gids = kzalloc(sizeof(*roce_gids), GFP_KERNEL);
86         if (!roce_gids)
87                 return;
88
89         roce_gids->gid_idx = gid_idx;
90         if (addr->sa_family == AF_INET)
91                 memcpy(&roce_gids->addr.sockaddr_in, addr, sizeof(roce_gids->addr.sockaddr_in));
92         else
93                 memcpy(&roce_gids->addr.sockaddr_in6, addr, sizeof(roce_gids->addr.sockaddr_in6));
94
95         list_add_tail(&roce_gids->roce_gid_list_entry, &macsec_device->macsec_roce_gids);
96 }
97
98 static void handle_macsec_gids(struct list_head *macsec_devices_list,
99                                struct mlx5_macsec_event_data *data)
100 {
101         struct mlx5_macsec_device *macsec_device;
102         struct mlx5_roce_gids *gid;
103
104         macsec_device = get_macsec_device(data->macdev, macsec_devices_list);
105         if (!macsec_device)
106                 return;
107
108         list_for_each_entry(gid, &macsec_device->macsec_roce_gids, roce_gid_list_entry) {
109                 mlx5_macsec_add_roce_sa_rules(data->fs_id, (struct sockaddr *)&gid->addr,
110                                               gid->gid_idx, &macsec_device->tx_rules_list,
111                                               &macsec_device->rx_rules_list, data->macsec_fs,
112                                               data->is_tx);
113         }
114 }
115
116 static void del_sa_roce_rule(struct list_head *macsec_devices_list,
117                              struct mlx5_macsec_event_data *data)
118 {
119         struct mlx5_macsec_device *macsec_device;
120
121         macsec_device = get_macsec_device(data->macdev, macsec_devices_list);
122         WARN_ON(!macsec_device);
123
124         mlx5_macsec_del_roce_sa_rules(data->fs_id, data->macsec_fs,
125                                       &macsec_device->tx_rules_list,
126                                       &macsec_device->rx_rules_list, data->is_tx);
127 }
128
129 static int macsec_event(struct notifier_block *nb, unsigned long event, void *data)
130 {
131         struct mlx5_macsec *macsec = container_of(nb, struct mlx5_macsec, blocking_events_nb);
132
133         mutex_lock(&macsec->lock);
134         switch (event) {
135         case MLX5_DRIVER_EVENT_MACSEC_SA_ADDED:
136                 handle_macsec_gids(&macsec->macsec_devices_list, data);
137                 break;
138         case MLX5_DRIVER_EVENT_MACSEC_SA_DELETED:
139                 del_sa_roce_rule(&macsec->macsec_devices_list, data);
140                 break;
141         default:
142                 mutex_unlock(&macsec->lock);
143                 return NOTIFY_DONE;
144         }
145         mutex_unlock(&macsec->lock);
146         return NOTIFY_OK;
147 }
148
149 void mlx5r_macsec_event_register(struct mlx5_ib_dev *dev)
150 {
151         if (!mlx5_is_macsec_roce_supported(dev->mdev)) {
152                 mlx5_ib_dbg(dev, "RoCE MACsec not supported due to capabilities\n");
153                 return;
154         }
155
156         dev->macsec.blocking_events_nb.notifier_call = macsec_event;
157         blocking_notifier_chain_register(&dev->mdev->macsec_nh,
158                                          &dev->macsec.blocking_events_nb);
159 }
160
161 void mlx5r_macsec_event_unregister(struct mlx5_ib_dev *dev)
162 {
163         if (!mlx5_is_macsec_roce_supported(dev->mdev)) {
164                 mlx5_ib_dbg(dev, "RoCE MACsec not supported due to capabilities\n");
165                 return;
166         }
167
168         blocking_notifier_chain_unregister(&dev->mdev->macsec_nh,
169                                            &dev->macsec.blocking_events_nb);
170 }
171
172 int mlx5r_macsec_init_gids_and_devlist(struct mlx5_ib_dev *dev)
173 {
174         int i, j, max_gids;
175
176         if (!mlx5_is_macsec_roce_supported(dev->mdev)) {
177                 mlx5_ib_dbg(dev, "RoCE MACsec not supported due to capabilities\n");
178                 return 0;
179         }
180
181         max_gids = MLX5_CAP_ROCE(dev->mdev, roce_address_table_size);
182         for (i = 0; i < dev->num_ports; i++) {
183                 dev->port[i].reserved_gids = kcalloc(max_gids,
184                                                      sizeof(*dev->port[i].reserved_gids),
185                                                      GFP_KERNEL);
186                 if (!dev->port[i].reserved_gids)
187                         goto err;
188
189                 for (j = 0; j < max_gids; j++)
190                         dev->port[i].reserved_gids[j].macsec_index = -1;
191         }
192
193         INIT_LIST_HEAD(&dev->macsec.macsec_devices_list);
194         mutex_init(&dev->macsec.lock);
195
196         return 0;
197 err:
198         while (i >= 0) {
199                 kfree(dev->port[i].reserved_gids);
200                 i--;
201         }
202         return -ENOMEM;
203 }
204
205 void mlx5r_macsec_dealloc_gids(struct mlx5_ib_dev *dev)
206 {
207         int i;
208
209         if (!mlx5_is_macsec_roce_supported(dev->mdev))
210                 mlx5_ib_dbg(dev, "RoCE MACsec not supported due to capabilities\n");
211
212         for (i = 0; i < dev->num_ports; i++)
213                 kfree(dev->port[i].reserved_gids);
214
215         mutex_destroy(&dev->macsec.lock);
216 }
217
218 int mlx5r_add_gid_macsec_operations(const struct ib_gid_attr *attr)
219 {
220         struct mlx5_ib_dev *dev = to_mdev(attr->device);
221         struct mlx5_macsec_device *macsec_device;
222         const struct ib_gid_attr *physical_gid;
223         struct mlx5_reserved_gids *mgids;
224         struct net_device *ndev;
225         int ret = 0;
226         union {
227                 struct sockaddr_in  sockaddr_in;
228                 struct sockaddr_in6 sockaddr_in6;
229         } addr;
230
231         if (attr->gid_type != IB_GID_TYPE_ROCE_UDP_ENCAP)
232                 return 0;
233
234         if (!mlx5_is_macsec_roce_supported(dev->mdev)) {
235                 mlx5_ib_dbg(dev, "RoCE MACsec not supported due to capabilities\n");
236                 return 0;
237         }
238
239         rcu_read_lock();
240         ndev = rcu_dereference(attr->ndev);
241         if (!ndev) {
242                 rcu_read_unlock();
243                 return -ENODEV;
244         }
245
246         if (!netif_is_macsec(ndev) || !macsec_netdev_is_offloaded(ndev)) {
247                 rcu_read_unlock();
248                 return 0;
249         }
250         dev_hold(ndev);
251         rcu_read_unlock();
252
253         mutex_lock(&dev->macsec.lock);
254         macsec_device = get_macsec_device(ndev, &dev->macsec.macsec_devices_list);
255         if (!macsec_device) {
256                 ret = -ENOMEM;
257                 goto dev_err;
258         }
259
260         physical_gid = rdma_find_gid(attr->device, &attr->gid,
261                                      attr->gid_type, NULL);
262         if (!IS_ERR(physical_gid)) {
263                 ret = set_roce_addr(to_mdev(physical_gid->device),
264                                     physical_gid->port_num,
265                                     physical_gid->index, NULL,
266                                     physical_gid);
267                 if (ret)
268                         goto gid_err;
269
270                 mgids = &dev->port[attr->port_num - 1].reserved_gids[physical_gid->index];
271                 mgids->macsec_index = attr->index;
272                 mgids->physical_gid = physical_gid;
273         }
274
275         /* Proceed with adding steering rules, regardless if there was gid ambiguity or not.*/
276         rdma_gid2ip((struct sockaddr *)&addr, &attr->gid);
277         ret = mlx5_macsec_add_roce_rule(ndev, (struct sockaddr *)&addr, attr->index,
278                                         &macsec_device->tx_rules_list,
279                                         &macsec_device->rx_rules_list, dev->mdev->macsec_fs);
280         if (ret && !IS_ERR(physical_gid))
281                 goto rule_err;
282
283         mlx5_macsec_save_roce_gid(macsec_device, (struct sockaddr *)&addr, attr->index);
284
285         dev_put(ndev);
286         mutex_unlock(&dev->macsec.lock);
287         return ret;
288
289 rule_err:
290         set_roce_addr(to_mdev(physical_gid->device), physical_gid->port_num,
291                       physical_gid->index, &physical_gid->gid, physical_gid);
292         mgids->macsec_index = -1;
293 gid_err:
294         rdma_put_gid_attr(physical_gid);
295         cleanup_macsec_device(macsec_device);
296 dev_err:
297         dev_put(ndev);
298         mutex_unlock(&dev->macsec.lock);
299         return ret;
300 }
301
302 void mlx5r_del_gid_macsec_operations(const struct ib_gid_attr *attr)
303 {
304         struct mlx5_ib_dev *dev = to_mdev(attr->device);
305         struct mlx5_macsec_device *macsec_device;
306         struct mlx5_reserved_gids *mgids;
307         struct net_device *ndev;
308         int i, max_gids;
309
310         if (attr->gid_type != IB_GID_TYPE_ROCE_UDP_ENCAP)
311                 return;
312
313         if (!mlx5_is_macsec_roce_supported(dev->mdev)) {
314                 mlx5_ib_dbg(dev, "RoCE MACsec not supported due to capabilities\n");
315                 return;
316         }
317
318         mgids = &dev->port[attr->port_num - 1].reserved_gids[attr->index];
319         if (mgids->macsec_index != -1) { /* Checking if physical gid has ambiguous IP */
320                 rdma_put_gid_attr(mgids->physical_gid);
321                 mgids->macsec_index = -1;
322                 return;
323         }
324
325         rcu_read_lock();
326         ndev = rcu_dereference(attr->ndev);
327         if (!ndev) {
328                 rcu_read_unlock();
329                 return;
330         }
331
332         if (!netif_is_macsec(ndev) || !macsec_netdev_is_offloaded(ndev)) {
333                 rcu_read_unlock();
334                 return;
335         }
336         dev_hold(ndev);
337         rcu_read_unlock();
338
339         mutex_lock(&dev->macsec.lock);
340         max_gids = MLX5_CAP_ROCE(dev->mdev, roce_address_table_size);
341         for (i = 0; i < max_gids; i++) { /* Checking if macsec gid has ambiguous IP */
342                 mgids = &dev->port[attr->port_num - 1].reserved_gids[i];
343                 if (mgids->macsec_index == attr->index) {
344                         const struct ib_gid_attr *physical_gid = mgids->physical_gid;
345
346                         set_roce_addr(to_mdev(physical_gid->device),
347                                       physical_gid->port_num,
348                                       physical_gid->index,
349                                       &physical_gid->gid, physical_gid);
350
351                         rdma_put_gid_attr(physical_gid);
352                         mgids->macsec_index = -1;
353                         break;
354                 }
355         }
356         macsec_device = get_macsec_device(ndev, &dev->macsec.macsec_devices_list);
357         mlx5_macsec_del_roce_rule(attr->index, dev->mdev->macsec_fs,
358                                   &macsec_device->tx_rules_list, &macsec_device->rx_rules_list);
359         mlx5_macsec_del_roce_gid(macsec_device, attr->index);
360         cleanup_macsec_device(macsec_device);
361
362         dev_put(ndev);
363         mutex_unlock(&dev->macsec.lock);
364 }
This page took 0.046415 seconds and 4 git commands to generate.