248 lines · c
1/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */2/*3 * Copyright (c) 2005 Voltaire Inc. All rights reserved.4 * Copyright (c) 2005 Intel Corporation. All rights reserved.5 */6 7#ifndef IB_ADDR_H8#define IB_ADDR_H9 10#include <linux/ethtool.h>11#include <linux/in.h>12#include <linux/in6.h>13#include <linux/if_arp.h>14#include <linux/netdevice.h>15#include <linux/inetdevice.h>16#include <linux/socket.h>17#include <linux/if_vlan.h>18#include <net/ipv6.h>19#include <net/if_inet6.h>20#include <net/ip.h>21#include <rdma/ib_verbs.h>22#include <rdma/ib_pack.h>23#include <net/net_namespace.h>24 25/**26 * struct rdma_dev_addr - Contains resolved RDMA hardware addresses27 * @src_dev_addr: Source MAC address.28 * @dst_dev_addr: Destination MAC address.29 * @broadcast: Broadcast address of the device.30 * @dev_type: The interface hardware type of the device.31 * @bound_dev_if: An optional device interface index.32 * @transport: The transport type used.33 * @net: Network namespace containing the bound_dev_if net_dev.34 * @sgid_attr: GID attribute to use for identified SGID35 */36struct rdma_dev_addr {37 unsigned char src_dev_addr[MAX_ADDR_LEN];38 unsigned char dst_dev_addr[MAX_ADDR_LEN];39 unsigned char broadcast[MAX_ADDR_LEN];40 unsigned short dev_type;41 int bound_dev_if;42 enum rdma_transport_type transport;43 struct net *net;44 const struct ib_gid_attr *sgid_attr;45 enum rdma_network_type network;46 int hoplimit;47};48 49/**50 * rdma_translate_ip - Translate a local IP address to an RDMA hardware51 * address.52 *53 * The dev_addr->net field must be initialized.54 */55int rdma_translate_ip(const struct sockaddr *addr,56 struct rdma_dev_addr *dev_addr);57 58/**59 * rdma_resolve_ip - Resolve source and destination IP addresses to60 * RDMA hardware addresses.61 * @src_addr: An optional source address to use in the resolution. If a62 * source address is not provided, a usable address will be returned via63 * the callback.64 * @dst_addr: The destination address to resolve.65 * @addr: A reference to a data location that will receive the resolved66 * addresses. The data location must remain valid until the callback has67 * been invoked. The net field of the addr struct must be valid.68 * @timeout_ms: Amount of time to wait for the address resolution to complete.69 * @callback: Call invoked once address resolution has completed, timed out,70 * or been canceled. A status of 0 indicates success.71 * @resolve_by_gid_attr: Resolve the ip based on the GID attribute from72 * rdma_dev_addr.73 * @context: User-specified context associated with the call.74 */75int rdma_resolve_ip(struct sockaddr *src_addr, const struct sockaddr *dst_addr,76 struct rdma_dev_addr *addr, unsigned long timeout_ms,77 void (*callback)(int status, struct sockaddr *src_addr,78 struct rdma_dev_addr *addr, void *context),79 bool resolve_by_gid_attr, void *context);80 81void rdma_addr_cancel(struct rdma_dev_addr *addr);82 83int rdma_addr_size(const struct sockaddr *addr);84int rdma_addr_size_in6(struct sockaddr_in6 *addr);85int rdma_addr_size_kss(struct __kernel_sockaddr_storage *addr);86 87static inline u16 ib_addr_get_pkey(struct rdma_dev_addr *dev_addr)88{89 return ((u16)dev_addr->broadcast[8] << 8) | (u16)dev_addr->broadcast[9];90}91 92static inline void ib_addr_set_pkey(struct rdma_dev_addr *dev_addr, u16 pkey)93{94 dev_addr->broadcast[8] = pkey >> 8;95 dev_addr->broadcast[9] = (unsigned char) pkey;96}97 98static inline void ib_addr_get_mgid(struct rdma_dev_addr *dev_addr,99 union ib_gid *gid)100{101 memcpy(gid, dev_addr->broadcast + 4, sizeof *gid);102}103 104static inline int rdma_addr_gid_offset(struct rdma_dev_addr *dev_addr)105{106 return dev_addr->dev_type == ARPHRD_INFINIBAND ? 4 : 0;107}108 109static inline u16 rdma_vlan_dev_vlan_id(const struct net_device *dev)110{111 return is_vlan_dev(dev) ? vlan_dev_vlan_id(dev) : 0xffff;112}113 114static inline int rdma_ip2gid(struct sockaddr *addr, union ib_gid *gid)115{116 switch (addr->sa_family) {117 case AF_INET:118 ipv6_addr_set_v4mapped(((struct sockaddr_in *)119 addr)->sin_addr.s_addr,120 (struct in6_addr *)gid);121 break;122 case AF_INET6:123 *(struct in6_addr *)&gid->raw =124 ((struct sockaddr_in6 *)addr)->sin6_addr;125 break;126 default:127 return -EINVAL;128 }129 return 0;130}131 132/* Important - sockaddr should be a union of sockaddr_in and sockaddr_in6 */133static inline void rdma_gid2ip(struct sockaddr *out, const union ib_gid *gid)134{135 if (ipv6_addr_v4mapped((struct in6_addr *)gid)) {136 struct sockaddr_in *out_in = (struct sockaddr_in *)out;137 memset(out_in, 0, sizeof(*out_in));138 out_in->sin_family = AF_INET;139 memcpy(&out_in->sin_addr.s_addr, gid->raw + 12, 4);140 } else {141 struct sockaddr_in6 *out_in = (struct sockaddr_in6 *)out;142 memset(out_in, 0, sizeof(*out_in));143 out_in->sin6_family = AF_INET6;144 memcpy(&out_in->sin6_addr.s6_addr, gid->raw, 16);145 }146}147 148/*149 * rdma_get/set_sgid/dgid() APIs are applicable to IB, and iWarp.150 * They are not applicable to RoCE.151 * RoCE GIDs are derived from the IP addresses.152 */153static inline void rdma_addr_get_sgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid)154{155 memcpy(gid, dev_addr->src_dev_addr + rdma_addr_gid_offset(dev_addr),156 sizeof(*gid));157}158 159static inline void rdma_addr_set_sgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid)160{161 memcpy(dev_addr->src_dev_addr + rdma_addr_gid_offset(dev_addr), gid, sizeof *gid);162}163 164static inline void rdma_addr_get_dgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid)165{166 memcpy(gid, dev_addr->dst_dev_addr + rdma_addr_gid_offset(dev_addr), sizeof *gid);167}168 169static inline void rdma_addr_set_dgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid)170{171 memcpy(dev_addr->dst_dev_addr + rdma_addr_gid_offset(dev_addr), gid, sizeof *gid);172}173 174static inline enum ib_mtu iboe_get_mtu(int mtu)175{176 /*177 * Reduce IB headers from effective IBoE MTU.178 */179 mtu = mtu - (IB_GRH_BYTES + IB_UDP_BYTES + IB_BTH_BYTES +180 IB_EXT_XRC_BYTES + IB_EXT_ATOMICETH_BYTES +181 IB_ICRC_BYTES);182 183 if (mtu >= ib_mtu_enum_to_int(IB_MTU_4096))184 return IB_MTU_4096;185 else if (mtu >= ib_mtu_enum_to_int(IB_MTU_2048))186 return IB_MTU_2048;187 else if (mtu >= ib_mtu_enum_to_int(IB_MTU_1024))188 return IB_MTU_1024;189 else if (mtu >= ib_mtu_enum_to_int(IB_MTU_512))190 return IB_MTU_512;191 else if (mtu >= ib_mtu_enum_to_int(IB_MTU_256))192 return IB_MTU_256;193 else194 return 0;195}196 197static inline int rdma_link_local_addr(struct in6_addr *addr)198{199 if (addr->s6_addr32[0] == htonl(0xfe800000) &&200 addr->s6_addr32[1] == 0)201 return 1;202 203 return 0;204}205 206static inline void rdma_get_ll_mac(struct in6_addr *addr, u8 *mac)207{208 memcpy(mac, &addr->s6_addr[8], 3);209 memcpy(mac + 3, &addr->s6_addr[13], 3);210 mac[0] ^= 2;211}212 213static inline int rdma_is_multicast_addr(struct in6_addr *addr)214{215 __be32 ipv4_addr;216 217 if (addr->s6_addr[0] == 0xff)218 return 1;219 220 ipv4_addr = addr->s6_addr32[3];221 return (ipv6_addr_v4mapped(addr) && ipv4_is_multicast(ipv4_addr));222}223 224static inline void rdma_get_mcast_mac(struct in6_addr *addr, u8 *mac)225{226 int i;227 228 mac[0] = 0x33;229 mac[1] = 0x33;230 for (i = 2; i < 6; ++i)231 mac[i] = addr->s6_addr[i + 10];232}233 234static inline u16 rdma_get_vlan_id(union ib_gid *dgid)235{236 u16 vid;237 238 vid = dgid->raw[11] << 8 | dgid->raw[12];239 return vid < 0x1000 ? vid : 0xffff;240}241 242static inline struct net_device *rdma_vlan_dev_real_dev(const struct net_device *dev)243{244 return is_vlan_dev(dev) ? vlan_dev_real_dev(dev) : NULL;245}246 247#endif /* IB_ADDR_H */248