|
@@ -29,6 +29,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
29
|
29
|
#include <ipxe/xfer.h>
|
30
|
30
|
#include <ipxe/netdevice.h>
|
31
|
31
|
#include <ipxe/features.h>
|
|
32
|
+#include <ipxe/errortab.h>
|
32
|
33
|
#include <ipxe/crc32.h>
|
33
|
34
|
#include <ipxe/fc.h>
|
34
|
35
|
#include <ipxe/fcoe.h>
|
|
@@ -41,6 +42,20 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
41
|
42
|
|
42
|
43
|
FEATURE ( FEATURE_PROTOCOL, "FCoE", DHCP_EB_FEATURE_FCOE, 1 );
|
43
|
44
|
|
|
45
|
+/* Disambiguate the various error causes */
|
|
46
|
+#define EINVAL_UNDERLENGTH __einfo_error ( EINFO_EINVAL_UNDERLENGTH )
|
|
47
|
+#define EINFO_EINVAL_UNDERLENGTH \
|
|
48
|
+ __einfo_uniqify ( EINFO_EINVAL, 0x01, "Underlength packet" )
|
|
49
|
+#define EINVAL_SOF __einfo_error ( EINFO_EINVAL_SOF )
|
|
50
|
+#define EINFO_EINVAL_SOF \
|
|
51
|
+ __einfo_uniqify ( EINFO_EINVAL, 0x02, "Invalid SoF delimiter" )
|
|
52
|
+#define EINVAL_CRC __einfo_error ( EINFO_EINVAL_CRC )
|
|
53
|
+#define EINFO_EINVAL_CRC \
|
|
54
|
+ __einfo_uniqify ( EINFO_EINVAL, 0x03, "Invalid CRC (not stripped?)" )
|
|
55
|
+#define EINVAL_EOF __einfo_error ( EINFO_EINVAL_EOF )
|
|
56
|
+#define EINFO_EINVAL_EOF \
|
|
57
|
+ __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid EoF delimiter" )
|
|
58
|
+
|
44
|
59
|
/** An FCoE port */
|
45
|
60
|
struct fcoe_port {
|
46
|
61
|
/** Reference count */
|
|
@@ -171,7 +186,7 @@ static int fcoe_rx ( struct io_buffer *iobuf,
|
171
|
186
|
if ( iob_len ( iobuf ) < ( sizeof ( *fcoehdr ) + sizeof ( *fcoeftr ) )){
|
172
|
187
|
DBGC ( fcoe, "FCoE %s received under-length frame (%zd "
|
173
|
188
|
"bytes)\n", fcoe->netdev->name, iob_len ( iobuf ) );
|
174
|
|
- rc = -EINVAL;
|
|
189
|
+ rc = -EINVAL_UNDERLENGTH;
|
175
|
190
|
goto done;
|
176
|
191
|
}
|
177
|
192
|
|
|
@@ -192,21 +207,21 @@ static int fcoe_rx ( struct io_buffer *iobuf,
|
192
|
207
|
( fcoehdr->sof == FCOE_SOF_N3 ) ) ) {
|
193
|
208
|
DBGC ( fcoe, "FCoE %s received unsupported start-of-frame "
|
194
|
209
|
"delimiter %02x\n", fcoe->netdev->name, fcoehdr->sof );
|
195
|
|
- rc = -EINVAL;
|
|
210
|
+ rc = -EINVAL_SOF;
|
196
|
211
|
goto done;
|
197
|
212
|
}
|
198
|
213
|
if ( ( le32_to_cpu ( fcoeftr->crc ) ^ ~((uint32_t)0) ) !=
|
199
|
214
|
crc32_le ( ~((uint32_t)0), iobuf->data, iob_len ( iobuf ) ) ) {
|
200
|
215
|
DBGC ( fcoe, "FCoE %s received invalid CRC\n",
|
201
|
216
|
fcoe->netdev->name );
|
202
|
|
- rc = -EINVAL;
|
|
217
|
+ rc = -EINVAL_CRC;
|
203
|
218
|
goto done;
|
204
|
219
|
}
|
205
|
220
|
if ( ! ( ( fcoeftr->eof == FCOE_EOF_N ) ||
|
206
|
221
|
( fcoeftr->eof == FCOE_EOF_T ) ) ) {
|
207
|
222
|
DBGC ( fcoe, "FCoE %s received unsupported end-of-frame "
|
208
|
223
|
"delimiter %02x\n", fcoe->netdev->name, fcoeftr->eof );
|
209
|
|
- rc = -EINVAL;
|
|
224
|
+ rc = -EINVAL_EOF;
|
210
|
225
|
goto done;
|
211
|
226
|
}
|
212
|
227
|
|
|
@@ -381,3 +396,13 @@ struct net_protocol fcoe_protocol __net_protocol = {
|
381
|
396
|
.net_proto = htons ( ETH_P_FCOE ),
|
382
|
397
|
.rx = fcoe_rx,
|
383
|
398
|
};
|
|
399
|
+
|
|
400
|
+/** Human-readable message for CRC errors
|
|
401
|
+ *
|
|
402
|
+ * It seems as though several drivers neglect to strip the Ethernet
|
|
403
|
+ * CRC, which will cause the FCoE footer to be misplaced and result
|
|
404
|
+ * (coincidentally) in an "invalid CRC" error from FCoE.
|
|
405
|
+ */
|
|
406
|
+struct errortab fcoe_errors[] __errortab = {
|
|
407
|
+ __einfo_errortab ( EINFO_EINVAL_CRC ),
|
|
408
|
+};
|