Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1f5175ad authored by Aleksey Senin's avatar Aleksey Senin Committed by Roland Dreier
Browse files

RDMA/cma: Add IPv6 support



Handle AF_INET6 cases where required, and use struct sockaddr_storage
wherever an IPv6 address might be stored.

Signed-off-by: default avatarAleksey Senin <aleksey@alst60.(none)>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 38617c64
Loading
Loading
Loading
Loading
+60 −26
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
#include <linux/inetdevice.h>

#include <net/tcp.h>
#include <net/ipv6.h>

#include <rdma/rdma_cm.h>
#include <rdma/rdma_cm_ib.h>
@@ -636,7 +637,12 @@ static inline int cma_zero_addr(struct sockaddr *addr)

static inline int cma_loopback_addr(struct sockaddr *addr)
{
	return ipv4_is_loopback(((struct sockaddr_in *) addr)->sin_addr.s_addr);
	if (addr->sa_family == AF_INET)
		return ipv4_is_loopback(
			((struct sockaddr_in *) addr)->sin_addr.s_addr);
	else
		return ipv6_addr_loopback(
			&((struct sockaddr_in6 *) addr)->sin6_addr);
}

static inline int cma_any_addr(struct sockaddr *addr)
@@ -1467,10 +1473,10 @@ static void cma_listen_on_all(struct rdma_id_private *id_priv)

static int cma_bind_any(struct rdma_cm_id *id, sa_family_t af)
{
	struct sockaddr_in addr_in;
	struct sockaddr_storage addr_in;

	memset(&addr_in, 0, sizeof addr_in);
	addr_in.sin_family = af;
	addr_in.ss_family = af;
	return rdma_bind_addr(id, (struct sockaddr *) &addr_in);
}

@@ -2073,7 +2079,7 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
	struct rdma_id_private *id_priv;
	int ret;

	if (addr->sa_family != AF_INET)
	if (addr->sa_family != AF_INET && addr->sa_family != AF_INET6)
		return -EAFNOSUPPORT;

	id_priv = container_of(id, struct rdma_id_private, id);
@@ -2113,10 +2119,12 @@ EXPORT_SYMBOL(rdma_bind_addr);
static int cma_format_hdr(void *hdr, enum rdma_port_space ps,
			  struct rdma_route *route)
{
	struct sockaddr_in *src4, *dst4;
	struct cma_hdr *cma_hdr;
	struct sdp_hh *sdp_hdr;

	if (route->addr.src_addr.ss_family == AF_INET) {
		struct sockaddr_in *src4, *dst4;

		src4 = (struct sockaddr_in *) &route->addr.src_addr;
		dst4 = (struct sockaddr_in *) &route->addr.dst_addr;

@@ -2139,6 +2147,32 @@ static int cma_format_hdr(void *hdr, enum rdma_port_space ps,
			cma_hdr->port = src4->sin_port;
			break;
		}
	} else {
		struct sockaddr_in6 *src6, *dst6;

		src6 = (struct sockaddr_in6 *) &route->addr.src_addr;
		dst6 = (struct sockaddr_in6 *) &route->addr.dst_addr;

		switch (ps) {
		case RDMA_PS_SDP:
			sdp_hdr = hdr;
			if (sdp_get_majv(sdp_hdr->sdp_version) != SDP_MAJ_VERSION)
				return -EINVAL;
			sdp_set_ip_ver(sdp_hdr, 6);
			sdp_hdr->src_addr.ip6 = src6->sin6_addr;
			sdp_hdr->dst_addr.ip6 = dst6->sin6_addr;
			sdp_hdr->port = src6->sin6_port;
			break;
		default:
			cma_hdr = hdr;
			cma_hdr->cma_version = CMA_VERSION;
			cma_set_ip_ver(cma_hdr, 6);
			cma_hdr->src_addr.ip6 = src6->sin6_addr;
			cma_hdr->dst_addr.ip6 = dst6->sin6_addr;
			cma_hdr->port = src6->sin6_port;
			break;
		}
	}
	return 0;
}