Emulex Logo
OneCoreā„¢ Storage SDK Release 11.2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ocs_fabric.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2015, Emulex
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors
16  * may be used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  */
32 
33 /**
34  * @file
35  *
36  * This file implements remote node state machines for:
37  * - Fabric logins.
38  * - Fabric controller events.
39  * - Name/directory services interaction.
40  * - Point-to-point logins.
41  */
42 
43 /*!
44 @defgroup fabric_sm Node State Machine: Fabric States
45 @defgroup ns_sm Node State Machine: Name/Directory Services States
46 @defgroup p2p_sm Node State Machine: Point-to-Point Node States
47 */
48 
49 #include "ocs.h"
50 #include "ocs_fabric.h"
51 #include "ocs_els.h"
52 #include "ocs_device.h"
53 
54 static void ocs_fabric_initiate_shutdown(ocs_node_t *node);
55 static void * __ocs_fabric_common(const char *funcname, ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg);
56 static int32_t ocs_start_ns_node(ocs_sport_t *sport);
57 static int32_t ocs_start_fdmi_node(ocs_sport_t *sport);
58 static int32_t ocs_start_fabctl_node(ocs_sport_t *sport);
59 static int32_t ocs_process_gidpt_payload(ocs_node_t *node, fcct_gidpt_acc_t *gidpt, uint32_t gidpt_len);
60 static void ocs_process_rscn(ocs_node_t *node, ocs_node_cb_t *cbdata);
61 static uint64_t ocs_get_wwpn(fc_plogi_payload_t *sp);
62 static void gidpt_delay_timer_cb(void *arg);
63 static void *
64 __ocs_fdmi_get_cmd_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg);
65 
66 #define FDMI_ATTR_TYPE_LEN_SIZE 4
67 #define OCS_MAX_CT_SIZE (60 * 4096)
68 
69 /* FDMI Port Speed definitions - FC-GS-8 */
70 #define OCS_PORTSPEED_1GFC 0x00000001 /* 1G FC */
71 #define OCS_PORTSPEED_2GFC 0x00000002 /* 2G FC */
72 #define OCS_PORTSPEED_4GFC 0x00000008 /* 4G FC */
73 #define OCS_PORTSPEED_8GFC 0x00000010 /* 8G FC */
74 #define OCS_PORTSPEED_16GFC 0x00000020 /* 16G FC */
75 #define OCS_PORTSPEED_32GFC 0x00000040 /* 32G FC */
76 #define OCS_PORTSPEED_64GFC 0x00000400 /* 64G FC */
77 #define OCS_PORTSPEED_128GFC 0x00000200 /* 128G FC*/
78 #define OCS_PORTSPEED_UNKNOWN 0x00008000 /* Unknown*/
79 
80 /* Defines for PORT port type attribute */
81 #define OCS_FDMI_PORTTYPE_UNKNOWN 0
82 #define OCS_FDMI_PORTTYPE_NPORT 1
83 #define OCS_FDMI_PORTTYPE_NLPORT 2
84 
85 /* Defines for PORT port state attribute */
86 #define OCS_FDMI_PORTSTATE_OFFLINE 1
87 #define OCS_FDMI_PORTSTATE_ONLINE 2
88 
89 /**
90  * @ingroup fabric_sm
91  * @brief Fabric node state machine: Initial state.
92  *
93  * @par Description
94  * Send an FLOGI to a well-known fabric.
95  *
96  * @param ctx Remote node sm context.
97  * @param evt Event to process.
98  * @param arg Per event optional argument.
99  *
100  * @return Returns NULL.
101  */
102 void *
103 __ocs_fabric_init(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
104 {
106 
107  node_sm_trace();
108 
109  switch(evt) {
110  case OCS_EVT_REENTER: // not sure why we're getting these ...
111  ocs_log_debug(node->ocs, ">>> reenter !!\n");
112  // fall through
113  case OCS_EVT_ENTER:
114  // sm: / send FLOGI
117  break;
118 
119  default:
120  __ocs_fabric_common(__func__, ctx, evt, arg);
121  break;
122  }
123 
124  return NULL;
125 }
126 
127 /**
128  * @ingroup fabric_sm
129  * @brief Set sport topology.
130  *
131  * @par Description
132  * Set sport topology.
133  *
134  * @param node Pointer to the node for which the topology is set.
135  * @param topology Topology to set.
136  *
137  * @return Returns NULL.
138  */
139 void
141 {
142  node->sport->topology = topology;
143 }
144 
145 
146 /**
147  * @ingroup fabric_sm
148  * @brief Notify sport topology.
149  *
150  * @par Description
151  * notify sport topology.
152  * @param node Pointer to the node for which the topology is set.
153  * @return Returns NULL.
154  */
155 void
156 ocs_fabric_notify_topology(ocs_node_t *node)
157 {
158  ocs_node_t *tmp_node;
159  ocs_node_t *next;
160  ocs_sport_topology_e topology = node->sport->topology;
161 
162  /* now loop through the nodes in the sport and send topology notification */
163  ocs_sport_lock(node->sport);
164  ocs_list_foreach_safe(&node->sport->node_list, tmp_node, next) {
165  if (tmp_node != node) {
166  ocs_node_post_event(tmp_node, OCS_EVT_SPORT_TOPOLOGY_NOTIFY, (void *)topology);
167  }
168  }
169  ocs_sport_unlock(node->sport);
170 }
171 
172 /**
173  * @ingroup fabric_sm
174  * @brief Fabric node state machine: Wait for an FLOGI response.
175  *
176  * @par Description
177  * Wait for an FLOGI response event.
178  *
179  * @param ctx Remote node state machine context.
180  * @param evt Event to process.
181  * @param arg Per event optional argument.
182  *
183  * @return Returns NULL.
184  */
185 
186 void *
187 __ocs_fabric_flogi_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
188 {
189  ocs_node_cb_t *cbdata = arg;
191 
192  node_sm_trace();
193 
194  switch(evt) {
196 
197  if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_FLOGI, __ocs_fabric_common, __func__)) {
198  return NULL;
199  }
200  ocs_assert(node->els_req_cnt, NULL);
201  node->els_req_cnt--;
202 
203  ocs_domain_save_sparms(node->sport->domain, cbdata->els->els_rsp.virt);
204 
205  ocs_display_sparams(node->display_name, "flogi rcvd resp", 0, NULL,
206  ((uint8_t*)cbdata->els->els_rsp.virt) + 4);
207 
208  /* Check to see if the fabric is an F_PORT or and N_PORT */
209  if (ocs_rnode_is_nport(cbdata->els->els_rsp.virt)) {
210  // sm: if nport and p2p_winner / ocs_domain_attach
212  if (ocs_p2p_setup(node->sport)) {
213  node_printf(node, "p2p setup failed, shutting down node\n");
214  node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
216  } else {
217  if (node->sport->p2p_winner) {
219  if (!node->sport->domain->attached) {
220  node_printf(node, "p2p winner, domain not attached\n");
221  ocs_domain_attach(node->sport->domain, node->sport->p2p_port_id);
222  } else {
223  /* already attached, just send ATTACH_OK */
224  node_printf(node, "p2p winner, domain already attached\n");
226  }
227  } else {
228  /* peer is p2p winner; PLOGI will be received on the
229  * remote SID=1 node; this node has served its purpose
230  */
231  node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
233  }
234  }
235  } else {
236  // sm: if not nport / ocs_domain_attach
237  /* ext_status has the fc_id, attach domain */
240  ocs_assert(!node->sport->domain->attached, NULL);
241  ocs_domain_attach(node->sport->domain, cbdata->ext_status);
243  }
244 
245  break;
246  }
247 
251  ocs_sport_t *sport = node->sport;
252  /*
253  * with these errors, we have no recovery, so shutdown the sport, leave the link
254  * up and the domain ready
255  */
256  if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_FLOGI, __ocs_fabric_common, __func__)) {
257  return NULL;
258  }
259  node_printf(node, "FLOGI failed evt=%s, shutting down sport [%s]\n", ocs_sm_event_name(evt),
260  sport->display_name);
261  ocs_assert(node->els_req_cnt, NULL);
262  node->els_req_cnt--;
263  ocs_sm_post_event(&sport->sm, OCS_EVT_SHUTDOWN, NULL);
264  break;
265  }
266 
267  default:
268  __ocs_fabric_common(__func__, ctx, evt, arg);
269  break;
270  }
271 
272  return NULL;
273 }
274 
275 /**
276  * @ingroup fabric_sm
277  * @brief Fabric node state machine: Initial state for a virtual port.
278  *
279  * @par Description
280  * State entered when a virtual port is created. Send FDISC.
281  *
282  * @param ctx Remote node state machine context.
283  * @param evt Event to process.
284  * @param arg Per event optional argument.
285  *
286  * @return Returns NULL.
287  */
288 void *
289 __ocs_vport_fabric_init(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
290 {
292 
293  node_sm_trace();
294 
295  switch(evt) {
296  case OCS_EVT_ENTER:
297  //sm: / send FDISC
300  break;
301 
302  default:
303  __ocs_fabric_common(__func__, ctx, evt, arg);
304  break;
305  }
306 
307  return NULL;
308 }
309 
310 /**
311  * @ingroup fabric_sm
312  * @brief Fabric node state machine: Wait for an FDISC response
313  *
314  * @par Description
315  * Used for a virtual port. Waits for an FDISC response. If OK, issue a HAL port attach.
316  *
317  * @param ctx Remote node state machine context.
318  * @param evt Event to process.
319  * @param arg Per event optional argument.
320  *
321  * @return Returns NULL.
322  */
323 void *
324 __ocs_fabric_fdisc_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
325 {
326  ocs_node_cb_t *cbdata = arg;
328 
329  node_sm_trace();
330 
331  switch(evt) {
333  /* fc_id is in ext_status */
334  if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_FDISC, __ocs_fabric_common, __func__)) {
335  return NULL;
336  }
337 
338  ocs_display_sparams(node->display_name, "fdisc rcvd resp", 0, NULL,
339  ((uint8_t*)cbdata->els->els_rsp.virt) + 4);
340 
341  ocs_assert(node->els_req_cnt, NULL);
342  node->els_req_cnt--;
343  /* Set vport topology to FABRIC */
345  //sm: / ocs_sport_attach
346  ocs_sport_attach(node->sport, cbdata->ext_status);
348  break;
349 
350  }
351 
354  if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_FDISC, __ocs_fabric_common, __func__)) {
355  return NULL;
356  }
357  ocs_assert(node->els_req_cnt, NULL);
358  node->els_req_cnt--;
359  ocs_log_err(ocs, "FDISC failed, shutting down sport\n");
360  //sm: / shutdown sport
361  ocs_sm_post_event(&node->sport->sm, OCS_EVT_SHUTDOWN, NULL);
362  break;
363  }
364 
365  default:
366  __ocs_fabric_common(__func__, ctx, evt, arg);
367  break;
368  }
369 
370  return NULL;
371 }
372 
373 /**
374  * @ingroup fabric_sm
375  * @brief Fabric node state machine: Wait for a domain/sport attach event.
376  *
377  * @par Description
378  * Waits for a domain/sport attach event.
379  *
380  * @param ctx Remote node state machine context.
381  * @param evt Event to process.
382  * @param arg Per event optional argument.
383  *
384  * @return Returns NULL.
385  */
386 void *
387 __ocs_fabric_wait_domain_attach(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
388 {
390 
391  node_sm_trace();
392 
393  switch(evt) {
394  case OCS_EVT_ENTER:
395  ocs_node_hold_frames(node);
396  break;
397 
398  case OCS_EVT_EXIT:
400  break;
403  int rc;
404 
405  rc = ocs_start_ns_node(node->sport);
406  if (rc)
407  return NULL;
408 
409  //sm: if enable_ini / start fabctl node
410  /* Instantiate the fabric controller (sends SCR) */
411  if (node->sport->enable_rscn) {
412  rc = ocs_start_fabctl_node(node->sport);
413  if (rc)
414  return NULL;
415  }
416 
417  rc = ocs_start_fdmi_node(node->sport);
418  if (rc)
419  return NULL;
420 
422  break;
423  }
424  default:
425  __ocs_fabric_common(__func__, ctx, evt, arg);
426  return NULL;
427  }
428 
429  return NULL;
430 }
431 
432 /**
433  * @ingroup fabric_sm
434  * @brief Fabric node state machine: Fabric node is idle.
435  *
436  * @par Description
437  * Wait for fabric node events.
438  *
439  * @param ctx Remote node state machine context.
440  * @param evt Event to process.
441  * @param arg Per event optional argument.
442  *
443  * @return Returns NULL.
444  */
445 void *
446 __ocs_fabric_idle(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
447 {
449 
450  node_sm_trace();
451 
452  switch(evt) {
454  break;
455  default:
456  __ocs_fabric_common(__func__, ctx, evt, arg);
457  return NULL;
458  }
459 
460  return NULL;
461 }
462 
463 /**
464  * @ingroup ns_sm
465  * @brief Name services node state machine: Initialize.
466  *
467  * @par Description
468  * A PLOGI is sent to the well-known name/directory services node.
469  *
470  * @param ctx Remote node state machine context.
471  * @param evt Event to process.
472  * @param arg Per event optional argument.
473  *
474  * @return Returns NULL.
475  */
476 void *
477 __ocs_ns_init(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
478 {
480 
481  node_sm_trace();
482 
483  switch(evt) {
484  case OCS_EVT_ENTER:
485  //sm: / send PLOGI
488  break;
489  default:
490  __ocs_fabric_common(__func__, ctx, evt, arg);
491  break;
492  }
493 
494  return NULL;
495 }
496 
497 /**
498  * @ingroup ns_sm
499  * @brief Name services node state machine: Wait for a PLOGI response.
500  *
501  * @par Description
502  * Waits for a response from PLOGI to name services node, then issues a
503  * node attach request to the HAL.
504  *
505  * @param ctx Remote node state machine context.
506  * @param evt Event to process.
507  * @param arg Per event optional argument.
508  *
509  * @return Returns NULL.
510  */
511 void *
512 __ocs_ns_plogi_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
513 {
514  int32_t rc;
515  ocs_node_cb_t *cbdata = arg;
517 
518  node_sm_trace();
519 
520  switch(evt) {
522  /* Save service parameters */
523  if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PLOGI, __ocs_fabric_common, __func__)) {
524  return NULL;
525  }
526  ocs_assert(node->els_req_cnt, NULL);
527  node->els_req_cnt--;
528  //sm: / save sparams, ocs_node_attach
529  ocs_node_save_sparms(node, cbdata->els->els_rsp.virt);
530  ocs_display_sparams(node->display_name, "plogi rcvd resp", 0, NULL,
531  ((uint8_t*)cbdata->els->els_rsp.virt) + 4);
532  rc = ocs_node_attach(node);
534  if (rc == OCS_HAL_RTN_SUCCESS_SYNC) {
536  }
537  break;
538  }
539  default:
540  __ocs_fabric_common(__func__, ctx, evt, arg);
541  return NULL;
542  }
543 
544  return NULL;
545 }
546 
547 /**
548  * @ingroup ns_sm
549  * @brief Name services node state machine: Wait for a node attach completion.
550  *
551  * @par Description
552  * Waits for a node attach completion, then issues an RFTID name services
553  * request.
554  *
555  * @param ctx Remote node state machine context.
556  * @param evt Event to process.
557  * @param arg Per event optional argument.
558  *
559  * @return Returns NULL.
560  */
561 void *
562 __ocs_ns_wait_node_attach(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
563 {
565 
566  node_sm_trace();
567 
568  switch(evt) {
569  case OCS_EVT_ENTER:
570  ocs_node_hold_frames(node);
571  break;
572 
573  case OCS_EVT_EXIT:
575  break;
576 
578  node->attached = TRUE;
579  //sm: / send RFTID
581  OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL);
583  break;
584 
586  /* node attach failed, shutdown the node */
587  node->attached = FALSE;
588  node_printf(node, "Node attach failed\n");
589  node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
591  break;
592 
593  case OCS_EVT_SHUTDOWN:
594  node_printf(node, "Shutdown event received\n");
595  node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
597  break;
598 
599  /* if receive RSCN just ignore, we haven't sent GID_PT yet (ACC sent by fabctl node) */
600  case OCS_EVT_RSCN_RCVD:
601  break;
602 
603  default:
604  __ocs_fabric_common(__func__, ctx, evt, arg);
605  return NULL;
606  }
607 
608  return NULL;
609 }
610 
611 /**
612  * @ingroup fdmi_sm
613  * @brief FDMI node state machine: Initialize.
614  *
615  * @par Description
616  * A PLOGI is sent to the well-known FDMI node.
617  *
618  * @param ctx Remote node state machine context.
619  * @param evt Event to process.
620  * @param arg Per event optional argument.
621  *
622  * @return Returns NULL.
623  */
624 void *
625 __ocs_fdmi_init(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
626 {
628 
629  node_sm_trace();
630 
631  switch(evt) {
632  case OCS_EVT_ENTER:
633  //sm: / send PLOGI
636  break;
637  default:
638  __ocs_fabric_common(__func__, ctx, evt, arg);
639  break;
640  }
641 
642  return NULL;
643 }
644 
645 /**
646  * @ingroup fdmi_sm
647  * @brief FDMI node state machine: Wait for a PLOGI response.
648  *
649  * @par Description
650  * Waits for a response from PLOGI to name services node, then issues a
651  * node attach request to the HAL.
652  *
653  * @param ctx Remote node state machine context.
654  * @param evt Event to process.
655  * @param arg Per event optional argument.
656  *
657  * @return Returns NULL.
658  */
659 void *
660 __ocs_fdmi_plogi_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
661 {
662  int32_t rc;
663  ocs_node_cb_t *cbdata = arg;
665 
666  node_sm_trace();
667 
668  switch(evt) {
670  /* Save service parameters */
671  if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PLOGI, __ocs_fabric_common, __func__)) {
672  return NULL;
673  }
674  ocs_assert(node->els_req_cnt, NULL);
675  node->els_req_cnt--;
676  //sm: / save sparams, ocs_node_attach
677  ocs_node_save_sparms(node, cbdata->els->els_rsp.virt);
678  ocs_display_sparams(node->display_name, "plogi rcvd resp", 0, NULL,
679  ((uint8_t*)cbdata->els->els_rsp.virt) + 4);
680  rc = ocs_node_attach(node);
682  if (rc == OCS_HAL_RTN_SUCCESS_SYNC) {
684  }
685  break;
686  }
687  default:
688  __ocs_fabric_common(__func__, ctx, evt, arg);
689  return NULL;
690  }
691 
692  return NULL;
693 }
694 
695 /**
696  * @ingroup ns_sm
697  * @brief FDMI node state machine: Wait for a node attach completion.
698  *
699  * @par Description
700  * Waits for a node attach completion, then issues RHAT/RPRT registration
701  * requests to FDMI server.
702  *
703  * @param ctx Remote node state machine context.
704  * @param evt Event to process.
705  * @param arg Per event optional argument.
706  *
707  * @return Returns NULL.
708  */
709 void *
710 __ocs_fdmi_wait_node_attach(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
711 {
713 
714  node_sm_trace();
715 
716  switch(evt) {
717  case OCS_EVT_ENTER:
718  ocs_node_hold_frames(node);
719  break;
720 
721  case OCS_EVT_EXIT:
723  break;
724 
726  node->attached = TRUE;
727  /* SM transaction
728  * Physical Port: DHBA -> DPRT -> RHBA -> RPA
729  * Virtual Port: DPRT -> RPRT
730  */
731  node->sport->fdmi_port_mask = FDMI_PORT_MASK_V2;
732  if (node->sport->is_vport) {
735  OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL);
737  } else {
738  node->sport->fdmi_hba_mask = FDMI_RHBA_MASK_V2;
741  OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL);
743  }
744  break;
745 
747  /* node attach failed, shutdown the node */
748  node->attached = FALSE;
749  node_printf(node, "Node attach failed\n");
750  node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
752  break;
753 
754  case OCS_EVT_SHUTDOWN:
755  node_printf(node, "Shutdown event received\n");
756  node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
758  break;
759 
760  default:
761  __ocs_fabric_common(__func__, ctx, evt, arg);
762  return NULL;
763  }
764 
765  return NULL;
766 }
767 
768 /**
769  * @ingroup ns_sm
770  * @brief Wait for a domain/sport/node attach completion, then
771  * shutdown.
772  *
773  * @par Description
774  * Waits for a domain/sport/node attach completion, then shuts
775  * node down.
776  *
777  * @param ctx Remote node state machine context.
778  * @param evt Event to process.
779  * @param arg Per event optional argument.
780  *
781  * @return Returns NULL.
782  */
783 void *
784 __ocs_fabric_wait_attach_evt_shutdown(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
785 {
787 
788  node_sm_trace();
789 
790  switch(evt) {
791  case OCS_EVT_ENTER:
792  ocs_node_hold_frames(node);
793  break;
794 
795  case OCS_EVT_EXIT:
797  break;
798 
799  /* wait for any of these attach events and then shutdown */
801  node->attached = TRUE;
802  node_printf(node, "Attach evt=%s, proceed to shutdown\n", ocs_sm_event_name(evt));
804  break;
805 
807  node->attached = FALSE;
808  node_printf(node, "Attach evt=%s, proceed to shutdown\n", ocs_sm_event_name(evt));
810  break;
811 
812  /* ignore shutdown event as we're already in shutdown path */
813  case OCS_EVT_SHUTDOWN:
814  node_printf(node, "Shutdown event received\n");
815  break;
816 
817  default:
818  __ocs_fabric_common(__func__, ctx, evt, arg);
819  return NULL;
820  }
821 
822  return NULL;
823 }
824 
825 /**
826  * @ingroup ns_sm
827  * @brief Name services node state machine: Wait for an RFTID response event.
828  *
829  * @par Description
830  * Waits for an RFTID response event; if configured for an initiator operation,
831  * a GIDPT name services request is issued.
832  *
833  * @param ctx Remote node state machine context.
834  * @param evt Event to process.
835  * @param arg Per event optional argument.
836  *
837  * @return Returns NULL.
838  */
839 void *
840 __ocs_ns_rftid_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
841 {
843 
844  node_sm_trace();
845 
846  switch(evt) {
848  if (node_check_ct_req(ctx, evt, arg, FC_GS_NAMESERVER_RFT_ID, __ocs_fabric_common, __func__)) {
849  return NULL;
850  }
851  ocs_assert(node->els_req_cnt, NULL);
852  node->els_req_cnt--;
853 
854  //sm: / send RFFID
855  if (ocs->enable_nvme_tgt) {
857  OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL);
859  } else {
861  OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL);
863  }
864  break;
865 
866  /* if receive RSCN just ignore, we haven't sent GID_PT yet (ACC sent by fabctl node) */
867  case OCS_EVT_RSCN_RCVD:
868  break;
869 
870  default:
871  __ocs_fabric_common(__func__, ctx, evt, arg);
872  return NULL;
873  }
874 
875  return NULL;
876 }
877 
878 
879 void *
880 __ocs_ns_nvme_rffid_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
881 {
883 
884  node_sm_trace();
885 
886  switch(evt) {
888  if (node_check_ct_req(ctx, evt, arg, FC_GS_NAMESERVER_RFF_ID, __ocs_fabric_common, __func__)) {
889  return NULL;
890  }
891  ocs_assert(node->els_req_cnt, NULL);
892  node->els_req_cnt--;
893 
894  /* Check if we need to send RFFID for scsi. */
895  if (node->sport->enable_ini || node->sport->enable_tgt) {
897  OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL);
899  } else {
900  if (node->sport->enable_rscn) {
901  //sm: if enable_rscn / send GIDFT
904  } else {
905  /* if 'T' only, we're done, go to idle */
906  ocs_node_transition(node, __ocs_ns_idle, NULL);
907  }
908  }
909 
910  break;
911  }
912 
913  /* if receive RSCN just ignore, we haven't sent GID_FT yet (ACC sent by fabctl node) */
914  case OCS_EVT_RSCN_RCVD:
915  break;
916 
917  default:
918  __ocs_fabric_common(__func__, ctx, evt, arg);
919  return NULL;
920  }
921 
922  return NULL;
923 }
924 
925 /**
926  * @ingroup ns_sm
927  * @brief Fabric node state machine: Wait for RFFID response event.
928  *
929  * @par Description
930  * Waits for an RFFID response event; if configured for an initiator operation,
931  * a GIDPT name services request is issued.
932  *
933  * @param ctx Remote node state machine context.
934  * @param evt Event to process.
935  * @param arg Per event optional argument.
936  *
937  * @return Returns NULL.
938  */
939 void *
940 __ocs_ns_rffid_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
941 {
943 
944  node_sm_trace();
945 
946  switch(evt) {
948  if (node_check_ct_req(ctx, evt, arg, FC_GS_NAMESERVER_RFF_ID, __ocs_fabric_common, __func__)) {
949  return NULL;
950  }
951  ocs_assert(node->els_req_cnt, NULL);
952  node->els_req_cnt--;
953  if (node->sport->enable_rscn) {
954  //sm: if enable_rscn / send GIDPT
956  OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL);
958  } else {
959  /* if 'T' only, we're done, go to idle */
960  ocs_node_transition(node, __ocs_ns_idle, NULL);
961  }
962  break;
963  }
964  /* if receive RSCN just ignore, we haven't sent GID_PT yet (ACC sent by fabctl node) */
965  case OCS_EVT_RSCN_RCVD:
966  break;
967 
968  default:
969  __ocs_fabric_common(__func__, ctx, evt, arg);
970  return NULL;
971  }
972 
973  return NULL;
974 }
975 
976 /**
977  * @ingroup ns_sm
978  * @brief Name services node state machine: Wait for a GIDPT response.
979  *
980  * @par Description
981  * Wait for a GIDPT response from the name server. Process the FC_IDs that are
982  * reported by creating new remote ports, as needed.
983  *
984  * @param ctx Remote node state machine context.
985  * @param evt Event to process.
986  * @param arg Per event optional argument.
987  *
988  * @return Returns NULL.
989  */
990 void *
991 __ocs_ns_gidpt_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
992 {
993  ocs_node_cb_t *cbdata = arg;
995 
996  node_sm_trace();
997 
998  switch(evt) {
1000  if (node_check_ct_req(ctx, evt, arg, FC_GS_NAMESERVER_GID_PT, __ocs_fabric_common, __func__)) {
1001  return NULL;
1002  }
1003  ocs_assert(node->els_req_cnt, NULL);
1004  node->els_req_cnt--;
1005  //sm: / process GIDPT payload
1006  ocs_process_gidpt_payload(node, cbdata->els->els_rsp.virt, cbdata->els->els_rsp.len);
1007 //TODO: should we logout at this point or just go idle
1008  ocs_node_transition(node, __ocs_ns_idle, NULL);
1009  break;
1010  }
1011 
1013  /* not much we can do; will retry with the next RSCN */
1014  node_printf(node, "GID_PT failed to complete\n");
1015  ocs_assert(node->els_req_cnt, NULL);
1016  node->els_req_cnt--;
1017  ocs_node_transition(node, __ocs_ns_idle, NULL);
1018  break;
1019  }
1020 
1021  /* if receive RSCN here, queue up another discovery processing */
1022  case OCS_EVT_RSCN_RCVD: {
1023  node_printf(node, "RSCN received during GID_PT processing\n");
1024  node->rscn_pending = 1;
1025  break;
1026  }
1027 
1028  default:
1029  __ocs_fabric_common(__func__, ctx, evt, arg);
1030  return NULL;
1031  }
1032 
1033  return NULL;
1034 }
1035 
1036 void *
1037 __ocs_ns_ganxt_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1038 {
1040 
1041  node_sm_trace();
1042 
1043  switch(evt) {
1044  case OCS_EVT_SRRS_ELS_REQ_OK: {
1045  if (node_check_ct_req(ctx, evt, arg, FC_GS_NAMESERVER_GA_NXT, __ocs_fabric_common, __func__)) {
1046  return NULL;
1047  }
1048  ocs_assert(node->els_req_cnt, NULL);
1049  node->els_req_cnt--;
1050  ocs_node_transition(node, __ocs_ns_idle, NULL);
1051  break;
1052  }
1053 
1055  ocs_assert(node->els_req_cnt, NULL);
1056  node->els_req_cnt--;
1057  ocs_node_transition(node, __ocs_ns_idle, NULL);
1058  break;
1059  }
1060 
1061  case OCS_EVT_RSCN_RCVD: {
1062  node->rscn_pending = 1;
1063  break;
1064  }
1065 
1066  default:
1067  __ocs_fabric_common(__func__, ctx, evt, arg);
1068  return NULL;
1069  }
1070 
1071  return NULL;
1072 }
1073 
1074 
1075 /**
1076  * @ingroup ns_sm
1077  * @brief Name services node state machine: Idle state.
1078  *
1079  * @par Description
1080  * Idle. Waiting for RSCN received events (posted from the fabric controller), and
1081  * restarts the GIDPT name services query and processing.
1082  *
1083  * @param ctx Remote node state machine context.
1084  * @param evt Event to process.
1085  * @param arg Per event optional argument.
1086  *
1087  * @return Returns NULL.
1088  */
1089 void *
1090 __ocs_ns_idle(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1091 {
1093 
1094  node_sm_trace();
1095 
1096  switch(evt) {
1097  case OCS_EVT_ENTER:
1098  if (!node->rscn_pending) {
1099  break;
1100  }
1101  node_printf(node, "RSCN pending, restart discovery\n");
1102  node->rscn_pending = 0;
1103 
1104  /* fall through */
1105 
1106  case OCS_EVT_RSCN_RCVD: {
1107  //sm: / send GIDPT
1108  /* If target RSCN processing is enabled, and this is target only (not initiator),
1109  * and tgt_rscn_delay is non-zero, then we delay issuing the GID_PT
1110  */
1111  if ((ocs->tgt_rscn_delay_msec != 0) && !node->sport->enable_ini && node->sport->enable_tgt &&
1112  enable_target_rscn(ocs)) {
1114  } else {
1116  OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL);
1118  }
1119  break;
1120  }
1121 
1122  default:
1123  __ocs_fabric_common(__func__, ctx, evt, arg);
1124  break;
1125  }
1126 
1127  return NULL;
1128 }
1129 
1130 /**
1131  * @ingroup fdmi_sm
1132  * @brief FDMI node state machine: FDMI node is idle.
1133  *
1134  * @par Description
1135  * Wait for fdmi node events.
1136  *
1137  * @param ctx Remote node state machine context.
1138  * @param evt Event to process.
1139  * @param arg Per event optional argument.
1140  *
1141  * @return Returns NULL.
1142  */
1143 void *
1144 __ocs_fdmi_idle(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1145 {
1147 
1148  node_sm_trace();
1149 
1150  switch(evt) {
1152  break;
1153  default:
1154  __ocs_fabric_common(__func__, ctx, evt, arg);
1155  return NULL;
1156  }
1157 
1158  return NULL;
1159 }
1160 
1161 /**
1162  * @brief Handle GIDPT delay timer callback
1163  *
1164  * @par Description
1165  * Post an OCS_EVT_GIDPT_DEIALY_EXPIRED event to the passed in node.
1166  *
1167  * @param arg Pointer to node.
1168  *
1169  * @return None.
1170  */
1171 static void
1173 {
1174  ocs_node_t *node = arg;
1175  int32_t rc;
1176 
1177  ocs_del_timer(&node->gidpt_delay_timer);
1178  rc = ocs_xport_control(node->ocs->xport, OCS_XPORT_POST_NODE_EVENT, node, OCS_EVT_GIDPT_DELAY_EXPIRED, NULL);
1179  if (rc) {
1180  ocs_log_err(node->ocs, "ocs_xport_control(OCS_XPORT_POST_NODE_EVENT) failed: %d\n", rc);
1181  }
1182 }
1183 
1184 /**
1185  * @ingroup ns_sm
1186  * @brief Name services node state machine: Delayed GIDPT.
1187  *
1188  * @par Description
1189  * Waiting for GIDPT delay to expire before submitting GIDPT to name server.
1190  *
1191  * @param ctx Remote node state machine context.
1192  * @param evt Event to process.
1193  * @param arg Per event optional argument.
1194  *
1195  * @return Returns NULL.
1196  */
1197 void *
1198 __ocs_ns_gidpt_delay(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1199 {
1201 
1202  node_sm_trace();
1203 
1204  switch(evt) {
1205  case OCS_EVT_ENTER: {
1206  time_t delay_msec;
1207 
1208  ocs_assert(ocs->tgt_rscn_delay_msec != 0, NULL);
1209 
1210  /*
1211  * Compute the delay time. Set to tgt_rscn_delay, if the time since last GIDPT
1212  * is less than tgt_rscn_period, then use tgt_rscn_period.
1213  */
1214  delay_msec = ocs->tgt_rscn_delay_msec;
1215  if ((ocs_msectime() - node->time_last_gidpt_msec) < ocs->tgt_rscn_period_msec) {
1216  delay_msec = ocs->tgt_rscn_period_msec;
1217  }
1218 
1219  ocs_setup_timer(ocs, &node->gidpt_delay_timer, gidpt_delay_timer_cb, node, delay_msec, false);
1220 
1221  break;
1222  }
1223 
1225  node->time_last_gidpt_msec = ocs_msectime();
1227  OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL);
1229  break;
1230 
1231  case OCS_EVT_RSCN_RCVD: {
1232  ocs_log_debug(ocs, "RSCN received while in GIDPT delay - no action\n");
1233  break;
1234  }
1235 
1236  default:
1237  __ocs_fabric_common(__func__, ctx, evt, arg);
1238  break;
1239  }
1240 
1241  return NULL;
1242 }
1243 
1244 /**
1245  * @ingroup fabric_sm
1246  * @brief Fabric controller node state machine: Initial state.
1247  *
1248  * @par Description
1249  * Issue a PLOGI to a well-known fabric controller address.
1250  *
1251  * @param ctx Remote node state machine context.
1252  * @param evt Event to process.
1253  * @param arg Per event optional argument.
1254  *
1255  * @return Returns NULL.
1256  */
1257 void *
1258 __ocs_fabctl_init(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1259 {
1260  ocs_node_t *node = ctx->app;
1261 
1262  node_sm_trace();
1263 
1264  switch(evt) {
1265  case OCS_EVT_ENTER:
1266  /* no need to login to fabric controller, just send SCR */
1269  break;
1270 
1272  node->attached = TRUE;
1273  break;
1274 
1275  default:
1276  __ocs_fabric_common(__func__, ctx, evt, arg);
1277  return NULL;
1278  }
1279 
1280  return NULL;
1281 }
1282 
1283 /**
1284  * @ingroup fabric_sm
1285  * @brief Fabric controller node state machine: Wait for a node attach request
1286  * to complete.
1287  *
1288  * @par Description
1289  * Wait for a node attach to complete. If successful, issue an SCR
1290  * to the fabric controller, subscribing to all RSCN.
1291  *
1292  * @param ctx Remote node state machine context.
1293  * @param evt Event to process.
1294  * @param arg Per event optional argument.
1295  *
1296  * @return Returns NULL.
1297  *
1298  */
1299 void *
1300 __ocs_fabctl_wait_node_attach(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1301 {
1303 
1304  node_sm_trace();
1305 
1306  switch(evt) {
1307  case OCS_EVT_ENTER:
1308  ocs_node_hold_frames(node);
1309  break;
1310 
1311  case OCS_EVT_EXIT:
1312  ocs_node_accept_frames(node);
1313  break;
1314 
1316  node->attached = TRUE;
1317  //sm: / send SCR
1320  break;
1321 
1323  /* node attach failed, shutdown the node */
1324  node->attached = FALSE;
1325  node_printf(node, "Node attach failed\n");
1326  node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
1328  break;
1329 
1330  case OCS_EVT_SHUTDOWN:
1331  node_printf(node, "Shutdown event received\n");
1332  node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
1334  break;
1335 
1336  default:
1337  __ocs_fabric_common(__func__, ctx, evt, arg);
1338  return NULL;
1339  }
1340 
1341  return NULL;
1342 }
1343 
1344 /**
1345  * @ingroup fabric_sm
1346  * @brief Fabric controller node state machine: Wait for an SCR response from the
1347  * fabric controller.
1348  *
1349  * @par Description
1350  * Waits for an SCR response from the fabric controller.
1351  *
1352  * @param ctx Remote node state machine context.
1353  * @param evt Event to process.
1354  * @param arg Per event optional argument.
1355  *
1356  * @return Returns NULL.
1357  */
1358 void *
1359 __ocs_fabctl_wait_scr_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1360 {
1362 
1363  node_sm_trace();
1364 
1365  switch(evt) {
1367  if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_SCR, __ocs_fabric_common, __func__)) {
1368  return NULL;
1369  }
1370  ocs_assert(node->els_req_cnt, NULL);
1371  node->els_req_cnt--;
1373  break;
1374 
1375  default:
1376  __ocs_fabric_common(__func__, ctx, evt, arg);
1377  return NULL;
1378  }
1379 
1380  return NULL;
1381 }
1382 
1383 /**
1384  * @ingroup fabric_sm
1385  * @brief Fabric controller node state machine: Ready.
1386  *
1387  * @par Description
1388  * In this state, the fabric controller sends a RSCN, which is received
1389  * by this node and is forwarded to the name services node object; and
1390  * the RSCN LS_ACC is sent.
1391  *
1392  * @param ctx Remote node state machine context.
1393  * @param evt Event to process.
1394  * @param arg Per event optional argument.
1395  *
1396  * @return Returns NULL.
1397  */
1398 
1399 void *
1400 __ocs_fabctl_ready(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1401 {
1402  ocs_node_cb_t *cbdata = arg;
1404 
1405  node_sm_trace();
1406 
1407  switch(evt) {
1408  case OCS_EVT_RSCN_RCVD: {
1409  fc_header_t *hdr = cbdata->header->dma.virt;
1410 
1411  //sm: / process RSCN (forward to name services node), send LS_ACC
1412  ocs_process_rscn(node, cbdata);
1413  ocs_send_ls_acc(cbdata->io, ocs_be16toh(hdr->ox_id), NULL, NULL);
1415  break;
1416  }
1417 
1418  default:
1419  __ocs_fabric_common(__func__, ctx, evt, arg);
1420  return NULL;
1421  }
1422 
1423  return NULL;
1424 }
1425 
1426 /**
1427  * @ingroup fabric_sm
1428  * @brief Fabric controller node state machine: Wait for LS_ACC.
1429  *
1430  * @par Description
1431  * Waits for the LS_ACC from the fabric controller.
1432  *
1433  * @param ctx Remote node state machine context.
1434  * @param evt Event to process.
1435  * @param arg Per event optional argument.
1436  *
1437  * @return Returns NULL.
1438  */
1439 
1440 void *
1441 __ocs_fabctl_wait_ls_acc_cmpl(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1442 {
1444 
1445  node_sm_trace();
1446 
1447  switch(evt) {
1448  case OCS_EVT_ENTER:
1449  ocs_node_hold_frames(node);
1450  break;
1451 
1452  case OCS_EVT_EXIT:
1453  ocs_node_accept_frames(node);
1454  break;
1455 
1457  ocs_assert(node->els_cmpl_cnt, NULL);
1458  node->els_cmpl_cnt--;
1460  break;
1461 
1462  default:
1463  __ocs_fabric_common(__func__, ctx, evt, arg);
1464  return NULL;
1465  }
1466 
1467  return NULL;
1468 }
1469 
1470 /**
1471  * @ingroup fabric_sm
1472  * @brief Initiate fabric node shutdown.
1473  *
1474  * @param node Node for which shutdown is initiated.
1475  *
1476  * @return Returns None.
1477  */
1478 
1479 static void
1481 {
1483  ocs_t *ocs = node->ocs;
1485 
1486  if (node->attached) {
1487  /* issue hal node free; don't care if succeeds right away
1488  * or sometime later, will check node->attached later in
1489  * shutdown process
1490  */
1491  rc = ocs_hal_node_detach(&ocs->hal, &node->rnode);
1492  if (node->rnode.free_group) {
1493  ocs_remote_node_group_free(node->node_group);
1494  node->node_group = NULL;
1495  node->rnode.free_group = FALSE;
1496  }
1497  if (rc != OCS_HAL_RTN_SUCCESS && rc != OCS_HAL_RTN_SUCCESS_SYNC) {
1498  node_printf(node, "Failed freeing HAL node, rc=%d\n", rc);
1499  }
1500  }
1501  /*
1502  * node has either been detached or is in the process of being detached,
1503  * call common node's initiate cleanup function
1504  */
1506 }
1507 
1508 /**
1509  * @ingroup fabric_sm
1510  * @brief Fabric node state machine: Handle the common fabric node events.
1511  *
1512  * @param funcname Function name text.
1513  * @param ctx Remote node state machine context.
1514  * @param evt Event to process.
1515  * @param arg Per event optional argument.
1516  *
1517  * @return Returns NULL.
1518  */
1519 
1520 static void *
1521 __ocs_fabric_common(const char *funcname, ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1522 {
1523  ocs_node_t *node = NULL;
1524  ocs_assert(ctx, NULL);
1525  ocs_assert(ctx->app, NULL);
1526  node = ctx->app;
1527 
1528  switch(evt) {
1530  break;
1531  case OCS_EVT_SHUTDOWN:
1532  node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
1534  break;
1535 
1536  default:
1537  /* call default event handler common to all nodes */
1538  __ocs_node_common(funcname, ctx, evt, arg);
1539  break;
1540  }
1541  return NULL;
1542 }
1543 
1544 /**
1545  * @brief Return TRUE if the remote node is an NPORT.
1546  *
1547  * @par Description
1548  * Examines the service parameters. Returns TRUE if the node reports itself as
1549  * an NPORT.
1550  *
1551  * @param remote_sparms Remote node service parameters.
1552  *
1553  * @return Returns TRUE if NPORT.
1554  */
1555 
1556 int32_t
1558 {
1559  return (ocs_be32toh(remote_sparms->common_service_parameters[1]) & (1U << 28)) == 0;
1560 }
1561 
1562 /**
1563  * @brief Return the node's WWPN as an uint64_t.
1564  *
1565  * @par Description
1566  * The WWPN is computed from service parameters, and returned as a uint64_t.
1567  *
1568  * @param sp Pointer to service parameters.
1569  *
1570  * @return Returns WWPN.
1571  *
1572  */
1573 
1574 static uint64_t
1576 {
1577  return (((uint64_t)ocs_be32toh(sp->port_name_hi) << 32ll) | (ocs_be32toh(sp->port_name_lo)));
1578 }
1579 
1580 /**
1581  * @brief Return TRUE if the remote node is the point-to-point winner.
1582  *
1583  * @par Description
1584  * Compares WWPNs. Returns TRUE if the remote node's WWPN is numerically
1585  * higher than the local node's WWPN.
1586  *
1587  * @param sport Pointer to the sport object.
1588  *
1589  * @return
1590  * - 0, if the remote node is the loser.
1591  * - 1, if the remote node is the winner.
1592  * - (-1), if remote node is neither the loser nor the winner
1593  * (WWPNs match)
1594  */
1595 
1596 static int32_t
1597 ocs_rnode_is_winner(ocs_sport_t *sport)
1598 {
1599  fc_plogi_payload_t *remote_sparms = (fc_plogi_payload_t*) sport->domain->flogi_service_params;
1600  uint64_t remote_wwpn = ocs_get_wwpn(remote_sparms);
1601  uint64_t local_wwpn = sport->wwpn;
1602  char prop_buf[32];
1603  uint64_t wwn_bump = 0;
1604 
1605  if (ocs_get_property("wwn_bump", prop_buf, sizeof(prop_buf)) == 0) {
1606  wwn_bump = ocs_strtoull(prop_buf, 0, 0);
1607  }
1608  local_wwpn ^= wwn_bump;
1609 
1610  remote_wwpn = ocs_get_wwpn(remote_sparms);
1611 
1612  ocs_log_debug(sport->ocs, "r: %08x %08x\n", ocs_be32toh(remote_sparms->port_name_hi), ocs_be32toh(remote_sparms->port_name_lo));
1613  ocs_log_debug(sport->ocs, "l: %08x %08x\n", (uint32_t) (local_wwpn >> 32ll), (uint32_t) local_wwpn);
1614 
1615  if (remote_wwpn == local_wwpn) {
1616  ocs_log_warn(sport->ocs, "WWPN of remote node [%08x %08x] matches local WWPN\n",
1617  (uint32_t) (local_wwpn >> 32ll), (uint32_t) local_wwpn);
1618  return (-1);
1619  }
1620 
1621  return (remote_wwpn > local_wwpn);
1622 }
1623 
1624 /**
1625  * @ingroup p2p_sm
1626  * @brief Point-to-point state machine: Wait for the domain attach to complete.
1627  *
1628  * @par Description
1629  * Once the domain attach has completed, a PLOGI is sent (if we're the
1630  * winning point-to-point node).
1631  *
1632  * @param ctx Remote node state machine context.
1633  * @param evt Event to process.
1634  * @param arg Per event optional argument.
1635  *
1636  * @return Returns NULL.
1637  */
1638 
1639 void *
1640 __ocs_p2p_wait_domain_attach(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1641 {
1643 
1644  node_sm_trace();
1645 
1646  switch(evt) {
1647  case OCS_EVT_ENTER:
1648  ocs_node_hold_frames(node);
1649  break;
1650 
1651  case OCS_EVT_EXIT:
1652  ocs_node_accept_frames(node);
1653  break;
1654 
1655  case OCS_EVT_DOMAIN_ATTACH_OK: {
1656  ocs_sport_t *sport = node->sport;
1657  ocs_node_t *rnode;
1658 
1659  /* this transient node (SID=0 (recv'd FLOGI) or DID=fabric (sent FLOGI))
1660  * is the p2p winner, will use a separate node to send PLOGI to peer
1661  */
1662  ocs_assert (node->sport->p2p_winner, NULL);
1663 
1664  rnode = ocs_node_find(sport, node->sport->p2p_remote_port_id);
1665  if (rnode != NULL) {
1666  /* the "other" transient p2p node has already kicked off the
1667  * new node from which PLOGI is sent */
1668  node_printf(node, "Node with fc_id x%x already exists\n", rnode->rnode.fc_id);
1669  ocs_assert (rnode != node, NULL);
1670  } else {
1671  /* create new node (SID=1, DID=2) from which to send PLOGI */
1672  rnode = ocs_node_alloc(sport, sport->p2p_remote_port_id, FALSE, FALSE);
1673  if (rnode == NULL) {
1674  ocs_log_err(ocs, "node alloc failed\n");
1675  return NULL;
1676  }
1677 
1679  //sm: / allocate p2p remote node
1681  }
1682 
1683  /* the transient node (SID=0 or DID=fabric) has served its purpose */
1684  if (node->rnode.fc_id == 0) {
1685  /* if this is the SID=0 node, move to the init state in case peer
1686  * has restarted FLOGI discovery and FLOGI is pending
1687  */
1688  /* don't send PLOGI on ocs_d_init entry */
1689  ocs_node_init_device(node, FALSE);
1690  } else {
1691  /* if this is the DID=fabric node (we initiated FLOGI), shut it down */
1692  node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
1694  }
1695  break;
1696  }
1697 
1698  default:
1699  __ocs_fabric_common(__func__, ctx, evt, arg);
1700  return NULL;
1701  }
1702 
1703  return NULL;
1704 }
1705 
1706 /**
1707  * @ingroup p2p_sm
1708  * @brief Point-to-point state machine: Remote node initialization state.
1709  *
1710  * @par Description
1711  * This state is entered after winning point-to-point, and the remote node
1712  * is instantiated.
1713  *
1714  * @param ctx Remote node state machine context.
1715  * @param evt Event to process.
1716  * @param arg Per event optional argument.
1717  *
1718  * @return Returns NULL.
1719  */
1720 
1721 void *
1722 __ocs_p2p_rnode_init(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1723 {
1724  ocs_node_cb_t *cbdata = arg;
1726 
1727  node_sm_trace();
1728 
1729  switch(evt) {
1730  case OCS_EVT_ENTER:
1731  //sm: / send PLOGI
1734  break;
1735 
1736  case OCS_EVT_ABTS_RCVD:
1737  //sm: send BA_ACC
1738  ocs_bls_send_acc_hdr(cbdata->io, cbdata->header->dma.virt);
1739  break;
1740 
1741  default:
1742  __ocs_fabric_common(__func__, ctx, evt, arg);
1743  return NULL;
1744  }
1745 
1746  return NULL;
1747 }
1748 
1749 /**
1750  * @ingroup p2p_sm
1751  * @brief Point-to-point node state machine: Wait for the FLOGI accept completion.
1752  *
1753  * @par Description
1754  * Wait for the FLOGI accept completion.
1755  *
1756  * @param ctx Remote node state machine context.
1757  * @param evt Event to process.
1758  * @param arg Per event optional argument.
1759  *
1760  * @return Returns NULL.
1761  */
1762 
1763 void *
1764 __ocs_p2p_wait_flogi_acc_cmpl(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1765 {
1766  ocs_node_cb_t *cbdata = arg;
1768 
1769  node_sm_trace();
1770 
1771  switch(evt) {
1772  case OCS_EVT_ENTER:
1773  ocs_node_hold_frames(node);
1774  break;
1775 
1776  case OCS_EVT_EXIT:
1777  ocs_node_accept_frames(node);
1778  break;
1779 
1781  ocs_assert(node->els_cmpl_cnt, NULL);
1782  node->els_cmpl_cnt--;
1783 
1784  //sm: if p2p_winner / domain_attach
1785  if (node->sport->p2p_winner) {
1787  if (node->sport->domain->attached &&
1788  !(node->sport->domain->domain_notify_pend)) {
1789  node_printf(node, "Domain already attached\n");
1791  }
1792  } else {
1793  /* this node has served its purpose; we'll expect a PLOGI on a separate
1794  * node (remote SID=0x1); return this node to init state in case peer
1795  * restarts discovery -- it may already have (pending frames may exist).
1796  */
1797  /* don't send PLOGI on ocs_d_init entry */
1798  ocs_node_init_device(node, FALSE);
1799  }
1800  break;
1801 
1803  /* LS_ACC failed, possibly due to link down; shutdown node and wait
1804  * for FLOGI discovery to restart */
1805  node_printf(node, "FLOGI LS_ACC failed, shutting down\n");
1806  ocs_assert(node->els_cmpl_cnt, NULL);
1807  node->els_cmpl_cnt--;
1808  node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
1810  break;
1811 
1812  case OCS_EVT_ABTS_RCVD: {
1813  //sm: / send BA_ACC
1814  ocs_bls_send_acc_hdr(cbdata->io, cbdata->header->dma.virt);
1815  break;
1816  }
1817 
1818  default:
1819  __ocs_fabric_common(__func__, ctx, evt, arg);
1820  return NULL;
1821  }
1822 
1823  return NULL;
1824 }
1825 
1826 
1827 /**
1828  * @ingroup p2p_sm
1829  * @brief Point-to-point node state machine: Wait for a PLOGI response
1830  * as a point-to-point winner.
1831  *
1832  * @par Description
1833  * Wait for a PLOGI response from the remote node as a point-to-point winner.
1834  * Submit node attach request to the HAL.
1835  *
1836  * @param ctx Remote node state machine context.
1837  * @param evt Event to process.
1838  * @param arg Per event optional argument.
1839  *
1840  * @return Returns NULL.
1841  */
1842 
1843 void *
1844 __ocs_p2p_wait_plogi_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1845 {
1846  int32_t rc;
1847  ocs_node_cb_t *cbdata = arg;
1849 
1850  node_sm_trace();
1851 
1852  switch(evt) {
1853  case OCS_EVT_SRRS_ELS_REQ_OK: {
1854  if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PLOGI, __ocs_fabric_common, __func__)) {
1855  return NULL;
1856  }
1857  ocs_assert(node->els_req_cnt, NULL);
1858  node->els_req_cnt--;
1859  //sm: / save sparams, ocs_node_attach
1860  ocs_node_save_sparms(node, cbdata->els->els_rsp.virt);
1861  rc = ocs_node_attach(node);
1863  if (rc == OCS_HAL_RTN_SUCCESS_SYNC) {
1865  }
1866  break;
1867  }
1869  if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PLOGI, __ocs_fabric_common, __func__)) {
1870  return NULL;
1871  }
1872  node_printf(node, "PLOGI failed, shutting down\n");
1873  ocs_assert(node->els_req_cnt, NULL);
1874  node->els_req_cnt--;
1875  node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
1877  break;
1878  }
1879 
1880  case OCS_EVT_PLOGI_RCVD: {
1881  fc_header_t *hdr = cbdata->header->dma.virt;
1882  /* if we're in external loopback mode, just send LS_ACC */
1883  if (node->ocs->external_loopback) {
1884  ocs_send_plogi_acc(cbdata->io, ocs_be16toh(hdr->ox_id), NULL, NULL);
1885  break;
1886  } else{
1887  /* if this isn't external loopback, pass to default handler */
1888  __ocs_fabric_common(__func__, ctx, evt, arg);
1889  }
1890  break;
1891  }
1892  case OCS_EVT_PRLI_RCVD:
1893  /* I, or I+T */
1894  /* sent PLOGI and before completion was seen, received the
1895  * PRLI from the remote node (WCQEs and RCQEs come in on
1896  * different queues and order of processing cannot be assumed)
1897  * Save OXID so PRLI can be sent after the attach and continue
1898  * to wait for PLOGI response
1899  */
1900  ocs_process_prli_payload(node, cbdata->payload->dma.virt);
1901  ocs_send_ls_acc_after_attach(cbdata->io, cbdata->header->dma.virt, OCS_NODE_SEND_LS_ACC_PRLI);
1903  break;
1904  default:
1905  __ocs_fabric_common(__func__, ctx, evt, arg);
1906  return NULL;
1907  }
1908 
1909  return NULL;
1910 }
1911 
1912 /**
1913  * @ingroup p2p_sm
1914  * @brief Point-to-point node state machine: Waiting on a response for a
1915  * sent PLOGI.
1916  *
1917  * @par Description
1918  * State is entered when the point-to-point winner has sent
1919  * a PLOGI and is waiting for a response. Before receiving the
1920  * response, a PRLI was received, implying that the PLOGI was
1921  * successful.
1922  *
1923  * @param ctx Remote node state machine context.
1924  * @param evt Event to process.
1925  * @param arg Per event optional argument.
1926  *
1927  * @return Returns NULL.
1928  */
1929 
1930 void *
1931 __ocs_p2p_wait_plogi_rsp_recvd_prli(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1932 {
1933  int32_t rc;
1934  ocs_node_cb_t *cbdata = arg;
1936 
1937  node_sm_trace();
1938 
1939  switch(evt) {
1940  case OCS_EVT_ENTER:
1941  /*
1942  * Since we've received a PRLI, we have a port login and will
1943  * just need to wait for the PLOGI response to do the node
1944  * attach and then we can send the LS_ACC for the PRLI. If,
1945  * during this time, we receive FCP_CMNDs (which is possible
1946  * since we've already sent a PRLI and our peer may have accepted).
1947  * At this time, we are not waiting on any other unsolicited
1948  * frames to continue with the login process. Thus, it will not
1949  * hurt to hold frames here.
1950  */
1951  ocs_node_hold_frames(node);
1952  break;
1953 
1954  case OCS_EVT_EXIT:
1955  ocs_node_accept_frames(node);
1956  break;
1957 
1958  case OCS_EVT_SRRS_ELS_REQ_OK: /* PLOGI response received */
1959  /* Completion from PLOGI sent */
1960  if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PLOGI, __ocs_fabric_common, __func__)) {
1961  return NULL;
1962  }
1963  ocs_assert(node->els_req_cnt, NULL);
1964  node->els_req_cnt--;
1965  //sm: / save sparams, ocs_node_attach
1966  ocs_node_save_sparms(node, cbdata->els->els_rsp.virt);
1967  ocs_display_sparams(node->display_name, "plogi rcvd resp", 0, NULL,
1968  ((uint8_t*)cbdata->els->els_rsp.virt) + 4);
1969  rc = ocs_node_attach(node);
1971  if (rc == OCS_HAL_RTN_SUCCESS_SYNC) {
1973  }
1974  break;
1975 
1976  case OCS_EVT_SRRS_ELS_REQ_FAIL: /* PLOGI response received */
1978  /* PLOGI failed, shutdown the node */
1979  if (node_check_els_req(ctx, evt, arg, FC_ELS_CMD_PLOGI, __ocs_fabric_common, __func__)) {
1980  return NULL;
1981  }
1982  ocs_assert(node->els_req_cnt, NULL);
1983  node->els_req_cnt--;
1984  node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
1986  break;
1987 
1988  default:
1989  __ocs_fabric_common(__func__, ctx, evt, arg);
1990  return NULL;
1991  }
1992 
1993  return NULL;
1994 }
1995 
1996 /**
1997  * @ingroup p2p_sm
1998  * @brief Point-to-point node state machine: Wait for a point-to-point node attach
1999  * to complete.
2000  *
2001  * @par Description
2002  * Waits for the point-to-point node attach to complete.
2003  *
2004  * @param ctx Remote node state machine context.
2005  * @param evt Event to process.
2006  * @param arg Per event optional argument.
2007  *
2008  * @return Returns NULL.
2009  */
2010 
2011 void *
2012 __ocs_p2p_wait_node_attach(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
2013 {
2014  ocs_node_cb_t *cbdata = arg;
2016 
2017  node_sm_trace();
2018 
2019  switch(evt) {
2020  case OCS_EVT_ENTER:
2021  ocs_node_hold_frames(node);
2022  break;
2023 
2024  case OCS_EVT_EXIT:
2025  ocs_node_accept_frames(node);
2026  break;
2027 
2029  node->attached = TRUE;
2030  switch (node->send_ls_acc) {
2032  ocs_d_send_prli_rsp(node->ls_acc_io, node->ls_acc_oxid, FC_TYPE_FCP);
2033  node->send_ls_acc = OCS_NODE_SEND_LS_ACC_NONE;
2034  node->ls_acc_io = NULL;
2035  break;
2036  }
2037  case OCS_NODE_SEND_LS_ACC_PLOGI: /* Can't happen in P2P */
2039  default:
2040  /* Normal case for I */
2041  //sm: send_plogi_acc is not set / send PLOGI acc
2043  break;
2044  }
2045  break;
2046 
2048  /* node attach failed, shutdown the node */
2049  node->attached = FALSE;
2050  node_printf(node, "Node attach failed\n");
2051  node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
2053  break;
2054 
2055  case OCS_EVT_SHUTDOWN:
2056  node_printf(node, "%s received\n", ocs_sm_event_name(evt));
2057  node->shutdown_reason = OCS_NODE_SHUTDOWN_DEFAULT;
2059  break;
2060  case OCS_EVT_PRLI_RCVD:
2061  node_printf(node, "%s: PRLI received before node is attached\n", ocs_sm_event_name(evt));
2062  ocs_process_prli_payload(node, cbdata->payload->dma.virt);
2063  ocs_send_ls_acc_after_attach(cbdata->io, cbdata->header->dma.virt, OCS_NODE_SEND_LS_ACC_PRLI);
2064  break;
2065  default:
2066  __ocs_fabric_common(__func__, ctx, evt, arg);
2067  return NULL;
2068  }
2069 
2070  return NULL;
2071 }
2072 
2073 /**
2074  * @brief Start up the name services node.
2075  *
2076  * @par Description
2077  * Allocates and starts up the name services node.
2078  *
2079  * @param sport Pointer to the sport structure.
2080  *
2081  * @return Returns 0 on success, or a negative error value on failure.
2082  */
2083 
2084 static int32_t
2085 ocs_start_ns_node(ocs_sport_t *sport)
2086 {
2087  ocs_node_t *ns;
2088 
2089  /* Instantiate a name services node */
2090  ns = ocs_node_find(sport, FC_ADDR_NAMESERVER);
2091  if (ns == NULL) {
2092  ns = ocs_node_alloc(sport, FC_ADDR_NAMESERVER, FALSE, FALSE);
2093  if (ns == NULL) {
2094  return -1;
2095  }
2096  }
2097  // TODO: for found ns, should we be transitioning from here?
2098  // breaks transition only 1. from within state machine or
2099  // 2. if after alloc
2100  if (ns->ocs->nodedb_mask & OCS_NODEDB_PAUSE_NAMESERVER) {
2102  } else {
2104  }
2105  return 0;
2106 }
2107 
2108 /**
2109  * @brief Start up the FDMI node.
2110  *
2111  * @par Description
2112  * Allocates and starts up the FDMI node.
2113  *
2114  * @param sport Pointer to the sport structure.
2115  *
2116  * @return Returns 0 on success, or a negative error value on failure.
2117  */
2118 
2119 static int32_t
2120 ocs_start_fdmi_node(ocs_sport_t *sport)
2121 {
2122  ocs_node_t *fdmi;
2123 
2124  /* Instantiate a fdmi node */
2125  fdmi = ocs_node_find(sport, FC_ADDR_FDMI);
2126  if (fdmi == NULL) {
2127  fdmi = ocs_node_alloc(sport, FC_ADDR_FDMI, FALSE, FALSE);
2128  if (fdmi == NULL) {
2129  return -1;
2130  }
2131  }
2132  ocs_node_transition(fdmi, __ocs_fdmi_init, NULL);
2133  return 0;
2134 }
2135 
2136 /**
2137  * @brief Start up the fabric controller node.
2138  *
2139  * @par Description
2140  * Allocates and starts up the fabric controller node.
2141  *
2142  * @param sport Pointer to the sport structure.
2143  *
2144  * @return Returns 0 on success, or a negative error value on failure.
2145  */
2146 
2147 static int32_t
2148 ocs_start_fabctl_node(ocs_sport_t *sport)
2149 {
2150  ocs_node_t *fabctl;
2151 
2152  fabctl = ocs_node_find(sport, FC_ADDR_CONTROLLER);
2153  if (fabctl == NULL) {
2154  fabctl = ocs_node_alloc(sport, FC_ADDR_CONTROLLER, FALSE, FALSE);
2155  if (fabctl == NULL) {
2156  return -1;
2157  }
2158  }
2159  // TODO: for found ns, should we be transitioning from here?
2160  // breaks transition only 1. from within state machine or
2161  // 2. if after alloc
2162  ocs_node_transition(fabctl, __ocs_fabctl_init, NULL);
2163  return 0;
2164 }
2165 
2166 /**
2167  * @brief Process the GIDPT payload.
2168  *
2169  * @par Description
2170  * The GIDPT payload is parsed, and new nodes are created, as needed.
2171  *
2172  * @param node Pointer to the node structure.
2173  * @param gidpt Pointer to the GIDPT payload.
2174  * @param gidpt_len Payload length
2175  *
2176  * @return Returns 0 on success, or a negative error value on failure.
2177  */
2178 
2179 static int32_t
2180 ocs_process_gidpt_payload(ocs_node_t *node, fcct_gidpt_acc_t *gidpt, uint32_t gidpt_len)
2181 {
2182  uint32_t i;
2183  uint32_t j;
2184  ocs_node_t *newnode;
2185  ocs_sport_t *sport = node->sport;
2186  ocs_t *ocs = node->ocs;
2187  uint32_t port_id;
2188  uint32_t port_count;
2189  ocs_node_t *n;
2190  ocs_node_t **active_nodes;
2191  uint32_t portlist_count;
2192  uint16_t residual;
2193 
2194  residual = ocs_be16toh(gidpt->hdr.max_residual_size);
2195 
2196  if (residual != 0) {
2197  ocs_log_debug(node->ocs, "residual is %u words\n", residual);
2198  }
2199 
2200  if (ocs_be16toh(gidpt->hdr.cmd_rsp_code) == FCCT_HDR_CMDRSP_REJECT) {
2201  node_printf(node, "GIDPT request failed: rsn %#x rsn_expl %#x\n",
2202  gidpt->hdr.reason_code, gidpt->hdr.reason_code_explanation);
2203  return -1;
2204  }
2205 
2206  portlist_count = (gidpt_len - sizeof(fcct_iu_header_t)) / sizeof(gidpt->port_list);
2207 
2208  /* Count the number of nodes */
2209  port_count = 0;
2210  ocs_sport_lock(sport);
2211  ocs_list_foreach(&sport->node_list, n) {
2212  port_count ++;
2213  }
2214 
2215  /* Allocate a buffer for all nodes */
2216  active_nodes = ocs_malloc(node->ocs, port_count * sizeof(*active_nodes), OCS_M_NOWAIT | OCS_M_ZERO);
2217  if (active_nodes == NULL) {
2218  node_printf(node, "ocs_malloc failed\n");
2219  ocs_sport_unlock(sport);
2220  return -1;
2221  }
2222 
2223  /* Fill buffer with fc_id of active nodes */
2224  i = 0;
2225  ocs_list_foreach(&sport->node_list, n) {
2226  port_id = n->rnode.fc_id;
2227  switch (port_id) {
2228  case FC_ADDR_FABRIC:
2229  case FC_ADDR_CONTROLLER:
2230  case FC_ADDR_NAMESERVER:
2231  break;
2232  default:
2233  if (!FC_ADDR_IS_DOMAIN_CTRL(port_id)) {
2234  active_nodes[i++] = n;
2235  }
2236  break;
2237  }
2238  }
2239 
2240  /* update the active nodes buffer */
2241  for (i = 0; i < portlist_count; i ++) {
2242  port_id = fc_be24toh(gidpt->port_list[i].port_id);
2243 
2244  for (j = 0; j < port_count; j ++) {
2245  if ((active_nodes[j] != NULL) && (port_id == active_nodes[j]->rnode.fc_id)) {
2246  active_nodes[j] = NULL;
2247  }
2248  }
2249 
2250  if (gidpt->port_list[i].ctl & FCCT_GID_PT_LAST_ID)
2251  break;
2252  }
2253 
2254  /* Those remaining in the active_nodes[] are now gone ! */
2255  for (i = 0; i < port_count; i ++) {
2256  /* if we're an initiator and the remote node is a target, then
2257  * post the node missing event. if we're target and we have enabled
2258  * target RSCN, then post the node missing event.
2259  */
2260  if (active_nodes[i] != NULL) {
2261  if ((node->sport->enable_ini && active_nodes[i]->targ) ||
2262  (node->sport->enable_tgt && enable_target_rscn(ocs))) {
2263  ocs_node_post_event(active_nodes[i], OCS_EVT_NODE_MISSING, NULL);
2264  } else {
2265  node_printf(node, "GID_PT: skipping non-tgt port_id x%06x\n",
2266  active_nodes[i]->rnode.fc_id);
2267  }
2268  }
2269  }
2270  ocs_free(ocs, active_nodes, port_count * sizeof(*active_nodes));
2271 
2272  for(i = 0; i < portlist_count; i ++) {
2273  uint32_t port_id = fc_be24toh(gidpt->port_list[i].port_id);
2274 
2275  /* node_printf(node, "GID_PT: port_id x%06x\n", port_id); */
2276 
2277  /* Don't create node for ourselves or the associated NPIV ports */
2278  if (port_id != node->rnode.sport->fc_id && !ocs_sport_find(sport->domain, port_id)) {
2279  newnode = ocs_node_find(sport, port_id);
2280  if (newnode) {
2281  // TODO: what if node deleted here??
2282  if (node->sport->enable_ini && newnode->targ) {
2283  ocs_node_post_event(newnode, OCS_EVT_NODE_REFOUND, NULL);
2284  }
2285  // original code sends ADISC, has notion of "refound"
2286  } else {
2287  if (node->sport->enable_ini) {
2288  newnode = ocs_node_alloc(sport, port_id, 0, 0);
2289  if (newnode == NULL) {
2290  ocs_log_err(ocs, "ocs_node_alloc() failed\n");
2291  ocs_sport_unlock(sport);
2292  return -1;
2293  }
2294  /* send PLOGI automatically if initiator */
2295  ocs_node_init_device(newnode, TRUE);
2296  }
2297  }
2298  }
2299 
2300  if (gidpt->port_list[i].ctl & FCCT_GID_PT_LAST_ID) {
2301  break;
2302  }
2303  }
2304  ocs_sport_unlock(sport);
2305  return 0;
2306 }
2307 
2308 /**
2309  * @brief Process the GRHL acc payload.
2310  *
2311  * @par Description
2312  * The GRHL payload is parsed, and new nodes are created, as needed.
2313  *
2314  * @param node Pointer to the node structure.
2315  * @param grhl Pointer to the GRHL payload.
2316  * @param grhl_len Payload length
2317  * @param buf destination buffer to copy the HBA list info
2318  *
2319  * @return Returns 0 on success, or a negative error value on failure.
2320  */
2321 int32_t
2323  uint32_t grhl_len, void *buf)
2324 {
2325  uint32_t hostlist_count;
2326  uint16_t residual;
2327  ocs_fdmi_hba_list_info_t *hba_list_buf = buf;
2328  uint32_t offset;
2329  int i = 0;
2330 
2331  residual = ocs_be16toh(grhl->hdr.max_residual_size);
2332 
2333  if (residual != 0) {
2334  ocs_log_debug(node->ocs, "residual is %u words\n", residual);
2335  }
2336 
2337  if (ocs_be16toh(grhl->hdr.cmd_rsp_code) == FCCT_HDR_CMDRSP_REJECT) {
2338  node_printf(node, "GRHL request failed: rsn x%x rsn_expl x%x\n",
2340  return -1;
2341  }
2342 
2343  hba_list_buf->entry_count = ocs_be32toh(grhl->hba_list.entry_count);
2344  hostlist_count = MIN(hba_list_buf->entry_count, MAX_FDMI_HBA_COUNT);
2345 
2346  offset = 0;
2347  while (hostlist_count) {
2348  ocs_memcpy(&hba_list_buf->hba_identifier[i], (uint8_t *)&grhl->hba_list.port_entry[0] + offset,
2349  sizeof(uint64_t));
2350  hba_list_buf->hba_identifier[i] = ocs_be64toh(hba_list_buf->hba_identifier[i]);
2351  i++;
2352  offset += sizeof(uint64_t);
2353  hostlist_count--;
2354  }
2355 
2356  return 0;
2357 }
2358 /**
2359  * @brief Process the GRPL acc payload.
2360  *
2361  * @par Description
2362  * The GRPL payload is parsed, and new nodes are created, as needed.
2363  *
2364  * @param node Pointer to the node structure.
2365  * @param grpl Pointer to the GRPL payload.
2366  * @param grpl_len Payload length
2367  * @param buf destination buffer to copy the Port list info
2368  *
2369  * @return Returns 0 on success, or a negative error value on failure.
2370  */
2371 int32_t
2373  uint32_t grpl_len, void *buf)
2374 {
2375  uint32_t portlist_count;
2376  uint16_t residual;
2377  ocs_fdmi_port_list_info_t *port_list_buf = buf;
2378  uint32_t offset;
2379  int i = 0;
2380 
2381  residual = ocs_be16toh(grpl->hdr.max_residual_size);
2382 
2383  if (residual != 0) {
2384  ocs_log_debug(node->ocs, "residual is %u words\n", residual);
2385  }
2386 
2387  if (ocs_be16toh(grpl->hdr.cmd_rsp_code) == FCCT_HDR_CMDRSP_REJECT) {
2388  node_printf(node, "GRPL request failed: rsn x%x rsn_expl x%x\n",
2390  return -1;
2391  }
2392 
2393  port_list_buf->entry_count = ocs_be32toh(grpl->port_list.entry_count);
2394  portlist_count = MIN(port_list_buf->entry_count, MAX_FDMI_HBA_COUNT);
2395 
2396  offset = 0;
2397  while (portlist_count) {
2398  ocs_memcpy(&port_list_buf->port_identifier[i],
2399  (uint8_t *)&grpl->port_list.port_entry[0] + offset, sizeof(uint64_t));
2400  port_list_buf->port_identifier[i] = ocs_be64toh(port_list_buf->port_identifier[i]);
2401  i++;
2402  offset += sizeof(uint64_t);
2403  portlist_count--;
2404  }
2405 
2406  return 0;
2407 }
2408 
2409 /**
2410  * @brief Process the GHAT acc payload.
2411  *
2412  * @par Description
2413  * The GHAT payload is parsed, and new nodes are created, as needed.
2414  *
2415  * @param node Pointer to the node structure.
2416  * @param ghat Pointer to the GHAT payload.
2417  * @param ghat_len Payload length
2418  * @param buf destination buffer to copy the HBA attributes info
2419  *
2420  * @return Returns 0 on success, or a negative error value on failure.
2421  */
2422 int32_t
2424  uint32_t ghat_len, void *buf)
2425 {
2426  uint32_t portlist_count;
2427  uint16_t residual;
2428  ocs_fdmi_hba_attr_info_t *hba_attr_info = buf;
2429  ocs_fdmi_attr_block_t *hba_attr_block = NULL;
2430  ocs_fdmi_attr_def_t *attr_def;
2432  uint16_t attr_type, attr_len;
2433  uint32_t offset, num_attr_entries;
2434  int i = 0;
2435 
2436  residual = ocs_be16toh(ghat->hdr.max_residual_size);
2437  if (residual != 0) {
2438  ocs_log_debug(node->ocs, "residual is %u words\n", residual);
2439  }
2440 
2441  if (ocs_be16toh(ghat->hdr.cmd_rsp_code) == FCCT_HDR_CMDRSP_REJECT) {
2442  node_printf(node, "GHAT request failed: rsn x%x rsn_expl x%x\n",
2444  return -1;
2445  }
2446 
2447  hba_attr_info->num_port_entries = MIN(ocs_be32toh(ghat->port_list.entry_count),
2449 
2450  portlist_count = hba_attr_info->num_port_entries;
2451  offset = 0;
2452  while (portlist_count) {
2453  ocs_memcpy(&hba_attr_info->port_identifier[i],
2454  (uint8_t *)&ghat->port_list.port_entry[0] + offset, sizeof(uint64_t));
2455  hba_attr_info->port_identifier[i] = ocs_be64toh(hba_attr_info->port_identifier[i]);
2456  i++;
2457  offset += sizeof(uint64_t);
2458  portlist_count--;
2459  }
2460 
2461  offset = sizeof(ghat->hdr) + sizeof(hba_attr_info->num_port_entries);
2462  offset += hba_attr_info->num_port_entries * sizeof(uint64_t);
2463  /* Point to HBA attribute block */
2464  hba_attr_block = (ocs_fdmi_attr_block_t *)(((uint8_t *)ghat + offset));
2465  num_attr_entries = ocs_be32toh(hba_attr_block->num_entries);
2466 
2467  offset += sizeof(hba_attr_block->num_entries);
2468  /* Walk through all attribute entries and copy the same to user buf */
2469  while (num_attr_entries) {
2470  /* Point to HBA attribute entry */
2471  attr_def = (ocs_fdmi_attr_def_t *)(((uint8_t *)ghat + offset));
2472  attr_type = ocs_be16toh(attr_def->attr_type);
2473  attr_len = ocs_be16toh(attr_def->attr_len);
2474  ae = (ocs_fdmi_attr_entry_t *)&attr_def->attr_value;
2475  switch (attr_type) {
2476  case RHBA_NODENAME:
2477  hba_attr_info->node_name_valid = true;
2478  hba_attr_info->node_name = ocs_be64toh(ae->attr_wwn);
2479  break;
2480  case RHBA_MANUFACTURER:
2481  hba_attr_info->manufacturer_valid = true;
2482  ocs_strncpy(hba_attr_info->manufacturer, (char *)ae->attr_string,
2483  MIN(sizeof(ae->attr_string),
2484  sizeof(hba_attr_info->manufacturer)));
2485  break;
2486  case RHBA_SERIAL_NUMBER:
2487  hba_attr_info->serial_num_valid = true;
2488  ocs_strncpy(hba_attr_info->serial_num, (char *)ae->attr_string,
2489  MIN(sizeof(ae->attr_string),
2490  sizeof(hba_attr_info->serial_num)));
2491  break;
2492  case RHBA_MODEL:
2493  hba_attr_info->model_name_valid = true;
2494  ocs_strncpy(hba_attr_info->model_name, (char *)ae->attr_string,
2495  MIN(sizeof(ae->attr_string),
2496  sizeof(hba_attr_info->model_name)));
2497  break;
2499  hba_attr_info->model_desc_valid = true;
2500  ocs_strncpy(hba_attr_info->model_desc, (char *)ae->attr_string,
2501  MIN(sizeof(ae->attr_string),
2502  sizeof(hba_attr_info->model_desc)));
2503  break;
2504  case RHBA_HARDWARE_VERSION:
2505  hba_attr_info->hw_ver_valid = true;
2506  ocs_strncpy(hba_attr_info->hw_ver, (char *)ae->attr_string,
2507  MIN(sizeof(ae->attr_string),
2508  sizeof(hba_attr_info->hw_ver)));
2509  break;
2510  case RHBA_DRIVER_VERSION:
2511  hba_attr_info->driver_ver_valid = true;
2512  ocs_strncpy(hba_attr_info->driver_ver, (char *)ae->attr_string,
2513  MIN(sizeof(ae->attr_string),
2514  sizeof(hba_attr_info->driver_ver)));
2515  break;
2517  hba_attr_info->opt_rom_ver_valid = true;
2518  ocs_strncpy(hba_attr_info->opt_rom_ver, (char *)ae->attr_string,
2519  MIN(sizeof(ae->attr_string),
2520  sizeof(hba_attr_info->opt_rom_ver)));
2521  break;
2522  case RHBA_FIRMWARE_VERSION:
2523  hba_attr_info->fw_ver_valid = true;
2524  ocs_strncpy(hba_attr_info->fw_ver, (char *)ae->attr_string,
2525  MIN(sizeof(ae->attr_string),
2526  sizeof(hba_attr_info->fw_ver)));
2527  break;
2528  case RHBA_OS_NAME_VERSION:
2529  hba_attr_info->os_name_ver_valid = true;
2530  ocs_strncpy(hba_attr_info->os_name_ver, (char *)ae->attr_string,
2531  MIN(sizeof(ae->attr_string),
2532  sizeof(hba_attr_info->os_name_ver)));
2533  break;
2535  hba_attr_info->max_ct_payload_valid = true;
2536  hba_attr_info->max_ct_payload_len = ocs_be32toh(ae->attr_int);
2537  break;
2538  case RHBA_SYM_NODENAME:
2539  hba_attr_info->node_symb_name_valid = true;
2540  ocs_strncpy(hba_attr_info->node_symb_name, (char *)ae->attr_string,
2541  MIN(sizeof(ae->attr_string),
2542  sizeof(hba_attr_info->node_symb_name)));
2543  break;
2544  case RHBA_VENDOR_INFO:
2545  hba_attr_info->vendor_info_valid = true;
2546  hba_attr_info->vendor_info = ocs_be32toh(ae->attr_int);
2547  break;
2548  case RHBA_NUM_PORTS:
2549  hba_attr_info->num_ports_valid = true;
2550  hba_attr_info->num_ports = ocs_be32toh(ae->attr_int);
2551  break;
2552  case RHBA_FABRIC_WWNN:
2553  hba_attr_info->fabric_name_valid = true;
2554  hba_attr_info->fabric_name = ocs_be64toh(ae->attr_wwn);
2555  break;
2556  case RHBA_BIOS_VERSION:
2557  hba_attr_info->bios_ver_valid = true;
2558  ocs_strncpy(hba_attr_info->bios_ver, (char *)ae->attr_string,
2559  MIN(sizeof(ae->attr_string),
2560  sizeof(hba_attr_info->bios_ver)));
2561  break;
2562  case RHBA_BIOS_STATE:
2563  hba_attr_info->boot_state_valid = true;
2564  hba_attr_info->boot_state = ocs_be32toh(ae->attr_int);
2565  break;
2566  case RHBA_VENDOR_ID:
2567  hba_attr_info->vendor_id_valid = true;
2568  ocs_strncpy(hba_attr_info->vendor_id, (char *)ae->attr_string,
2569  MIN(sizeof(ae->attr_string),
2570  sizeof(hba_attr_info->vendor_id)));
2571  break;
2572  default:
2573  ocs_log_warn(node->ocs, "Unrecognized HBA attribute(type: 0x%x)\n",
2574  attr_type);
2575  }
2576 
2577  /* Now point to next attribute */
2578  offset += attr_len;
2579  num_attr_entries--;
2580  }
2581 
2582  return 0;
2583 }
2584 
2585 /**
2586  * @brief Process the GPAT acc payload.
2587  *
2588  * @par Description
2589  * The GPAT payload is parsed, and new nodes are created, as needed.
2590  *
2591  * @param node Pointer to the node structure.
2592  * @param gpat Pointer to the GPAT payload.
2593  * @param gpat_len Payload length
2594  * @param buf destination buffer to copy the Port attributes info
2595  *
2596  * @return Returns 0 on success, or a negative error value on failure.
2597  */
2598 int32_t
2600  uint32_t gpat_len, void *buf)
2601 {
2602  uint16_t residual;
2603  ocs_fdmi_port_attr_info_t *port_attr_info = buf;
2604  ocs_fdmi_attr_block_t *port_attr_block;
2605  ocs_fdmi_attr_def_t *attr_def;
2607  uint16_t attr_type, attr_len;
2608  uint32_t offset, num_attr_entries;
2609 
2610  residual = ocs_be16toh(gpat->hdr.max_residual_size);
2611  if (residual != 0) {
2612  ocs_log_debug(node->ocs, "residual is %u words\n", residual);
2613  }
2614 
2615  if (ocs_be16toh(gpat->hdr.cmd_rsp_code) == FCCT_HDR_CMDRSP_REJECT) {
2616  node_printf(node, "GPAT request failed: rsn x%x rsn_expl x%x\n",
2618  return -1;
2619  }
2620 
2621  offset = sizeof(gpat->hdr);
2622  port_attr_block = (ocs_fdmi_attr_block_t *)((uint8_t *)gpat + offset);
2623  port_attr_info->num_port_attr_entries = ocs_be32toh(port_attr_block->num_entries);
2624 
2625  num_attr_entries = port_attr_info->num_port_attr_entries;
2626  offset += sizeof(port_attr_block->num_entries);
2627 
2628  /* Walk through all attribute entries and copy the same to user buf */
2629  while (num_attr_entries) {
2630  /* Point to Port attribute entry */
2631  attr_def = (ocs_fdmi_attr_def_t *)(((uint8_t *)gpat + offset));
2632  attr_type = ocs_be16toh(attr_def->attr_type);
2633  attr_len = ocs_be16toh(attr_def->attr_len);
2634  ae = (ocs_fdmi_attr_entry_t *)&attr_def->attr_value;
2635  switch (attr_type) {
2637  port_attr_info->supported_fc_types_valid= true;
2638  ocs_memcpy(port_attr_info->supported_fc4_types, ae->attr_types,
2639  sizeof(port_attr_info->supported_fc4_types));
2640  break;
2641  case RPRT_SUPPORTED_SPEED:
2642  port_attr_info->supported_speed_valid = true;
2643  port_attr_info->supported_speed = ocs_be32toh(ae->attr_int);
2644  break;
2645  case RPRT_PORT_SPEED:
2646  port_attr_info->current_speed_valid = true;
2647  port_attr_info->current_port_speed = ocs_be32toh(ae->attr_int);
2648  break;
2649  case RPRT_MAX_FRAME_SIZE:
2650  port_attr_info->max_frame_size_valid = true;
2651  port_attr_info->max_frame_size = ocs_be32toh(ae->attr_int);
2652  break;
2653  case RPRT_OS_DEVICE_NAME:
2654  port_attr_info->os_dev_name_valid = true;
2655  ocs_strncpy(port_attr_info->os_dev_name, (char *)ae->attr_string,
2656  MIN(sizeof(ae->attr_string),
2657  sizeof(port_attr_info->os_dev_name)));
2658  break;
2659  case RPRT_HOST_NAME:
2660  port_attr_info->host_name_valid = true;
2661  ocs_strncpy(port_attr_info->host_name, (char *)ae->attr_string,
2662  MIN(sizeof(ae->attr_string),
2663  sizeof(port_attr_info->host_name)));
2664  break;
2665  case RPRT_NODENAME:
2666  port_attr_info->node_name_valid = true;
2667  port_attr_info->node_name = ocs_be64toh(ae->attr_wwn);
2668  break;
2669  case RPRT_PORTNAME:
2670  port_attr_info->port_name_valid = true;
2671  port_attr_info->port_name = ocs_be64toh(ae->attr_wwn);
2672  break;
2673  case RPRT_SYM_PORTNAME:
2674  port_attr_info->port_symb_name_valid = true;
2675  ocs_strncpy(port_attr_info->port_symb_name, (char *)ae->attr_string,
2676  MIN(sizeof(ae->attr_string),
2677  sizeof(port_attr_info->port_symb_name)));
2678  break;
2679  case RPRT_PORT_TYPE:
2680  port_attr_info->port_type_valid = true;
2681  port_attr_info->port_type = ocs_be32toh(ae->attr_int);
2682  break;
2683  case RPRT_SUPPORTED_CLASS:
2684  port_attr_info->supported_cos_valid = true;
2685  port_attr_info->supported_class_of_service = ocs_be32toh(ae->attr_int);
2686  break;
2687  case RPRT_FABRICNAME:
2688  port_attr_info->port_fabric_name_valid = true;
2689  port_attr_info->port_fabric_name = ocs_be64toh(ae->attr_wwn);
2690  break;
2691  case RPRT_ACTIVE_FC4_TYPES:
2692  port_attr_info->active_fc_types_valid= true;
2693  ocs_memcpy(port_attr_info->active_fc4_types, ae->attr_types,
2694  sizeof(port_attr_info->active_fc4_types));
2695  break;
2696  case RPRT_PORT_STATE:
2697  port_attr_info->port_state_valid = true;
2698  port_attr_info->port_state = ocs_be32toh(ae->attr_int);
2699  break;
2700  case RPRT_DISC_PORT:
2701  port_attr_info->num_disc_ports_valid = true;
2702  port_attr_info->num_disc_ports = ocs_be32toh(ae->attr_int);
2703  break;
2704  case RPRT_PORT_ID:
2705  port_attr_info->port_id_valid = true;
2706  port_attr_info->port_identifier = ocs_be32toh(ae->attr_int);
2707  break;
2708  default:
2709  ocs_log_warn(node->ocs, "Unrecognized HBA attribute(type: 0x%x)\n",
2710  attr_type);
2711  }
2712 
2713  /* Now point to next attribute */
2714  offset += attr_len;
2715  num_attr_entries--;
2716  }
2717 
2718  return 0;
2719 }
2720 /**
2721  * @brief Set up the domain point-to-point parameters.
2722  *
2723  * @par Description
2724  * The remote node service parameters are examined, and various point-to-point
2725  * variables are set.
2726  *
2727  * @param sport Pointer to the sport object.
2728  *
2729  * @return Returns 0 on success, or a negative error value on failure.
2730  */
2731 
2732 int32_t
2733 ocs_p2p_setup(ocs_sport_t *sport)
2734 {
2735  ocs_t *ocs = sport->ocs;
2736  int32_t rnode_winner;
2737  rnode_winner = ocs_rnode_is_winner(sport);
2738 
2739  /* set sport flags to indicate p2p "winner" */
2740  if (rnode_winner == 1) {
2741  sport->p2p_remote_port_id = 0;
2742  sport->p2p_port_id = 0;
2743  sport->p2p_winner = FALSE;
2744  } else if (rnode_winner == 0) {
2745  sport->p2p_remote_port_id = 2;
2746  sport->p2p_port_id = 1;
2747  sport->p2p_winner = TRUE;
2748  } else {
2749  /* no winner; only okay if external loopback enabled */
2750  if (sport->ocs->external_loopback) {
2751  /*
2752  * External loopback mode enabled; local sport and remote node
2753  * will be registered with an NPortID = 1;
2754  */
2755  ocs_log_debug(ocs, "External loopback mode enabled\n");
2756  sport->p2p_remote_port_id = 1;
2757  sport->p2p_port_id = 1;
2758  sport->p2p_winner = TRUE;
2759  } else {
2760  ocs_log_warn(ocs, "failed to determine p2p winner\n");
2761  return rnode_winner;
2762  }
2763  }
2764  return 0;
2765 }
2766 
2767 /**
2768  * @brief Process the FABCTL node RSCN.
2769  *
2770  * <h3 class="desc">Description</h3>
2771  * Processes the FABCTL node RSCN payload, simply passes the event to the name server.
2772  *
2773  * @param node Pointer to the node structure.
2774  * @param cbdata Callback data to pass forward.
2775  *
2776  * @return None.
2777  */
2778 
2779 static void
2780 ocs_process_rscn(ocs_node_t *node, ocs_node_cb_t *cbdata)
2781 {
2782  ocs_t *ocs = node->ocs;
2783  ocs_sport_t *sport = node->sport;
2784  ocs_node_t *ns;
2785 
2786  /* Forward this event to the name-services node */
2787  ns = ocs_node_find(sport, FC_ADDR_NAMESERVER);
2788  if (ns != NULL) {
2790  } else {
2791  ocs_log_warn(ocs, "can't find name server node\n");
2792  }
2793 }
2794 
2795 /* Routines for all individual HBA attributes */
2796 int
2798 {
2800  uint32_t size;
2801  uint64_t wwnn = ocs_be64toh(sport->wwnn);
2802 
2803  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
2804  memset(ae, 0, sizeof(sport->wwnn));
2805 
2806  ocs_memcpy(&ae->attr_wwn, &wwnn,
2807  sizeof(sport->sli_wwnn));
2808  size = FDMI_ATTR_TYPE_LEN_SIZE + sizeof(sport->sli_wwnn);
2809  ad->attr_len = ocs_htobe16(size);
2810  ad->attr_type = ocs_htobe16(RHBA_NODENAME);
2811  return size;
2812 }
2813 int
2815 {
2817  uint32_t len, size;
2818 
2819  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
2820  memset(ae, 0, 256);
2821 
2822  ocs_strncpy(ae->attr_string,
2823  "Emulex Corporation", sizeof(ae->attr_string));
2824  len = ocs_strnlen((char *)ae->attr_string,
2825  sizeof(ae->attr_string));
2826  len += 4 - (len & 3);
2827  size = FDMI_ATTR_TYPE_LEN_SIZE + len;
2828  ad->attr_len = ocs_htobe16(size);
2829  ad->attr_type = ocs_htobe16(RHBA_MANUFACTURER);
2830  return size;
2831 }
2832 
2833 int
2835 {
2836  ocs_t *ocs = sport->ocs;
2838  uint32_t len, size, serialnum_len = 0;
2839  char *serialnum = NULL;
2840 
2841  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
2842  memset(ae, 0, 256);
2843 
2845 
2846  serialnum_len = *serialnum++;
2847 
2848  ocs_strncpy(ae->attr_string, serialnum, MIN(254, serialnum_len));
2849  len = ocs_strlen(ae->attr_string);
2850  len += 4 - (len & 3);
2851  size = FDMI_ATTR_TYPE_LEN_SIZE + len;
2852  ad->attr_len = ocs_htobe16(size);
2853  ad->attr_type = ocs_htobe16(RHBA_SERIAL_NUMBER);
2854  return size;
2855 }
2856 
2857 int
2859 {
2860  ocs_t *ocs = sport->ocs;
2862  uint32_t len, size;
2863 
2864  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
2865  memset(ae, 0, 256);
2866 
2867  ocs_strncpy(ae->attr_string, ocs->model,
2868  sizeof(ae->attr_string));
2869  len = ocs_strnlen(ae->attr_string, sizeof(ae->attr_string));
2870  len += 4 - (len & 3);
2871  size = FDMI_ATTR_TYPE_LEN_SIZE + len;
2872  ad->attr_len = ocs_htobe16(size);
2873  ad->attr_type = ocs_htobe16(RHBA_MODEL);
2874  return size;
2875 }
2876 
2877 int
2879 {
2880  ocs_t *ocs = sport->ocs;
2882  uint32_t len, size;
2883 
2884  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
2885  memset(ae, 0, 256);
2886 
2887  ocs_strncpy(ae->attr_string, ocs->desc,
2888  sizeof(ae->attr_string));
2889  len = ocs_strnlen(ae->attr_string, sizeof(ae->attr_string));
2890  len += 4 - (len & 3);
2891  size = FDMI_ATTR_TYPE_LEN_SIZE + len;
2892  ad->attr_len = ocs_htobe16(size);
2893  ad->attr_type = ocs_htobe16(RHBA_MODEL_DESCRIPTION);
2894 
2895  return size;
2896 }
2897 
2898 int
2900 {
2902  ocs_t *ocs = sport->ocs;
2903  uint32_t len, size;
2904 
2905  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
2906  memset(ae, 0, 256);
2907 
2908  ocs_strncpy(ae->attr_string, ocs->driver_version,
2909  sizeof(ae->attr_string));
2910  len = ocs_strnlen(ae->attr_string,
2911  sizeof(ae->attr_string));
2912  len += 4 - (len & 3);
2913  size = FDMI_ATTR_TYPE_LEN_SIZE + len;
2914  ad->attr_len = ocs_htobe16(size);
2915  ad->attr_type = ocs_htobe16(RHBA_DRIVER_VERSION);
2916  return size;
2917 }
2918 
2919 int
2921 {
2922  ocs_t *ocs = sport->ocs;
2924  uint32_t len, size;
2925 
2926  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
2927  memset(ae, 0, 256);
2928 
2929  ocs_strncpy(ae->attr_string, ocs->fw_version, MIN(255, strlen(ocs->fw_version)));
2930  len = ocs_strnlen(ae->attr_string,
2931  sizeof(ae->attr_string));
2932  len += 4 - (len & 3);
2933  size = FDMI_ATTR_TYPE_LEN_SIZE + len;
2934  ad->attr_len = ocs_htobe16(size);
2935  ad->attr_type = ocs_htobe16(RHBA_OPTION_ROM_VERSION);
2936  return size;
2937 }
2938 
2939 int
2941 {
2943  ocs_t *ocs = sport->ocs;
2944  uint32_t len, size;
2945 
2946  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
2947  memset(ae, 0, 256);
2948 
2949  ocs_strncpy(ae->attr_string, ocs->fw_version, MIN(255, strlen(ocs->fw_version)));
2950  len = ocs_strnlen(ae->attr_string, sizeof(ae->attr_string));
2951  len += 4 - (len & 3);
2952  size = FDMI_ATTR_TYPE_LEN_SIZE + len;
2953  ad->attr_len = ocs_htobe16(size);
2954  ad->attr_type = ocs_htobe16(RHBA_FIRMWARE_VERSION);
2955  return size;
2956 }
2957 
2958 int
2960 {
2962  uint32_t len, size;
2963 
2964  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
2965  memset(ae, 0, 256);
2966 
2967  ocs_get_os_version_and_name(sport->ocs, ae->attr_string,
2968  sizeof(ae->attr_string));
2969 
2970  len = ocs_strnlen(ae->attr_string, sizeof(ae->attr_string));
2971  len += 4 - (len & 3);
2972  size = FDMI_ATTR_TYPE_LEN_SIZE + len;
2973  ad->attr_len = ocs_htobe16(size);
2974  ad->attr_type = ocs_htobe16(RHBA_OS_NAME_VERSION);
2975  return size;
2976 }
2977 
2978 int
2980 {
2982  uint32_t size;
2983 
2984  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
2985 
2986  ae->attr_int = ocs_htobe32(OCS_MAX_CT_SIZE);
2987  size = FDMI_ATTR_TYPE_LEN_SIZE + sizeof(uint32_t);
2988  ad->attr_len = ocs_htobe16(size);
2989  ad->attr_type = ocs_htobe16(RHBA_MAX_CT_PAYLOAD_LEN);
2990  return size;
2991 }
2992 
2993 int
2995 {
2996  ocs_t *ocs = sport->ocs;
2998  uint32_t len, size;
2999 
3000  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3001  memset(ae, 0, 256);
3002 
3003  ocs_snprintf(ae->attr_string, sizeof(ae->attr_string),
3004  "Emulex %s FV%s DV%s", ocs->model,ocs->fw_version,
3005  ocs->driver_version);
3006 
3007  len = ocs_strnlen(ae->attr_string, sizeof(ae->attr_string));
3008  len += 4 - (len & 3);
3009  size = FDMI_ATTR_TYPE_LEN_SIZE + len;
3010  ad->attr_len = ocs_htobe16(size);
3011  ad->attr_type = ocs_htobe16(RHBA_SYM_NODENAME);
3012  return size;
3013 }
3014 
3015 int
3017 {
3019  uint32_t size;
3020 
3021  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3022  ae->attr_int = ocs_htobe32(0);
3023  size = FDMI_ATTR_TYPE_LEN_SIZE + sizeof(uint32_t);
3024  ad->attr_len = ocs_htobe16(size);
3025  ad->attr_type = ocs_htobe16(RHBA_VENDOR_INFO);
3026  return size;
3027 }
3028 
3029 int
3031 {
3033  uint32_t size;
3034 
3035  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3036 
3037  /* Each driver instance corresponds to a single port */
3038  ae->attr_int = ocs_htobe32(1);
3039  size = FDMI_ATTR_TYPE_LEN_SIZE + sizeof(uint32_t);
3040  ad->attr_len = ocs_htobe16(size);
3041  ad->attr_type = ocs_htobe16(RHBA_NUM_PORTS);
3042  return size;
3043 }
3044 
3045 int
3047 {
3049  uint32_t size;
3050 
3051  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3052  memset(ae, 0, sizeof(sport->sli_wwpn));
3053 
3054  ocs_memcpy(&ae->attr_wwn, &sport->sli_wwpn,
3055  sizeof(sport->sli_wwpn));
3056  size = FDMI_ATTR_TYPE_LEN_SIZE + sizeof(sport->sli_wwpn);
3057  ad->attr_len = ocs_htobe16(size);
3058  ad->attr_type = ocs_htobe16(RHBA_FABRIC_WWNN);
3059  return size;
3060 }
3061 
3062 int
3064 {
3065  ocs_t *ocs = sport->ocs;
3067  uint32_t len, size;
3068 
3069  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3070  memset(ae, 0, 256);
3071 
3072  ocs_strncpy(ae->attr_string, ocs->fw_version, MIN(255, strlen(ocs->fw_version)));
3073  len = ocs_strnlen(ae->attr_string, sizeof(ae->attr_string));
3074  len += 4 - (len & 3);
3075  size = FDMI_ATTR_TYPE_LEN_SIZE + len;
3076  ad->attr_len = ocs_htobe16(size);
3077  ad->attr_type = ocs_htobe16(RHBA_BIOS_VERSION);
3078  return size;
3079 }
3080 
3081 int
3083 {
3085  uint32_t size;
3086 
3087  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3088 
3089  /* Driver doesn't have access to this information */
3090  ae->attr_int = ocs_htobe32(0);
3091  size = FDMI_ATTR_TYPE_LEN_SIZE + sizeof(uint32_t);
3092  ad->attr_len = ocs_htobe16(size);
3093  ad->attr_type = ocs_htobe16(RHBA_BIOS_STATE);
3094  return size;
3095 }
3096 
3097 int
3099 {
3101  uint32_t len, size;
3102 
3103  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3104  memset(ae, 0, 256);
3105 
3106  ocs_strncpy(ae->attr_string, "Emulex",
3107  sizeof(ae->attr_string));
3108  len = ocs_strnlen(ae->attr_string,
3109  sizeof(ae->attr_string));
3110  len += 4 - (len & 3);
3111  size = FDMI_ATTR_TYPE_LEN_SIZE + len;
3112  ad->attr_len = ocs_htobe16(size);
3113  ad->attr_type = ocs_htobe16(RHBA_VENDOR_ID);
3114  return size;
3115 }
3116 
3117 /**
3118  * @ingroup ns_sm
3119  * @brief Fabric node state machine: Wait for RHBA response event.
3120  *
3121  * @par Description
3122  * Waits for an RHBA response event;
3123  *
3124  * @param ctx Remote node state machine context.
3125  * @param evt Event to process.
3126  * @param arg Per event optional argument.
3127  *
3128  * @return Returns NULL.
3129  */
3130 void *
3131 __ocs_fdmi_rhba_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
3132 {
3133  int resp_status;
3135 
3136  node_sm_trace();
3137 
3138  switch(evt) {
3139  case OCS_EVT_SRRS_ELS_REQ_OK: {
3140  if (node_check_ct_req(ctx, evt, arg, FC_GS_FDMI_RHBA, __ocs_fabric_common, __func__)) {
3141  return NULL;
3142  }
3143  ocs_assert(node->els_req_cnt, NULL);
3144  node->els_req_cnt--;
3145 
3146  resp_status = node_check_ct_resp(ctx, evt, arg);
3147  if (resp_status == FCCT_HDR_CMDRSP_REJECT) {
3148  ocs_log_debug(node->ocs, "FDMI RHBA request got rejected curr HBA attrmask: 0x%x\n",
3149  node->sport->fdmi_hba_mask);
3150  /* If rejected & mask is V2, fall back to FDMI-V1 and send RHBA */
3151  if (node->sport->fdmi_hba_mask == FDMI_RHBA_MASK_V2) {
3152  node->sport->fdmi_hba_mask = FDMI_RHBA_MASK_V1;
3154  OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL);
3156  } else {
3157  ocs_node_transition(node, __ocs_fdmi_idle, NULL);
3158  }
3159  } else if (resp_status == FCCT_HDR_CMDRSP_ACCEPT) {
3162  OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL);
3164 
3165  }
3166  break;
3167  }
3168  default:
3169  __ocs_fabric_common(__func__, ctx, evt, arg);
3170  return NULL;
3171  }
3172 
3173  return NULL;
3174 }
3175 
3176 /**
3177  * @ingroup ns_sm
3178  * @brief Fabric node state machine: Wait for DHBA response event.
3179  *
3180  * @par Description
3181  * Waits for an DHBA response event;
3182  *
3183  * @param ctx Remote node state machine context.
3184  * @param evt Event to process.
3185  * @param arg Per event optional argument.
3186  *
3187  * @return Returns NULL.
3188  */
3189 void *
3190 __ocs_fdmi_dhba_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
3191 {
3193 
3194  node_sm_trace();
3195 
3196  switch(evt) {
3197  case OCS_EVT_SRRS_ELS_REQ_OK: {
3198  if (node_check_ct_req(ctx, evt, arg, FC_GS_FDMI_DHBA, __ocs_fabric_common, __func__)) {
3199  return NULL;
3200  }
3201  ocs_assert(node->els_req_cnt, NULL);
3202  node->els_req_cnt--;
3203 
3204  /* Now send FDMI DPRT request */
3207  OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL);
3209  break;
3210  }
3211  default:
3212  __ocs_fabric_common(__func__, ctx, evt, arg);
3213  return NULL;
3214  }
3215 
3216  return NULL;
3217 }
3218 
3219 void *
3220 __ocs_fdmi_reg_port_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
3221 {
3222  uint32_t expected_code, resp_status;
3224 
3225  node_sm_trace();
3226 
3227  switch(evt) {
3228  case OCS_EVT_SRRS_ELS_REQ_OK: {
3229  if (node->sport->is_vport) {
3230  expected_code = FC_GS_FDMI_RPRT;
3231  } else {
3232  expected_code = FC_GS_FDMI_RPA;
3233  }
3234  if (node_check_ct_req(ctx, evt, arg, expected_code, __ocs_fabric_common, __func__)) {
3235  return NULL;
3236  }
3237  ocs_assert(node->els_req_cnt, NULL);
3238  node->els_req_cnt--;
3239  resp_status = node_check_ct_resp(ctx, evt, arg);
3240  if (resp_status == FCCT_HDR_CMDRSP_REJECT) {
3241  ocs_log_debug(node->ocs, "FDMI reg port request(cmd: 0x%x) curr Port attrmask: 0x%x\n",
3242  expected_code, node->sport->fdmi_port_mask);
3243  /* If rejected & mask is V2, fall back to FDMI-V1 and send RPRT/RPA */
3244  if (node->sport->fdmi_port_mask == FDMI_PORT_MASK_V2) {
3245  node->sport->fdmi_port_mask = FDMI_PORT_MASK_V1;
3246  ocs_log_debug(node->ocs, "Send regport with port attrmask: 0x%x\n",
3247  node->sport->fdmi_port_mask);
3248  ocs_fdmi_send_reg_port(node, expected_code,
3250  OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL);
3252  break;
3253  }
3254  }
3255  ocs_node_transition(node, __ocs_fdmi_idle, NULL);
3256  break;
3257  }
3258  default:
3259  __ocs_fabric_common(__func__, ctx, evt, arg);
3260  return NULL;
3261  }
3262 
3263  return NULL;
3264 }
3265 
3266 /**
3267  * @ingroup ns_sm
3268  * @brief Fabric node state machine: Wait for DPRT response event.
3269  *
3270  * @par Description
3271  * Waits for an DPRT response event;
3272  *
3273  * @param ctx Remote node state machine context.
3274  * @param evt Event to process.
3275  * @param arg Per event optional argument.
3276  *
3277  * @return Returns NULL.
3278  */
3279 void *
3280 __ocs_fdmi_dprt_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
3281 {
3283 
3284  node_sm_trace();
3285 
3286  switch(evt) {
3287  case OCS_EVT_SRRS_ELS_REQ_OK: {
3288  if (node_check_ct_req(ctx, evt, arg, FC_GS_FDMI_DPRT, __ocs_fabric_common, __func__)) {
3289  return NULL;
3290  }
3291  ocs_assert(node->els_req_cnt, NULL);
3292  node->els_req_cnt--;
3293  if (node->sport->is_vport) {
3296  OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL);
3298  } else {
3300  OCS_FC_ELS_DEFAULT_RETRIES, NULL, NULL);
3302  }
3303  break;
3304  }
3305  default:
3306  __ocs_fabric_common(__func__, ctx, evt, arg);
3307  return NULL;
3308  }
3309 
3310  return NULL;
3311 }
3312 
3313 /* Routines for all individual PORT attributes */
3314 int
3316 {
3318  uint32_t size;
3319 
3320  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3321  memset(ae, 0, 32);
3322 
3323  ae->attr_types[3] = 0x02; /* Type 1 - ELS */
3324  ae->attr_types[2] = 0x01; /* Type 8 - FCP */
3325  ae->attr_types[7] = 0x01; /* Type 32 - CT */
3326  size = FDMI_ATTR_TYPE_LEN_SIZE + 32;
3327  ad->attr_len = ocs_htobe16(size);
3328  ad->attr_type = ocs_htobe16(RPRT_SUPPORTED_FC4_TYPES);
3329 
3330  return size;
3331 }
3332 
3333 int
3335 {
3336  ocs_t *ocs = sport->ocs;
3338  uint32_t size;
3339  ocs_xport_stats_t speed;
3340  uint32_t supported_speeds = 0;
3341 
3342  speed.value = 1000;
3343  if (ocs_xport_status(ocs->xport, OCS_XPORT_IS_SUPPORTED_LINK_SPEED, &speed)) {
3344  supported_speeds |= OCS_PORTSPEED_1GFC;
3345  }
3346  speed.value = 2000;
3347  if (ocs_xport_status(ocs->xport, OCS_XPORT_IS_SUPPORTED_LINK_SPEED, &speed)) {
3348  supported_speeds |= OCS_PORTSPEED_2GFC;
3349  }
3350  speed.value = 4000;
3351  if (ocs_xport_status(ocs->xport, OCS_XPORT_IS_SUPPORTED_LINK_SPEED, &speed)) {
3352  supported_speeds |= OCS_PORTSPEED_4GFC;
3353  }
3354  speed.value = 8000;
3355  if (ocs_xport_status(ocs->xport, OCS_XPORT_IS_SUPPORTED_LINK_SPEED, &speed)) {
3356  supported_speeds |= OCS_PORTSPEED_8GFC;
3357  }
3358  speed.value = 16000;
3359  if (ocs_xport_status(ocs->xport, OCS_XPORT_IS_SUPPORTED_LINK_SPEED, &speed)) {
3360  supported_speeds |= OCS_PORTSPEED_16GFC;
3361  }
3362  speed.value = 32000;
3363  if (ocs_xport_status(ocs->xport, OCS_XPORT_IS_SUPPORTED_LINK_SPEED, &speed)) {
3364  supported_speeds |= OCS_PORTSPEED_32GFC;
3365  }
3366  speed.value = 64000;
3367  if (ocs_xport_status(ocs->xport, OCS_XPORT_IS_SUPPORTED_LINK_SPEED, &speed)) {
3368  supported_speeds |= OCS_PORTSPEED_64GFC;
3369  }
3370  speed.value = 128000;
3371  if (ocs_xport_status(ocs->xport, OCS_XPORT_IS_SUPPORTED_LINK_SPEED, &speed)) {
3372  supported_speeds |= OCS_PORTSPEED_128GFC;
3373  }
3374 
3375  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3376  ae->attr_int = ocs_htobe32(supported_speeds);
3377  size = FDMI_ATTR_TYPE_LEN_SIZE + sizeof(uint32_t);
3378  ad->attr_len = ocs_htobe16(size);
3379  ad->attr_type = ocs_htobe16(RPRT_SUPPORTED_SPEED);
3380  return size;
3381 }
3382 
3383 int
3385 {
3386  ocs_t *ocs = sport->ocs;
3388  ocs_xport_stats_t speed;
3389  uint32_t size;
3390  int rc;
3391 
3392  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3393 
3395  rc = ocs_xport_status(ocs->xport, OCS_XPORT_LINK_SPEED, &speed);
3396  if (rc == 0) {
3397  switch (speed.value) {
3398  case 1000:
3400  break;
3401  case 2000:
3403  break;
3404  case 4000:
3406  break;
3407  case 8000:
3409  break;
3410  case 16000:
3412  break;
3413  case 32000:
3415  break;
3416  case 64000:
3418  break;
3419  case 128000:
3421  break;
3422  }
3423 
3424  }
3425  ae->attr_int = ocs_htobe32(ae->attr_int);
3426  size = FDMI_ATTR_TYPE_LEN_SIZE + sizeof(uint32_t);
3427  ad->attr_len = ocs_htobe16(size);
3428  ad->attr_type = ocs_htobe16(RPRT_PORT_SPEED);
3429  return size;
3430 }
3431 int
3433 {
3435  uint32_t size;
3436  fc_plogi_payload_t *sp = (fc_plogi_payload_t *)sport->service_params;
3437  uint16_t b2b_recv_data_size;
3438 
3439  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3440 
3441  /*
3442  * common_service_parameters will be in big-endian format
3443  * Convert it to host order and extract b2b
3444  */
3445  b2b_recv_data_size = ocs_be32toh(sp->common_service_parameters[1]);
3446  /* Return received buffer-to-buffer data frame size from service params */
3447  ae->attr_int = b2b_recv_data_size >> 16;
3448  ae->attr_int = ocs_htobe32(b2b_recv_data_size);
3449 
3450  size = FDMI_ATTR_TYPE_LEN_SIZE + sizeof(uint32_t);
3451  ad->attr_len = ocs_htobe16(size);
3452  ad->attr_type = ocs_htobe16(RPRT_MAX_FRAME_SIZE);
3453  return size;
3454 }
3455 
3456 int
3458 {
3459  ocs_t *ocs = sport->ocs;
3461  uint32_t len, size;
3462 
3463  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3464  memset(ae, 0, 256);
3465 
3466  ocs_scsi_get_host_name(ocs, ae->attr_string, sizeof(ae->attr_string));
3467 
3468  len = ocs_strnlen((char *)ae->attr_string,
3469  sizeof(ae->attr_string));
3470  len += 4 - (len & 3);
3471  size = FDMI_ATTR_TYPE_LEN_SIZE + len;
3472  ad->attr_len = ocs_htobe16(size);
3473  ad->attr_type = ocs_htobe16(RPRT_OS_DEVICE_NAME);
3474  return size;
3475 }
3476 
3477 int
3479 {
3481  uint32_t len, size;
3482 
3483  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3484  memset(ae, 0, 256);
3485 
3486  ocs_get_os_host_name(sport->ocs, ae->attr_string, sizeof(ae->attr_string));
3487 
3488  len = ocs_strnlen(ae->attr_string, sizeof(ae->attr_string));
3489  len += 4 - (len & 3);
3490  size = FDMI_ATTR_TYPE_LEN_SIZE + len;
3491  ad->attr_len = ocs_htobe16(size);
3492  ad->attr_type = ocs_htobe16(RPRT_HOST_NAME);
3493  return size;
3494 }
3495 
3496 int
3498 {
3500  uint32_t size;
3501  uint64_t wwnn = ocs_be64toh(sport->wwnn);
3502 
3503  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3504  memset(ae, 0, sizeof(sport->sli_wwnn));
3505 
3506  ocs_memcpy(&ae->attr_wwn, &wwnn,
3507  sizeof(sport->sli_wwnn));
3508  size = FDMI_ATTR_TYPE_LEN_SIZE + sizeof(sport->sli_wwnn);
3509  ad->attr_len = ocs_htobe16(size);
3510  ad->attr_type = ocs_htobe16(RPRT_NODENAME);
3511  return size;
3512 }
3513 
3514 int
3516 {
3518  uint32_t size;
3519 
3520  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3521  memset(ae, 0, sizeof(sport->sli_wwpn));
3522 
3523  ocs_memcpy(&ae->attr_wwn, &sport->sli_wwpn,
3524  sizeof(sport->sli_wwnn));
3525  size = FDMI_ATTR_TYPE_LEN_SIZE + sizeof(sport->sli_wwpn);
3526  ad->attr_len = ocs_htobe16(size);
3527  ad->attr_type = ocs_htobe16(RPRT_PORTNAME);
3528  return size;
3529 }
3530 
3531 int
3533 {
3535  uint32_t len, size;
3536 
3537  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3538  memset(ae, 0, 256);
3539 
3540  len = ocs_snprintf(ae->attr_string, 256, "%d", sport->instance_index);
3541  len += (len & 3) ? (4 - (len & 3)) : 0;
3542  size = FDMI_ATTR_TYPE_LEN_SIZE + len;
3543  ad->attr_len = ocs_htobe16(size);
3544  ad->attr_type = ocs_htobe16(RPRT_SYM_PORTNAME);
3545  return size;
3546 }
3547 
3548 int
3550 {
3552  uint32_t size;
3553 
3554  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3555  if (sport->topology == OCS_SPORT_TOPOLOGY_LOOP) {
3556  ae->attr_int = ocs_htobe32(OCS_FDMI_PORTTYPE_NLPORT);
3557  } else if ((sport->topology == OCS_SPORT_TOPOLOGY_FABRIC) ||
3558  (sport->topology == OCS_SPORT_TOPOLOGY_LOOP)) {
3559  ae->attr_int = ocs_htobe32(OCS_FDMI_PORTTYPE_NPORT);
3560  } else {
3561  ae->attr_int = ocs_htobe32(OCS_FDMI_PORTTYPE_UNKNOWN);
3562  }
3563  size = FDMI_ATTR_TYPE_LEN_SIZE + sizeof(uint32_t);
3564  ad->attr_len = ocs_htobe16(size);
3565  ad->attr_type = ocs_htobe16(RPRT_PORT_TYPE);
3566  return size;
3567 }
3568 
3569 int
3571 {
3573  uint32_t size;
3574 
3575  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3576  ae->attr_int = ocs_htobe32(FCCT_CLASS_OF_SERVICE_3);
3577  size = FDMI_ATTR_TYPE_LEN_SIZE + sizeof(uint32_t);
3578  ad->attr_len = ocs_htobe16(size);
3579  ad->attr_type = ocs_htobe16(RPRT_SUPPORTED_CLASS);
3580  return size;
3581 }
3582 
3583 int
3585 {
3587  uint32_t size;
3588  ocs_t *ocs = sport->ocs;
3589 
3590  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3591 
3592  ae->attr_wwn = 0;
3593  if (ocs->domain) {
3595  ocs->domain->flogi_service_params;
3596 
3597  ae->attr_wwn = (((uint64_t)sp->node_name_lo << 32ll) |
3598  sp->node_name_hi);
3599 
3600  }
3601  size = FDMI_ATTR_TYPE_LEN_SIZE + sizeof(sport->sli_wwpn);
3602  ad->attr_len = ocs_htobe16(size);
3603  ad->attr_type = ocs_htobe16(RPRT_FABRICNAME);
3604  return size;
3605 }
3606 
3607 int
3609 {
3611  uint32_t size;
3612 
3613  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3614  ocs_memset(ae, 0, 32);
3615 
3616  ae->attr_types[3] = 0x02; /* Type 1 - ELS */
3617  ae->attr_types[2] = 0x01; /* Type 8 - FCP */
3618  ae->attr_types[7] = 0x01; /* Type 32 - CT */
3619  size = FDMI_ATTR_TYPE_LEN_SIZE + 32;
3620  ad->attr_len = ocs_htobe16(size);
3621  ad->attr_type = ocs_htobe16(RPRT_ACTIVE_FC4_TYPES);
3622  return size;
3623 }
3624 
3625 int
3627 {
3628  ocs_t *ocs = sport->ocs;
3630  uint32_t size;
3631  ocs_xport_stats_t link_status;
3632  int rc;
3633 
3634  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3635 
3636  rc = ocs_xport_status(ocs->xport, OCS_XPORT_PORT_STATUS, &link_status);
3637  if ((rc == OCS_HAL_RTN_SUCCESS) &&
3638  (link_status.value == OCS_XPORT_PORT_ONLINE)) {
3639  ae->attr_int = ocs_htobe32(OCS_FDMI_PORTSTATE_ONLINE);
3640  } else {
3641  ae->attr_int = ocs_htobe32(OCS_FDMI_PORTSTATE_OFFLINE);
3642  }
3643  size = FDMI_ATTR_TYPE_LEN_SIZE + sizeof(uint32_t);
3644  ad->attr_len = ocs_htobe16(size);
3645  ad->attr_type = ocs_htobe16(RPRT_PORT_STATE);
3646  return size;
3647 }
3648 
3649 int
3651 {
3653  uint32_t size;
3654 
3655  ae = (ocs_fdmi_attr_entry_t *)&ad->attr_value;
3656  ae->attr_int = ocs_htobe32(sport->fc_id);
3657  size = FDMI_ATTR_TYPE_LEN_SIZE + sizeof(uint32_t);
3658  ad->attr_len = ocs_htobe16(size);
3659  ad->attr_type = ocs_htobe16(RPRT_PORT_ID);
3660  return size;
3661 }
3662 
3663 /**
3664  * @ingroup ns_sm
3665  * @brief Fabric node state machine: Wait for FDMI response event.
3666  *
3667  * @par Description
3668  * Waits for an FDMI cmd response event;
3669  *
3670  * @param ctx Remote node state machine context.
3671  * @param evt Event to process.
3672  * @param arg Per event optional argument.
3673  *
3674  * @return Returns NULL.
3675  */
3676 static void *
3677 __ocs_fdmi_get_cmd_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
3678 {
3680 
3681  node_sm_trace();
3682 
3683  switch(evt) {
3684  case OCS_EVT_SRRS_ELS_REQ_OK: {
3685  ocs_assert(node->els_req_cnt, NULL);
3686  node->els_req_cnt--;
3687  /* SM: process GRHL response payload */
3688  ocs_node_transition(node, __ocs_fdmi_idle, NULL);
3689  break;
3690  }
3691  default:
3692  __ocs_fabric_common(__func__, ctx, evt, arg);
3693  return NULL;
3694  }
3695 
3696  return NULL;
3697 }
3698 
3699 int
3700 ocs_fdmi_get_cmd(ocs_sport_t *sport, els_cb_t cb, void *cb_arg,
3701  ocs_fdmi_get_cmd_req_info_t *fdmi_cmd_req)
3702 {
3703  ocs_node_t *node;
3704 
3705  node = ocs_node_find(sport, FC_ADDR_FDMI);
3706  if (node == NULL) {
3707  ocs_log_err(sport->ocs, "failed to find FDMI node\n")
3708  return -1;
3709  }
3710 
3712  OCS_FC_ELS_DEFAULT_RETRIES, cb, cb_arg, fdmi_cmd_req)) {
3714  } else {
3715  ocs_log_err(sport->ocs, "failed to send FDMI request\n");
3716  return -1;
3717  }
3718 
3719  return 0;
3720 }
uint32_t port_fabric_name_valid
Definition: ocs_ioctl.h:427
#define RHBA_BIOS_STATE
Definition: ocs_fabric.h:115
#define RHBA_MODEL
Definition: ocs_fabric.h:102
void * __ocs_p2p_wait_domain_attach(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Point-to-point state machine: Wait for the domain attach to complete.
Definition: ocs_fabric.c:1640
#define FC_GS_NAMESERVER_GA_NXT
Definition: ocs_fcp.h:91
void * __ocs_fabctl_wait_scr_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Fabric controller node state machine: Wait for an SCR response from the fabric controller.
Definition: ocs_fabric.c:1359
ocs_io_t * ocs_fdmi_send_rhba(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries, els_cb_t cb, void *cbarg)
Send a RHBA CT request.
Definition: ocs_els.c:2246
ocs_io_t * ocs_send_scr(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries, els_cb_t cb, void *cbarg)
Send an SCR ELS command.
Definition: ocs_els.c:1196
int ocs_fdmi_port_attr_fabric_wwpn(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3584
int ocs_fdmi_port_attr_active_fc4type(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3608
#define FDMI_PORT_MASK_V2
Definition: ocs_fabric.h:149
#define OCS_PORTSPEED_2GFC
Definition: ocs_fabric.c:71
ocs_sport_t * ocs_sport_find(ocs_domain_t *domain, uint32_t d_id)
Find a SLI port object, given an FC_ID.
Definition: ocs_sport.c:365
void * __ocs_p2p_wait_node_attach(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Point-to-point node state machine: Wait for a point-to-point node attach to complete.
Definition: ocs_fabric.c:2012
int ocs_fdmi_hba_attr_num_ports(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3030
uint8_t os_name_ver[256]
Definition: ocs_ioctl.h:414
void * __ocs_fdmi_dprt_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Fabric node state machine: Wait for DPRT response event.
Definition: ocs_fabric.c:3280
int ocs_fdmi_hba_attr_bios_ver(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3063
#define FC_GS_FDMI_RPRT
Definition: ocs_fcp.h:113
fcct_iu_header_t hdr
Definition: ocs_fcp.h:700
static int32_t ocs_start_fabctl_node(ocs_sport_t *sport)
Start up the fabric controller node.
Definition: ocs_fabric.c:2148
uint32_t max_residual_size
Definition: ocs_fcp.h:485
#define OCS_FDMI_PORTTYPE_NPORT
Definition: ocs_fabric.c:82
#define OCS_FDMI_PORTTYPE_UNKNOWN
Definition: ocs_fabric.c:81
int ocs_fdmi_hba_attr_model(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:2858
void * __ocs_ns_plogi_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Name services node state machine: Wait for a PLOGI response.
Definition: ocs_fabric.c:512
void * __ocs_ns_idle(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Name services node state machine: Idle state.
Definition: ocs_fabric.c:1090
#define FC_GS_NAMESERVER_RFT_ID
Definition: ocs_fcp.h:97
void * __ocs_ns_wait_node_attach(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Name services node state machine: Wait for a node attach completion.
Definition: ocs_fabric.c:562
#define OCS_PORTSPEED_16GFC
Definition: ocs_fabric.c:74
uint8_t os_dev_name[256]
Definition: ocs_ioctl.h:448
#define OCS_PORTSPEED_128GFC
Definition: ocs_fabric.c:77
#define OCS_MAX_CT_SIZE
Definition: ocs_fabric.c:67
#define enable_target_rscn(ocs)
#define RHBA_OPTION_ROM_VERSION
Definition: ocs_fabric.h:106
uint8_t bios_ver[256]
Definition: ocs_ioctl.h:420
#define FC_ADDR_CONTROLLER
Definition: ocs_fcp.h:62
void * __ocs_fabctl_init(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Fabric controller node state machine: Initial state.
Definition: ocs_fabric.c:1258
uint32_t max_ct_payload_valid
Definition: ocs_ioctl.h:386
fcct_fdmi_reg_port_list_t hba_list
Definition: ocs_fcp.h:701
uint32_t node_name_hi
Definition: ocs_fcp.h:326
uint8_t active_fc4_types[32]
Definition: ocs_ioctl.h:456
#define FDMI_PORT_MASK_V1
Definition: ocs_fabric.h:146
uint8_t attr_types[32]
Definition: ocs_fcp.h:652
int ocs_fdmi_port_attr_class(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3570
#define OCS_PORTSPEED_8GFC
Definition: ocs_fabric.c:73
#define FCCT_HDR_CMDRSP_ACCEPT
Definition: ocs_fcp.h:594
int32_t node_check_ct_req(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg, uint32_t cmd, ocs_node_common_func_t node_common_func, const char *funcname)
check CT request completion
Definition: ocs_node.c:1788
uint32_t cmd_rsp_code
Definition: ocs_fcp.h:485
#define OCS_NODEDB_PAUSE_NAMESERVER
Definition: ocs_node.h:72
uint32_t ctl
Definition: ocs_fcp.h:806
#define RPRT_MAX_FRAME_SIZE
Definition: ocs_fabric.h:124
static void ocs_process_rscn(ocs_node_t *node, ocs_node_cb_t *cbdata)
Process the FABCTL node RSCN.
Definition: ocs_fabric.c:2780
uint32_t supported_class_of_service
Definition: ocs_ioctl.h:454
uint32_t node_symb_name_valid
Definition: ocs_ioctl.h:386
#define FC_GS_NAMESERVER_GID_PT
Definition: ocs_fcp.h:90
int32_t ocs_sport_attach(ocs_sport_t *sport, uint32_t fc_id)
Request a SLI port attach.
Definition: ocs_sport.c:426
void ocs_remote_node_group_free(ocs_remote_node_group_t *node_group)
Free a remote node group object.
Definition: ocs_sport.c:1995
int ocs_fdmi_hba_attr_fmw_ver(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:2940
static int32_t ocs_process_gidpt_payload(ocs_node_t *node, fcct_gidpt_acc_t *gidpt, uint32_t gidpt_len)
Process the GIDPT payload.
Definition: ocs_fabric.c:2180
static void gidpt_delay_timer_cb(void *arg)
Handle GIDPT delay timer callback.
Definition: ocs_fabric.c:1172
void * __ocs_p2p_rnode_init(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Point-to-point state machine: Remote node initialization state.
Definition: ocs_fabric.c:1722
void ocs_node_post_event(ocs_node_t *node, ocs_sm_event_t evt, void *arg)
Post event to node state machine context.
Definition: ocs_node.c:1498
void * __ocs_fabric_flogi_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Fabric node state machine: Wait for an FLOGI response.
Definition: ocs_fabric.c:187
#define FC_TYPE_NVME
Definition: ocs_fcp.h:57
uint32_t supported_speed_valid
Definition: ocs_ioctl.h:427
void * __ocs_ns_gidpt_delay(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Name services node state machine: Delayed GIDPT.
Definition: ocs_fabric.c:1198
int32_t ocs_rnode_is_nport(fc_plogi_payload_t *remote_sparms)
Return TRUE if the remote node is an NPORT.
Definition: ocs_fabric.c:1557
int ocs_fdmi_get_cmd(ocs_sport_t *sport, els_cb_t cb, void *cb_arg, ocs_fdmi_get_cmd_req_info_t *fdmi_cmd_req)
Definition: ocs_fabric.c:3700
#define OCS_PORTSPEED_1GFC
Definition: ocs_fabric.c:70
#define RHBA_SERIAL_NUMBER
Definition: ocs_fabric.h:101
ocs_io_t * ocs_send_plogi_acc(ocs_io_t *io, uint32_t ox_id, els_cb_t cb, void *cbarg)
Send a PLOGI accept response.
Definition: ocs_els.c:1403
#define RPRT_NODENAME
Definition: ocs_fabric.h:127
#define RPRT_DISC_PORT
Definition: ocs_fabric.h:135
static void ocs_node_accept_frames(ocs_node_t *node)
accept frames
Definition: ocs_node.h:120
uint32_t ox_id
Definition: ocs_fcp.h:168
static int32_t ocs_start_fdmi_node(ocs_sport_t *sport)
Start up the FDMI node.
Definition: ocs_fabric.c:2120
ocs_hal_rtn_e
Definition: ocs_hal.h:159
void ocs_node_transition(ocs_node_t *node, ocs_sm_function_t state, void *data)
transition state of a node
Definition: ocs_node.c:1547
#define FC_ELS_CMD_FDISC
Definition: ocs_fcp.h:50
#define RHBA_FIRMWARE_VERSION
Definition: ocs_fabric.h:107
#define FDMI_RHBA_MASK_V1
Definition: ocs_fabric.h:140
ocs_io_t * ocs_ns_send_rftid(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries, els_cb_t cb, void *cbarg)
Send a RFTID CT request.
Definition: ocs_els.c:1942
int ocs_fdmi_port_attr_nportid(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3650
#define FC_TYPE_FCP
Definition: ocs_fcp.h:56
static void * __ocs_fdmi_get_cmd_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Fabric node state machine: Wait for FDMI response event.
Definition: ocs_fabric.c:3677
int ocs_fdmi_port_attr_wwpn(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3515
uint32_t reason_code_explanation
Definition: ocs_fcp.h:487
#define FC_ADDR_FDMI
Definition: ocs_fcp.h:66
uint8_t model_desc[256]
Definition: ocs_ioctl.h:409
#define RPRT_SYM_PORTNAME
Definition: ocs_fabric.h:129
int ocs_fdmi_port_attr_os_devname(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3457
int32_t ocs_node_attach(ocs_node_t *node)
Perform HAL call to attach a remote node.
Definition: ocs_node.c:671
#define RHBA_BIOS_VERSION
Definition: ocs_fabric.h:114
ocs_io_t * ocs_send_plogi(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries, void(*cb)(ocs_node_t *node, ocs_node_cb_t *cbdata, void *arg), void *cbarg)
Format and send a PLOGI ELS command.
Definition: ocs_els.c:696
fcct_fdmi_reg_port_list_t port_list
Definition: ocs_fcp.h:713
void * __ocs_fdmi_wait_node_attach(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
FDMI node state machine: Wait for a node attach completion.
Definition: ocs_fabric.c:710
void * __ocs_fabctl_wait_ls_acc_cmpl(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Fabric controller node state machine: Wait for LS_ACC.
Definition: ocs_fabric.c:1441
int ocs_fdmi_hba_attr_bios_state(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3082
void ocs_display_sparams(const char *prelabel, const char *reqlabel, int dest, void *textbuf, void *sparams)
Display service parameters.
Definition: ocs_debug.c:495
ocs_node_t * ocs_node_find(ocs_sport_t *sport, uint32_t port_id)
Find an FC node structure given the FC port ID.
Definition: ocs_node.c:202
fcct_fdmi_reg_port_list_t port_list
Definition: ocs_fcp.h:725
#define RHBA_MANUFACTURER
Definition: ocs_fabric.h:100
int ocs_fdmi_port_attr_max_frame(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3432
#define RHBA_NODENAME
Definition: ocs_fabric.h:99
Definition: ocs_fcp.h:650
void * __ocs_fdmi_idle(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
FDMI node state machine: FDMI node is idle.
Definition: ocs_fabric.c:1144
ocs_io_t * ocs_fdmi_send_dereg_cmd(ocs_node_t *node, uint16_t dereg_code, uint32_t timeout_sec, uint32_t retries, els_cb_t cb, void *cbarg)
Send a FDMI dereg CT request.
Definition: ocs_els.c:2332
uint64_t hba_identifier[MAX_FDMI_HBA_COUNT]
Definition: ocs_ioctl.h:375
uint32_t port_entry[0]
Definition: ocs_fcp.h:666
void ocs_node_init_device(ocs_node_t *node, int send_plogi)
Initialize device node.
Definition: ocs_device.c:781
#define FC_GS_NAMESERVER_RFF_ID
Definition: ocs_fcp.h:98
#define RPRT_FABRICNAME
Definition: ocs_fabric.h:132
#define RPRT_PORT_SPEED
Definition: ocs_fabric.h:123
uint32_t port_id
Definition: ocs_fcp.h:806
#define OCS_FDMI_PORTSTATE_ONLINE
Definition: ocs_fabric.c:87
#define RPRT_PORT_ID
Definition: ocs_fabric.h:136
uint8_t driver_ver[256]
Definition: ocs_ioctl.h:411
void ocs_get_os_version_and_name(ocs_t *ocs, void *os_ver_name_str, size_t size)
#define FCCT_GID_PT_LAST_ID
Definition: ocs_fcp.h:811
ocs_io_t * ocs_fdmi_send_get_cmd(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries, els_cb_t cb, void *cbarg, ocs_fdmi_get_cmd_req_info_t *req_info)
Send a GHRL CT request.
Definition: ocs_els.c:2492
void ocs_scsi_io_alloc_disable(ocs_node_t *node)
Disable IO allocation.
Definition: ocs_scsi.c:144
const char * ocs_sm_event_name(ocs_sm_event_t evt)
Definition: ocs_sm.c:92
uint8_t host_name[256]
Definition: ocs_ioctl.h:449
struct fcct_gidpt_acc_t::@7 port_list[1]
#define RHBA_DRIVER_VERSION
Definition: ocs_fabric.h:105
int32_t ocs_xport_control(ocs_xport_t *xport, ocs_xport_ctrl_e cmd,...)
Perform transport attach function.
Definition: ocs_xport.c:866
uint32_t reason_code
Definition: ocs_fcp.h:487
ocs_hal_rtn_e ocs_hal_node_detach(ocs_hal_t *hal, ocs_remote_node_t *rnode)
Free a remote node object.
Definition: ocs_hal.c:3562
void * __ocs_ns_init(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Name services node state machine: Initialize.
Definition: ocs_fabric.c:477
int ocs_fdmi_hba_attr_ct_len(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:2979
void(* els_cb_t)(ocs_node_t *node, ocs_node_cb_t *cbdata, void *arg)
Definition: ocs_els.h:58
#define FC_GS_FDMI_RHBA
Definition: ocs_fcp.h:111
uint32_t attr_int
Definition: ocs_fcp.h:651
FC header in big-endian order.
Definition: ocs_fcp.h:157
int32_t ocs_process_fdmi_grpl_payload(ocs_node_t *node, fcct_fdmi_grpl_rsp_t *grpl, uint32_t grpl_len, void *buf)
Process the GRPL acc payload.
Definition: ocs_fabric.c:2372
#define RPRT_PORT_TYPE
Definition: ocs_fabric.h:130
uint32_t num_port_attr_entries
Definition: ocs_ioctl.h:426
#define OCS_FDMI_PORTSTATE_OFFLINE
Definition: ocs_fabric.c:86
#define FC_ADDR_IS_DOMAIN_CTRL(x)
Definition: ocs_fcp.h:63
#define FDMI_RHBA_MASK_V2
Definition: ocs_fabric.h:143
#define RPRT_OS_DEVICE_NAME
Definition: ocs_fabric.h:125
uint32_t value
Definition: ocs_xport.h:170
void * __ocs_p2p_wait_plogi_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Point-to-point node state machine: Wait for a PLOGI response as a point-to-point winner.
Definition: ocs_fabric.c:1844
uint32_t node_name_lo
Definition: ocs_fcp.h:327
fcct_iu_header_t hdr
Definition: ocs_fcp.h:736
#define ocs_list_foreach_safe(list, item, nxt)
Iterate a linked list safely.
Definition: ocs_list.h:446
void ocs_d_send_prli_rsp(ocs_io_t *io, uint16_t ox_id, uint8_t fc_type)
Send response to PRLI.
Definition: ocs_device.c:67
int ocs_fdmi_hba_attr_symbolic_name(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:2994
void * __ocs_vport_fabric_init(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Fabric node state machine: Initial state for a virtual port.
Definition: ocs_fabric.c:289
int ocs_fdmi_hba_attr_rom_ver(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:2920
#define RHBA_VENDOR_INFO
Definition: ocs_fabric.h:111
int32_t ocs_process_fdmi_ghat_payload(ocs_node_t *node, fcct_fdmi_ghat_rsp_t *ghat, uint32_t ghat_len, void *buf)
Process the GHAT acc payload.
Definition: ocs_fabric.c:2423
int ocs_fdmi_hba_attr_drvr_ver(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:2899
ocs_io_t * ocs_ns_send_gidpt(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries, els_cb_t cb, void *cbarg)
Send a GIDPT CT request.
Definition: ocs_els.c:2076
int ocs_fdmi_hba_attr_fabric_wwnn(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3046
#define OCS_PORTSPEED_4GFC
Definition: ocs_fabric.c:72
void * __ocs_fdmi_dhba_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Fabric node state machine: Wait for DHBA response event.
Definition: ocs_fabric.c:3190
#define RHBA_FABRIC_WWNN
Definition: ocs_fabric.h:113
uint8_t serial_num[64]
Definition: ocs_ioctl.h:407
#define FC_GS_FDMI_DPRT
Definition: ocs_fcp.h:117
uint32_t port_name_lo
Definition: ocs_fcp.h:325
#define RPRT_PORT_STATE
Definition: ocs_fabric.h:134
#define FC_ELS_CMD_PLOGI
Definition: ocs_fcp.h:43
static void * __ocs_fabric_common(const char *funcname, ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Fabric node state machine: Handle the common fabric node events.
Definition: ocs_fabric.c:1521
uint64_t attr_wwn
Definition: ocs_fcp.h:654
void * __ocs_fabctl_ready(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Fabric controller node state machine: Ready.
Definition: ocs_fabric.c:1400
void ocs_node_initiate_cleanup(ocs_node_t *node)
Initiate node IO cleanup.
Definition: ocs_node.c:1025
void * __ocs_p2p_wait_flogi_acc_cmpl(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Point-to-point node state machine: Wait for the FLOGI accept completion.
Definition: ocs_fabric.c:1764
uint64_t port_identifier[MAX_FDMI_PORT_COUNT]
Definition: ocs_ioctl.h:380
void * __ocs_fabric_fdisc_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Fabric node state machine: Wait for an FDISC response.
Definition: ocs_fabric.c:324
uint32_t port_name_hi
Definition: ocs_fcp.h:324
#define FC_GS_FDMI_DHBA
Definition: ocs_fcp.h:115
int ocs_fdmi_hba_attr_vendor_info(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3016
void * __ocs_fdmi_plogi_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
FDMI node state machine: Wait for a PLOGI response.
Definition: ocs_fabric.c:660
uint32_t active_fc_types_valid
Definition: ocs_ioctl.h:427
#define FC_ELS_CMD_FLOGI
Definition: ocs_fcp.h:44
void ocs_domain_attach(ocs_domain_t *domain, uint32_t s_id)
Initiator domain attach.
Definition: ocs_domain.c:1299
ocs_io_t * ocs_send_ls_acc(ocs_io_t *io, uint32_t ox_id, els_cb_t cb, void *cbarg)
Send a generic LS_ACC response without a payload.
Definition: ocs_els.c:1787
ocs_io_t * ocs_ns_send_rffid(ocs_node_t *node, uint8_t fc_type, uint32_t timeout_sec, uint32_t retries, els_cb_t cb, void *cbarg)
Send a RFFID CT request.
Definition: ocs_els.c:2005
void ocs_fabric_notify_topology(ocs_node_t *node)
Notify sport topology.
Definition: ocs_fabric.c:156
ocs_io_t * ocs_fdmi_send_reg_port(ocs_node_t *node, int req_code, uint32_t timeout_sec, uint32_t retries, els_cb_t cb, void *cbarg)
Send a RPRT/RPA CT request.
Definition: ocs_els.c:2388
#define FC_ELS_CMD_SCR
Definition: ocs_fcp.h:53
#define RPRT_SUPPORTED_SPEED
Definition: ocs_fabric.h:122
uint32_t supported_fc_types_valid
Definition: ocs_ioctl.h:427
static void ocs_sport_lock(ocs_sport_t *sport)
Definition: ocs_sport.h:67
ocs_node_t * ocs_node_alloc(ocs_sport_t *sport, uint32_t port_id, uint8_t init, uint8_t targ)
Allocate an fc node structure and add to node list.
Definition: ocs_node.c:415
void ocs_node_pause(ocs_node_t *node, ocs_sm_function_t state)
Pause a node.
Definition: ocs_node.c:2140
#define RHBA_MODEL_DESCRIPTION
Definition: ocs_fabric.h:103
int32_t ocs_process_fdmi_gpat_payload(ocs_node_t *node, fcct_fdmi_gpat_rsp_t *gpat, uint32_t gpat_len, void *buf)
Process the GPAT acc payload.
Definition: ocs_fabric.c:2599
#define MAX_FDMI_HBA_COUNT
Definition: ocs_ioctl.h:41
#define FCCT_CLASS_OF_SERVICE_3
Definition: ocs_fcp.h:567
#define RHBA_SYM_NODENAME
Definition: ocs_fabric.h:110
void * __ocs_fabric_idle(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Fabric node state machine: Fabric node is idle.
Definition: ocs_fabric.c:446
void * __ocs_fabric_wait_attach_evt_shutdown(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Wait for a domain/sport/node attach completion, then shutdown.
Definition: ocs_fabric.c:784
fcct_iu_header_t hdr
Definition: ocs_fcp.h:804
int ocs_fdmi_hba_attr_wwnn(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:2797
int ocs_sm_post_event(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *data)
Post an event to a context.
Definition: ocs_sm.c:58
void * __ocs_ns_rffid_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Fabric node state machine: Wait for RFFID response event.
Definition: ocs_fabric.c:940
void * __ocs_fdmi_rhba_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Fabric node state machine: Wait for RHBA response event.
Definition: ocs_fabric.c:3131
uint32_t num_entries
Definition: ocs_fcp.h:660
void * __ocs_fabctl_wait_node_attach(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Fabric controller node state machine: Wait for a node attach request to complete. ...
Definition: ocs_fabric.c:1300
int32_t node_check_ct_resp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Definition: ocs_node.c:1821
int ocs_fdmi_port_attr_host_name(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3478
uint64_t port_identifier[MAX_FDMI_PORT_COUNT]
Definition: ocs_ioctl.h:385
fcct_iu_header_t hdr
Definition: ocs_fcp.h:724
void * __ocs_fdmi_reg_port_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Definition: ocs_fabric.c:3220
void * __ocs_fabric_init(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Fabric node state machine: Initial state.
Definition: ocs_fabric.c:103
void * __ocs_ns_rftid_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Name services node state machine: Wait for an RFTID response event.
Definition: ocs_fabric.c:840
uint8_t port_symb_name[256]
Definition: ocs_ioctl.h:452
static uint64_t ocs_get_wwpn(fc_plogi_payload_t *sp)
Return the node&#39;s WWPN as an uint64_t.
Definition: ocs_fabric.c:1575
#define OCS_FC_ELS_DEFAULT_RETRIES
Definition: ocs_fc_config.h:85
#define FCCT_HDR_CMDRSP_REJECT
Definition: ocs_fcp.h:595
void * __ocs_ns_nvme_rffid_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Definition: ocs_fabric.c:880
#define RHBA_OS_NAME_VERSION
Definition: ocs_fabric.h:108
#define FC_ADDR_NAMESERVER
Definition: ocs_fcp.h:65
int ocs_fdmi_port_attr_speed(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3384
ocs_sport_topology_e
Definition: ocs_common.h:116
int ocs_fdmi_hba_attr_sn(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:2834
#define RPRT_SUPPORTED_CLASS
Definition: ocs_fabric.h:131
fcct_iu_header_t hdr
Definition: ocs_fcp.h:712
void * __ocs_fabric_wait_domain_attach(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Fabric node state machine: Wait for a domain/sport attach event.
Definition: ocs_fabric.c:387
#define FDMI_ATTR_TYPE_LEN_SIZE
Definition: ocs_fabric.c:66
uint8_t supported_fc4_types[32]
Definition: ocs_ioctl.h:444
#define OCS_PORTSPEED_64GFC
Definition: ocs_fabric.c:76
ocs_io_t * ocs_bls_send_acc_hdr(ocs_io_t *io, fc_header_t *hdr)
Send a BA_ACC given the request&#39;s FC header.
Definition: ocs_els.c:2573
#define RPRT_HOST_NAME
Definition: ocs_fabric.h:126
int ocs_fdmi_hba_attr_description(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:2878
void * __ocs_node_common(const char *funcname, ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
state: common node event handler
Definition: ocs_node.c:1317
#define std_node_state_decl(...)
Definition: ocs_node.h:62
void * __ocs_d_port_logged_in(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Device node state machine: Port is logged in.
Definition: ocs_device.c:1512
static void ocs_node_hold_frames(ocs_node_t *node)
hold frames in pending frame list
Definition: ocs_node.h:102
uint8_t manufacturer[64]
Definition: ocs_ioctl.h:406
void ocs_fabric_set_topology(ocs_node_t *node, ocs_sport_topology_e topology)
Set sport topology.
Definition: ocs_fabric.c:140
uint8_t node_symb_name[256]
Definition: ocs_ioctl.h:416
#define OCS_FDMI_PORTTYPE_NLPORT
Definition: ocs_fabric.c:83
#define RHBA_MAX_CT_PAYLOAD_LEN
Definition: ocs_fabric.h:109
int ocs_fdmi_port_attr_wwnn(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3497
#define node_sm_trace()
Definition: ocs_node.h:42
int ocs_fdmi_hba_attr_os_ver(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:2959
void * __ocs_fdmi_init(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
FDMI node state machine: Initialize.
Definition: ocs_fabric.c:625
static void ocs_fabric_initiate_shutdown(ocs_node_t *node)
Initiate fabric node shutdown.
Definition: ocs_fabric.c:1480
ocs_io_t * ocs_send_fdisc(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries, els_cb_t cb, void *cbarg)
Format and send a FDISC ELS command.
Definition: ocs_els.c:842
#define RPRT_ACTIVE_FC4_TYPES
Definition: ocs_fabric.h:133
#define node_printf(node, fmt,...)
Definition: ocs_node.h:48
void ocs_domain_save_sparms(ocs_domain_t *domain, void *payload)
Save the port&#39;s service parameters.
Definition: ocs_domain.c:1261
int ocs_fdmi_hba_attr_vendor_id(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3098
int32_t ocs_get_property(const char *prop_name, char *buffer, uint32_t buffer_len)
get driver wide property value
ocs_io_t * ocs_send_flogi(ocs_node_t *node, uint32_t timeout_sec, uint32_t retries, els_cb_t cb, void *cbarg)
Format and send a FLOGI ELS command.
Definition: ocs_els.c:773
uint8_t attr_string[256]
Definition: ocs_fcp.h:653
#define ocs_assert(cond,...)
Definition: ocs_debug.h:176
int ocs_fdmi_port_attr_fc4type(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3315
#define RHBA_NUM_PORTS
Definition: ocs_fabric.h:112
static uint32_t fc_be24toh(uint32_t x)
Definition: ocs_fcp.h:143
int ocs_fdmi_port_attr_support_speed(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3334
void ocs_scsi_get_host_name(ocs_t *ocs, void *host_name, size_t size)
int ocs_fdmi_port_attr_symbolic_name(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3532
ocs_sm_event_t
Definition: ocs_sm.h:60
int32_t ocs_xport_status(ocs_xport_t *xport, ocs_xport_status_e cmd, ocs_xport_stats_t *result)
Return status on a link.
Definition: ocs_xport.c:1073
#define OCS_PORTSPEED_UNKNOWN
Definition: ocs_fabric.c:78
#define ocs_list_foreach(list, item)
Iterate a linked list.
Definition: ocs_list.h:428
#define OCS_FC_ELS_CT_SEND_DEFAULT_TIMEOUT
Definition: ocs_fc_config.h:81
void ocs_process_prli_payload(ocs_node_t *node, fc_prli_payload_t *prli)
Process the PRLI payload.
Definition: ocs_device.c:518
int32_t node_check_els_req(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg, uint8_t cmd, ocs_node_common_func_t node_common_func, const char *funcname)
check ELS request completion
Definition: ocs_node.c:1738
uint8_t opt_rom_ver[256]
Definition: ocs_ioctl.h:412
#define OCS_FC_FLOGI_TIMEOUT_SEC
Definition: ocs_fc_config.h:89
#define MAX_FDMI_PORT_COUNT
Definition: ocs_ioctl.h:42
static int32_t ocs_rnode_is_winner(ocs_sport_t *sport)
Return TRUE if the remote node is the point-to-point winner.
Definition: ocs_fabric.c:1597
#define RHBA_VENDOR_ID
Definition: ocs_fabric.h:116
static int32_t ocs_start_ns_node(ocs_sport_t *sport)
Start up the name services node.
Definition: ocs_fabric.c:2085
void * ocs_scsi_get_property_ptr(ocs_t *ocs, ocs_scsi_property_e prop)
Return a property pointer.
Definition: ocs_scsi.c:2871
void ocs_get_os_host_name(ocs_t *ocs, void *os_ver_name_str, size_t size)
uint8_t model_name[256]
Definition: ocs_ioctl.h:408
static void ocs_sport_unlock(ocs_sport_t *sport)
Definition: ocs_sport.h:74
#define RHBA_HARDWARE_VERSION
Definition: ocs_fabric.h:104
void * __ocs_ns_gidpt_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Name services node state machine: Wait for a GIDPT response.
Definition: ocs_fabric.c:991
#define OCS_PORTSPEED_32GFC
Definition: ocs_fabric.c:75
void ocs_node_save_sparms(ocs_node_t *node, void *payload)
save node service parameters
Definition: ocs_node.c:1467
#define RPRT_SUPPORTED_FC4_TYPES
Definition: ocs_fabric.h:121
void * __ocs_p2p_wait_plogi_rsp_recvd_prli(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Point-to-point node state machine: Waiting on a response for a sent PLOGI.
Definition: ocs_fabric.c:1931
#define RPRT_PORTNAME
Definition: ocs_fabric.h:128
int ocs_fdmi_hba_attr_manufacturer(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:2814
int ocs_fdmi_port_attr_port_type(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3549
uint32_t common_service_parameters[4]
Definition: ocs_fcp.h:323
#define OCS_FC_ELS_SEND_DEFAULT_TIMEOUT
Definition: ocs_fc_config.h:77
void * __ocs_ns_ganxt_wait_rsp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Definition: ocs_fabric.c:1037
int32_t ocs_p2p_setup(ocs_sport_t *sport)
Set up the domain point-to-point parameters.
Definition: ocs_fabric.c:2733
int32_t ocs_process_fdmi_grhl_payload(ocs_node_t *node, fcct_fdmi_grhl_rsp_t *grhl, uint32_t grhl_len, void *buf)
Process the GRHL acc payload.
Definition: ocs_fabric.c:2322
#define FC_ADDR_FABRIC
Definition: ocs_fcp.h:61
#define FC_GS_FDMI_RPA
Definition: ocs_fcp.h:114
int ocs_fdmi_port_attr_port_state(ocs_sport_t *sport, ocs_fdmi_attr_def_t *ad)
Definition: ocs_fabric.c:3626
void ocs_send_ls_acc_after_attach(ocs_io_t *io, fc_header_t *hdr, ocs_node_send_ls_acc_e ls)
Save the OX_ID for sending LS_ACC sometime later.
Definition: ocs_device.c:475