1 /* 2 * Copyright (c) 2016-2017, Mellanox Technologies. All rights reserved. 3 * Copyright (c) 2016-2017, Dave Watson <davejwatson@fb.com>. All rights reserved. 4 * 5 * This software is available to you under a choice of one of two 6 * licenses. You may choose to be licensed under the terms of the GNU 7 * General Public License (GPL) Version 2, available from the file 8 * COPYING in the main directory of this source tree, or the 9 * OpenIB.org BSD license below: 10 * 11 * Redistribution and use in source and binary forms, with or 12 * without modification, are permitted provided that the following 13 * conditions are met: 14 * 15 * - Redistributions of source code must retain the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer. 18 * 19 * - Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials 22 * provided with the distribution. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 * SOFTWARE. 32 */ 33 34 #include <linux/list.h> 35 #include <linux/rcupdate.h> 36 #include <linux/spinlock.h> 37 #include <net/inet_connection_sock.h> 38 #include <net/tls.h> 39 #include <net/tls_toe.h> 40 41 static LIST_HEAD(device_list); 42 static DEFINE_SPINLOCK(device_spinlock); 43 44 static void tls_toe_sk_destruct(struct sock *sk) 45 { 46 struct inet_connection_sock *icsk = inet_csk(sk); 47 struct tls_context *ctx = tls_get_ctx(sk); 48 49 ctx->sk_destruct(sk); 50 /* Free ctx */ 51 rcu_assign_pointer(icsk->icsk_ulp_data, NULL); 52 tls_ctx_free(sk, ctx); 53 } 54 55 int tls_toe_bypass(struct sock *sk) 56 { 57 struct tls_toe_device *dev; 58 struct tls_context *ctx; 59 int rc = 0; 60 61 spin_lock_bh(&device_spinlock); 62 list_for_each_entry(dev, &device_list, dev_list) { 63 if (dev->feature && dev->feature(dev)) { 64 ctx = tls_ctx_create(sk); 65 if (!ctx) 66 goto out; 67 68 ctx->sk_destruct = sk->sk_destruct; 69 sk->sk_destruct = tls_toe_sk_destruct; 70 ctx->rx_conf = TLS_HW_RECORD; 71 ctx->tx_conf = TLS_HW_RECORD; 72 update_sk_prot(sk, ctx); 73 rc = 1; 74 break; 75 } 76 } 77 out: 78 spin_unlock_bh(&device_spinlock); 79 return rc; 80 } 81 82 void tls_toe_unhash(struct sock *sk) 83 { 84 struct tls_context *ctx = tls_get_ctx(sk); 85 struct tls_toe_device *dev; 86 87 spin_lock_bh(&device_spinlock); 88 list_for_each_entry(dev, &device_list, dev_list) { 89 if (dev->unhash) { 90 kref_get(&dev->kref); 91 spin_unlock_bh(&device_spinlock); 92 dev->unhash(dev, sk); 93 kref_put(&dev->kref, dev->release); 94 spin_lock_bh(&device_spinlock); 95 } 96 } 97 spin_unlock_bh(&device_spinlock); 98 ctx->sk_proto->unhash(sk); 99 } 100 101 int tls_toe_hash(struct sock *sk) 102 { 103 struct tls_context *ctx = tls_get_ctx(sk); 104 struct tls_toe_device *dev; 105 int err; 106 107 err = ctx->sk_proto->hash(sk); 108 spin_lock_bh(&device_spinlock); 109 list_for_each_entry(dev, &device_list, dev_list) { 110 if (dev->hash) { 111 kref_get(&dev->kref); 112 spin_unlock_bh(&device_spinlock); 113 err |= dev->hash(dev, sk); 114 kref_put(&dev->kref, dev->release); 115 spin_lock_bh(&device_spinlock); 116 } 117 } 118 spin_unlock_bh(&device_spinlock); 119 120 if (err) 121 tls_toe_unhash(sk); 122 return err; 123 } 124 125 void tls_toe_register_device(struct tls_toe_device *device) 126 { 127 spin_lock_bh(&device_spinlock); 128 list_add_tail(&device->dev_list, &device_list); 129 spin_unlock_bh(&device_spinlock); 130 } 131 EXPORT_SYMBOL(tls_toe_register_device); 132 133 void tls_toe_unregister_device(struct tls_toe_device *device) 134 { 135 spin_lock_bh(&device_spinlock); 136 list_del(&device->dev_list); 137 spin_unlock_bh(&device_spinlock); 138 } 139 EXPORT_SYMBOL(tls_toe_unregister_device); 140