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 
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 
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 */
78  /** Network device */
79  struct net_device *netdev;
80 
81  /** Node WWN */
83  /** Port WWN */
85 
86  /** FIP retransmission 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 */
98  /** Local MAC address */
100 };
101 
102 /** FCoE flags */
104  /** Underlying network device is available */
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 */
110  /** FCoE forwarder supports server-provided MAC addresses */
112  /** An alternative VLAN has been found */
113  FCOE_VLAN_FOUND = 0x0010,
114  /** VLAN discovery has timed out */
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 */
123  { 0x01, 0x10, 0x18, 0x01, 0x00, 0x00 };
124 
125 /** FCoE All-ENode-MACs address */
127  { 0x01, 0x10, 0x18, 0x01, 0x00, 0x01 };
128 
129 /** FCoE All-FCF-MACs address */
131  { 0x01, 0x10, 0x18, 0x01, 0x00, 0x02 };
132 
133 /** Default FCoE forwarded MAC address */
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 ) ) ?
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 ) ?
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 ) );
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 */
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 *,
474 };
475 
476 /** FCoE transport interface descriptor */
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 */
903  /** Protocol 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[] = {
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,
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,
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  */
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_MS ) );
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 ) {
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 */
1141  memcpy ( &fcoe->node_wwn.fcoe.mac, netdev->ll_addr,
1142  sizeof ( fcoe->node_wwn.fcoe.mac ) );
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 = {
1233 };
#define iob_pull(iobuf, len)
Definition: iobuf.h:98
struct list_head list
List of FCoE ports.
Definition: fcoe.c:75
#define __attribute__(x)
Definition: compiler.h:10
#define EINVAL
Invalid argument.
Definition: errno.h:428
An object interface operation.
Definition: interface.h:17
A FIP descriptor containing an encapsulated login frame.
Definition: fip.h:219
Fibre Channel ELS frame common parameters.
Definition: fcels.h:22
#define FCOE_AUTHORITY_IEEE
IEEE 48-bit address.
Definition: fcoe.h:31
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
Definition: xfer.c:145
unsigned short uint16_t
Definition: stdint.h:11
#define FCOE_VLAN_POLL_DELAY
Delay between retrying polling VLAN requests.
Definition: fcoe.c:144
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:244
const char * name
Protocol name.
Definition: netdevice.h:66
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition: interface.c:337
fcoe_flags
FCoE flags.
Definition: fcoe.c:103
#define iob_put(iobuf, len)
Definition: iobuf.h:116
Error message tables.
Data transfer metadata.
Definition: xfer.h:22
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition: interface.c:273
An alternative VLAN has been found.
Definition: fcoe.c:113
#define EINVAL_UNDERLENGTH
Definition: fcoe.c:57
int xfer_deliver_iob(struct interface *intf, struct io_buffer *iobuf)
Deliver datagram as I/O buffer without metadata.
Definition: xfer.c:254
Reserved.
Definition: fip.h:102
unsigned int priority
FCoE forwarder priority.
Definition: fcoe.c:93
#define FIP_LOWEST_PRIORITY
Lowest FIP priority.
Definition: fip.h:142
static void start_timer_nodelay(struct retry_timer *timer)
Start timer with no delay.
Definition: retry.h:99
Discovery advertisement.
Definition: fip.h:60
uint8_t type
Type.
Definition: fip.h:93
static int fcoe_fip_tx_keepalive(struct fcoe_port *fcoe)
Send FIP keepalive.
Definition: fcoe.c:859
unsigned int flags
Flags.
Definition: fcoe.c:91
#define FEATURE_PROTOCOL
Network protocols.
Definition: features.h:21
#define le32_to_cpu(value)
Definition: byteswap.h:113
Fabric Login.
Definition: fcels.h:34
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:69
A FIP priority descriptor.
Definition: fip.h:124
struct net_device * netdev
Network device.
Definition: fcoe.c:79
uint16_t seq_cnt
Sequence count.
Definition: fc.h:146
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:64
Error codes.
uint8_t len
Length in 32-bit words.
Definition: fip.h:95
#define FCOE_VLAN_RETRY_DELAY
Delay between retrying VLAN requests.
Definition: fcoe.c:141
#define iob_push(iobuf, len)
Definition: iobuf.h:80
u16 fc
802.11 Frame Control field
Definition: ieee80211.h:14
uint8_t mac[ETH_ALEN]
MAC address.
Definition: fcoe.h:26
I/O buffers.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:145
uint8_t flags
Flags.
Definition: fip.h:315
static struct interface_operation fcoe_transport_op[]
FCoE transport interface operations.
Definition: fcoe.c:467
#define FIP_VERSION
FIP frame version.
Definition: fip.h:47
uint8_t command
ELS command code.
Definition: fcels.h:24
static struct fip_handler fip_handlers[]
FIP handlers.
Definition: fcoe.c:918
#define __einfo_errortab(einfo)
Definition: errortab.h:23
Retry timers.
static struct interface_descriptor fcoe_transport_desc
FCoE transport interface descriptor.
Definition: fcoe.c:477
unsigned int timeouts
FIP timeout counter.
Definition: fcoe.c:89
A FIP handler.
Definition: fcoe.c:900
#define FCOE_VLAN_PRIORITY
FCoE VLAN priority.
Definition: fcoe.h:90
#define DBGC(...)
Definition: compiler.h:505
MAC address.
Definition: fip.h:104
FLOGI.
Definition: fip.h:109
A retry timer.
Definition: retry.h:21
uint8_t version
FCoE frame version.
Definition: fcoe.h:52
Underlying network device is available.
Definition: fcoe.c:105
#define FCOE_FIP_RETRY_DELAY
Delay between retrying FIP solicitations.
Definition: fcoe.c:150
#define ntohl(value)
Definition: byteswap.h:134
Max FCoE size.
Definition: fip.h:108
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
Definition: xfer.c:157
Extended Link Services.
Definition: fc.h:162
#define ETH_MAX_MTU
Definition: if_ether.h:14
Forwarder.
Definition: fip.h:87
static void fcoe_close(struct fcoe_port *fcoe, int rc)
Close FCoE port.
Definition: fcoe.c:447
iPXE timers
Available for login.
Definition: fip.h:85
#define ntohs(value)
Definition: byteswap.h:136
const char * fc_ntoa(const struct fc_name *wwn)
Format Fibre Channel WWN.
Definition: fc.c:127
struct fip_common common
Common fields.
Definition: fip.h:350
#define offsetof(type, field)
Get offset of a field within a structure.
Definition: stddef.h:24
static int fcoe_fip_tx_vlan(struct fcoe_port *fcoe)
Send FIP VLAN request.
Definition: fcoe.c:569
uint8_t local_mac[ETH_ALEN]
Local MAC address.
Definition: fcoe.c:99
An FCoE header.
Definition: fcoe.h:50
struct net_protocol fcoe_protocol __net_protocol
FCoE protocol.
Definition: fcoe.c:118
Last Data Frame of Sequence.
Definition: fc.h:203
uint8_t type
Type.
Definition: fip.h:147
Unsolicited Control.
Definition: fc.h:178
uint8_t len
Length in 32-bit words.
Definition: fip.h:223
#define FCOE_MAX_VLAN_REQUESTS
Maximum number of VLAN requests before giving up on VLAN discovery.
Definition: fcoe.c:138
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:342
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:128
A network upper-layer driver.
Definition: netdevice.h:461
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition: xfer.c:115
static struct fcoe_port * fcoe_demux(struct net_device *netdev)
Identify FCoE port by network device.
Definition: fcoe.c:171
A link-layer protocol.
Definition: netdevice.h:114
Address Resolution Protocol constants and types.
int vlan_create(struct net_device *trunk, unsigned int tag, unsigned int priority)
Create VLAN device.
Definition: vlan.c:338
End of Frame Terminate.
Definition: fcoe.h:84
#define ECANCELED
Operation canceled.
Definition: errno.h:343
int xfer_deliver_raw(struct interface *intf, const void *data, size_t len)
Deliver datagram as raw data without metadata.
Definition: xfer.c:287
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:496
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
A doubly-linked list entry (or list head)
Definition: list.h:18
A FIP VLAN descriptor.
Definition: fip.h:338
Data transfer interfaces.
A reference counter.
Definition: refcnt.h:26
static uint8_t all_enode_macs[ETH_ALEN]
FCoE All-ENode-MACs address.
Definition: fcoe.c:126
A timer.
Definition: timer.h:28
u32 crc32_le(u32 seed, const void *data, size_t len)
Calculate 32-bit little-endian CRC checksum.
Definition: crc32.c:39
Keep alive.
Definition: fip.h:71
uint16_t code
Protocol code.
Definition: fip.h:35
Fibre Channel over Ethernet.
A FIP frame header.
Definition: fip.h:29
unsigned long frame
Definition: xengrant.h:178
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
#define ENOMEM
Not enough space.
Definition: errno.h:534
static int fcoe_deliver(struct fcoe_port *fcoe, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
Transmit FCoE packet.
Definition: fcoe.c:224
A hardware device.
Definition: device.h:73
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition: iobuf.h:208
void * memcpy(void *dest, const void *src, size_t len) __nonnull
static struct io_buffer * fcoe_alloc_iob(struct fcoe_port *fcoe __unused, size_t len)
Allocate FCoE I/O buffer.
Definition: fcoe.c:319
const char * name
Name.
Definition: netdevice.h:463
Discovery solicitation.
Definition: fip.h:59
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition: netdevice.h:652
static void fcoe_remove(struct net_device *netdev)
Destroy FCoE port.
Definition: fcoe.c:1189
struct fcoe_name::@524 fcoe
FCoE name.
struct refcnt refcnt
Reference count.
Definition: fcoe.c:73
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition: netdevice.h:555
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
Ethernet protocol.
An object interface.
Definition: interface.h:109
static uint8_t all_fcf_macs[ETH_ALEN]
FCoE All-FCF-MACs address.
Definition: fcoe.c:130
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:420
Object interfaces.
#define ETH_P_FIP
Definition: if_ether.h:27
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:724
struct errortab fcoe_errors [] __errortab
Human-readable message for CRC errors.
Definition: fcoe.c:1231
static int netdev_link_ok(struct net_device *netdev)
Check link state of network device.
Definition: netdevice.h:630
static struct net_device * netdev
Definition: gdbudp.c:52
#define MAX_LL_HEADER_LEN
Maximum length of a link-layer header.
Definition: netdevice.h:45
uint16_t flags
Flags.
Definition: fip.h:43
Feature list.
union fcoe_name node_wwn
Node WWN.
Definition: fcoe.c:82
We have a FIP-capable FCoE forwarder available to be used.
Definition: fcoe.c:109
#define EINFO_EINVAL_CRC
Definition: fcoe.c:64
#define FCOE_MAX_FIP_MISSING_KEEPALIVES
Maximum number of missing discovery advertisements.
Definition: fcoe.c:153
static void fcoe_reset(struct fcoe_port *fcoe)
Reset FCoE port.
Definition: fcoe.c:186
uint8_t version
Frame version.
Definition: fip.h:31
uint16_t vlan
VLAN ID.
Definition: fip.h:344
uint16_t authority
Naming authority.
Definition: fcoe.h:24
Maintain virtual links.
Definition: fip.h:53
#define cpu_to_le32(value)
Definition: byteswap.h:107
int meta(WINDOW *, bool)
FCoE forwarder supports server-provided MAC addresses.
Definition: fcoe.c:111
#define ENOTCONN
The socket is not connected.
Definition: errno.h:569
static void fcoe_notify(struct net_device *netdev)
Handle FCoE port device or link state change.
Definition: fcoe.c:1166
An object interface descriptor.
Definition: interface.h:40
#define iob_unput(iobuf, len)
Definition: iobuf.h:131
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
uint8_t len
Length in 32-bit words.
Definition: fip.h:149
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
static int fcoe_probe(struct net_device *netdev)
Create FCoE port.
Definition: fcoe.c:1115
static int fcoe_fip_tx_solicitation(struct fcoe_port *fcoe)
Send FIP discovery solicitation.
Definition: fcoe.c:663
uint8_t r_ctl
Routing control.
Definition: fc.h:126
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:151
const char * eth_ntoa(const void *ll_addr)
Transcribe Ethernet address.
Definition: ethernet.c:175
A FIP descriptor set.
Definition: fip.h:406
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:32
VLAN.
Definition: fip.h:54
uint16_t len
Descriptor list length in 32-bit words.
Definition: fip.h:41
ELS response.
Definition: fip.h:66
A network device.
Definition: netdevice.h:348
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:1189
Name identifier.
Definition: fip.h:106
#define FCOE_MAX_FIP_SOLICITATIONS
Maximum number of FIP solicitations before giving up on FIP.
Definition: fcoe.c:147
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:193
A FIP MAC address descriptor.
Definition: fip.h:145
An FCoE port.
Definition: fcoe.c:71
unsigned char uint8_t
Definition: stdint.h:10
A FIP max FCoE size descriptor.
Definition: fip.h:195
static struct net_device * netdev_get(struct net_device *netdev)
Get reference to network device.
Definition: netdevice.h:544
static struct device * fcoe_identify_device(struct fcoe_port *fcoe)
Identify device underlying FCoE port.
Definition: fcoe.c:462
#define ETH_ALEN
Definition: if_ether.h:8
Fibre Channel.
uint16_t ll_proto
Link-layer protocol.
Definition: netdevice.h:194
A FIP FKA ADV period descriptor.
Definition: fip.h:307
unsigned int uint32_t
Definition: stdint.h:12
union fip_descriptor * desc[FIP_NUM_DESCRIPTOR_TYPES]
Descriptors, indexed by type.
Definition: fip.h:408
#define EINVAL_CRC
Definition: fcoe.c:63
struct retry_timer timer
FIP retransmission timer.
Definition: fcoe.c:87
A FIP descriptor containing an encapsulated ELS frame.
Definition: fip.h:205
#define EINVAL_EOF
Definition: fcoe.c:66
static size_t fcoe_window(struct fcoe_port *fcoe)
Check FCoE flow control window.
Definition: fcoe.c:437
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:937
struct device * dev
Underlying hardware device.
Definition: netdevice.h:360
struct fc_name fc
Fibre Channel name.
Definition: fcoe.h:20
uint32_t hdr
Message header.
Definition: intelvf.h:12
A network-layer protocol.
Definition: netdevice.h:64
static void fcoe_expired(struct retry_timer *timer, int over __unused)
Handle FCoE timer expiry.
Definition: fcoe.c:1007
Solicited.
Definition: fip.h:86
Network device management.
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition: retry.c:64
uint8_t f_ctl_es
Frame control - exchange and sequence.
Definition: fc.h:136
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
VLAN discovery has timed out.
Definition: fcoe.c:115
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:617
Start of Frame Initiate Class 3.
Definition: fcoe.h:67
#define iob_reserve(iobuf, len)
Definition: iobuf.h:63
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition: interface.h:65
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition: retry.c:117
VLAN request.
Definition: fip.h:77
int vlan_can_be_trunk(struct net_device *trunk)
Check if network device can be used as a VLAN trunk device.
Definition: vlan.c:324
Extended link services.
Definition: fip.h:52
char name[NETDEV_NAME_LEN]
Name of this network device.
Definition: netdevice.h:358
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:999
uint32_t len
Length.
Definition: ena.h:14
unsigned int keepalive
Keepalive delay (in ms)
Definition: fcoe.c:95
#define DBGC2(...)
Definition: compiler.h:522
VLAN notification.
Definition: fip.h:78
#define EPROTONOSUPPORT
Protocol not supported.
Definition: errno.h:629
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:814
struct net_driver fcoe_driver __net_driver
FCoE driver.
Definition: fcoe.c:1204
uint16_t priority
Priotity.
Definition: stp.h:12
uint8_t subcode
Protocol subcode.
Definition: fcoe.c:904
uint16_t code
Protocol code.
Definition: fcoe.c:902
#define EINVAL_SOF
Definition: fcoe.c:60
void * data
Start of data.
Definition: iobuf.h:44
static LIST_HEAD(fcoe_ports)
List of FCoE ports.
int(* rx)(struct fcoe_port *fcoe, struct fip_descriptors *descs, unsigned int flags)
Receive FIP packet.
Definition: fcoe.c:913
u8 request[0]
List of IEs requested.
Definition: ieee80211.h:16
Virtual LANs.
We have selected an FCoE forwarder to use.
Definition: fcoe.c:107
uint8_t mac[ETH_ALEN]
MAC address.
Definition: fip.h:151
Device model.
struct device * identify_device(struct interface *intf)
Identify a device behind an interface.
Definition: device.c:125
uint8_t sof
Start of Frame marker.
Definition: fcoe.h:56
uint8_t ll_addr[MAX_LL_ADDR_LEN]
Link-layer address.
Definition: netdevice.h:381
#define DHCP_EB_FEATURE_FCOE
FCoE protocol.
Definition: features.h:53
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
Fabric-provided MAC address.
Definition: fip.h:83
uint8_t subcode
Subcode.
Definition: fip.h:39
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition: interface.h:173
#define FCOE_FRAME_VER
FCoE frame version.
Definition: fcoe.h:60
#define ARPHRD_ETHER
Ethernet 10Mbps.
Definition: if_arp.h:16
ELS request.
Definition: fip.h:65
struct fc_frame_header fc
Fibre Channel frame header.
Definition: fip.h:213
A FIP descriptor.
Definition: fip.h:348
#define FCOE_AUTHORITY_IEEE_EXTENDED
IEEE extended.
Definition: fcoe.h:34
uint8_t type
Type.
Definition: fip.h:221
uint64_t tag
Identity tag.
Definition: edd.h:30
union fcoe_name port_wwn
Port WWN.
Definition: fcoe.c:84
static uint8_t all_fcoe_macs[ETH_ALEN]
FCoE All-FCoE-MACs address.
Definition: fcoe.c:122
A FIP name identifier descriptor.
Definition: fip.h:167
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:98
#define FIP_IS_CRITICAL(type)
FIP descriptor type is critical.
Definition: fip.h:121
static uint8_t default_fcf_mac[ETH_ALEN]
Default FCoE forwarded MAC address.
Definition: fcoe.c:134
Discovery.
Definition: fip.h:51
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
Do not send keepalives.
Definition: fip.h:322
Start of Frame Normal Class 3.
Definition: fcoe.h:68
#define htons(value)
Definition: byteswap.h:135
struct bofm_section_header done
Definition: bofm_test.c:46
uint8_t fcf_mac[ETH_ALEN]
FCoE forwarder MAC address.
Definition: fcoe.c:97
#define TICKS_PER_MS
Number of ticks per millisecond.
Definition: timer.h:25
uint8_t len
Length in 32-bit words.
Definition: fip.h:209
uint32_t period
Keep alive advertisement period in milliseconds.
Definition: fip.h:317
struct ll_protocol * ll_protocol
Link-layer protocol.
Definition: netdevice.h:366
struct interface transport
Transport interface.
Definition: fcoe.c:77
Server-provided MAC address.
Definition: fip.h:84
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106
End of Frame Normal.
Definition: fcoe.h:83
An FCoE name.
Definition: fcoe.h:18
A Fibre Channel Frame Header.
Definition: fc.h:120
#define ETH_P_FCOE
Definition: if_ether.h:26
void * memset(void *dest, int character, size_t len) __nonnull
A persistent I/O buffer.
Definition: iobuf.h:32
uint8_t flags
Flags.
Definition: ena.h:18
FEATURE(FEATURE_PROTOCOL, "FCoE", DHCP_EB_FEATURE_FCOE, 1)