選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

fcoe.c 34KB

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