1 /* 2 * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved. 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 * 32 */ 33 #include <linux/bitmap.h> 34 #include <linux/file.h> 35 #include <linux/module.h> 36 #include <linux/slab.h> 37 #include <net/inet_sock.h> 38 39 #include "usnic_transport.h" 40 #include "usnic_log.h" 41 42 /* ROCE */ 43 static unsigned long *roce_bitmap; 44 static u16 roce_next_port = 1; 45 #define ROCE_BITMAP_SZ ((1 << (8 /*CHAR_BIT*/ * sizeof(u16)))/8 /*CHAR BIT*/) 46 static DEFINE_SPINLOCK(roce_bitmap_lock); 47 48 const char *usnic_transport_to_str(enum usnic_transport_type type) 49 { 50 switch (type) { 51 case USNIC_TRANSPORT_UNKNOWN: 52 return "Unknown"; 53 case USNIC_TRANSPORT_ROCE_CUSTOM: 54 return "roce custom"; 55 case USNIC_TRANSPORT_IPV4_UDP: 56 return "IPv4 UDP"; 57 case USNIC_TRANSPORT_MAX: 58 return "Max?"; 59 default: 60 return "Not known"; 61 } 62 } 63 64 int usnic_transport_sock_to_str(char *buf, int buf_sz, 65 struct socket *sock) 66 { 67 int err; 68 uint32_t addr; 69 uint16_t port; 70 int proto; 71 72 memset(buf, 0, buf_sz); 73 err = usnic_transport_sock_get_addr(sock, &proto, &addr, &port); 74 if (err) 75 return 0; 76 77 return scnprintf(buf, buf_sz, "Proto:%u Addr:%pI4h Port:%hu", 78 proto, &addr, port); 79 } 80 81 /* 82 * reserve a port number. if "0" specified, we will try to pick one 83 * starting at roce_next_port. roce_next_port will take on the values 84 * 1..4096 85 */ 86 u16 usnic_transport_rsrv_port(enum usnic_transport_type type, u16 port_num) 87 { 88 if (type == USNIC_TRANSPORT_ROCE_CUSTOM) { 89 spin_lock(&roce_bitmap_lock); 90 if (!port_num) { 91 port_num = bitmap_find_next_zero_area(roce_bitmap, 92 ROCE_BITMAP_SZ, 93 roce_next_port /* start */, 94 1 /* nr */, 95 0 /* align */); 96 roce_next_port = (port_num & 4095) + 1; 97 } else if (test_bit(port_num, roce_bitmap)) { 98 usnic_err("Failed to allocate port for %s\n", 99 usnic_transport_to_str(type)); 100 spin_unlock(&roce_bitmap_lock); 101 goto out_fail; 102 } 103 bitmap_set(roce_bitmap, port_num, 1); 104 spin_unlock(&roce_bitmap_lock); 105 } else { 106 usnic_err("Failed to allocate port - transport %s unsupported\n", 107 usnic_transport_to_str(type)); 108 goto out_fail; 109 } 110 111 usnic_dbg("Allocating port %hu for %s\n", port_num, 112 usnic_transport_to_str(type)); 113 return port_num; 114 115 out_fail: 116 return 0; 117 } 118 119 void usnic_transport_unrsrv_port(enum usnic_transport_type type, u16 port_num) 120 { 121 if (type == USNIC_TRANSPORT_ROCE_CUSTOM) { 122 spin_lock(&roce_bitmap_lock); 123 if (!port_num) { 124 usnic_err("Unreserved invalid port num 0 for %s\n", 125 usnic_transport_to_str(type)); 126 goto out_roce_custom; 127 } 128 129 if (!test_bit(port_num, roce_bitmap)) { 130 usnic_err("Unreserving invalid %hu for %s\n", 131 port_num, 132 usnic_transport_to_str(type)); 133 goto out_roce_custom; 134 } 135 bitmap_clear(roce_bitmap, port_num, 1); 136 usnic_dbg("Freeing port %hu for %s\n", port_num, 137 usnic_transport_to_str(type)); 138 out_roce_custom: 139 spin_unlock(&roce_bitmap_lock); 140 } else { 141 usnic_err("Freeing invalid port %hu for %d\n", port_num, type); 142 } 143 } 144 145 struct socket *usnic_transport_get_socket(int sock_fd) 146 { 147 struct socket *sock; 148 int err; 149 char buf[25]; 150 151 /* sockfd_lookup will internally do a fget */ 152 sock = sockfd_lookup(sock_fd, &err); 153 if (!sock) { 154 usnic_err("Unable to lookup socket for fd %d with err %d\n", 155 sock_fd, err); 156 return ERR_PTR(-ENOENT); 157 } 158 159 usnic_transport_sock_to_str(buf, sizeof(buf), sock); 160 usnic_dbg("Get sock %s\n", buf); 161 162 return sock; 163 } 164 165 void usnic_transport_put_socket(struct socket *sock) 166 { 167 char buf[100]; 168 169 usnic_transport_sock_to_str(buf, sizeof(buf), sock); 170 usnic_dbg("Put sock %s\n", buf); 171 sockfd_put(sock); 172 } 173 174 int usnic_transport_sock_get_addr(struct socket *sock, int *proto, 175 uint32_t *addr, uint16_t *port) 176 { 177 int err; 178 struct sockaddr_in sock_addr; 179 180 err = sock->ops->getname(sock, 181 (struct sockaddr *)&sock_addr, 182 0); 183 if (err < 0) 184 return err; 185 186 if (sock_addr.sin_family != AF_INET) 187 return -EINVAL; 188 189 if (proto) 190 *proto = sock->sk->sk_protocol; 191 if (port) 192 *port = ntohs(((struct sockaddr_in *)&sock_addr)->sin_port); 193 if (addr) 194 *addr = ntohl(((struct sockaddr_in *) 195 &sock_addr)->sin_addr.s_addr); 196 197 return 0; 198 } 199 200 int usnic_transport_init(void) 201 { 202 roce_bitmap = kzalloc(ROCE_BITMAP_SZ, GFP_KERNEL); 203 if (!roce_bitmap) 204 return -ENOMEM; 205 206 /* Do not ever allocate bit 0, hence set it here */ 207 bitmap_set(roce_bitmap, 0, 1); 208 return 0; 209 } 210 211 void usnic_transport_fini(void) 212 { 213 kfree(roce_bitmap); 214 } 215