brintos

brintos / linux-shallow public Read only

0
0
Text · 9.8 KiB · 3c56eb5 Raw
365 lines · c
1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB2/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. */3 4#include "macsec.h"5#include <linux/mlx5/macsec.h>6 7struct mlx5_reserved_gids {8	int macsec_index;9	const struct ib_gid_attr *physical_gid;10};11 12struct 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 21struct 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 29static 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 40static 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 68static 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 80static 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	else93		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 98static 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 116static 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 129static 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 149void 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 161void 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 172int 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;197err:198	while (i >= 0) {199		kfree(dev->port[i].reserved_gids);200		i--;201	}202	return -ENOMEM;203}204 205void 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 218int 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 289rule_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;293gid_err:294	rdma_put_gid_attr(physical_gid);295	cleanup_macsec_device(macsec_device);296dev_err:297	dev_put(ndev);298	mutex_unlock(&dev->macsec.lock);299	return ret;300}301 302void 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}365