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