rxe_net.c 14.8 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
M
Moni Shoua 已提交
2 3 4 5 6 7 8 9 10
/*
 * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
 * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
 */

#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/netdevice.h>
#include <linux/if.h>
11
#include <linux/if_vlan.h>
M
Moni Shoua 已提交
12 13 14 15 16 17 18 19 20
#include <net/udp_tunnel.h>
#include <net/sch_generic.h>
#include <linux/netfilter.h>
#include <rdma/ib_addr.h>

#include "rxe.h"
#include "rxe_net.h"
#include "rxe_loc.h"

21
static struct rxe_recv_sockets recv_sockets;
M
Moni Shoua 已提交
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58

static struct dst_entry *rxe_find_route4(struct net_device *ndev,
				  struct in_addr *saddr,
				  struct in_addr *daddr)
{
	struct rtable *rt;
	struct flowi4 fl = { { 0 } };

	memset(&fl, 0, sizeof(fl));
	fl.flowi4_oif = ndev->ifindex;
	memcpy(&fl.saddr, saddr, sizeof(*saddr));
	memcpy(&fl.daddr, daddr, sizeof(*daddr));
	fl.flowi4_proto = IPPROTO_UDP;

	rt = ip_route_output_key(&init_net, &fl);
	if (IS_ERR(rt)) {
		pr_err_ratelimited("no route to %pI4\n", &daddr->s_addr);
		return NULL;
	}

	return &rt->dst;
}

#if IS_ENABLED(CONFIG_IPV6)
static struct dst_entry *rxe_find_route6(struct net_device *ndev,
					 struct in6_addr *saddr,
					 struct in6_addr *daddr)
{
	struct dst_entry *ndst;
	struct flowi6 fl6 = { { 0 } };

	memset(&fl6, 0, sizeof(fl6));
	fl6.flowi6_oif = ndev->ifindex;
	memcpy(&fl6.saddr, saddr, sizeof(*saddr));
	memcpy(&fl6.daddr, daddr, sizeof(*daddr));
	fl6.flowi6_proto = IPPROTO_UDP;

59 60 61
	ndst = ipv6_stub->ipv6_dst_lookup_flow(sock_net(recv_sockets.sk6->sk),
					       recv_sockets.sk6->sk, &fl6,
					       NULL);
B
Bob Pearson 已提交
62
	if (IS_ERR(ndst)) {
M
Moni Shoua 已提交
63
		pr_err_ratelimited("no route to %pI6\n", daddr);
64
		return NULL;
M
Moni Shoua 已提交
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
	}

	if (unlikely(ndst->error)) {
		pr_err("no route to %pI6\n", daddr);
		goto put;
	}

	return ndst;
put:
	dst_release(ndst);
	return NULL;
}

#else

static struct dst_entry *rxe_find_route6(struct net_device *ndev,
					 struct in6_addr *saddr,
					 struct in6_addr *daddr)
{
	return NULL;
}

#endif

89
static struct dst_entry *rxe_find_route(struct net_device *ndev,
90 91 92 93 94 95 96 97
					struct rxe_qp *qp,
					struct rxe_av *av)
{
	struct dst_entry *dst = NULL;

	if (qp_type(qp) == IB_QPT_RC)
		dst = sk_dst_get(qp->sk->sk);

98
	if (!dst || !dst_check(dst, qp->dst_cookie)) {
99 100 101
		if (dst)
			dst_release(dst);

102
		if (av->network_type == RXE_NETWORK_TYPE_IPV4) {
103 104 105 106 107
			struct in_addr *saddr;
			struct in_addr *daddr;

			saddr = &av->sgid_addr._sockaddr_in.sin_addr;
			daddr = &av->dgid_addr._sockaddr_in.sin_addr;
108
			dst = rxe_find_route4(ndev, saddr, daddr);
109
		} else if (av->network_type == RXE_NETWORK_TYPE_IPV6) {
110 111 112 113 114
			struct in6_addr *saddr6;
			struct in6_addr *daddr6;

			saddr6 = &av->sgid_addr._sockaddr_in6.sin6_addr;
			daddr6 = &av->dgid_addr._sockaddr_in6.sin6_addr;
115
			dst = rxe_find_route6(ndev, saddr6, daddr6);
116 117 118 119 120
#if IS_ENABLED(CONFIG_IPV6)
			if (dst)
				qp->dst_cookie =
					rt6_get_cookie((struct rt6_info *)dst);
#endif
121
		}
122 123 124 125 126

		if (dst && (qp_type(qp) == IB_QPT_RC)) {
			dst_hold(dst);
			sk_dst_set(qp->sk->sk, dst);
		}
127 128 129 130
	}
	return dst;
}

M
Moni Shoua 已提交
131 132 133
static int rxe_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
{
	struct udphdr *udph;
134
	struct rxe_dev *rxe;
M
Moni Shoua 已提交
135 136 137
	struct net_device *ndev = skb->dev;
	struct rxe_pkt_info *pkt = SKB_TO_PKT(skb);

138 139 140 141
	/* takes a reference on rxe->ib_dev
	 * drop when skb is freed
	 */
	rxe = rxe_get_dev_from_net(ndev);
142 143
	if (!rxe && is_vlan_dev(ndev))
		rxe = rxe_get_dev_from_net(vlan_dev_real_dev(ndev));
M
Moni Shoua 已提交
144 145 146 147 148
	if (!rxe)
		goto drop;

	if (skb_linearize(skb)) {
		pr_err("skb_linearize failed\n");
149
		ib_device_put(&rxe->ib_dev);
M
Moni Shoua 已提交
150 151 152 153 154 155 156 157 158 159
		goto drop;
	}

	udph = udp_hdr(skb);
	pkt->rxe = rxe;
	pkt->port_num = 1;
	pkt->hdr = (u8 *)(udph + 1);
	pkt->mask = RXE_GRH_MASK;
	pkt->paylen = be16_to_cpu(udph->len) - sizeof(*udph);

160 161 162
	rxe_rcv(skb);

	return 0;
M
Moni Shoua 已提交
163 164
drop:
	kfree_skb(skb);
165

M
Moni Shoua 已提交
166 167 168 169 170 171 172 173
	return 0;
}

static struct socket *rxe_setup_udp_tunnel(struct net *net, __be16 port,
					   bool ipv6)
{
	int err;
	struct socket *sock;
174 175
	struct udp_port_cfg udp_cfg = { };
	struct udp_tunnel_sock_cfg tnl_cfg = { };
M
Moni Shoua 已提交
176 177 178 179 180 181 182 183 184 185 186 187

	if (ipv6) {
		udp_cfg.family = AF_INET6;
		udp_cfg.ipv6_v6only = 1;
	} else {
		udp_cfg.family = AF_INET;
	}

	udp_cfg.local_udp_port = port;

	/* Create UDP socket */
	err = udp_sock_create(net, &udp_cfg, &sock);
188
	if (err < 0)
M
Moni Shoua 已提交
189 190 191 192 193 194 195 196 197 198 199
		return ERR_PTR(err);

	tnl_cfg.encap_type = 1;
	tnl_cfg.encap_rcv = rxe_udp_encap_recv;

	/* Setup UDP tunnel */
	setup_udp_tunnel_sock(net, sock, &tnl_cfg);

	return sock;
}

200
static void rxe_release_udp_tunnel(struct socket *sk)
M
Moni Shoua 已提交
201
{
202 203
	if (sk)
		udp_tunnel_sock_release(sk);
M
Moni Shoua 已提交
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
}

static void prepare_udp_hdr(struct sk_buff *skb, __be16 src_port,
			    __be16 dst_port)
{
	struct udphdr *udph;

	__skb_push(skb, sizeof(*udph));
	skb_reset_transport_header(skb);
	udph = udp_hdr(skb);

	udph->dest = dst_port;
	udph->source = src_port;
	udph->len = htons(skb->len);
	udph->check = 0;
}

static void prepare_ipv4_hdr(struct dst_entry *dst, struct sk_buff *skb,
			     __be32 saddr, __be32 daddr, __u8 proto,
			     __u8 tos, __u8 ttl, __be16 df, bool xnet)
{
	struct iphdr *iph;

	skb_scrub_packet(skb, xnet);

	skb_clear_hash(skb);
230
	skb_dst_set(skb, dst_clone(dst));
M
Moni Shoua 已提交
231 232 233 234 235 236 237 238 239
	memset(IPCB(skb), 0, sizeof(*IPCB(skb)));

	skb_push(skb, sizeof(struct iphdr));
	skb_reset_network_header(skb);

	iph = ip_hdr(skb);

	iph->version	=	IPVERSION;
	iph->ihl	=	sizeof(struct iphdr) >> 2;
240
	iph->tot_len	=	htons(skb->len);
M
Moni Shoua 已提交
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
	iph->frag_off	=	df;
	iph->protocol	=	proto;
	iph->tos	=	tos;
	iph->daddr	=	daddr;
	iph->saddr	=	saddr;
	iph->ttl	=	ttl;
	__ip_select_ident(dev_net(dst->dev), iph,
			  skb_shinfo(skb)->gso_segs ?: 1);
}

static void prepare_ipv6_hdr(struct dst_entry *dst, struct sk_buff *skb,
			     struct in6_addr *saddr, struct in6_addr *daddr,
			     __u8 proto, __u8 prio, __u8 ttl)
{
	struct ipv6hdr *ip6h;

	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
	IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED
			    | IPSKB_REROUTED);
260
	skb_dst_set(skb, dst_clone(dst));
M
Moni Shoua 已提交
261 262 263 264 265 266 267 268 269 270 271 272 273

	__skb_push(skb, sizeof(*ip6h));
	skb_reset_network_header(skb);
	ip6h		  = ipv6_hdr(skb);
	ip6_flow_hdr(ip6h, prio, htonl(0));
	ip6h->payload_len = htons(skb->len);
	ip6h->nexthdr     = proto;
	ip6h->hop_limit   = ttl;
	ip6h->daddr	  = *daddr;
	ip6h->saddr	  = *saddr;
	ip6h->payload_len = htons(skb->len - sizeof(*ip6h));
}

274 275
static int prepare4(struct rxe_av *av, struct rxe_pkt_info *pkt,
		    struct sk_buff *skb)
M
Moni Shoua 已提交
276
{
277
	struct rxe_qp *qp = pkt->qp;
M
Moni Shoua 已提交
278 279 280 281 282 283
	struct dst_entry *dst;
	bool xnet = false;
	__be16 df = htons(IP_DF);
	struct in_addr *saddr = &av->sgid_addr._sockaddr_in.sin_addr;
	struct in_addr *daddr = &av->dgid_addr._sockaddr_in.sin_addr;

284
	dst = rxe_find_route(skb->dev, qp, av);
M
Moni Shoua 已提交
285 286 287 288 289
	if (!dst) {
		pr_err("Host not reachable\n");
		return -EHOSTUNREACH;
	}

290 291
	prepare_udp_hdr(skb, cpu_to_be16(qp->src_port),
			cpu_to_be16(ROCE_V2_UDP_DPORT));
M
Moni Shoua 已提交
292 293 294

	prepare_ipv4_hdr(dst, skb, saddr->s_addr, daddr->s_addr, IPPROTO_UDP,
			 av->grh.traffic_class, av->grh.hop_limit, df, xnet);
295

296
	dst_release(dst);
M
Moni Shoua 已提交
297 298 299
	return 0;
}

300 301
static int prepare6(struct rxe_av *av, struct rxe_pkt_info *pkt,
		    struct sk_buff *skb)
M
Moni Shoua 已提交
302
{
303
	struct rxe_qp *qp = pkt->qp;
304
	struct dst_entry *dst;
M
Moni Shoua 已提交
305 306 307
	struct in6_addr *saddr = &av->sgid_addr._sockaddr_in6.sin6_addr;
	struct in6_addr *daddr = &av->dgid_addr._sockaddr_in6.sin6_addr;

308
	dst = rxe_find_route(skb->dev, qp, av);
M
Moni Shoua 已提交
309 310 311 312 313
	if (!dst) {
		pr_err("Host not reachable\n");
		return -EHOSTUNREACH;
	}

314 315
	prepare_udp_hdr(skb, cpu_to_be16(qp->src_port),
			cpu_to_be16(ROCE_V2_UDP_DPORT));
M
Moni Shoua 已提交
316 317 318 319

	prepare_ipv6_hdr(dst, skb, saddr, daddr, IPPROTO_UDP,
			 av->grh.traffic_class,
			 av->grh.hop_limit);
320

321
	dst_release(dst);
M
Moni Shoua 已提交
322 323 324
	return 0;
}

325 326
int rxe_prepare(struct rxe_av *av, struct rxe_pkt_info *pkt,
		struct sk_buff *skb)
M
Moni Shoua 已提交
327 328 329
{
	int err = 0;

330
	if (skb->protocol == htons(ETH_P_IP))
331
		err = prepare4(av, pkt, skb);
332
	else if (skb->protocol == htons(ETH_P_IPV6))
333
		err = prepare6(av, pkt, skb);
M
Moni Shoua 已提交
334

335
	if (ether_addr_equal(skb->dev->dev_addr, av->dmac))
K
Kamal Heib 已提交
336 337
		pkt->mask |= RXE_LOOPBACK_MASK;

M
Moni Shoua 已提交
338 339 340 341 342 343 344 345 346 347 348 349
	return err;
}

static void rxe_skb_tx_dtor(struct sk_buff *skb)
{
	struct sock *sk = skb->sk;
	struct rxe_qp *qp = sk->sk_user_data;
	int skb_out = atomic_dec_return(&qp->skb_out);

	if (unlikely(qp->need_req_skb &&
		     skb_out < RXE_INFLIGHT_SKBS_PER_QP_LOW))
		rxe_run_task(&qp->req.task, 1);
350 351

	rxe_drop_ref(qp);
M
Moni Shoua 已提交
352 353
}

354
static int rxe_send(struct sk_buff *skb, struct rxe_pkt_info *pkt)
M
Moni Shoua 已提交
355 356 357
{
	int err;

358 359
	skb->destructor = rxe_skb_tx_dtor;
	skb->sk = pkt->qp->sk->sk;
M
Moni Shoua 已提交
360

361 362 363
	rxe_add_ref(pkt->qp);
	atomic_inc(&pkt->qp->skb_out);

364
	if (skb->protocol == htons(ETH_P_IP)) {
365
		err = ip_local_out(dev_net(skb_dst(skb)->dev), skb->sk, skb);
366
	} else if (skb->protocol == htons(ETH_P_IPV6)) {
367
		err = ip6_local_out(dev_net(skb_dst(skb)->dev), skb->sk, skb);
M
Moni Shoua 已提交
368
	} else {
369
		pr_err("Unknown layer 3 protocol: %d\n", skb->protocol);
370 371
		atomic_dec(&pkt->qp->skb_out);
		rxe_drop_ref(pkt->qp);
372
		kfree_skb(skb);
M
Moni Shoua 已提交
373 374 375 376 377 378 379 380 381 382 383
		return -EINVAL;
	}

	if (unlikely(net_xmit_eval(err))) {
		pr_debug("error sending packet: %d\n", err);
		return -EAGAIN;
	}

	return 0;
}

384 385 386
/* fix up a send packet to match the packets
 * received from UDP before looping them back
 */
387
static int rxe_loopback(struct sk_buff *skb, struct rxe_pkt_info *pkt)
M
Moni Shoua 已提交
388
{
389
	memcpy(SKB_TO_PKT(skb), pkt, sizeof(*pkt));
390

391 392 393 394 395
	if (skb->protocol == htons(ETH_P_IP))
		skb_pull(skb, sizeof(struct iphdr));
	else
		skb_pull(skb, sizeof(struct ipv6hdr));

396
	if (WARN_ON(!ib_device_try_get(&pkt->rxe->ib_dev))) {
397
		kfree_skb(skb);
398 399 400 401 402 403
		return -EIO;
	}

	rxe_rcv(skb);

	return 0;
M
Moni Shoua 已提交
404 405
}

406 407 408 409 410 411 412 413 414 415 416 417 418
int rxe_xmit_packet(struct rxe_qp *qp, struct rxe_pkt_info *pkt,
		    struct sk_buff *skb)
{
	int err;
	int is_request = pkt->mask & RXE_REQ_MASK;
	struct rxe_dev *rxe = to_rdev(qp->ibqp.device);

	if ((is_request && (qp->req.state != QP_STATE_READY)) ||
	    (!is_request && (qp->resp.state != QP_STATE_READY))) {
		pr_info("Packet dropped. QP is not in ready state\n");
		goto drop;
	}

419 420
	rxe_icrc_generate(skb, pkt);

421 422 423 424
	if (pkt->mask & RXE_LOOPBACK_MASK)
		err = rxe_loopback(skb, pkt);
	else
		err = rxe_send(skb, pkt);
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
	if (err) {
		rxe_counter_inc(rxe, RXE_CNT_SEND_ERR);
		return err;
	}

	if ((qp_type(qp) != IB_QPT_RC) &&
	    (pkt->mask & RXE_END_MASK)) {
		pkt->wqe->state = wqe_state_done;
		rxe_run_task(&qp->comp.task, 1);
	}

	rxe_counter_inc(rxe, RXE_CNT_SENT_PKTS);
	goto done;

drop:
	kfree_skb(skb);
	err = 0;
done:
	return err;
}

446 447
struct sk_buff *rxe_init_packet(struct rxe_dev *rxe, struct rxe_av *av,
				int paylen, struct rxe_pkt_info *pkt)
M
Moni Shoua 已提交
448 449
{
	unsigned int hdr_len;
450
	struct sk_buff *skb = NULL;
451
	struct net_device *ndev;
P
Parav Pandit 已提交
452
	const struct ib_gid_attr *attr;
453 454
	const int port_num = 1;

P
Parav Pandit 已提交
455 456 457
	attr = rdma_get_gid_attr(&rxe->ib_dev, port_num, av->grh.sgid_index);
	if (IS_ERR(attr))
		return NULL;
M
Moni Shoua 已提交
458

459
	if (av->network_type == RXE_NETWORK_TYPE_IPV4)
M
Moni Shoua 已提交
460 461 462 463 464 465
		hdr_len = ETH_HLEN + sizeof(struct udphdr) +
			sizeof(struct iphdr);
	else
		hdr_len = ETH_HLEN + sizeof(struct udphdr) +
			sizeof(struct ipv6hdr);

466 467 468 469 470 471
	rcu_read_lock();
	ndev = rdma_read_gid_attr_ndev_rcu(attr);
	if (IS_ERR(ndev)) {
		rcu_read_unlock();
		goto out;
	}
472
	skb = alloc_skb(paylen + hdr_len + LL_RESERVED_SPACE(ndev),
M
Moni Shoua 已提交
473
			GFP_ATOMIC);
474

475 476
	if (unlikely(!skb)) {
		rcu_read_unlock();
P
Parav Pandit 已提交
477
		goto out;
478
	}
M
Moni Shoua 已提交
479

480
	skb_reserve(skb, hdr_len + LL_RESERVED_SPACE(ndev));
M
Moni Shoua 已提交
481

482
	/* FIXME: hold reference to this netdev until life of this skb. */
483
	skb->dev	= ndev;
484 485
	rcu_read_unlock();

486
	if (av->network_type == RXE_NETWORK_TYPE_IPV4)
M
Moni Shoua 已提交
487 488 489 490 491
		skb->protocol = htons(ETH_P_IP);
	else
		skb->protocol = htons(ETH_P_IPV6);

	pkt->rxe	= rxe;
492
	pkt->port_num	= port_num;
493
	pkt->hdr	= skb_put(skb, paylen);
M
Moni Shoua 已提交
494 495
	pkt->mask	|= RXE_GRH_MASK;

P
Parav Pandit 已提交
496 497
out:
	rdma_put_gid_attr(attr);
M
Moni Shoua 已提交
498 499 500 501 502 503 504
	return skb;
}

/*
 * this is required by rxe_cfg to match rxe devices in
 * /sys/class/infiniband up with their underlying ethernet devices
 */
505
const char *rxe_parent_name(struct rxe_dev *rxe, unsigned int port_num)
M
Moni Shoua 已提交
506 507 508 509
{
	return rxe->ndev->name;
}

510
int rxe_net_add(const char *ibdev_name, struct net_device *ndev)
M
Moni Shoua 已提交
511 512 513 514
{
	int err;
	struct rxe_dev *rxe = NULL;

515
	rxe = ib_alloc_device(rxe_dev, ib_dev);
M
Moni Shoua 已提交
516
	if (!rxe)
517
		return -ENOMEM;
M
Moni Shoua 已提交
518 519 520

	rxe->ndev = ndev;

521
	err = rxe_add(rxe, ndev->mtu, ibdev_name);
M
Moni Shoua 已提交
522 523
	if (err) {
		ib_dealloc_device(&rxe->ib_dev);
524
		return err;
M
Moni Shoua 已提交
525 526
	}

527
	return 0;
M
Moni Shoua 已提交
528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
}

static void rxe_port_event(struct rxe_dev *rxe,
			   enum ib_event_type event)
{
	struct ib_event ev;

	ev.device = &rxe->ib_dev;
	ev.element.port_num = 1;
	ev.event = event;

	ib_dispatch_event(&ev);
}

/* Caller must hold net_info_lock */
void rxe_port_up(struct rxe_dev *rxe)
{
	struct rxe_port *port;

	port = &rxe->port;
	port->attr.state = IB_PORT_ACTIVE;

	rxe_port_event(rxe, IB_EVENT_PORT_ACTIVE);
551
	dev_info(&rxe->ib_dev.dev, "set active\n");
M
Moni Shoua 已提交
552 553 554 555 556 557 558 559 560 561 562
}

/* Caller must hold net_info_lock */
void rxe_port_down(struct rxe_dev *rxe)
{
	struct rxe_port *port;

	port = &rxe->port;
	port->attr.state = IB_PORT_DOWN;

	rxe_port_event(rxe, IB_EVENT_PORT_ERR);
563
	rxe_counter_inc(rxe, RXE_CNT_LINK_DOWNED);
564
	dev_info(&rxe->ib_dev.dev, "set down\n");
M
Moni Shoua 已提交
565 566
}

567 568 569 570 571 572 573 574
void rxe_set_port_state(struct rxe_dev *rxe)
{
	if (netif_running(rxe->ndev) && netif_carrier_ok(rxe->ndev))
		rxe_port_up(rxe);
	else
		rxe_port_down(rxe);
}

M
Moni Shoua 已提交
575 576 577 578 579
static int rxe_notify(struct notifier_block *not_blk,
		      unsigned long event,
		      void *arg)
{
	struct net_device *ndev = netdev_notifier_info_to_dev(arg);
580
	struct rxe_dev *rxe = rxe_get_dev_from_net(ndev);
M
Moni Shoua 已提交
581 582

	if (!rxe)
583
		return NOTIFY_OK;
M
Moni Shoua 已提交
584 585 586

	switch (event) {
	case NETDEV_UNREGISTER:
587 588
		ib_unregister_device_queued(&rxe->ib_dev);
		break;
M
Moni Shoua 已提交
589 590 591 592 593 594 595
	case NETDEV_UP:
		rxe_port_up(rxe);
		break;
	case NETDEV_DOWN:
		rxe_port_down(rxe);
		break;
	case NETDEV_CHANGEMTU:
596
		pr_info("%s changed mtu to %d\n", ndev->name, ndev->mtu);
M
Moni Shoua 已提交
597 598 599
		rxe_set_mtu(rxe, ndev->mtu);
		break;
	case NETDEV_CHANGE:
600
		rxe_set_port_state(rxe);
601 602
		break;
	case NETDEV_REBOOT:
M
Moni Shoua 已提交
603 604 605 606 607
	case NETDEV_GOING_DOWN:
	case NETDEV_CHANGEADDR:
	case NETDEV_CHANGENAME:
	case NETDEV_FEAT_CHANGE:
	default:
608
		pr_info("ignoring netdev event = %ld for %s\n",
M
Moni Shoua 已提交
609 610 611
			event, ndev->name);
		break;
	}
612 613

	ib_device_put(&rxe->ib_dev);
M
Moni Shoua 已提交
614 615 616
	return NOTIFY_OK;
}

Z
Zhu Yanjun 已提交
617
static struct notifier_block rxe_net_notifier = {
M
Moni Shoua 已提交
618 619 620
	.notifier_call = rxe_notify,
};

621
static int rxe_net_ipv4_init(void)
M
Moni Shoua 已提交
622 623
{
	recv_sockets.sk4 = rxe_setup_udp_tunnel(&init_net,
624
				htons(ROCE_V2_UDP_DPORT), false);
M
Moni Shoua 已提交
625 626
	if (IS_ERR(recv_sockets.sk4)) {
		recv_sockets.sk4 = NULL;
627
		pr_err("Failed to create IPv4 UDP tunnel\n");
M
Moni Shoua 已提交
628 629 630
		return -1;
	}

631
	return 0;
M
Moni Shoua 已提交
632 633
}

634
static int rxe_net_ipv6_init(void)
M
Moni Shoua 已提交
635
{
636
#if IS_ENABLED(CONFIG_IPV6)
M
Moni Shoua 已提交
637

638 639
	recv_sockets.sk6 = rxe_setup_udp_tunnel(&init_net,
						htons(ROCE_V2_UDP_DPORT), true);
640 641 642 643 644 645
	if (PTR_ERR(recv_sockets.sk6) == -EAFNOSUPPORT) {
		recv_sockets.sk6 = NULL;
		pr_warn("IPv6 is not supported, can not create a UDPv6 socket\n");
		return 0;
	}

646 647
	if (IS_ERR(recv_sockets.sk6)) {
		recv_sockets.sk6 = NULL;
648
		pr_err("Failed to create IPv6 UDP tunnel\n");
649 650 651 652 653 654 655 656 657 658
		return -1;
	}
#endif
	return 0;
}

void rxe_net_exit(void)
{
	rxe_release_udp_tunnel(recv_sockets.sk6);
	rxe_release_udp_tunnel(recv_sockets.sk4);
M
Moni Shoua 已提交
659 660
	unregister_netdevice_notifier(&rxe_net_notifier);
}
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683

int rxe_net_init(void)
{
	int err;

	recv_sockets.sk6 = NULL;

	err = rxe_net_ipv4_init();
	if (err)
		return err;
	err = rxe_net_ipv6_init();
	if (err)
		goto err_out;
	err = register_netdevice_notifier(&rxe_net_notifier);
	if (err) {
		pr_err("Failed to register netdev notifier\n");
		goto err_out;
	}
	return 0;
err_out:
	rxe_net_exit();
	return err;
}