hc
2023-12-06 08f87f769b595151be1afeff53e144f543faa614
kernel/drivers/scsi/qedf/qedf_fip.c
....@@ -1,10 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * QLogic FCoE Offload Driver
34 * Copyright (c) 2016-2018 Cavium Inc.
4
- *
5
- * This software is available under the terms of the GNU General Public License
6
- * (GPL) Version 2, available from the file COPYING in the main directory of
7
- * this source tree.
85 */
96 #include <linux/if_ether.h>
107 #include <linux/if_vlan.h>
....@@ -19,17 +16,19 @@
1916 {
2017 struct sk_buff *skb;
2118 char *eth_fr;
22
- int fr_len;
2319 struct fip_vlan *vlan;
2420 #define MY_FIP_ALL_FCF_MACS ((__u8[6]) { 1, 0x10, 0x18, 1, 0, 2 })
2521 static u8 my_fcoe_all_fcfs[ETH_ALEN] = MY_FIP_ALL_FCF_MACS;
2622 unsigned long flags = 0;
23
+ int rc;
2724
2825 skb = dev_alloc_skb(sizeof(struct fip_vlan));
29
- if (!skb)
26
+ if (!skb) {
27
+ QEDF_ERR(&qedf->dbg_ctx,
28
+ "Failed to allocate skb.\n");
3029 return;
30
+ }
3131
32
- fr_len = sizeof(*vlan);
3332 eth_fr = (char *)skb->data;
3433 vlan = (struct fip_vlan *)eth_fr;
3534
....@@ -68,7 +67,13 @@
6867 }
6968
7069 set_bit(QED_LL2_XMIT_FLAGS_FIP_DISCOVERY, &flags);
71
- qed_ops->ll2->start_xmit(qedf->cdev, skb, flags);
70
+ rc = qed_ops->ll2->start_xmit(qedf->cdev, skb, flags);
71
+ if (rc) {
72
+ QEDF_ERR(&qedf->dbg_ctx, "start_xmit failed rc = %d.\n", rc);
73
+ kfree_skb(skb);
74
+ return;
75
+ }
76
+
7277 }
7378
7479 static void qedf_fcoe_process_vlan_resp(struct qedf_ctx *qedf,
....@@ -95,6 +100,12 @@
95100 rlen -= dlen;
96101 }
97102
103
+ if (atomic_read(&qedf->link_state) == QEDF_LINK_DOWN) {
104
+ QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC,
105
+ "Dropping VLAN response as link is down.\n");
106
+ return;
107
+ }
108
+
98109 QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, "VLAN response, "
99110 "vid=0x%x.\n", vid);
100111
....@@ -114,6 +125,7 @@
114125 struct fip_header *fiph;
115126 u16 op, vlan_tci = 0;
116127 u8 sub;
128
+ int rc = -1;
117129
118130 if (!test_bit(QEDF_LL2_STARTED, &qedf->flags)) {
119131 QEDF_WARN(&(qedf->dbg_ctx), "LL2 not started\n");
....@@ -142,8 +154,15 @@
142154 print_hex_dump(KERN_WARNING, "fip ", DUMP_PREFIX_OFFSET, 16, 1,
143155 skb->data, skb->len, false);
144156
145
- qed_ops->ll2->start_xmit(qedf->cdev, skb, 0);
157
+ rc = qed_ops->ll2->start_xmit(qedf->cdev, skb, 0);
158
+ if (rc) {
159
+ QEDF_ERR(&qedf->dbg_ctx, "start_xmit failed rc = %d.\n", rc);
160
+ kfree_skb(skb);
161
+ return;
162
+ }
146163 }
164
+
165
+static u8 fcoe_all_enode[ETH_ALEN] = FIP_ALL_ENODE_MACS;
147166
148167 /* Process incoming FIP frames. */
149168 void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff *skb)
....@@ -157,19 +176,36 @@
157176 size_t rlen, dlen;
158177 u16 op;
159178 u8 sub;
160
- bool do_reset = false;
179
+ bool fcf_valid = false;
180
+ /* Default is to handle CVL regardless of fabric id descriptor */
181
+ bool fabric_id_valid = true;
182
+ bool fc_wwpn_valid = false;
183
+ u64 switch_name;
184
+ u16 vlan = 0;
161185
162186 eth_hdr = (struct ethhdr *)skb_mac_header(skb);
163187 fiph = (struct fip_header *) ((void *)skb->data + 2 * ETH_ALEN + 2);
164188 op = ntohs(fiph->fip_op);
165189 sub = fiph->fip_subcode;
166190
167
- QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2, "FIP frame received: "
168
- "skb=%p fiph=%p source=%pM op=%x sub=%x", skb, fiph,
169
- eth_hdr->h_source, op, sub);
191
+ QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_LL2,
192
+ "FIP frame received: skb=%p fiph=%p source=%pM destn=%pM op=%x sub=%x vlan=%04x",
193
+ skb, fiph, eth_hdr->h_source, eth_hdr->h_dest, op,
194
+ sub, vlan);
170195 if (qedf_dump_frames)
171196 print_hex_dump(KERN_WARNING, "fip ", DUMP_PREFIX_OFFSET, 16, 1,
172197 skb->data, skb->len, false);
198
+
199
+ if (!ether_addr_equal(eth_hdr->h_dest, qedf->mac) &&
200
+ !ether_addr_equal(eth_hdr->h_dest, fcoe_all_enode) &&
201
+ !ether_addr_equal(eth_hdr->h_dest, qedf->data_src_addr)) {
202
+ QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_LL2,
203
+ "Dropping FIP type 0x%x pkt due to destination MAC mismatch dest_mac=%pM ctlr.dest_addr=%pM data_src_addr=%pM.\n",
204
+ op, eth_hdr->h_dest, qedf->mac,
205
+ qedf->data_src_addr);
206
+ kfree_skb(skb);
207
+ return;
208
+ }
173209
174210 /* Handle FIP VLAN resp in the driver */
175211 if (op == FIP_OP_VLAN && sub == FIP_SC_VL_NOTE) {
....@@ -199,25 +235,42 @@
199235 switch (desc->fip_dtype) {
200236 case FIP_DT_MAC:
201237 mp = (struct fip_mac_desc *)desc;
202
- QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2,
203
- "fd_mac=%pM\n", mp->fd_mac);
238
+ QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC,
239
+ "Switch fd_mac=%pM.\n", mp->fd_mac);
204240 if (ether_addr_equal(mp->fd_mac,
205241 qedf->ctlr.sel_fcf->fcf_mac))
206
- do_reset = true;
242
+ fcf_valid = true;
207243 break;
208244 case FIP_DT_NAME:
209245 wp = (struct fip_wwn_desc *)desc;
210
- QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2,
211
- "fc_wwpn=%016llx.\n",
212
- get_unaligned_be64(&wp->fd_wwn));
246
+ switch_name = get_unaligned_be64(&wp->fd_wwn);
247
+ QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC,
248
+ "Switch fd_wwn=%016llx fcf_switch_name=%016llx.\n",
249
+ switch_name,
250
+ qedf->ctlr.sel_fcf->switch_name);
251
+ if (switch_name ==
252
+ qedf->ctlr.sel_fcf->switch_name)
253
+ fc_wwpn_valid = true;
213254 break;
214255 case FIP_DT_VN_ID:
256
+ fabric_id_valid = false;
215257 vp = (struct fip_vn_desc *)desc;
216
- QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2,
217
- "fd_fc_id=%x.\n", ntoh24(vp->fd_fc_id));
218
- if (ntoh24(vp->fd_fc_id) ==
219
- qedf->lport->port_id)
220
- do_reset = true;
258
+
259
+ QEDF_ERR(&qedf->dbg_ctx,
260
+ "CVL vx_port fd_fc_id=0x%x fd_mac=%pM fd_wwpn=%016llx.\n",
261
+ ntoh24(vp->fd_fc_id), vp->fd_mac,
262
+ get_unaligned_be64(&vp->fd_wwpn));
263
+ /* Check for vx_port wwpn OR Check vx_port
264
+ * fabric ID OR Check vx_port MAC
265
+ */
266
+ if ((get_unaligned_be64(&vp->fd_wwpn) ==
267
+ qedf->wwpn) ||
268
+ (ntoh24(vp->fd_fc_id) ==
269
+ qedf->lport->port_id) ||
270
+ (ether_addr_equal(vp->fd_mac,
271
+ qedf->data_src_addr))) {
272
+ fabric_id_valid = true;
273
+ }
221274 break;
222275 default:
223276 /* Ignore anything else */
....@@ -227,13 +280,11 @@
227280 rlen -= dlen;
228281 }
229282
230
- QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2,
231
- "do_reset=%d.\n", do_reset);
232
- if (do_reset) {
233
- fcoe_ctlr_link_down(&qedf->ctlr);
234
- qedf_wait_for_upload(qedf);
235
- fcoe_ctlr_link_up(&qedf->ctlr);
236
- }
283
+ QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC,
284
+ "fcf_valid=%d fabric_id_valid=%d fc_wwpn_valid=%d.\n",
285
+ fcf_valid, fabric_id_valid, fc_wwpn_valid);
286
+ if (fcf_valid && fabric_id_valid && fc_wwpn_valid)
287
+ qedf_ctx_soft_reset(qedf->lport);
237288 kfree_skb(skb);
238289 } else {
239290 /* Everything else is handled by libfcoe */