1 /*
2  * Copyright (c) 2013-2018 Intel Corporation. All rights reserved.
3  * Copyright (c) 2016 Cisco Systems, Inc. All rights reserved.
4  *
5  * This software is available to you under a choice of one of two
6  * licenses.  You may choose to be licensed under the terms of the GNU
7  * General Public License (GPL) Version 2, available from the file
8  * COPYING in the main directory of this source tree, or the
9  * BSD license below:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      - Redistributions of source code must retain the above
16  *        copyright notice, this list of conditions and the following
17  *        disclaimer.
18  *
19  *      - Redistributions in binary form must reproduce the above
20  *        copyright notice, this list of conditions and the following
21  *        disclaimer in the documentation and/or other materials
22  *        provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  */
33 
34 #ifndef _OFI_NET_H_
35 #define _OFI_NET_H_
36 
37 #include "config.h"
38 
39 #include <assert.h>
40 #include <pthread.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sys/param.h>
44 #include <netinet/in.h>
45 #include <ifaddrs.h>
46 
47 #include <ofi_osd.h>
48 #include <ofi_list.h>
49 
50 #include <rdma/fabric.h>
51 #include <rdma/providers/fi_prov.h>
52 #include <rdma/providers/fi_log.h>
53 
54 
55 #ifdef __cplusplus
56 extern "C" {
57 #endif
58 
59 
60 extern struct fi_provider core_prov;
61 
62 
63 /*
64  * OS X doesn't have __BYTE_ORDER, Linux usually has BYTE_ORDER but not under
65  * all features.h flags
66  */
67 #if !defined(BYTE_ORDER)
68 #  if defined(__BYTE_ORDER) && \
69       defined(__LITTLE_ENDIAN) && \
70       defined(__BIG_ENDIAN)
71 #    define BYTE_ORDER __BYTE_ORDER
72 #    define LITTLE_ENDIAN __LITTLE_ENDIAN
73 #    define BIG_ENDIAN __BIG_ENDIAN
74 #  else
75 #    error "cannot determine endianness!"
76 #  endif
77 #endif
78 
79 #if BYTE_ORDER == LITTLE_ENDIAN
80 #ifndef htonll
htonll(uint64_t x)81 static inline uint64_t htonll(uint64_t x) { return bswap_64(x); }
82 #endif
83 #ifndef ntohll
ntohll(uint64_t x)84 static inline uint64_t ntohll(uint64_t x) { return bswap_64(x); }
85 #endif
86 #else
87 #ifndef htonll
htonll(uint64_t x)88 static inline uint64_t htonll(uint64_t x) { return x; }
89 #endif
90 #ifndef ntohll
ntohll(uint64_t x)91 static inline uint64_t ntohll(uint64_t x) { return x; }
92 #endif
93 #endif
94 
95 
ofi_recvall_socket(SOCKET sock,void * buf,size_t len)96 static inline int ofi_recvall_socket(SOCKET sock, void *buf, size_t len)
97 {
98 	ssize_t ret;
99 
100 	ret = ofi_recv_socket(sock, buf, len, MSG_WAITALL);
101 	return (size_t) ret != len;
102 }
103 
ofi_sendall_socket(SOCKET sock,const void * buf,size_t len)104 static inline int ofi_sendall_socket(SOCKET sock, const void *buf, size_t len)
105 {
106 	size_t sent;
107 	ssize_t ret;
108 
109 	for (sent = 0, ret = 0; (sent < len) && (ret >= 0); ) {
110 		ret = ofi_send_socket(sock, ((char *) buf) + sent, len - sent, 0);
111 		if (ret > 0)
112 			sent += ret;
113 	}
114 
115 	return (size_t) sent != len;
116 }
117 
118 int ofi_discard_socket(SOCKET sock, size_t len);
119 
120 /*
121  * Address utility functions
122  */
123 
124 #ifndef AF_IB
125 #define AF_IB 27
126 #endif
127 
128 #define OFI_ADDRSTRLEN (INET6_ADDRSTRLEN + 50)
129 
130 union ofi_sock_ip {
131 	struct sockaddr		sa;
132 	struct sockaddr_in	sin;
133 	struct sockaddr_in6	sin6;
134 	uint8_t			align[32];
135 };
136 
137 struct ofi_addr_list_entry {
138 	struct slist_entry	entry;
139 	char			ipstr[INET6_ADDRSTRLEN];
140 	union ofi_sock_ip	ipaddr;
141 	size_t			speed;
142 	char			net_name[OFI_ADDRSTRLEN];
143 	char			ifa_name[OFI_ADDRSTRLEN];
144 };
145 
146 int ofi_addr_cmp(const struct fi_provider *prov, const struct sockaddr *sa1,
147 		const struct sockaddr *sa2);
148 int ofi_getifaddrs(struct ifaddrs **ifap);
149 
150 void ofi_set_netmask_str(char *netstr, size_t len, struct ifaddrs *ifa);
151 
152 void ofi_get_list_of_addr(const struct fi_provider *prov, const char *env_name,
153 			  struct slist *addr_list);
154 void ofi_free_list_of_addr(struct slist *addr_list);
155 
156 #define ofi_sa_family(addr) ((struct sockaddr *)(addr))->sa_family
157 #define ofi_sin_addr(addr) (((struct sockaddr_in *)(addr))->sin_addr)
158 #define ofi_sin_port(addr) (((struct sockaddr_in *)(addr))->sin_port)
159 
160 #define ofi_sin6_addr(addr) (((struct sockaddr_in6 *)(addr))->sin6_addr)
161 #define ofi_sin6_port(addr) (((struct sockaddr_in6 *)(addr))->sin6_port)
162 
163 
ofi_sizeofaddr(const struct sockaddr * addr)164 static inline size_t ofi_sizeofaddr(const struct sockaddr *addr)
165 {
166 	switch (addr->sa_family) {
167 	case AF_INET:
168 		return sizeof(struct sockaddr_in);
169 	case AF_INET6:
170 		return sizeof(struct sockaddr_in6);
171 	default:
172 		FI_WARN(&core_prov, FI_LOG_CORE, "Unknown address format\n");
173 		return 0;
174 	}
175 }
176 
ofi_sizeofip(const struct sockaddr * addr)177 static inline size_t ofi_sizeofip(const struct sockaddr *addr)
178 {
179 	switch (addr->sa_family) {
180 	case AF_INET:
181 		return sizeof(struct in_addr);
182 	case AF_INET6:
183 		return sizeof(struct in6_addr);
184 	default:
185 		FI_WARN(&core_prov, FI_LOG_CORE, "Unknown address format\n");
186 		return 0;
187 	}
188 }
189 
ofi_translate_addr_format(int family)190 static inline int ofi_translate_addr_format(int family)
191 {
192 	switch (family) {
193 	case AF_INET:
194 		return FI_SOCKADDR_IN;
195 	case AF_INET6:
196 		return FI_SOCKADDR_IN6;
197 	case AF_IB:
198 		return FI_SOCKADDR_IB;
199 	default:
200 		return FI_FORMAT_UNSPEC;
201 	}
202 }
203 
204 uint16_t ofi_get_sa_family(const struct fi_info *info);
205 
ofi_ipv4_is_any_addr(struct sockaddr * sa)206 static inline int ofi_ipv4_is_any_addr(struct sockaddr *sa)
207 {
208 	struct in_addr ia_any = {
209 		.s_addr = INADDR_ANY,
210 	};
211 
212 	if (!sa)
213 		return 0;
214 
215 	return !memcmp(&ofi_sin_addr(sa).s_addr, &ia_any, sizeof(ia_any));
216 
217 }
218 
ofi_ipv6_is_any_addr(struct sockaddr * sa)219 static inline int ofi_ipv6_is_any_addr(struct sockaddr *sa)
220 {
221 	struct in6_addr ia6_any = IN6ADDR_ANY_INIT;
222 
223 	if (!sa)
224 		return 0;
225 
226 	return !memcmp(&ofi_sin6_addr(sa), &ia6_any, sizeof(ia6_any));
227 }
228 
ofi_is_any_addr(struct sockaddr * sa)229 static inline int ofi_is_any_addr(struct sockaddr *sa)
230 {
231 	if (!sa)
232 		return 0;
233 
234 	switch(sa->sa_family) {
235 	case AF_INET:
236 		return ofi_ipv4_is_any_addr(sa);
237 	case AF_INET6:
238 		return ofi_ipv6_is_any_addr(sa);
239 	default:
240 		FI_WARN(&core_prov, FI_LOG_CORE, "Unknown address format!\n");
241 		return 0;
242 	}
243 }
244 
ofi_addr_get_port(const struct sockaddr * addr)245 static inline uint16_t ofi_addr_get_port(const struct sockaddr *addr)
246 {
247 	if (!addr)
248 		return 0;
249 
250 	switch (ofi_sa_family(addr)) {
251 	case AF_INET:
252 		return ntohs(ofi_sin_port((const struct sockaddr_in *) addr));
253 	case AF_INET6:
254 		return ntohs(ofi_sin6_port((const struct sockaddr_in6 *) addr));
255 	default:
256 		FI_WARN(&core_prov, FI_LOG_FABRIC, "Unknown address format\n");
257 		assert(0);
258 		return 0;
259 	}
260 }
261 
ofi_addr_set_port(struct sockaddr * addr,uint16_t port)262 static inline void ofi_addr_set_port(struct sockaddr *addr, uint16_t port)
263 {
264 	switch (ofi_sa_family(addr)) {
265 	case AF_INET:
266 		ofi_sin_port(addr) = htons(port);
267 		break;
268 	case AF_INET6:
269 		ofi_sin6_port(addr) = htons(port);
270 		break;
271 	default:
272 		FI_WARN(&core_prov, FI_LOG_FABRIC, "Unknown address format\n");
273 		assert(0);
274 	}
275 }
276 
ofi_get_ipaddr(const struct sockaddr * addr)277 static inline void * ofi_get_ipaddr(const struct sockaddr *addr)
278 {
279 	switch (addr->sa_family) {
280 	case AF_INET:
281 		return &ofi_sin_addr((const struct sockaddr_in *) addr);
282 	case AF_INET6:
283 		return &ofi_sin6_addr((const struct sockaddr_in6 *) addr);
284 	default:
285 		return NULL;
286 	}
287 }
288 
ofi_equals_ipaddr(const struct sockaddr * addr1,const struct sockaddr * addr2)289 static inline int ofi_equals_ipaddr(const struct sockaddr *addr1,
290 				    const struct sockaddr *addr2)
291 {
292 	if (addr1->sa_family != addr2->sa_family)
293 		return 0;
294 
295 	switch (addr1->sa_family) {
296 	case AF_INET:
297 	        return !memcmp(&ofi_sin_addr(addr1), &ofi_sin_addr(addr2),
298 				sizeof(ofi_sin_addr(addr1)));
299 	case AF_INET6:
300 	        return !memcmp(&ofi_sin6_addr(addr1), &ofi_sin6_addr(addr2),
301 				sizeof(ofi_sin6_addr(addr1)));
302 	default:
303 		return 0;
304 	}
305 }
306 
ofi_equals_sockaddr(const struct sockaddr * addr1,const struct sockaddr * addr2)307 static inline int ofi_equals_sockaddr(const struct sockaddr *addr1,
308 				      const struct sockaddr *addr2)
309 {
310         return (ofi_addr_get_port(addr1) == ofi_addr_get_port(addr2)) &&
311 		ofi_equals_ipaddr(addr1, addr2);
312 }
313 
314 int ofi_is_wildcard_listen_addr(const char *node, const char *service,
315 				uint64_t flags, const struct fi_info *hints);
316 
317 size_t ofi_mask_addr(struct sockaddr *maskaddr, const struct sockaddr *srcaddr,
318 		     const struct sockaddr *netmask);
319 
320 
321 /*
322  * Address logging
323  */
324 const char *ofi_straddr(char *buf, size_t *len,
325 			uint32_t addr_format, const void *addr);
326 
327 /* Returns allocated address to caller.  Caller must free.  */
328 int ofi_str_toaddr(const char *str, uint32_t *addr_format,
329 		   void **addr, size_t *len);
330 
331 void ofi_straddr_log_internal(const char *func, int line,
332 			      const struct fi_provider *prov,
333 			      enum fi_log_level level,
334 			      enum fi_log_subsys subsys, char *log_str,
335 			      const void *addr);
336 
337 #define ofi_straddr_log(...) \
338 	ofi_straddr_log_internal(__func__, __LINE__, __VA_ARGS__)
339 
340 #if ENABLE_DEBUG
341 #define ofi_straddr_dbg(prov, subsystem, ...) \
342 	ofi_straddr_log(prov, FI_LOG_DEBUG, subsystem, __VA_ARGS__)
343 #else
344 #define ofi_straddr_dbg(prov, subsystem, ...) do {} while(0)
345 #endif
346 
347 
348 #ifdef __cplusplus
349 }
350 #endif
351 
352 #endif /* _OFI_NET_H_ */
353