iPXE
fcoe.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26#include <stddef.h>
27#include <stdlib.h>
28#include <string.h>
29#include <errno.h>
30#include <byteswap.h>
31#include <ipxe/if_ether.h>
32#include <ipxe/if_arp.h>
33#include <ipxe/iobuf.h>
34#include <ipxe/interface.h>
35#include <ipxe/xfer.h>
36#include <ipxe/netdevice.h>
37#include <ipxe/ethernet.h>
38#include <ipxe/vlan.h>
39#include <ipxe/features.h>
40#include <ipxe/errortab.h>
41#include <ipxe/device.h>
42#include <ipxe/crc32.h>
43#include <ipxe/retry.h>
44#include <ipxe/timer.h>
45#include <ipxe/fc.h>
46#include <ipxe/fip.h>
47#include <ipxe/fcoe.h>
48
49/** @file
50 *
51 * FCoE protocol
52 *
53 */
54
56
57/* Disambiguate the various error causes */
58#define EINVAL_UNDERLENGTH __einfo_error ( EINFO_EINVAL_UNDERLENGTH )
59#define EINFO_EINVAL_UNDERLENGTH \
60 __einfo_uniqify ( EINFO_EINVAL, 0x01, "Underlength packet" )
61#define EINVAL_SOF __einfo_error ( EINFO_EINVAL_SOF )
62#define EINFO_EINVAL_SOF \
63 __einfo_uniqify ( EINFO_EINVAL, 0x02, "Invalid SoF delimiter" )
64#define EINVAL_CRC __einfo_error ( EINFO_EINVAL_CRC )
65#define EINFO_EINVAL_CRC \
66 __einfo_uniqify ( EINFO_EINVAL, 0x03, "Invalid CRC (not stripped?)" )
67#define EINVAL_EOF __einfo_error ( EINFO_EINVAL_EOF )
68#define EINFO_EINVAL_EOF \
69 __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid EoF delimiter" )
70
71/** An FCoE port */
72struct fcoe_port {
73 /** Transport interface */
75 /** Network device */
77
78 /** Node WWN */
80 /** Port WWN */
82
83 /** FIP retransmission timer */
85 /** FIP timeout counter */
86 unsigned int timeouts;
87 /** Flags */
88 unsigned int flags;
89 /** FCoE forwarder priority */
90 unsigned int priority;
91 /** Keepalive delay (in ms) */
92 unsigned int keepalive;
93 /** FCoE forwarder MAC address */
95 /** Local MAC address */
97};
98
99/** FCoE flags */
101 /** Underlying network device is available */
103 /** We have selected an FCoE forwarder to use */
105 /** We have a FIP-capable FCoE forwarder available to be used */
107 /** FCoE forwarder supports server-provided MAC addresses */
109 /** An alternative VLAN has been found */
111 /** VLAN discovery has timed out */
113};
114
115struct net_driver fcoe_driver __net_driver;
116struct net_protocol fcoe_protocol __net_protocol;
117struct net_protocol fip_protocol __net_protocol;
118
119/** FCoE All-FCoE-MACs address */
121 { 0x01, 0x10, 0x18, 0x01, 0x00, 0x00 };
122
123/** FCoE All-ENode-MACs address */
125 { 0x01, 0x10, 0x18, 0x01, 0x00, 0x01 };
126
127/** FCoE All-FCF-MACs address */
129 { 0x01, 0x10, 0x18, 0x01, 0x00, 0x02 };
130
131/** Default FCoE forwarded MAC address */
133 { 0x0e, 0xfc, 0x00, 0xff, 0xff, 0xfe };
134
135/** Maximum number of VLAN requests before giving up on VLAN discovery */
136#define FCOE_MAX_VLAN_REQUESTS 2
137
138/** Delay between retrying VLAN requests */
139#define FCOE_VLAN_RETRY_DELAY ( TICKS_PER_SEC )
140
141/** Delay between retrying polling VLAN requests */
142#define FCOE_VLAN_POLL_DELAY ( 30 * TICKS_PER_SEC )
143
144/** Maximum number of FIP solicitations before giving up on FIP */
145#define FCOE_MAX_FIP_SOLICITATIONS 2
146
147/** Delay between retrying FIP solicitations */
148#define FCOE_FIP_RETRY_DELAY ( TICKS_PER_SEC )
149
150/** Maximum number of missing discovery advertisements */
151#define FCOE_MAX_FIP_MISSING_KEEPALIVES 4
152
153/******************************************************************************
154 *
155 * FCoE protocol
156 *
157 ******************************************************************************
158 */
159
160/**
161 * Reset FCoE port
162 *
163 * @v fcoe FCoE port
164 */
165static void fcoe_reset ( struct fcoe_port *fcoe ) {
166
167 /* Detach FC port, if any */
168 intf_restart ( &fcoe->transport, -ECANCELED );
169
170 /* Reset any FIP state */
171 stop_timer ( &fcoe->timer );
172 fcoe->timeouts = 0;
173 fcoe->flags = 0;
174 fcoe->priority = ( FIP_LOWEST_PRIORITY + 1 );
175 fcoe->keepalive = 0;
177 sizeof ( fcoe->fcf_mac ) );
178 memcpy ( fcoe->local_mac, fcoe->netdev->ll_addr,
179 sizeof ( fcoe->local_mac ) );
180
181 /* Start FIP solicitation if network is available */
182 if ( netdev_is_open ( fcoe->netdev ) &&
183 netdev_link_ok ( fcoe->netdev ) ) {
184 fcoe->flags |= FCOE_HAVE_NETWORK;
185 start_timer_nodelay ( &fcoe->timer );
186 DBGC ( fcoe, "FCoE %s starting %s\n", fcoe->netdev->name,
187 ( vlan_can_be_trunk ( fcoe->netdev ) ?
188 "VLAN discovery" : "FIP solicitation" ) );
189 }
190
191 /* Send notification of window change */
193}
194
195/**
196 * Transmit FCoE packet
197 *
198 * @v fcoe FCoE port
199 * @v iobuf I/O buffer
200 * @v meta Data transfer metadata
201 * @ret rc Return status code
202 */
203static int fcoe_deliver ( struct fcoe_port *fcoe,
204 struct io_buffer *iobuf,
205 struct xfer_metadata *meta __unused ) {
206 struct fc_frame_header *fchdr = iobuf->data;
207 struct fc_els_frame_common *els = ( iobuf->data + sizeof ( *fchdr ) );
208 struct fcoe_header *fcoehdr;
209 struct fcoe_footer *fcoeftr;
210 struct fip_header *fiphdr;
211 struct fip_login *fipflogi;
212 struct fip_mac_address *fipmac;
213 uint32_t crc;
215 void *ll_source;
216 int rc;
217
218 /* Send as FIP or FCoE as appropriate */
219 if ( ( fchdr->r_ctl == ( FC_R_CTL_ELS | FC_R_CTL_UNSOL_CTRL ) ) &&
220 ( els->command == FC_ELS_FLOGI ) &&
221 ( fcoe->flags & FCOE_HAVE_FIP_FCF ) ) {
222
223 /* Create FIP FLOGI descriptor */
224 fipflogi = iob_push ( iobuf,
225 offsetof ( typeof ( *fipflogi ), fc ) );
226 memset ( fipflogi, 0, offsetof ( typeof ( *fipflogi ), fc ) );
227 fipflogi->type = FIP_FLOGI;
228 fipflogi->len = ( iob_len ( iobuf ) / 4 );
229
230 /* Create FIP MAC address descriptor */
231 fipmac = iob_put ( iobuf, sizeof ( *fipmac ) );
232 memset ( fipmac, 0, sizeof ( *fipmac ) );
233 fipmac->type = FIP_MAC_ADDRESS;
234 fipmac->len = ( sizeof ( *fipmac ) / 4 );
235 if ( fcoe->flags & FCOE_FCF_ALLOWS_SPMA ) {
236 memcpy ( fipmac->mac, fcoe->netdev->ll_addr,
237 sizeof ( fipmac->mac ) );
238 }
239
240 /* Create FIP header */
241 fiphdr = iob_push ( iobuf, sizeof ( *fiphdr ) );
242 memset ( fiphdr, 0, sizeof ( *fiphdr ) );
243 fiphdr->version = FIP_VERSION;
244 fiphdr->code = htons ( FIP_CODE_ELS );
245 fiphdr->subcode = FIP_ELS_REQUEST;
246 fiphdr->len =
247 htons ( ( iob_len ( iobuf ) - sizeof ( *fiphdr ) ) / 4);
248 fiphdr->flags = ( ( fcoe->flags & FCOE_FCF_ALLOWS_SPMA ) ?
249 htons ( FIP_SP ) : htons ( FIP_FP ) );
250
251 /* Send as FIP packet from netdev's own MAC address */
252 net_protocol = &fip_protocol;
253 ll_source = fcoe->netdev->ll_addr;
254
255 } else {
256
257 /* Calculate CRC */
258 crc = crc32_le ( ~((uint32_t)0), iobuf->data,
259 iob_len ( iobuf ) );
260
261 /* Create FCoE header */
262 fcoehdr = iob_push ( iobuf, sizeof ( *fcoehdr ) );
263 memset ( fcoehdr, 0, sizeof ( *fcoehdr ) );
264 fcoehdr->sof = ( ( fchdr->seq_cnt == ntohs ( 0 ) ) ?
266
267 /* Create FCoE footer */
268 fcoeftr = iob_put ( iobuf, sizeof ( *fcoeftr ) );
269 memset ( fcoeftr, 0, sizeof ( *fcoeftr ) );
270 fcoeftr->crc = cpu_to_le32 ( crc ^ ~((uint32_t)0) );
271 fcoeftr->eof = ( ( fchdr->f_ctl_es & FC_F_CTL_ES_END ) ?
273
274 /* Send as FCoE packet from FCoE MAC address */
275 net_protocol = &fcoe_protocol;
276 ll_source = fcoe->local_mac;
277 }
278
279 /* Transmit packet */
280 if ( ( rc = net_tx ( iob_disown ( iobuf ), fcoe->netdev, net_protocol,
281 fcoe->fcf_mac, ll_source ) ) != 0 ) {
282 DBGC ( fcoe, "FCoE %s could not transmit: %s\n",
283 fcoe->netdev->name, strerror ( rc ) );
284 goto done;
285 }
286
287 done:
288 free_iob ( iobuf );
289 return rc;
290}
291
292/**
293 * Allocate FCoE I/O buffer
294 *
295 * @v len Payload length
296 * @ret iobuf I/O buffer, or NULL
297 */
298static struct io_buffer * fcoe_alloc_iob ( struct fcoe_port *fcoe __unused,
299 size_t len ) {
300 struct io_buffer *iobuf;
301
302 iobuf = alloc_iob ( MAX_LL_HEADER_LEN + sizeof ( struct fcoe_header ) +
303 len + sizeof ( struct fcoe_footer ) );
304 if ( iobuf ) {
305 iob_reserve ( iobuf, ( MAX_LL_HEADER_LEN +
306 sizeof ( struct fcoe_header ) ) );
307 }
308 return iobuf;
309}
310
311/**
312 * Process incoming FCoE packets
313 *
314 * @v iobuf I/O buffer
315 * @v netdev Network device
316 * @v ll_dest Link-layer destination address
317 * @v ll_source Link-layer source address
318 * @v flags Packet flags
319 * @ret rc Return status code
320 */
321static int fcoe_rx ( struct io_buffer *iobuf, struct net_device *netdev,
322 const void *ll_dest, const void *ll_source,
323 unsigned int flags __unused ) {
324 struct fcoe_header *fcoehdr;
325 struct fcoe_footer *fcoeftr;
326 struct fcoe_port *fcoe;
327 int rc;
328
329 /* Identify FCoE port */
330 fcoe = netdev_priv ( netdev, &fcoe_driver );
331 if ( ! fcoe->netdev ) {
332 DBG ( "FCoE received frame for net device %s missing FCoE "
333 "port\n", netdev->name );
334 rc = -ENOTCONN;
335 goto done;
336 }
337
338 /* Discard packets not destined for us */
339 if ( ( memcmp ( fcoe->local_mac, ll_dest,
340 sizeof ( fcoe->local_mac ) ) != 0 ) &&
341 ( memcmp ( default_fcf_mac, ll_dest,
342 sizeof ( default_fcf_mac ) ) != 0 ) ) {
343 DBGC2 ( fcoe, "FCoE %s ignoring packet for %s\n",
344 fcoe->netdev->name, eth_ntoa ( ll_dest ) );
345 rc = -ENOTCONN;
346 goto done;
347 }
348
349 /* Sanity check */
350 if ( iob_len ( iobuf ) < ( sizeof ( *fcoehdr ) + sizeof ( *fcoeftr ) )){
351 DBGC ( fcoe, "FCoE %s received under-length frame (%zd "
352 "bytes)\n", fcoe->netdev->name, iob_len ( iobuf ) );
354 goto done;
355 }
356
357 /* Strip header and footer */
358 fcoehdr = iobuf->data;
359 iob_pull ( iobuf, sizeof ( *fcoehdr ) );
360 fcoeftr = ( iobuf->data + iob_len ( iobuf ) - sizeof ( *fcoeftr ) );
361 iob_unput ( iobuf, sizeof ( *fcoeftr ) );
362
363 /* Validity checks */
364 if ( fcoehdr->version != FCOE_FRAME_VER ) {
365 DBGC ( fcoe, "FCoE %s received unsupported frame version "
366 "%02x\n", fcoe->netdev->name, fcoehdr->version );
368 goto done;
369 }
370 if ( ! ( ( fcoehdr->sof == FCOE_SOF_I3 ) ||
371 ( fcoehdr->sof == FCOE_SOF_N3 ) ) ) {
372 DBGC ( fcoe, "FCoE %s received unsupported start-of-frame "
373 "delimiter %02x\n", fcoe->netdev->name, fcoehdr->sof );
374 rc = -EINVAL_SOF;
375 goto done;
376 }
377 if ( ( le32_to_cpu ( fcoeftr->crc ) ^ ~((uint32_t)0) ) !=
378 crc32_le ( ~((uint32_t)0), iobuf->data, iob_len ( iobuf ) ) ) {
379 DBGC ( fcoe, "FCoE %s received invalid CRC\n",
380 fcoe->netdev->name );
381 rc = -EINVAL_CRC;
382 goto done;
383 }
384 if ( ! ( ( fcoeftr->eof == FCOE_EOF_N ) ||
385 ( fcoeftr->eof == FCOE_EOF_T ) ) ) {
386 DBGC ( fcoe, "FCoE %s received unsupported end-of-frame "
387 "delimiter %02x\n", fcoe->netdev->name, fcoeftr->eof );
388 rc = -EINVAL_EOF;
389 goto done;
390 }
391
392 /* Record FCF address if applicable */
393 if ( ( fcoe->flags & FCOE_HAVE_FCF ) &&
394 ( ! ( fcoe->flags & FCOE_HAVE_FIP_FCF ) ) ) {
395 memcpy ( &fcoe->fcf_mac, ll_source, sizeof ( fcoe->fcf_mac ) );
396 }
397
398 /* Hand off via transport interface */
399 if ( ( rc = xfer_deliver_iob ( &fcoe->transport,
400 iob_disown ( iobuf ) ) ) != 0 ) {
401 DBGC ( fcoe, "FCoE %s could not deliver frame: %s\n",
402 fcoe->netdev->name, strerror ( rc ) );
403 goto done;
404 }
405
406 done:
407 free_iob ( iobuf );
408 return rc;
409}
410
411/**
412 * Check FCoE flow control window
413 *
414 * @v fcoe FCoE port
415 * @ret len Length of window
416 */
417static size_t fcoe_window ( struct fcoe_port *fcoe ) {
418 return ( ( fcoe->flags & FCOE_HAVE_FCF ) ? ~( ( size_t ) 0 ) : 0 );
419}
420
421/**
422 * Close FCoE port
423 *
424 * @v fcoe FCoE port
425 * @v rc Reason for close
426 */
427static void fcoe_close ( struct fcoe_port *fcoe, int rc ) {
428
429 stop_timer ( &fcoe->timer );
430 intf_shutdown ( &fcoe->transport, rc );
431}
432
433/**
434 * Identify device underlying FCoE port
435 *
436 * @v fcoe FCoE port
437 * @ret device Underlying device
438 */
439static struct device * fcoe_identify_device ( struct fcoe_port *fcoe ) {
440 return fcoe->netdev->dev;
441}
442
443/** FCoE transport interface operations */
452
453/** FCoE transport interface descriptor */
455 INTF_DESC ( struct fcoe_port, transport, fcoe_transport_op );
456
457/******************************************************************************
458 *
459 * FIP protocol
460 *
461 ******************************************************************************
462 */
463
464/**
465 * Parse FIP packet into descriptor set
466 *
467 * @v fcoe FCoE port
468 * @v fiphdr FIP header
469 * @v len Length of FIP packet
470 * @v descs Descriptor set to fill in
471 * @ret rc Return status code
472 */
473static int fcoe_fip_parse ( struct fcoe_port *fcoe, struct fip_header *fiphdr,
474 size_t len, struct fip_descriptors *descs ) {
475 union fip_descriptor *desc;
476 size_t descs_len;
477 size_t desc_len;
478 size_t desc_offset;
479 unsigned int desc_type;
480
481 /* Check FIP version */
482 if ( fiphdr->version != FIP_VERSION ) {
483 DBGC ( fcoe, "FCoE %s received unsupported FIP version %02x\n",
484 fcoe->netdev->name, fiphdr->version );
485 return -EINVAL;
486 }
487
488 /* Check length */
489 descs_len = ( ntohs ( fiphdr->len ) * 4 );
490 if ( ( sizeof ( *fiphdr ) + descs_len ) > len ) {
491 DBGC ( fcoe, "FCoE %s received bad descriptor list length\n",
492 fcoe->netdev->name );
493 return -EINVAL;
494 }
495
496 /* Parse descriptor list */
497 memset ( descs, 0, sizeof ( *descs ) );
498 for ( desc_offset = 0 ;
499 ( desc_offset + sizeof ( desc->common ) ) <= descs_len ;
500 desc_offset += desc_len ) {
501
502 /* Find descriptor and validate length */
503 desc = ( ( ( void * ) ( fiphdr + 1 ) ) + desc_offset );
504 desc_type = desc->common.type;
505 desc_len = ( desc->common.len * 4 );
506 if ( desc_len == 0 ) {
507 DBGC ( fcoe, "FCoE %s received zero-length "
508 "descriptor\n", fcoe->netdev->name );
509 return -EINVAL;
510 }
511 if ( ( desc_offset + desc_len ) > descs_len ) {
512 DBGC ( fcoe, "FCoE %s descriptor overrun\n",
513 fcoe->netdev->name );
514 return -EINVAL;
515 }
516
517 /* Handle descriptors that we understand */
518 if ( ( desc_type > FIP_RESERVED ) &&
519 ( desc_type < FIP_NUM_DESCRIPTOR_TYPES ) ) {
520 /* Use only the first instance of a descriptor */
521 if ( descs->desc[desc_type] == NULL ) {
522 descs->desc[desc_type] = desc;
523 descs->len[desc_type] = desc_len;
524 }
525 continue;
526 }
527
528 /* Abort if we cannot understand a critical descriptor */
529 if ( FIP_IS_CRITICAL ( desc_type ) ) {
530 DBGC ( fcoe, "FCoE %s cannot understand critical "
531 "descriptor type %02x\n",
532 fcoe->netdev->name, desc_type );
533 return -ENOTSUP;
534 }
535
536 /* Ignore non-critical descriptors that we cannot understand */
537 }
538
539 return 0;
540}
541
542/**
543 * Send FIP VLAN request
544 *
545 * @v fcoe FCoE port
546 * @ret rc Return status code
547 */
548static int fcoe_fip_tx_vlan ( struct fcoe_port *fcoe ) {
549 struct io_buffer *iobuf;
550 struct {
551 struct fip_header hdr;
552 struct fip_mac_address mac_address;
553 } __attribute__ (( packed )) *request;
554 int rc;
555
556 /* Allocate I/O buffer */
557 iobuf = alloc_iob ( MAX_LL_HEADER_LEN + sizeof ( *request ) );
558 if ( ! iobuf )
559 return -ENOMEM;
561
562 /* Construct VLAN request */
563 request = iob_put ( iobuf, sizeof ( *request ) );
564 memset ( request, 0, sizeof ( *request ) );
565 request->hdr.version = FIP_VERSION;
566 request->hdr.code = htons ( FIP_CODE_VLAN );
567 request->hdr.subcode = FIP_VLAN_REQUEST;
568 request->hdr.len = htons ( ( sizeof ( *request ) -
569 sizeof ( request->hdr ) ) / 4 );
570 request->mac_address.type = FIP_MAC_ADDRESS;
571 request->mac_address.len =
572 ( sizeof ( request->mac_address ) / 4 );
573 memcpy ( request->mac_address.mac, fcoe->netdev->ll_addr,
574 sizeof ( request->mac_address.mac ) );
575
576 /* Send VLAN request */
577 if ( ( rc = net_tx ( iob_disown ( iobuf ), fcoe->netdev,
578 &fip_protocol, all_fcf_macs,
579 fcoe->netdev->ll_addr ) ) != 0 ) {
580 DBGC ( fcoe, "FCoE %s could not send VLAN request: "
581 "%s\n", fcoe->netdev->name, strerror ( rc ) );
582 return rc;
583 }
584
585 return 0;
586}
587
588/**
589 * Handle received FIP VLAN notification
590 *
591 * @v fcoe FCoE port
592 * @v descs Descriptor list
593 * @v flags Flags
594 * @ret rc Return status code
595 */
596static int fcoe_fip_rx_vlan ( struct fcoe_port *fcoe,
597 struct fip_descriptors *descs,
598 unsigned int flags __unused ) {
599 struct fip_mac_address *mac_address = fip_mac_address ( descs );
600 struct fip_vlan *vlan = fip_vlan ( descs );
601 unsigned int tag;
602 int rc;
603
604 /* Sanity checks */
605 if ( ! mac_address ) {
606 DBGC ( fcoe, "FCoE %s received VLAN notification missing MAC "
607 "address\n", fcoe->netdev->name );
608 return -EINVAL;
609 }
610 if ( ! vlan ) {
611 DBGC ( fcoe, "FCoE %s received VLAN notification missing VLAN "
612 "tag\n", fcoe->netdev->name );
613 return -EINVAL;
614 }
615
616 /* Create VLAN */
617 tag = ntohs ( vlan->vlan );
618 DBGC ( fcoe, "FCoE %s creating VLAN %d for FCF %s\n",
619 fcoe->netdev->name, tag, eth_ntoa ( mac_address->mac ) );
620 if ( ( rc = vlan_create ( fcoe->netdev, tag,
621 FCOE_VLAN_PRIORITY ) ) != 0 ) {
622 DBGC ( fcoe, "FCoE %s could not create VLAN %d: %s\n",
623 fcoe->netdev->name, tag, strerror ( rc ) );
624 return rc;
625 }
626
627 /* Record that a VLAN was found. This FCoE port will play no
628 * further active role; the real FCoE traffic will use the
629 * port automatically created for the new VLAN device.
630 */
631 fcoe->flags |= FCOE_VLAN_FOUND;
632
633 return 0;
634}
635
636/**
637 * Send FIP discovery solicitation
638 *
639 * @v fcoe FCoE port
640 * @ret rc Return status code
641 */
642static int fcoe_fip_tx_solicitation ( struct fcoe_port *fcoe ) {
643 struct io_buffer *iobuf;
644 struct {
645 struct fip_header hdr;
646 struct fip_mac_address mac_address;
647 struct fip_name_id name_id;
648 struct fip_max_fcoe_size max_fcoe_size;
649 } __attribute__ (( packed )) *solicitation;
650 int rc;
651
652 /* Allocate I/O buffer */
653 iobuf = alloc_iob ( MAX_LL_HEADER_LEN + sizeof ( *solicitation ) );
654 if ( ! iobuf )
655 return -ENOMEM;
657
658 /* Construct discovery solicitation */
659 solicitation = iob_put ( iobuf, sizeof ( *solicitation ) );
660 memset ( solicitation, 0, sizeof ( *solicitation ) );
661 solicitation->hdr.version = FIP_VERSION;
662 solicitation->hdr.code = htons ( FIP_CODE_DISCOVERY );
663 solicitation->hdr.subcode = FIP_DISCOVERY_SOLICIT;
664 solicitation->hdr.len = htons ( ( sizeof ( *solicitation ) -
665 sizeof ( solicitation->hdr ) ) / 4 );
666 solicitation->hdr.flags = htons ( FIP_FP | FIP_SP );
667 solicitation->mac_address.type = FIP_MAC_ADDRESS;
668 solicitation->mac_address.len =
669 ( sizeof ( solicitation->mac_address ) / 4 );
670 memcpy ( solicitation->mac_address.mac, fcoe->netdev->ll_addr,
671 sizeof ( solicitation->mac_address.mac ) );
672 solicitation->name_id.type = FIP_NAME_ID;
673 solicitation->name_id.len = ( sizeof ( solicitation->name_id ) / 4 );
674 memcpy ( &solicitation->name_id.name, &fcoe->node_wwn.fc,
675 sizeof ( solicitation->name_id.name ) );
676 solicitation->max_fcoe_size.type = FIP_MAX_FCOE_SIZE;
677 solicitation->max_fcoe_size.len =
678 ( sizeof ( solicitation->max_fcoe_size ) / 4 );
679 solicitation->max_fcoe_size.mtu =
680 htons ( ETH_MAX_MTU - sizeof ( struct fcoe_header ) -
681 sizeof ( struct fcoe_footer ) );
682
683 /* Send discovery solicitation */
684 if ( ( rc = net_tx ( iob_disown ( iobuf ), fcoe->netdev,
685 &fip_protocol, all_fcf_macs,
686 fcoe->netdev->ll_addr ) ) != 0 ) {
687 DBGC ( fcoe, "FCoE %s could not send discovery solicitation: "
688 "%s\n", fcoe->netdev->name, strerror ( rc ) );
689 return rc;
690 }
691
692 return 0;
693}
694
695/**
696 * Handle received FIP discovery advertisement
697 *
698 * @v fcoe FCoE port
699 * @v descs Descriptor list
700 * @v flags Flags
701 * @ret rc Return status code
702 */
703static int fcoe_fip_rx_advertisement ( struct fcoe_port *fcoe,
704 struct fip_descriptors *descs,
705 unsigned int flags ) {
706 struct fip_priority *priority = fip_priority ( descs );
707 struct fip_mac_address *mac_address = fip_mac_address ( descs );
708 struct fip_fka_adv_p *fka_adv_p = fip_fka_adv_p ( descs );
709
710 /* Sanity checks */
711 if ( ! priority ) {
712 DBGC ( fcoe, "FCoE %s received advertisement missing "
713 "priority\n", fcoe->netdev->name );
714 return -EINVAL;
715 }
716 if ( ! mac_address ) {
717 DBGC ( fcoe, "FCoE %s received advertisement missing MAC "
718 "address\n", fcoe->netdev->name );
719 return -EINVAL;
720 }
721 if ( ! fka_adv_p ) {
722 DBGC ( fcoe, "FCoE %s received advertisement missing FKA ADV "
723 "period\n", fcoe->netdev->name );
724 return -EINVAL;
725 }
726
727 if ( ! ( fcoe->flags & FCOE_HAVE_FCF ) ) {
728
729 /* We are soliciting for an FCF. Store the highest
730 * (i.e. lowest-valued) priority solicited
731 * advertisement that we receive.
732 */
733 if ( ( ( flags & ( FIP_A | FIP_S | FIP_F ) ) ==
734 ( FIP_A | FIP_S | FIP_F ) ) &&
735 ( priority->priority < fcoe->priority ) ) {
736
737 fcoe->flags |= FCOE_HAVE_FIP_FCF;
738 fcoe->priority = priority->priority;
739 if ( fka_adv_p->flags & FIP_NO_KEEPALIVE ) {
740 fcoe->keepalive = 0;
741 } else {
742 fcoe->keepalive = ntohl ( fka_adv_p->period );
743 }
745 if ( flags & FIP_SP )
747 memcpy ( fcoe->fcf_mac, mac_address->mac,
748 sizeof ( fcoe->fcf_mac ) );
749 DBGC ( fcoe, "FCoE %s selected FCF %s (pri %d",
750 fcoe->netdev->name, eth_ntoa ( fcoe->fcf_mac ),
751 fcoe->priority );
752 if ( fcoe->keepalive ) {
753 DBGC ( fcoe, ", FKA ADV %dms",
754 fcoe->keepalive );
755 }
756 DBGC ( fcoe, ", %cPMA)\n",
757 ( ( fcoe->flags & FCOE_FCF_ALLOWS_SPMA ) ?
758 'S' : 'F' ) );
759 }
760
761 } else if ( fcoe->flags & FCOE_HAVE_FIP_FCF ) {
762
763 /* We are checking that the FCF remains alive. Reset
764 * the timeout counter if this is an advertisement
765 * from our forwarder.
766 */
767 if ( memcmp ( fcoe->fcf_mac, mac_address->mac,
768 sizeof ( fcoe->fcf_mac ) ) == 0 ) {
769 fcoe->timeouts = 0;
770 }
771
772 } else {
773
774 /* We are operating in non-FIP mode and have received
775 * a FIP advertisement. Reset the link in order to
776 * attempt FIP.
777 */
778 fcoe_reset ( fcoe );
779
780 }
781
782 return 0;
783}
784
785/**
786 * Handle received FIP ELS response
787 *
788 * @v fcoe FCoE port
789 * @v descs Descriptor list
790 * @v flags Flags
791 * @ret rc Return status code
792 */
793static int fcoe_fip_rx_els_response ( struct fcoe_port *fcoe,
794 struct fip_descriptors *descs,
795 unsigned int flags __unused ) {
796 struct fip_els *flogi = fip_flogi ( descs );
797 struct fip_mac_address *mac_address = fip_mac_address ( descs );
798 void *frame;
799 size_t frame_len;
800 int rc;
801
802 /* Sanity checks */
803 if ( ! flogi ) {
804 DBGC ( fcoe, "FCoE %s received ELS response missing FLOGI\n",
805 fcoe->netdev->name );
806 return -EINVAL;
807 }
808 if ( ! mac_address ) {
809 DBGC ( fcoe, "FCoE %s received ELS response missing MAC "
810 "address\n", fcoe->netdev->name );
811 return -EINVAL;
812 }
813
814 /* Record local MAC address */
815 memcpy ( fcoe->local_mac, mac_address->mac, sizeof ( fcoe->local_mac ));
816 DBGC ( fcoe, "FCoE %s using local MAC %s\n",
817 fcoe->netdev->name, eth_ntoa ( fcoe->local_mac ) );
818
819 /* Hand off via transport interface */
820 frame = &flogi->fc;
821 frame_len = ( ( flogi->len * 4 ) - offsetof ( typeof ( *flogi ), fc ) );
822 if ( ( rc = xfer_deliver_raw ( &fcoe->transport, frame,
823 frame_len ) ) != 0 ) {
824 DBGC ( fcoe, "FCoE %s could not deliver FIP FLOGI frame: %s\n",
825 fcoe->netdev->name, strerror ( rc ) );
826 return rc;
827 }
828
829 return 0;
830}
831
832/**
833 * Send FIP keepalive
834 *
835 * @v fcoe FCoE port
836 * @ret rc Return status code
837 */
838static int fcoe_fip_tx_keepalive ( struct fcoe_port *fcoe ) {
839 struct io_buffer *iobuf;
840 struct {
841 struct fip_header hdr;
842 struct fip_mac_address mac_address;
843 } __attribute__ (( packed )) *keepalive;
844 int rc;
845
846 /* Allocate I/O buffer */
847 iobuf = alloc_iob ( MAX_LL_HEADER_LEN + sizeof ( *keepalive ) );
848 if ( ! iobuf )
849 return -ENOMEM;
851
852 /* Construct keepalive */
853 keepalive = iob_put ( iobuf, sizeof ( *keepalive ) );
854 memset ( keepalive, 0, sizeof ( *keepalive ) );
855 keepalive->hdr.version = FIP_VERSION;
856 keepalive->hdr.code = htons ( FIP_CODE_MAINTAIN );
857 keepalive->hdr.subcode = FIP_MAINTAIN_KEEP_ALIVE;
858 keepalive->hdr.len = htons ( ( sizeof ( *keepalive ) -
859 sizeof ( keepalive->hdr ) ) / 4 );
860 keepalive->mac_address.type = FIP_MAC_ADDRESS;
861 keepalive->mac_address.len =
862 ( sizeof ( keepalive->mac_address ) / 4 );
863 memcpy ( keepalive->mac_address.mac, fcoe->netdev->ll_addr,
864 sizeof ( keepalive->mac_address.mac ) );
865
866 /* Send keepalive */
867 if ( ( rc = net_tx ( iob_disown ( iobuf ), fcoe->netdev,
868 &fip_protocol, fcoe->fcf_mac,
869 fcoe->netdev->ll_addr ) ) != 0 ) {
870 DBGC ( fcoe, "FCoE %s could not send keepalive: %s\n",
871 fcoe->netdev->name, strerror ( rc ) );
872 return rc;
873 }
874
875 return 0;
876}
877
878/** A FIP handler */
880 /** Protocol code */
882 /** Protocol subcode */
884 /**
885 * Receive FIP packet
886 *
887 * @v fcoe FCoE port
888 * @v descs Descriptor list
889 * @v flags Flags
890 * @ret rc Return status code
891 */
892 int ( * rx ) ( struct fcoe_port *fcoe, struct fip_descriptors *descs,
893 unsigned int flags );
894};
895
896/** FIP handlers */
905
906/**
907 * Process incoming FIP packets
908 *
909 * @v iobuf I/O buffer
910 * @v netdev Network device
911 * @v ll_dest Link-layer destination address
912 * @v ll_source Link-layer source address
913 * @v flags Packet flags
914 * @ret rc Return status code
915 */
916static int fcoe_fip_rx ( struct io_buffer *iobuf,
917 struct net_device *netdev,
918 const void *ll_dest,
919 const void *ll_source __unused,
920 unsigned int flags __unused ) {
921 struct fip_header *fiphdr;
922 struct fip_descriptors descs;
923 struct fip_handler *handler;
924 struct fcoe_port *fcoe;
925 unsigned int i;
926 int rc;
927
928 /* Identify FCoE port */
929 fcoe = netdev_priv ( netdev, &fcoe_driver );
930 if ( ! fcoe->netdev ) {
931 DBG ( "FCoE received FIP frame for net device %s missing FCoE "
932 "port\n", netdev->name );
933 rc = -ENOTCONN;
934 goto done;
935 }
936
937 /* Discard packets not destined for us */
938 if ( ( memcmp ( fcoe->netdev->ll_addr, ll_dest, ETH_ALEN ) != 0 ) &&
939 ( memcmp ( all_fcoe_macs, ll_dest,
940 sizeof ( all_fcoe_macs ) ) != 0 ) &&
941 ( memcmp ( all_enode_macs, ll_dest,
942 sizeof ( all_enode_macs ) ) != 0 ) ) {
943 DBGC2 ( fcoe, "FCoE %s ignoring FIP packet for %s\n",
944 fcoe->netdev->name, eth_ntoa ( ll_dest ) );
945 rc = -ENOTCONN;
946 goto done;
947 }
948
949 /* Sanity check */
950 if ( iob_len ( iobuf ) < sizeof ( *fiphdr ) ) {
951 DBGC ( fcoe, "FCoE %s received under-length FIP packet (%zd "
952 "bytes)\n", fcoe->netdev->name, iob_len ( iobuf ) );
954 goto done;
955 }
956 fiphdr = iobuf->data;
957
958 /* Parse FIP packet */
959 if ( ( rc = fcoe_fip_parse ( fcoe, fiphdr, iob_len ( iobuf ),
960 &descs ) ) != 0 )
961 goto done;
962
963 /* Find a suitable handler */
964 for ( i = 0 ; i < ( sizeof ( fip_handlers ) /
965 sizeof ( fip_handlers[0] ) ) ; i++ ) {
966 handler = &fip_handlers[i];
967 if ( ( handler->code == ntohs ( fiphdr->code ) ) &&
968 ( handler->subcode == fiphdr->subcode ) ) {
969 rc = handler->rx ( fcoe, &descs,
970 ntohs ( fiphdr->flags ) );
971 goto done;
972 }
973 }
974 DBGC ( fcoe, "FCoE %s received unsupported FIP code %04x.%02x\n",
975 fcoe->netdev->name, ntohs ( fiphdr->code ), fiphdr->subcode );
976 rc = -ENOTSUP;
977
978 done:
979 free_iob ( iobuf );
980 return rc;
981}
982
983/******************************************************************************
984 *
985 * FCoE ports
986 *
987 ******************************************************************************
988 */
989
990/**
991 * Handle FCoE timer expiry
992 *
993 * @v timer FIP timer
994 * @v over Timer expired
995 */
996static void fcoe_expired ( struct retry_timer *timer, int over __unused ) {
997 struct fcoe_port *fcoe =
998 container_of ( timer, struct fcoe_port, timer );
999 int rc;
1000
1001 /* Sanity check */
1002 assert ( fcoe->flags & FCOE_HAVE_NETWORK );
1003
1004 /* Increment the timeout counter */
1005 fcoe->timeouts++;
1006
1007 if ( vlan_can_be_trunk ( fcoe->netdev ) &&
1008 ! ( fcoe->flags & FCOE_VLAN_TIMED_OUT ) ) {
1009
1010 /* If we have already found a VLAN, send infrequent
1011 * VLAN requests, in case VLAN information changes.
1012 */
1013 if ( fcoe->flags & FCOE_VLAN_FOUND ) {
1014 fcoe->flags &= ~FCOE_VLAN_FOUND;
1015 fcoe->timeouts = 0;
1016 start_timer_fixed ( &fcoe->timer,
1018 fcoe_fip_tx_vlan ( fcoe );
1019 return;
1020 }
1021
1022 /* If we have not yet found a VLAN, and we have not
1023 * yet timed out and given up on finding one, then
1024 * send a VLAN request and wait.
1025 */
1026 if ( fcoe->timeouts <= FCOE_MAX_VLAN_REQUESTS ) {
1027 start_timer_fixed ( &fcoe->timer,
1029 fcoe_fip_tx_vlan ( fcoe );
1030 return;
1031 }
1032
1033 /* We have timed out waiting for a VLAN; proceed to
1034 * FIP discovery.
1035 */
1036 fcoe->flags |= FCOE_VLAN_TIMED_OUT;
1037 fcoe->timeouts = 0;
1038 DBGC ( fcoe, "FCoE %s giving up on VLAN discovery\n",
1039 fcoe->netdev->name );
1040 start_timer_nodelay ( &fcoe->timer );
1041
1042 } else if ( ! ( fcoe->flags & FCOE_HAVE_FCF ) ) {
1043
1044 /* If we have not yet found a FIP-capable forwarder,
1045 * and we have not yet timed out and given up on
1046 * finding one, then send a FIP solicitation and wait.
1047 */
1049 if ( ( ! ( fcoe->flags & FCOE_HAVE_FIP_FCF ) ) &&
1050 ( fcoe->timeouts <= FCOE_MAX_FIP_SOLICITATIONS ) ) {
1051 fcoe_fip_tx_solicitation ( fcoe );
1052 return;
1053 }
1054
1055 /* Attach Fibre Channel port */
1056 if ( ( rc = fc_port_open ( &fcoe->transport, &fcoe->node_wwn.fc,
1057 &fcoe->port_wwn.fc,
1058 fcoe->netdev->name ) ) != 0 ) {
1059 DBGC ( fcoe, "FCoE %s could not create FC port: %s\n",
1060 fcoe->netdev->name, strerror ( rc ) );
1061 /* We will try again on the next timer expiry */
1062 return;
1063 }
1064 stop_timer ( &fcoe->timer );
1065
1066 /* Either we have found a FIP-capable forwarder, or we
1067 * have timed out and will fall back to pre-FIP mode.
1068 */
1069 fcoe->flags |= FCOE_HAVE_FCF;
1070 fcoe->timeouts = 0;
1071 DBGC ( fcoe, "FCoE %s using %sFIP FCF %s\n", fcoe->netdev->name,
1072 ( ( fcoe->flags & FCOE_HAVE_FIP_FCF ) ? "" : "non-" ),
1073 eth_ntoa ( fcoe->fcf_mac ) );
1074
1075 /* Start sending keepalives if applicable */
1076 if ( fcoe->keepalive )
1077 start_timer_nodelay ( &fcoe->timer );
1078
1079 /* Send notification of window change */
1080 xfer_window_changed ( &fcoe->transport );
1081
1082 } else {
1083
1084 /* Send keepalive */
1085 start_timer_fixed ( &fcoe->timer,
1086 ( fcoe->keepalive * TICKS_PER_MS ) );
1087 fcoe_fip_tx_keepalive ( fcoe );
1088
1089 /* Abandon FCF if we have not seen its advertisements */
1091 DBGC ( fcoe, "FCoE %s abandoning FCF %s\n",
1092 fcoe->netdev->name, eth_ntoa ( fcoe->fcf_mac ));
1093 fcoe_reset ( fcoe );
1094 }
1095 }
1096}
1097
1098/**
1099 * Create FCoE port
1100 *
1101 * @v netdev Network device
1102 * @v priv Private data
1103 * @ret rc Return status code
1104 */
1105static int fcoe_probe ( struct net_device *netdev, void *priv ) {
1106 struct ll_protocol *ll_protocol = netdev->ll_protocol;
1107 struct fcoe_port *fcoe = priv;
1108
1109 /* Sanity check */
1110 if ( ll_protocol->ll_proto != htons ( ARPHRD_ETHER ) ) {
1111 /* Not an error; simply skip this net device */
1112 DBG ( "FCoE skipping non-Ethernet device %s\n", netdev->name );
1113 return 0;
1114 }
1115
1116 /* Initialise structure */
1117 intf_init ( &fcoe->transport, &fcoe_transport_desc, &netdev->refcnt );
1118 timer_init ( &fcoe->timer, fcoe_expired, &netdev->refcnt );
1119 fcoe->netdev = netdev;
1120
1121 /* Construct node and port names */
1123 memcpy ( &fcoe->node_wwn.fcoe.mac, netdev->ll_addr,
1124 sizeof ( fcoe->node_wwn.fcoe.mac ) );
1126 memcpy ( &fcoe->port_wwn.fcoe.mac, netdev->ll_addr,
1127 sizeof ( fcoe->port_wwn.fcoe.mac ) );
1128
1129 DBGC ( fcoe, "FCoE %s is %s", fcoe->netdev->name,
1130 fc_ntoa ( &fcoe->node_wwn.fc ) );
1131 DBGC ( fcoe, " port %s\n", fc_ntoa ( &fcoe->port_wwn.fc ) );
1132
1133 return 0;
1134}
1135
1136/**
1137 * Handle FCoE port device or link state change
1138 *
1139 * @v netdev Network device
1140 * @v priv Private data
1141 */
1142static void fcoe_notify ( struct net_device *netdev, void *priv ) {
1143 struct fcoe_port *fcoe = priv;
1144
1145 /* Skip non-FCoE net devices */
1146 if ( ! fcoe->netdev )
1147 return;
1148
1149 /* Reset the FCoE link if necessary */
1150 if ( ! ( netdev_is_open ( netdev ) &&
1151 netdev_link_ok ( netdev ) &&
1152 ( fcoe->flags & FCOE_HAVE_NETWORK ) ) ) {
1153 fcoe_reset ( fcoe );
1154 }
1155}
1156
1157/**
1158 * Destroy FCoE port
1159 *
1160 * @v netdev Network device
1161 * @v priv Private data
1162 */
1163static void fcoe_remove ( struct net_device *netdev __unused, void *priv ) {
1164 struct fcoe_port *fcoe = priv;
1165
1166 /* Skip non-FCoE net devices */
1167 if ( ! fcoe->netdev )
1168 return;
1169
1170 /* Close FCoE device */
1171 fcoe_close ( fcoe, 0 );
1172}
1173
1174/** FCoE driver */
1175struct net_driver fcoe_driver __net_driver = {
1176 .name = "FCoE",
1177 .priv_len = sizeof ( struct fcoe_port ),
1178 .probe = fcoe_probe,
1179 .notify = fcoe_notify,
1180 .remove = fcoe_remove,
1181};
1182
1183/** FCoE protocol */
1184struct net_protocol fcoe_protocol __net_protocol = {
1185 .name = "FCoE",
1186 .net_proto = htons ( ETH_P_FCOE ),
1187 .rx = fcoe_rx,
1188};
1189
1190/** FIP protocol */
1191struct net_protocol fip_protocol __net_protocol = {
1192 .name = "FIP",
1193 .net_proto = htons ( ETH_P_FIP ),
1194 .rx = fcoe_fip_rx,
1195};
1196
1197/** Human-readable message for CRC errors
1198 *
1199 * It seems as though several drivers neglect to strip the Ethernet
1200 * CRC, which will cause the FCoE footer to be misplaced and result
1201 * (coincidentally) in an "invalid CRC" error from FCoE.
1202 */
1203struct errortab fcoe_errors[] __errortab = {
1205};
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
struct golan_inbox_hdr hdr
Message header.
Definition CIB_PRM.h:0
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition acpi.c:48
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned short uint16_t
Definition stdint.h:11
unsigned int uint32_t
Definition stdint.h:12
unsigned char uint8_t
Definition stdint.h:10
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
struct bofm_section_header done
Definition bofm_test.c:46
u32 crc32_le(u32 seed, const void *data, size_t len)
Calculate 32-bit little-endian CRC checksum.
Definition crc32.c:40
struct device * identify_device(struct interface *intf)
Identify a device behind an interface.
Definition device.c:126
Device model.
ring len
Length.
Definition dwmac.h:226
uint64_t tag
Identity tag.
Definition edd.h:1
uint8_t flags
Flags.
Definition ena.h:7
uint8_t meta
Metadata flags.
Definition ena.h:3
struct ena_llq_option desc
Descriptor counts.
Definition ena.h:9
Error codes.
Error message tables.
#define __errortab
Definition errortab.h:22
#define __einfo_errortab(einfo)
Definition errortab.h:24
const char * eth_ntoa(const void *ll_addr)
Transcribe Ethernet address.
Definition ethernet.c:177
Ethernet protocol.
const char * fc_ntoa(const struct fc_name *wwn)
Format Fibre Channel WWN.
Definition fc.c:127
int fc_port_open(struct interface *transport, const struct fc_name *node_wwn, const struct fc_name *port_wwn, const char *name)
Create Fibre Channel port.
Definition fc.c:1190
Fibre Channel.
@ FC_R_CTL_ELS
Extended Link Services.
Definition fc.h:163
@ FC_R_CTL_UNSOL_CTRL
Unsolicited Control.
Definition fc.h:179
@ FC_F_CTL_ES_END
Last Data Frame of Sequence.
Definition fc.h:204
@ FC_ELS_FLOGI
Fabric Login.
Definition fcels.h:35
static uint8_t all_fcf_macs[ETH_ALEN]
FCoE All-FCF-MACs address.
Definition fcoe.c:128
static size_t fcoe_window(struct fcoe_port *fcoe)
Check FCoE flow control window.
Definition fcoe.c:417
static void fcoe_reset(struct fcoe_port *fcoe)
Reset FCoE port.
Definition fcoe.c:165
static struct io_buffer * fcoe_alloc_iob(struct fcoe_port *fcoe __unused, size_t len)
Allocate FCoE I/O buffer.
Definition fcoe.c:298
#define EINVAL_CRC
Definition fcoe.c:64
static uint8_t default_fcf_mac[ETH_ALEN]
Default FCoE forwarded MAC address.
Definition fcoe.c:132
static int fcoe_fip_rx_advertisement(struct fcoe_port *fcoe, struct fip_descriptors *descs, unsigned int flags)
Handle received FIP discovery advertisement.
Definition fcoe.c:703
#define EINVAL_SOF
Definition fcoe.c:61
#define EINVAL_UNDERLENGTH
Definition fcoe.c:58
static void fcoe_remove(struct net_device *netdev __unused, void *priv)
Destroy FCoE port.
Definition fcoe.c:1163
static int fcoe_rx(struct io_buffer *iobuf, struct net_device *netdev, const void *ll_dest, const void *ll_source, unsigned int flags __unused)
Process incoming FCoE packets.
Definition fcoe.c:321
static int fcoe_fip_tx_vlan(struct fcoe_port *fcoe)
Send FIP VLAN request.
Definition fcoe.c:548
#define EINVAL_EOF
Definition fcoe.c:67
static uint8_t all_fcoe_macs[ETH_ALEN]
FCoE All-FCoE-MACs address.
Definition fcoe.c:120
static struct interface_operation fcoe_transport_op[]
FCoE transport interface operations.
Definition fcoe.c:444
static uint8_t all_enode_macs[ETH_ALEN]
FCoE All-ENode-MACs address.
Definition fcoe.c:124
#define FCOE_MAX_FIP_SOLICITATIONS
Maximum number of FIP solicitations before giving up on FIP.
Definition fcoe.c:145
static int fcoe_probe(struct net_device *netdev, void *priv)
Create FCoE port.
Definition fcoe.c:1105
#define FCOE_MAX_VLAN_REQUESTS
Maximum number of VLAN requests before giving up on VLAN discovery.
Definition fcoe.c:136
static void fcoe_notify(struct net_device *netdev, void *priv)
Handle FCoE port device or link state change.
Definition fcoe.c:1142
static int fcoe_fip_rx(struct io_buffer *iobuf, struct net_device *netdev, const void *ll_dest, const void *ll_source __unused, unsigned int flags __unused)
Process incoming FIP packets.
Definition fcoe.c:916
static int fcoe_fip_tx_solicitation(struct fcoe_port *fcoe)
Send FIP discovery solicitation.
Definition fcoe.c:642
static int fcoe_fip_rx_els_response(struct fcoe_port *fcoe, struct fip_descriptors *descs, unsigned int flags __unused)
Handle received FIP ELS response.
Definition fcoe.c:793
#define FCOE_FIP_RETRY_DELAY
Delay between retrying FIP solicitations.
Definition fcoe.c:148
static int fcoe_fip_tx_keepalive(struct fcoe_port *fcoe)
Send FIP keepalive.
Definition fcoe.c:838
static int fcoe_fip_rx_vlan(struct fcoe_port *fcoe, struct fip_descriptors *descs, unsigned int flags __unused)
Handle received FIP VLAN notification.
Definition fcoe.c:596
static void fcoe_close(struct fcoe_port *fcoe, int rc)
Close FCoE port.
Definition fcoe.c:427
#define FCOE_VLAN_POLL_DELAY
Delay between retrying polling VLAN requests.
Definition fcoe.c:142
static int fcoe_deliver(struct fcoe_port *fcoe, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
Transmit FCoE packet.
Definition fcoe.c:203
static struct fip_handler fip_handlers[]
FIP handlers.
Definition fcoe.c:897
#define EINFO_EINVAL_CRC
Definition fcoe.c:65
static struct interface_descriptor fcoe_transport_desc
FCoE transport interface descriptor.
Definition fcoe.c:454
#define FCOE_VLAN_RETRY_DELAY
Delay between retrying VLAN requests.
Definition fcoe.c:139
static int fcoe_fip_parse(struct fcoe_port *fcoe, struct fip_header *fiphdr, size_t len, struct fip_descriptors *descs)
Parse FIP packet into descriptor set.
Definition fcoe.c:473
static struct device * fcoe_identify_device(struct fcoe_port *fcoe)
Identify device underlying FCoE port.
Definition fcoe.c:439
static void fcoe_expired(struct retry_timer *timer, int over __unused)
Handle FCoE timer expiry.
Definition fcoe.c:996
fcoe_flags
FCoE flags.
Definition fcoe.c:100
@ FCOE_VLAN_TIMED_OUT
VLAN discovery has timed out.
Definition fcoe.c:112
@ FCOE_VLAN_FOUND
An alternative VLAN has been found.
Definition fcoe.c:110
@ FCOE_FCF_ALLOWS_SPMA
FCoE forwarder supports server-provided MAC addresses.
Definition fcoe.c:108
@ FCOE_HAVE_FIP_FCF
We have a FIP-capable FCoE forwarder available to be used.
Definition fcoe.c:106
@ FCOE_HAVE_NETWORK
Underlying network device is available.
Definition fcoe.c:102
@ FCOE_HAVE_FCF
We have selected an FCoE forwarder to use.
Definition fcoe.c:104
#define FCOE_MAX_FIP_MISSING_KEEPALIVES
Maximum number of missing discovery advertisements.
Definition fcoe.c:151
Fibre Channel over Ethernet.
@ FCOE_EOF_T
End of Frame Terminate.
Definition fcoe.h:84
@ FCOE_EOF_N
End of Frame Normal.
Definition fcoe.h:83
#define FCOE_VLAN_PRIORITY
FCoE VLAN priority.
Definition fcoe.h:90
@ FCOE_SOF_I3
Start of Frame Initiate Class 3.
Definition fcoe.h:67
@ FCOE_SOF_N3
Start of Frame Normal Class 3.
Definition fcoe.h:68
#define FCOE_FRAME_VER
FCoE frame version.
Definition fcoe.h:60
#define FCOE_AUTHORITY_IEEE_EXTENDED
IEEE extended.
Definition fcoe.h:34
#define FCOE_AUTHORITY_IEEE
IEEE 48-bit address.
Definition fcoe.h:31
@ FIP_MAINTAIN_KEEP_ALIVE
Keep alive.
Definition fip.h:71
@ FIP_CODE_ELS
Extended link services.
Definition fip.h:52
@ FIP_CODE_DISCOVERY
Discovery.
Definition fip.h:51
@ FIP_CODE_MAINTAIN
Maintain virtual links.
Definition fip.h:53
@ FIP_CODE_VLAN
VLAN.
Definition fip.h:54
#define FIP_LOWEST_PRIORITY
Lowest FIP priority.
Definition fip.h:142
@ FIP_ELS_REQUEST
ELS request.
Definition fip.h:65
@ FIP_ELS_RESPONSE
ELS response.
Definition fip.h:66
@ FIP_SP
Server-provided MAC address.
Definition fip.h:84
@ FIP_FP
Fabric-provided MAC address.
Definition fip.h:83
@ FIP_S
Solicited.
Definition fip.h:86
@ FIP_A
Available for login.
Definition fip.h:85
@ FIP_F
Forwarder.
Definition fip.h:87
#define FIP_IS_CRITICAL(type)
FIP descriptor type is critical.
Definition fip.h:121
@ FIP_VLAN_REQUEST
VLAN request.
Definition fip.h:77
@ FIP_VLAN_NOTIFY
VLAN notification.
Definition fip.h:78
@ FIP_NO_KEEPALIVE
Do not send keepalives.
Definition fip.h:322
#define FIP_VERSION
FIP frame version.
Definition fip.h:47
@ FIP_MAX_FCOE_SIZE
Max FCoE size.
Definition fip.h:108
@ FIP_RESERVED
Reserved.
Definition fip.h:102
@ FIP_MAC_ADDRESS
MAC address.
Definition fip.h:104
@ FIP_NUM_DESCRIPTOR_TYPES
Definition fip.h:117
@ FIP_NAME_ID
Name identifier.
Definition fip.h:106
@ FIP_FLOGI
FLOGI.
Definition fip.h:109
@ FIP_DISCOVERY_SOLICIT
Discovery solicitation.
Definition fip.h:59
@ FIP_DISCOVERY_ADVERTISE
Discovery advertisement.
Definition fip.h:60
static struct net_device * netdev
Definition gdbudp.c:53
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:598
#define DBGC2(...)
Definition compiler.h:547
#define DBGC(...)
Definition compiler.h:530
#define DBG(...)
Print a debugging message.
Definition compiler.h:523
#define DHCP_EB_FEATURE_FCOE
FCoE protocol.
Definition features.h:54
#define FEATURE_PROTOCOL
Network protocols.
Definition features.h:22
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:921
#define EINVAL
Invalid argument.
Definition errno.h:472
#define ENOMEM
Not enough space.
Definition errno.h:578
#define ENOTSUP
Operation not supported.
Definition errno.h:633
#define ECANCELED
Operation canceled.
Definition errno.h:387
#define EPROTONOSUPPORT
Protocol not supported.
Definition errno.h:673
#define ENOTCONN
The socket is not connected.
Definition errno.h:613
u16 fc
802.11 Frame Control field
Definition ieee80211.h:0
u8 request[0]
List of IEs requested.
Definition ieee80211.h:2
Address Resolution Protocol constants and types.
#define ARPHRD_ETHER
Ethernet 10Mbps.
Definition if_arp.h:17
#define ETH_P_FIP
Definition if_ether.h:29
#define ETH_P_FCOE
Definition if_ether.h:28
#define ETH_MAX_MTU
Definition if_ether.h:15
#define ETH_ALEN
Definition if_ether.h:9
#define ntohl(value)
Definition byteswap.h:135
#define le32_to_cpu(value)
Definition byteswap.h:114
#define cpu_to_le32(value)
Definition byteswap.h:108
#define htons(value)
Definition byteswap.h:136
#define ntohs(value)
Definition byteswap.h:137
#define __attribute__(x)
Definition compiler.h:10
iPXE timers
#define TICKS_PER_MS
Number of ticks per millisecond.
Definition timer.h:26
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition interface.c:250
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition interface.c:279
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition interface.c:344
Object interfaces.
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition interface.h:81
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition interface.h:204
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition iobuf.c:131
I/O buffers.
#define iob_push(iobuf, len)
Definition iobuf.h:149
#define iob_put(iobuf, len)
Definition iobuf.h:185
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition iobuf.h:277
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:220
#define iob_reserve(iobuf, len)
Definition iobuf.h:132
#define iob_pull(iobuf, len)
Definition iobuf.h:167
#define iob_unput(iobuf, len)
Definition iobuf.h:200
Feature list.
#define FEATURE(category, text, feature_opt, version)
Declare a feature.
Definition features.h:101
int net_tx(struct io_buffer *iobuf, struct net_device *netdev, struct net_protocol *net_protocol, const void *ll_dest, const void *ll_source)
Transmit network-layer packet.
Definition netdevice.c:1078
void * netdev_priv(struct net_device *netdev, struct net_driver *driver)
Get network device driver private data.
Definition netdevice.c:153
Network device management.
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition netdevice.h:665
static int netdev_link_ok(struct net_device *netdev)
Check link state of network device.
Definition netdevice.h:643
#define __net_driver
Declare a network driver.
Definition netdevice.h:510
#define MAX_LL_HEADER_LEN
Maximum length of a link-layer header.
Definition netdevice.h:46
#define __net_protocol
Declare a network-layer protocol.
Definition netdevice.h:477
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition retry.c:65
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition retry.c:118
Retry timers.
static void start_timer_nodelay(struct retry_timer *timer)
Start timer with no delay.
Definition retry.h:100
#define offsetof(type, field)
Get offset of a field within a structure.
Definition stddef.h:25
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
uint16_t priority
Priotity.
Definition stp.h:1
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
A hardware device.
Definition device.h:77
Fibre Channel ELS frame common parameters.
Definition fcels.h:23
uint8_t command
ELS command code.
Definition fcels.h:25
A Fibre Channel Frame Header.
Definition fc.h:121
uint8_t f_ctl_es
Frame control - exchange and sequence.
Definition fc.h:137
uint8_t r_ctl
Routing control.
Definition fc.h:127
uint16_t seq_cnt
Sequence count.
Definition fc.h:147
An FCoE header.
Definition fcoe.h:50
uint8_t version
FCoE frame version.
Definition fcoe.h:52
uint8_t sof
Start of Frame marker.
Definition fcoe.h:56
An FCoE port.
Definition fcoe.c:72
union fcoe_name node_wwn
Node WWN.
Definition fcoe.c:79
struct retry_timer timer
FIP retransmission timer.
Definition fcoe.c:84
unsigned int flags
Flags.
Definition fcoe.c:88
unsigned int keepalive
Keepalive delay (in ms).
Definition fcoe.c:92
uint8_t fcf_mac[ETH_ALEN]
FCoE forwarder MAC address.
Definition fcoe.c:94
struct net_device * netdev
Network device.
Definition fcoe.c:76
unsigned int timeouts
FIP timeout counter.
Definition fcoe.c:86
union fcoe_name port_wwn
Port WWN.
Definition fcoe.c:81
uint8_t local_mac[ETH_ALEN]
Local MAC address.
Definition fcoe.c:96
unsigned int priority
FCoE forwarder priority.
Definition fcoe.c:90
struct interface transport
Transport interface.
Definition fcoe.c:74
A FIP descriptor set.
Definition fip.h:406
size_t len[FIP_NUM_DESCRIPTOR_TYPES]
Descriptor lengths, indexed by type.
Definition fip.h:410
union fip_descriptor * desc[FIP_NUM_DESCRIPTOR_TYPES]
Descriptors, indexed by type.
Definition fip.h:408
A FIP descriptor containing an encapsulated ELS frame.
Definition fip.h:205
struct fc_frame_header fc
Fibre Channel frame header.
Definition fip.h:213
uint8_t len
Length in 32-bit words.
Definition fip.h:209
A FIP FKA ADV period descriptor.
Definition fip.h:307
uint8_t flags
Flags.
Definition fip.h:315
uint32_t period
Keep alive advertisement period in milliseconds.
Definition fip.h:317
A FIP handler.
Definition fcoe.c:879
uint8_t subcode
Protocol subcode.
Definition fcoe.c:883
int(* rx)(struct fcoe_port *fcoe, struct fip_descriptors *descs, unsigned int flags)
Receive FIP packet.
Definition fcoe.c:892
uint16_t code
Protocol code.
Definition fcoe.c:881
A FIP frame header.
Definition fip.h:29
uint16_t len
Descriptor list length in 32-bit words.
Definition fip.h:41
uint16_t code
Protocol code.
Definition fip.h:35
uint8_t version
Frame version.
Definition fip.h:31
uint8_t subcode
Subcode.
Definition fip.h:39
uint16_t flags
Flags.
Definition fip.h:43
A FIP descriptor containing an encapsulated login frame.
Definition fip.h:219
uint8_t type
Type.
Definition fip.h:221
uint8_t len
Length in 32-bit words.
Definition fip.h:223
A FIP MAC address descriptor.
Definition fip.h:145
uint8_t mac[ETH_ALEN]
MAC address.
Definition fip.h:151
uint8_t len
Length in 32-bit words.
Definition fip.h:149
uint8_t type
Type.
Definition fip.h:147
A FIP max FCoE size descriptor.
Definition fip.h:195
A FIP name identifier descriptor.
Definition fip.h:167
A FIP priority descriptor.
Definition fip.h:124
A FIP VLAN descriptor.
Definition fip.h:338
uint16_t vlan
VLAN ID.
Definition fip.h:344
An object interface descriptor.
Definition interface.h:56
An object interface operation.
Definition interface.h:18
An object interface.
Definition interface.h:125
A persistent I/O buffer.
Definition iobuf.h:98
void * data
Start of data.
Definition iobuf.h:113
A link-layer protocol.
Definition netdevice.h:115
uint16_t ll_proto
Link-layer protocol.
Definition netdevice.h:195
A network device.
Definition netdevice.h:353
char name[NETDEV_NAME_LEN]
Name of this network device.
Definition netdevice.h:363
struct device * dev
Underlying hardware device.
Definition netdevice.h:365
uint8_t ll_addr[MAX_LL_ADDR_LEN]
Link-layer address.
Definition netdevice.h:388
A network upper-layer driver.
Definition netdevice.h:480
A network-layer protocol.
Definition netdevice.h:65
A retry timer.
Definition retry.h:22
A timer.
Definition timer.h:29
Data transfer metadata.
Definition xfer.h:23
static struct tlan_private * priv
Definition tlan.c:225
An FCoE name.
Definition fcoe.h:18
uint8_t mac[ETH_ALEN]
MAC address.
Definition fcoe.h:26
struct fc_name fc
Fibre Channel name.
Definition fcoe.h:20
struct fcoe_name::@146233060014345030116354157144043320206274366016 fcoe
FCoE name.
uint16_t authority
Naming authority.
Definition fcoe.h:24
A FIP descriptor.
Definition fip.h:348
int vlan_can_be_trunk(struct net_device *trunk)
Check if network device can be used as a VLAN trunk device.
Definition vlan.c:331
int vlan_create(struct net_device *trunk, unsigned int tag, unsigned int priority)
Create VLAN device.
Definition vlan.c:345
Virtual LANs.
unsigned long frame
Definition xengrant.h:180
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition xfer.c:117
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition xfer.c:195
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
Definition xfer.c:159
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
Definition xfer.c:147
int xfer_deliver_iob(struct interface *intf, struct io_buffer *iobuf)
Deliver datagram as I/O buffer without metadata.
Definition xfer.c:256
int xfer_deliver_raw(struct interface *intf, const void *data, size_t len)
Deliver datagram as raw data without metadata.
Definition xfer.c:289
Data transfer interfaces.