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