1e3cf00d0SUpinder Malhi /* 2e3cf00d0SUpinder Malhi * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved. 3e3cf00d0SUpinder Malhi * 43805eadeSJeff Squyres * This software is available to you under a choice of one of two 53805eadeSJeff Squyres * licenses. You may choose to be licensed under the terms of the GNU 63805eadeSJeff Squyres * General Public License (GPL) Version 2, available from the file 73805eadeSJeff Squyres * COPYING in the main directory of this source tree, or the 83805eadeSJeff Squyres * BSD license below: 93805eadeSJeff Squyres * 103805eadeSJeff Squyres * Redistribution and use in source and binary forms, with or 113805eadeSJeff Squyres * without modification, are permitted provided that the following 123805eadeSJeff Squyres * conditions are met: 133805eadeSJeff Squyres * 143805eadeSJeff Squyres * - Redistributions of source code must retain the above 153805eadeSJeff Squyres * copyright notice, this list of conditions and the following 163805eadeSJeff Squyres * disclaimer. 173805eadeSJeff Squyres * 183805eadeSJeff Squyres * - Redistributions in binary form must reproduce the above 193805eadeSJeff Squyres * copyright notice, this list of conditions and the following 203805eadeSJeff Squyres * disclaimer in the documentation and/or other materials 213805eadeSJeff Squyres * provided with the distribution. 22e3cf00d0SUpinder Malhi * 23e3cf00d0SUpinder Malhi * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24e3cf00d0SUpinder Malhi * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25e3cf00d0SUpinder Malhi * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26e3cf00d0SUpinder Malhi * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27e3cf00d0SUpinder Malhi * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28e3cf00d0SUpinder Malhi * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29e3cf00d0SUpinder Malhi * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30e3cf00d0SUpinder Malhi * SOFTWARE. 31e3cf00d0SUpinder Malhi * 32e3cf00d0SUpinder Malhi */ 33e3cf00d0SUpinder Malhi #include <linux/bitmap.h> 3462141054SUpinder Malhi #include <linux/file.h> 35e3cf00d0SUpinder Malhi #include <linux/module.h> 36e3cf00d0SUpinder Malhi #include <linux/slab.h> 3762141054SUpinder Malhi #include <net/inet_sock.h> 38e3cf00d0SUpinder Malhi 39e3cf00d0SUpinder Malhi #include "usnic_transport.h" 40e3cf00d0SUpinder Malhi #include "usnic_log.h" 41e3cf00d0SUpinder Malhi 42e3cf00d0SUpinder Malhi /* ROCE */ 43e3cf00d0SUpinder Malhi static unsigned long *roce_bitmap; 44e3cf00d0SUpinder Malhi static u16 roce_next_port = 1; 45e3cf00d0SUpinder Malhi #define ROCE_BITMAP_SZ ((1 << (8 /*CHAR_BIT*/ * sizeof(u16)))/8 /*CHAR BIT*/) 46e3cf00d0SUpinder Malhi static DEFINE_SPINLOCK(roce_bitmap_lock); 47e3cf00d0SUpinder Malhi 4862141054SUpinder Malhi const char *usnic_transport_to_str(enum usnic_transport_type type) 49e3cf00d0SUpinder Malhi { 50e3cf00d0SUpinder Malhi switch (type) { 51e3cf00d0SUpinder Malhi case USNIC_TRANSPORT_UNKNOWN: 52e3cf00d0SUpinder Malhi return "Unknown"; 53e3cf00d0SUpinder Malhi case USNIC_TRANSPORT_ROCE_CUSTOM: 54e3cf00d0SUpinder Malhi return "roce custom"; 5562141054SUpinder Malhi case USNIC_TRANSPORT_IPV4_UDP: 5662141054SUpinder Malhi return "IPv4 UDP"; 57e3cf00d0SUpinder Malhi case USNIC_TRANSPORT_MAX: 58e3cf00d0SUpinder Malhi return "Max?"; 59e3cf00d0SUpinder Malhi default: 60e3cf00d0SUpinder Malhi return "Not known"; 61e3cf00d0SUpinder Malhi } 62e3cf00d0SUpinder Malhi } 63e3cf00d0SUpinder Malhi 6462141054SUpinder Malhi int usnic_transport_sock_to_str(char *buf, int buf_sz, 6562141054SUpinder Malhi struct socket *sock) 6662141054SUpinder Malhi { 6762141054SUpinder Malhi int err; 6862141054SUpinder Malhi uint32_t addr; 6962141054SUpinder Malhi uint16_t port; 7062141054SUpinder Malhi int proto; 7162141054SUpinder Malhi 7262141054SUpinder Malhi memset(buf, 0, buf_sz); 7362141054SUpinder Malhi err = usnic_transport_sock_get_addr(sock, &proto, &addr, &port); 7462141054SUpinder Malhi if (err) 7562141054SUpinder Malhi return 0; 7662141054SUpinder Malhi 774942c0b4SUpinder Malhi return scnprintf(buf, buf_sz, "Proto:%u Addr:%pI4h Port:%hu", 7862141054SUpinder Malhi proto, &addr, port); 7962141054SUpinder Malhi } 8062141054SUpinder Malhi 81e3cf00d0SUpinder Malhi /* 82e3cf00d0SUpinder Malhi * reserve a port number. if "0" specified, we will try to pick one 83e3cf00d0SUpinder Malhi * starting at roce_next_port. roce_next_port will take on the values 84e3cf00d0SUpinder Malhi * 1..4096 85e3cf00d0SUpinder Malhi */ 86e3cf00d0SUpinder Malhi u16 usnic_transport_rsrv_port(enum usnic_transport_type type, u16 port_num) 87e3cf00d0SUpinder Malhi { 88e3cf00d0SUpinder Malhi if (type == USNIC_TRANSPORT_ROCE_CUSTOM) { 89e3cf00d0SUpinder Malhi spin_lock(&roce_bitmap_lock); 90e3cf00d0SUpinder Malhi if (!port_num) { 91e3cf00d0SUpinder Malhi port_num = bitmap_find_next_zero_area(roce_bitmap, 92e3cf00d0SUpinder Malhi ROCE_BITMAP_SZ, 93e3cf00d0SUpinder Malhi roce_next_port /* start */, 94e3cf00d0SUpinder Malhi 1 /* nr */, 95e3cf00d0SUpinder Malhi 0 /* align */); 96e3cf00d0SUpinder Malhi roce_next_port = (port_num & 4095) + 1; 97e3cf00d0SUpinder Malhi } else if (test_bit(port_num, roce_bitmap)) { 98e3cf00d0SUpinder Malhi usnic_err("Failed to allocate port for %s\n", 9962141054SUpinder Malhi usnic_transport_to_str(type)); 100e3cf00d0SUpinder Malhi spin_unlock(&roce_bitmap_lock); 101e3cf00d0SUpinder Malhi goto out_fail; 102e3cf00d0SUpinder Malhi } 103e3cf00d0SUpinder Malhi bitmap_set(roce_bitmap, port_num, 1); 104e3cf00d0SUpinder Malhi spin_unlock(&roce_bitmap_lock); 105e3cf00d0SUpinder Malhi } else { 106e3cf00d0SUpinder Malhi usnic_err("Failed to allocate port - transport %s unsupported\n", 10762141054SUpinder Malhi usnic_transport_to_str(type)); 108e3cf00d0SUpinder Malhi goto out_fail; 109e3cf00d0SUpinder Malhi } 110e3cf00d0SUpinder Malhi 111e3cf00d0SUpinder Malhi usnic_dbg("Allocating port %hu for %s\n", port_num, 11262141054SUpinder Malhi usnic_transport_to_str(type)); 113e3cf00d0SUpinder Malhi return port_num; 114e3cf00d0SUpinder Malhi 115e3cf00d0SUpinder Malhi out_fail: 116e3cf00d0SUpinder Malhi return 0; 117e3cf00d0SUpinder Malhi } 118e3cf00d0SUpinder Malhi 119e3cf00d0SUpinder Malhi void usnic_transport_unrsrv_port(enum usnic_transport_type type, u16 port_num) 120e3cf00d0SUpinder Malhi { 121e3cf00d0SUpinder Malhi if (type == USNIC_TRANSPORT_ROCE_CUSTOM) { 122e3cf00d0SUpinder Malhi spin_lock(&roce_bitmap_lock); 123e3cf00d0SUpinder Malhi if (!port_num) { 124e3b00e9cSColin Ian King usnic_err("Unreserved invalid port num 0 for %s\n", 12562141054SUpinder Malhi usnic_transport_to_str(type)); 126e3cf00d0SUpinder Malhi goto out_roce_custom; 127e3cf00d0SUpinder Malhi } 128e3cf00d0SUpinder Malhi 129e3cf00d0SUpinder Malhi if (!test_bit(port_num, roce_bitmap)) { 130e3cf00d0SUpinder Malhi usnic_err("Unreserving invalid %hu for %s\n", 131e3cf00d0SUpinder Malhi port_num, 13262141054SUpinder Malhi usnic_transport_to_str(type)); 133e3cf00d0SUpinder Malhi goto out_roce_custom; 134e3cf00d0SUpinder Malhi } 135e3cf00d0SUpinder Malhi bitmap_clear(roce_bitmap, port_num, 1); 136e3cf00d0SUpinder Malhi usnic_dbg("Freeing port %hu for %s\n", port_num, 13762141054SUpinder Malhi usnic_transport_to_str(type)); 138e3cf00d0SUpinder Malhi out_roce_custom: 139e3cf00d0SUpinder Malhi spin_unlock(&roce_bitmap_lock); 140e3cf00d0SUpinder Malhi } else { 141e3cf00d0SUpinder Malhi usnic_err("Freeing invalid port %hu for %d\n", port_num, type); 142e3cf00d0SUpinder Malhi } 143e3cf00d0SUpinder Malhi } 144e3cf00d0SUpinder Malhi 14562141054SUpinder Malhi struct socket *usnic_transport_get_socket(int sock_fd) 14662141054SUpinder Malhi { 14762141054SUpinder Malhi struct socket *sock; 14862141054SUpinder Malhi int err; 14962141054SUpinder Malhi char buf[25]; 15062141054SUpinder Malhi 15162141054SUpinder Malhi /* sockfd_lookup will internally do a fget */ 15262141054SUpinder Malhi sock = sockfd_lookup(sock_fd, &err); 15362141054SUpinder Malhi if (!sock) { 15462141054SUpinder Malhi usnic_err("Unable to lookup socket for fd %d with err %d\n", 15562141054SUpinder Malhi sock_fd, err); 15662141054SUpinder Malhi return ERR_PTR(-ENOENT); 15762141054SUpinder Malhi } 15862141054SUpinder Malhi 15962141054SUpinder Malhi usnic_transport_sock_to_str(buf, sizeof(buf), sock); 16062141054SUpinder Malhi usnic_dbg("Get sock %s\n", buf); 16162141054SUpinder Malhi 16262141054SUpinder Malhi return sock; 16362141054SUpinder Malhi } 16462141054SUpinder Malhi 16562141054SUpinder Malhi void usnic_transport_put_socket(struct socket *sock) 16662141054SUpinder Malhi { 16762141054SUpinder Malhi char buf[100]; 16862141054SUpinder Malhi 16962141054SUpinder Malhi usnic_transport_sock_to_str(buf, sizeof(buf), sock); 17062141054SUpinder Malhi usnic_dbg("Put sock %s\n", buf); 17162141054SUpinder Malhi sockfd_put(sock); 17262141054SUpinder Malhi } 17362141054SUpinder Malhi 17462141054SUpinder Malhi int usnic_transport_sock_get_addr(struct socket *sock, int *proto, 17562141054SUpinder Malhi uint32_t *addr, uint16_t *port) 17662141054SUpinder Malhi { 17762141054SUpinder Malhi int err; 17862141054SUpinder Malhi struct sockaddr_in sock_addr; 17962141054SUpinder Malhi 18062141054SUpinder Malhi err = sock->ops->getname(sock, 18162141054SUpinder Malhi (struct sockaddr *)&sock_addr, 1829b2c45d4SDenys Vlasenko 0); 1839b2c45d4SDenys Vlasenko if (err < 0) 18462141054SUpinder Malhi return err; 18562141054SUpinder Malhi 18662141054SUpinder Malhi if (sock_addr.sin_family != AF_INET) 18762141054SUpinder Malhi return -EINVAL; 18862141054SUpinder Malhi 18962141054SUpinder Malhi if (proto) 19062141054SUpinder Malhi *proto = sock->sk->sk_protocol; 19162141054SUpinder Malhi if (port) 19262141054SUpinder Malhi *port = ntohs(((struct sockaddr_in *)&sock_addr)->sin_port); 19362141054SUpinder Malhi if (addr) 19462141054SUpinder Malhi *addr = ntohl(((struct sockaddr_in *) 19562141054SUpinder Malhi &sock_addr)->sin_addr.s_addr); 19662141054SUpinder Malhi 19762141054SUpinder Malhi return 0; 19862141054SUpinder Malhi } 19962141054SUpinder Malhi 200e3cf00d0SUpinder Malhi int usnic_transport_init(void) 201e3cf00d0SUpinder Malhi { 202e3cf00d0SUpinder Malhi roce_bitmap = kzalloc(ROCE_BITMAP_SZ, GFP_KERNEL); 203b7c5bc73SMarkus Elfring if (!roce_bitmap) 204e3cf00d0SUpinder Malhi return -ENOMEM; 205e3cf00d0SUpinder Malhi 206e3cf00d0SUpinder Malhi /* Do not ever allocate bit 0, hence set it here */ 207e3cf00d0SUpinder Malhi bitmap_set(roce_bitmap, 0, 1); 208e3cf00d0SUpinder Malhi return 0; 209e3cf00d0SUpinder Malhi } 210e3cf00d0SUpinder Malhi 211e3cf00d0SUpinder Malhi void usnic_transport_fini(void) 212e3cf00d0SUpinder Malhi { 213e3cf00d0SUpinder Malhi kfree(roce_bitmap); 214e3cf00d0SUpinder Malhi } 215