1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
3 * Copyright (c) 2020 Mellanox Technologies. All rights reserved.
6 #include <rdma/ib_verbs.h>
7 #include <rdma/ib_cache.h>
10 static struct sk_buff
*rdma_build_skb(struct ib_device
*device
,
11 struct net_device
*netdev
,
12 struct rdma_ah_attr
*ah_attr
,
24 is_ipv4
= ipv6_addr_v4mapped((struct in6_addr
*)ah_attr
->grh
.dgid
.raw
);
25 hdr_len
= ETH_HLEN
+ sizeof(struct udphdr
) + LL_RESERVED_SPACE(netdev
);
26 hdr_len
+= is_ipv4
? sizeof(struct iphdr
) : sizeof(struct ipv6hdr
);
28 skb
= alloc_skb(hdr_len
, flags
);
33 skb_reserve(skb
, hdr_len
);
34 skb_push(skb
, sizeof(struct udphdr
));
35 skb_reset_transport_header(skb
);
38 htons(rdma_flow_label_to_udp_sport(ah_attr
->grh
.flow_label
));
39 uh
->dest
= htons(ROCE_V2_UDP_DPORT
);
40 uh
->len
= htons(sizeof(struct udphdr
));
43 skb_push(skb
, sizeof(struct iphdr
));
44 skb_reset_network_header(skb
);
48 iph
->protocol
= IPPROTO_UDP
;
50 iph
->tot_len
= htons(sizeof(struct udphdr
) + sizeof(struct
52 memcpy(&iph
->saddr
, ah_attr
->grh
.sgid_attr
->gid
.raw
+ 12,
53 sizeof(struct in_addr
));
54 memcpy(&iph
->daddr
, ah_attr
->grh
.dgid
.raw
+ 12,
55 sizeof(struct in_addr
));
57 skb_push(skb
, sizeof(struct ipv6hdr
));
58 skb_reset_network_header(skb
);
61 ip6h
->nexthdr
= IPPROTO_UDP
;
62 memcpy(&ip6h
->flow_lbl
, &ah_attr
->grh
.flow_label
,
63 sizeof(*ip6h
->flow_lbl
));
64 memcpy(&ip6h
->saddr
, ah_attr
->grh
.sgid_attr
->gid
.raw
,
65 sizeof(struct in6_addr
));
66 memcpy(&ip6h
->daddr
, ah_attr
->grh
.dgid
.raw
,
67 sizeof(struct in6_addr
));
70 skb_push(skb
, sizeof(struct ethhdr
));
71 skb_reset_mac_header(skb
);
73 skb
->protocol
= eth
->h_proto
= htons(is_ipv4
? ETH_P_IP
: ETH_P_IPV6
);
74 rdma_read_gid_l2_fields(ah_attr
->grh
.sgid_attr
, NULL
, smac
);
75 memcpy(eth
->h_source
, smac
, ETH_ALEN
);
76 memcpy(eth
->h_dest
, ah_attr
->roce
.dmac
, ETH_ALEN
);
81 static struct net_device
*rdma_get_xmit_slave_udp(struct ib_device
*device
,
82 struct net_device
*master
,
83 struct rdma_ah_attr
*ah_attr
,
86 struct net_device
*slave
;
89 skb
= rdma_build_skb(device
, master
, ah_attr
, flags
);
91 return ERR_PTR(-ENOMEM
);
94 slave
= netdev_get_xmit_slave(master
, skb
,
95 !!(device
->lag_flags
&
96 RDMA_LAG_FLAGS_HASH_ALL_SLAVES
));
104 void rdma_lag_put_ah_roce_slave(struct net_device
*xmit_slave
)
110 struct net_device
*rdma_lag_get_ah_roce_slave(struct ib_device
*device
,
111 struct rdma_ah_attr
*ah_attr
,
114 struct net_device
*slave
= NULL
;
115 struct net_device
*master
;
117 if (!(ah_attr
->type
== RDMA_AH_ATTR_TYPE_ROCE
&&
118 ah_attr
->grh
.sgid_attr
->gid_type
== IB_GID_TYPE_ROCE_UDP_ENCAP
&&
119 ah_attr
->grh
.flow_label
))
123 master
= rdma_read_gid_attr_ndev_rcu(ah_attr
->grh
.sgid_attr
);
124 if (IS_ERR(master
)) {
131 if (!netif_is_bond_master(master
))
134 slave
= rdma_get_xmit_slave_udp(device
, master
, ah_attr
, flags
);