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/slab.h> 36 #include <net/inet_sock.h> 37 38 #include "usnic_transport.h" 39 #include "usnic_log.h" 40 41 /* ROCE */ 42 static unsigned long *roce_bitmap; 43 static u16 roce_next_port = 1; 44 #define ROCE_BITMAP_SZ ((1 << (8 /*CHAR_BIT*/ * sizeof(u16)))/8 /*CHAR BIT*/) 45 static DEFINE_SPINLOCK(roce_bitmap_lock); 46 47 const char *usnic_transport_to_str(enum usnic_transport_type type) 48 { 49 switch (type) { 50 case USNIC_TRANSPORT_UNKNOWN: 51 return "Unknown"; 52 case USNIC_TRANSPORT_ROCE_CUSTOM: 53 return "roce custom"; 54 case USNIC_TRANSPORT_IPV4_UDP: 55 return "IPv4 UDP"; 56 case USNIC_TRANSPORT_MAX: 57 return "Max?"; 58 default: 59 return "Not known"; 60 } 61 } 62 63 int usnic_transport_sock_to_str(char *buf, int buf_sz, 64 struct socket *sock) 65 { 66 int err; 67 uint32_t addr; 68 uint16_t port; 69 int proto; 70 71 memset(buf, 0, buf_sz); 72 err = usnic_transport_sock_get_addr(sock, &proto, &addr, &port); 73 if (err) 74 return 0; 75 76 return scnprintf(buf, buf_sz, "Proto:%u Addr:%pI4h Port:%hu", 77 proto, &addr, port); 78 } 79 80 /* 81 * reserve a port number. if "0" specified, we will try to pick one 82 * starting at roce_next_port. roce_next_port will take on the values 83 * 1..4096 84 */ 85 u16 usnic_transport_rsrv_port(enum usnic_transport_type type, u16 port_num) 86 { 87 if (type == USNIC_TRANSPORT_ROCE_CUSTOM) { 88 spin_lock(&roce_bitmap_lock); 89 if (!port_num) { 90 port_num = bitmap_find_next_zero_area(roce_bitmap, 91 ROCE_BITMAP_SZ, 92 roce_next_port /* start */, 93 1 /* nr */, 94 0 /* align */); 95 roce_next_port = (port_num & 4095) + 1; 96 } else if (test_bit(port_num, roce_bitmap)) { 97 usnic_err("Failed to allocate port for %s\n", 98 usnic_transport_to_str(type)); 99 spin_unlock(&roce_bitmap_lock); 100 goto out_fail; 101 } 102 bitmap_set(roce_bitmap, port_num, 1); 103 spin_unlock(&roce_bitmap_lock); 104 } else { 105 usnic_err("Failed to allocate port - transport %s unsupported\n", 106 usnic_transport_to_str(type)); 107 goto out_fail; 108 } 109 110 usnic_dbg("Allocating port %hu for %s\n", port_num, 111 usnic_transport_to_str(type)); 112 return port_num; 113 114 out_fail: 115 return 0; 116 } 117 118 void usnic_transport_unrsrv_port(enum usnic_transport_type type, u16 port_num) 119 { 120 if (type == USNIC_TRANSPORT_ROCE_CUSTOM) { 121 spin_lock(&roce_bitmap_lock); 122 if (!port_num) { 123 usnic_err("Unreserved invalid port num 0 for %s\n", 124 usnic_transport_to_str(type)); 125 goto out_roce_custom; 126 } 127 128 if (!test_bit(port_num, roce_bitmap)) { 129 usnic_err("Unreserving invalid %hu for %s\n", 130 port_num, 131 usnic_transport_to_str(type)); 132 goto out_roce_custom; 133 } 134 bitmap_clear(roce_bitmap, port_num, 1); 135 usnic_dbg("Freeing port %hu for %s\n", port_num, 136 usnic_transport_to_str(type)); 137 out_roce_custom: 138 spin_unlock(&roce_bitmap_lock); 139 } else { 140 usnic_err("Freeing invalid port %hu for %d\n", port_num, type); 141 } 142 } 143 144 struct socket *usnic_transport_get_socket(int sock_fd) 145 { 146 struct socket *sock; 147 int err; 148 char buf[25]; 149 150 /* sockfd_lookup will internally do a fget */ 151 sock = sockfd_lookup(sock_fd, &err); 152 if (!sock) { 153 usnic_err("Unable to lookup socket for fd %d with err %d\n", 154 sock_fd, err); 155 return ERR_PTR(-ENOENT); 156 } 157 158 usnic_transport_sock_to_str(buf, sizeof(buf), sock); 159 usnic_dbg("Get sock %s\n", buf); 160 161 return sock; 162 } 163 164 void usnic_transport_put_socket(struct socket *sock) 165 { 166 char buf[100]; 167 168 usnic_transport_sock_to_str(buf, sizeof(buf), sock); 169 usnic_dbg("Put sock %s\n", buf); 170 sockfd_put(sock); 171 } 172 173 int usnic_transport_sock_get_addr(struct socket *sock, int *proto, 174 uint32_t *addr, uint16_t *port) 175 { 176 int err; 177 struct sockaddr_in sock_addr; 178 179 err = sock->ops->getname(sock, 180 (struct sockaddr *)&sock_addr, 181 0); 182 if (err < 0) 183 return err; 184 185 if (sock_addr.sin_family != AF_INET) 186 return -EINVAL; 187 188 if (proto) 189 *proto = sock->sk->sk_protocol; 190 if (port) 191 *port = ntohs(((struct sockaddr_in *)&sock_addr)->sin_port); 192 if (addr) 193 *addr = ntohl(((struct sockaddr_in *) 194 &sock_addr)->sin_addr.s_addr); 195 196 return 0; 197 } 198 199 int usnic_transport_init(void) 200 { 201 roce_bitmap = kzalloc(ROCE_BITMAP_SZ, GFP_KERNEL); 202 if (!roce_bitmap) 203 return -ENOMEM; 204 205 /* Do not ever allocate bit 0, hence set it here */ 206 bitmap_set(roce_bitmap, 0, 1); 207 return 0; 208 } 209 210 void usnic_transport_fini(void) 211 { 212 kfree(roce_bitmap); 213 } 214