.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved. |
---|
3 | 4 | * Copyright (c) 2015 System Fabric Works, 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 | | - * OpenIB.org 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 | 5 | */ |
---|
33 | 6 | |
---|
34 | 7 | #include <linux/skbuff.h> |
---|
.. | .. |
---|
106 | 79 | static int check_keys(struct rxe_dev *rxe, struct rxe_pkt_info *pkt, |
---|
107 | 80 | u32 qpn, struct rxe_qp *qp) |
---|
108 | 81 | { |
---|
109 | | - int i; |
---|
110 | | - int found_pkey = 0; |
---|
111 | 82 | struct rxe_port *port = &rxe->port; |
---|
112 | 83 | u16 pkey = bth_pkey(pkt); |
---|
113 | 84 | |
---|
114 | 85 | pkt->pkey_index = 0; |
---|
115 | 86 | |
---|
116 | | - if (qpn == 1) { |
---|
117 | | - for (i = 0; i < port->attr.pkey_tbl_len; i++) { |
---|
118 | | - if (pkey_match(pkey, port->pkey_tbl[i])) { |
---|
119 | | - pkt->pkey_index = i; |
---|
120 | | - found_pkey = 1; |
---|
121 | | - break; |
---|
122 | | - } |
---|
123 | | - } |
---|
124 | | - |
---|
125 | | - if (!found_pkey) { |
---|
126 | | - pr_warn_ratelimited("bad pkey = 0x%x\n", pkey); |
---|
127 | | - set_bad_pkey_cntr(port); |
---|
128 | | - goto err1; |
---|
129 | | - } |
---|
130 | | - } else if (qpn != 0) { |
---|
131 | | - if (unlikely(!pkey_match(pkey, |
---|
132 | | - port->pkey_tbl[qp->attr.pkey_index] |
---|
133 | | - ))) { |
---|
134 | | - pr_warn_ratelimited("bad pkey = 0x%0x\n", pkey); |
---|
135 | | - set_bad_pkey_cntr(port); |
---|
136 | | - goto err1; |
---|
137 | | - } |
---|
138 | | - pkt->pkey_index = qp->attr.pkey_index; |
---|
| 87 | + if (!pkey_match(pkey, IB_DEFAULT_PKEY_FULL)) { |
---|
| 88 | + pr_warn_ratelimited("bad pkey = 0x%x\n", pkey); |
---|
| 89 | + set_bad_pkey_cntr(port); |
---|
| 90 | + goto err1; |
---|
139 | 91 | } |
---|
140 | 92 | |
---|
141 | 93 | if ((qp_type(qp) == IB_QPT_UD || qp_type(qp) == IB_QPT_GSI) && |
---|
142 | | - qpn != 0 && pkt->mask) { |
---|
| 94 | + pkt->mask) { |
---|
143 | 95 | u32 qkey = (qpn == 1) ? GSI_QKEY : qp->attr.qkey; |
---|
144 | 96 | |
---|
145 | 97 | if (unlikely(deth_qkey(pkt) != qkey)) { |
---|
.. | .. |
---|
271 | 223 | return -EINVAL; |
---|
272 | 224 | } |
---|
273 | 225 | |
---|
274 | | -static inline void rxe_rcv_pkt(struct rxe_dev *rxe, |
---|
275 | | - struct rxe_pkt_info *pkt, |
---|
276 | | - struct sk_buff *skb) |
---|
| 226 | +static inline void rxe_rcv_pkt(struct rxe_pkt_info *pkt, struct sk_buff *skb) |
---|
277 | 227 | { |
---|
278 | 228 | if (pkt->mask & RXE_REQ_MASK) |
---|
279 | | - rxe_resp_queue_pkt(rxe, pkt->qp, skb); |
---|
| 229 | + rxe_resp_queue_pkt(pkt->qp, skb); |
---|
280 | 230 | else |
---|
281 | | - rxe_comp_queue_pkt(rxe, pkt->qp, skb); |
---|
| 231 | + rxe_comp_queue_pkt(pkt->qp, skb); |
---|
282 | 232 | } |
---|
283 | 233 | |
---|
284 | 234 | static void rxe_rcv_mcast_pkt(struct rxe_dev *rxe, struct sk_buff *skb) |
---|
.. | .. |
---|
288 | 238 | struct rxe_mc_elem *mce; |
---|
289 | 239 | struct rxe_qp *qp; |
---|
290 | 240 | union ib_gid dgid; |
---|
| 241 | + struct sk_buff *per_qp_skb; |
---|
| 242 | + struct rxe_pkt_info *per_qp_pkt; |
---|
291 | 243 | int err; |
---|
292 | 244 | |
---|
293 | 245 | if (skb->protocol == htons(ETH_P_IP)) |
---|
.. | .. |
---|
305 | 257 | |
---|
306 | 258 | list_for_each_entry(mce, &mcg->qp_list, qp_list) { |
---|
307 | 259 | qp = mce->qp; |
---|
308 | | - pkt = SKB_TO_PKT(skb); |
---|
309 | 260 | |
---|
310 | 261 | /* validate qp for incoming packet */ |
---|
311 | 262 | err = check_type_state(rxe, pkt, qp); |
---|
.. | .. |
---|
316 | 267 | if (err) |
---|
317 | 268 | continue; |
---|
318 | 269 | |
---|
319 | | - /* if *not* the last qp in the list |
---|
320 | | - * increase the users of the skb then post to the next qp |
---|
| 270 | + /* for all but the last qp create a new clone of the |
---|
| 271 | + * skb and pass to the qp. If an error occurs in the |
---|
| 272 | + * checks for the last qp in the list we need to |
---|
| 273 | + * free the skb since it hasn't been passed on to |
---|
| 274 | + * rxe_rcv_pkt() which would free it later. |
---|
321 | 275 | */ |
---|
322 | | - if (mce->qp_list.next != &mcg->qp_list) |
---|
323 | | - skb_get(skb); |
---|
| 276 | + if (mce->qp_list.next != &mcg->qp_list) { |
---|
| 277 | + per_qp_skb = skb_clone(skb, GFP_ATOMIC); |
---|
| 278 | + } else { |
---|
| 279 | + per_qp_skb = skb; |
---|
| 280 | + /* show we have consumed the skb */ |
---|
| 281 | + skb = NULL; |
---|
| 282 | + } |
---|
324 | 283 | |
---|
325 | | - pkt->qp = qp; |
---|
| 284 | + if (unlikely(!per_qp_skb)) |
---|
| 285 | + continue; |
---|
| 286 | + |
---|
| 287 | + per_qp_pkt = SKB_TO_PKT(per_qp_skb); |
---|
| 288 | + per_qp_pkt->qp = qp; |
---|
326 | 289 | rxe_add_ref(qp); |
---|
327 | | - rxe_rcv_pkt(rxe, pkt, skb); |
---|
| 290 | + rxe_rcv_pkt(per_qp_pkt, per_qp_skb); |
---|
328 | 291 | } |
---|
329 | 292 | |
---|
330 | 293 | spin_unlock_bh(&mcg->mcg_lock); |
---|
.. | .. |
---|
332 | 295 | rxe_drop_ref(mcg); /* drop ref from rxe_pool_get_key. */ |
---|
333 | 296 | |
---|
334 | 297 | err1: |
---|
| 298 | + /* free skb if not consumed */ |
---|
335 | 299 | kfree_skb(skb); |
---|
336 | 300 | } |
---|
337 | 301 | |
---|
338 | | -static int rxe_match_dgid(struct rxe_dev *rxe, struct sk_buff *skb) |
---|
| 302 | +/** |
---|
| 303 | + * rxe_chk_dgid - validate destination IP address |
---|
| 304 | + * @rxe: rxe device that received packet |
---|
| 305 | + * @skb: the received packet buffer |
---|
| 306 | + * |
---|
| 307 | + * Accept any loopback packets |
---|
| 308 | + * Extract IP address from packet and |
---|
| 309 | + * Accept if multicast packet |
---|
| 310 | + * Accept if matches an SGID table entry |
---|
| 311 | + */ |
---|
| 312 | +static int rxe_chk_dgid(struct rxe_dev *rxe, struct sk_buff *skb) |
---|
339 | 313 | { |
---|
340 | 314 | struct rxe_pkt_info *pkt = SKB_TO_PKT(skb); |
---|
341 | 315 | const struct ib_gid_attr *gid_attr; |
---|
.. | .. |
---|
352 | 326 | } else { |
---|
353 | 327 | pdgid = (union ib_gid *)&ipv6_hdr(skb)->daddr; |
---|
354 | 328 | } |
---|
| 329 | + |
---|
| 330 | + if (rdma_is_multicast_addr((struct in6_addr *)pdgid)) |
---|
| 331 | + return 0; |
---|
355 | 332 | |
---|
356 | 333 | gid_attr = rdma_find_gid_by_port(&rxe->ib_dev, pdgid, |
---|
357 | 334 | IB_GID_TYPE_ROCE_UDP_ENCAP, |
---|
.. | .. |
---|
377 | 354 | if (unlikely(skb->len < pkt->offset + RXE_BTH_BYTES)) |
---|
378 | 355 | goto drop; |
---|
379 | 356 | |
---|
380 | | - if (rxe_match_dgid(rxe, skb) < 0) { |
---|
381 | | - pr_warn_ratelimited("failed matching dgid\n"); |
---|
| 357 | + if (rxe_chk_dgid(rxe, skb) < 0) { |
---|
| 358 | + pr_warn_ratelimited("failed checking dgid\n"); |
---|
382 | 359 | goto drop; |
---|
383 | 360 | } |
---|
384 | 361 | |
---|
.. | .. |
---|
420 | 397 | if (unlikely(bth_qpn(pkt) == IB_MULTICAST_QPN)) |
---|
421 | 398 | rxe_rcv_mcast_pkt(rxe, skb); |
---|
422 | 399 | else |
---|
423 | | - rxe_rcv_pkt(rxe, pkt, skb); |
---|
| 400 | + rxe_rcv_pkt(pkt, skb); |
---|
424 | 401 | |
---|
425 | 402 | return; |
---|
426 | 403 | |
---|