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