xref: /openbmc/linux/net/tls/tls_toe.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
108700dabSJakub Kicinski /*
208700dabSJakub Kicinski  * Copyright (c) 2016-2017, Mellanox Technologies. All rights reserved.
308700dabSJakub Kicinski  * Copyright (c) 2016-2017, Dave Watson <davejwatson@fb.com>. All rights reserved.
408700dabSJakub Kicinski  *
508700dabSJakub Kicinski  * This software is available to you under a choice of one of two
608700dabSJakub Kicinski  * licenses.  You may choose to be licensed under the terms of the GNU
708700dabSJakub Kicinski  * General Public License (GPL) Version 2, available from the file
808700dabSJakub Kicinski  * COPYING in the main directory of this source tree, or the
908700dabSJakub Kicinski  * OpenIB.org BSD license below:
1008700dabSJakub Kicinski  *
1108700dabSJakub Kicinski  *     Redistribution and use in source and binary forms, with or
1208700dabSJakub Kicinski  *     without modification, are permitted provided that the following
1308700dabSJakub Kicinski  *     conditions are met:
1408700dabSJakub Kicinski  *
1508700dabSJakub Kicinski  *      - Redistributions of source code must retain the above
1608700dabSJakub Kicinski  *        copyright notice, this list of conditions and the following
1708700dabSJakub Kicinski  *        disclaimer.
1808700dabSJakub Kicinski  *
1908700dabSJakub Kicinski  *      - Redistributions in binary form must reproduce the above
2008700dabSJakub Kicinski  *        copyright notice, this list of conditions and the following
2108700dabSJakub Kicinski  *        disclaimer in the documentation and/or other materials
2208700dabSJakub Kicinski  *        provided with the distribution.
2308700dabSJakub Kicinski  *
2408700dabSJakub Kicinski  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2508700dabSJakub Kicinski  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2608700dabSJakub Kicinski  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2708700dabSJakub Kicinski  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
2808700dabSJakub Kicinski  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
2908700dabSJakub Kicinski  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
3008700dabSJakub Kicinski  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3108700dabSJakub Kicinski  * SOFTWARE.
3208700dabSJakub Kicinski  */
3308700dabSJakub Kicinski 
3408700dabSJakub Kicinski #include <linux/list.h>
3508700dabSJakub Kicinski #include <linux/rcupdate.h>
3608700dabSJakub Kicinski #include <linux/spinlock.h>
3708700dabSJakub Kicinski #include <net/inet_connection_sock.h>
3808700dabSJakub Kicinski #include <net/tls.h>
3908700dabSJakub Kicinski #include <net/tls_toe.h>
4008700dabSJakub Kicinski 
41*58790314SJakub Kicinski #include "tls.h"
42*58790314SJakub Kicinski 
4308700dabSJakub Kicinski static LIST_HEAD(device_list);
4408700dabSJakub Kicinski static DEFINE_SPINLOCK(device_spinlock);
4508700dabSJakub Kicinski 
tls_toe_sk_destruct(struct sock * sk)460eb8745eSJakub Kicinski static void tls_toe_sk_destruct(struct sock *sk)
4708700dabSJakub Kicinski {
4808700dabSJakub Kicinski 	struct inet_connection_sock *icsk = inet_csk(sk);
4908700dabSJakub Kicinski 	struct tls_context *ctx = tls_get_ctx(sk);
5008700dabSJakub Kicinski 
5108700dabSJakub Kicinski 	ctx->sk_destruct(sk);
5208700dabSJakub Kicinski 	/* Free ctx */
5308700dabSJakub Kicinski 	rcu_assign_pointer(icsk->icsk_ulp_data, NULL);
5408700dabSJakub Kicinski 	tls_ctx_free(sk, ctx);
5508700dabSJakub Kicinski }
5608700dabSJakub Kicinski 
tls_toe_bypass(struct sock * sk)570eb8745eSJakub Kicinski int tls_toe_bypass(struct sock *sk)
5808700dabSJakub Kicinski {
5908700dabSJakub Kicinski 	struct tls_toe_device *dev;
6008700dabSJakub Kicinski 	struct tls_context *ctx;
6108700dabSJakub Kicinski 	int rc = 0;
6208700dabSJakub Kicinski 
6308700dabSJakub Kicinski 	spin_lock_bh(&device_spinlock);
6408700dabSJakub Kicinski 	list_for_each_entry(dev, &device_list, dev_list) {
6508700dabSJakub Kicinski 		if (dev->feature && dev->feature(dev)) {
6608700dabSJakub Kicinski 			ctx = tls_ctx_create(sk);
6708700dabSJakub Kicinski 			if (!ctx)
6808700dabSJakub Kicinski 				goto out;
6908700dabSJakub Kicinski 
7008700dabSJakub Kicinski 			ctx->sk_destruct = sk->sk_destruct;
710eb8745eSJakub Kicinski 			sk->sk_destruct = tls_toe_sk_destruct;
7208700dabSJakub Kicinski 			ctx->rx_conf = TLS_HW_RECORD;
7308700dabSJakub Kicinski 			ctx->tx_conf = TLS_HW_RECORD;
7408700dabSJakub Kicinski 			update_sk_prot(sk, ctx);
7508700dabSJakub Kicinski 			rc = 1;
7608700dabSJakub Kicinski 			break;
7708700dabSJakub Kicinski 		}
7808700dabSJakub Kicinski 	}
7908700dabSJakub Kicinski out:
8008700dabSJakub Kicinski 	spin_unlock_bh(&device_spinlock);
8108700dabSJakub Kicinski 	return rc;
8208700dabSJakub Kicinski }
8308700dabSJakub Kicinski 
tls_toe_unhash(struct sock * sk)840eb8745eSJakub Kicinski void tls_toe_unhash(struct sock *sk)
8508700dabSJakub Kicinski {
8608700dabSJakub Kicinski 	struct tls_context *ctx = tls_get_ctx(sk);
8708700dabSJakub Kicinski 	struct tls_toe_device *dev;
8808700dabSJakub Kicinski 
8908700dabSJakub Kicinski 	spin_lock_bh(&device_spinlock);
9008700dabSJakub Kicinski 	list_for_each_entry(dev, &device_list, dev_list) {
9108700dabSJakub Kicinski 		if (dev->unhash) {
9208700dabSJakub Kicinski 			kref_get(&dev->kref);
9308700dabSJakub Kicinski 			spin_unlock_bh(&device_spinlock);
9408700dabSJakub Kicinski 			dev->unhash(dev, sk);
9508700dabSJakub Kicinski 			kref_put(&dev->kref, dev->release);
9608700dabSJakub Kicinski 			spin_lock_bh(&device_spinlock);
9708700dabSJakub Kicinski 		}
9808700dabSJakub Kicinski 	}
9908700dabSJakub Kicinski 	spin_unlock_bh(&device_spinlock);
10008700dabSJakub Kicinski 	ctx->sk_proto->unhash(sk);
10108700dabSJakub Kicinski }
10208700dabSJakub Kicinski 
tls_toe_hash(struct sock * sk)1030eb8745eSJakub Kicinski int tls_toe_hash(struct sock *sk)
10408700dabSJakub Kicinski {
10508700dabSJakub Kicinski 	struct tls_context *ctx = tls_get_ctx(sk);
10608700dabSJakub Kicinski 	struct tls_toe_device *dev;
10708700dabSJakub Kicinski 	int err;
10808700dabSJakub Kicinski 
10908700dabSJakub Kicinski 	err = ctx->sk_proto->hash(sk);
11008700dabSJakub Kicinski 	spin_lock_bh(&device_spinlock);
11108700dabSJakub Kicinski 	list_for_each_entry(dev, &device_list, dev_list) {
11208700dabSJakub Kicinski 		if (dev->hash) {
11308700dabSJakub Kicinski 			kref_get(&dev->kref);
11408700dabSJakub Kicinski 			spin_unlock_bh(&device_spinlock);
11508700dabSJakub Kicinski 			err |= dev->hash(dev, sk);
11608700dabSJakub Kicinski 			kref_put(&dev->kref, dev->release);
11708700dabSJakub Kicinski 			spin_lock_bh(&device_spinlock);
11808700dabSJakub Kicinski 		}
11908700dabSJakub Kicinski 	}
12008700dabSJakub Kicinski 	spin_unlock_bh(&device_spinlock);
12108700dabSJakub Kicinski 
12208700dabSJakub Kicinski 	if (err)
1230eb8745eSJakub Kicinski 		tls_toe_unhash(sk);
12408700dabSJakub Kicinski 	return err;
12508700dabSJakub Kicinski }
12608700dabSJakub Kicinski 
tls_toe_register_device(struct tls_toe_device * device)12708700dabSJakub Kicinski void tls_toe_register_device(struct tls_toe_device *device)
12808700dabSJakub Kicinski {
12908700dabSJakub Kicinski 	spin_lock_bh(&device_spinlock);
13008700dabSJakub Kicinski 	list_add_tail(&device->dev_list, &device_list);
13108700dabSJakub Kicinski 	spin_unlock_bh(&device_spinlock);
13208700dabSJakub Kicinski }
13308700dabSJakub Kicinski EXPORT_SYMBOL(tls_toe_register_device);
13408700dabSJakub Kicinski 
tls_toe_unregister_device(struct tls_toe_device * device)13508700dabSJakub Kicinski void tls_toe_unregister_device(struct tls_toe_device *device)
13608700dabSJakub Kicinski {
13708700dabSJakub Kicinski 	spin_lock_bh(&device_spinlock);
13808700dabSJakub Kicinski 	list_del(&device->dev_list);
13908700dabSJakub Kicinski 	spin_unlock_bh(&device_spinlock);
14008700dabSJakub Kicinski }
14108700dabSJakub Kicinski EXPORT_SYMBOL(tls_toe_unregister_device);
142