Emulex Logo
OneCoreā„¢ Storage SDK Release 11.2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ocs_mgmt.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  * ocs_mgmt top level functions for iSCSI
36  */
37 
38 /*!
39  * @defgroup mgmt Management Functions
40  */
41 
42 #include "ocs.h"
43 #include "ocs_mgmt.h"
44 #include "ocs_vpd.h"
45 #if defined(OCS_INCLUDE_RAMD)
46 #include "ocs_ramd.h"
47 #endif
48 
49 /* Getters */
50 static void get_desc(ocs_t *, char *, ocs_textbuf_t*);
51 static void get_fw_rev(ocs_t *, char *, ocs_textbuf_t*);
52 static void get_fw_rev2(ocs_t *, char *, ocs_textbuf_t*);
53 static void get_ipl(ocs_t *, char *, ocs_textbuf_t*);
54 static void get_sn(ocs_t *, char *, ocs_textbuf_t*);
55 static void get_pn(ocs_t *, char *, ocs_textbuf_t*);
56 static void get_sli4_intf_reg(ocs_t *, char *, ocs_textbuf_t*);
57 static void get_phy_port_num(ocs_t *, char *, ocs_textbuf_t*);
58 static void get_asic_id_reg(ocs_t *, char *, ocs_textbuf_t*);
59 static void get_enable_ini(ocs_t *, char *, ocs_textbuf_t*);
60 static void get_enable_tgt(ocs_t *, char *, ocs_textbuf_t*);
61 static void get_enable_sgl_chaining(ocs_t *, char *, ocs_textbuf_t*);
62 static void get_max_sge_size(ocs_t *, char *, ocs_textbuf_t*);
63 static void get_num_tgts(ocs_t *, char *, ocs_textbuf_t*);
64 static void get_local_ip(ocs_t *, char *, ocs_textbuf_t*);
65 static void get_local_subnet(ocs_t *, char *, ocs_textbuf_t*);
66 static void get_pci_vendor(ocs_t *, char *, ocs_textbuf_t*);
67 static void get_pci_device(ocs_t *, char *, ocs_textbuf_t*);
68 static void get_pci_subsystem_vendor(ocs_t *, char *, ocs_textbuf_t*);
69 static void get_pci_subsystem_device(ocs_t *, char *, ocs_textbuf_t*);
70 static void get_businfo(ocs_t *, char *, ocs_textbuf_t*);
71 static void get_sfp_a0(ocs_t *, char *, ocs_textbuf_t*);
72 static void get_sfp_a2(ocs_t *, char *, ocs_textbuf_t*);
73 static void get_debug_mq_dump(ocs_t*, char*, ocs_textbuf_t*);
74 static void get_debug_cq_dump(ocs_t*, char*, ocs_textbuf_t*);
75 static void get_debug_wq_dump(ocs_t*, char*, ocs_textbuf_t*);
76 static void get_debug_io_trace(ocs_t*, char*, ocs_textbuf_t*);
77 static void get_debug_sm_trace(ocs_t*, char*, ocs_textbuf_t*);
78 static void get_debug_scsi_tgt_trace(ocs_t*, char*, ocs_textbuf_t*);
79 static void get_mac_address(ocs_t*, char*, ocs_textbuf_t*);
80 static void get_profile_list(ocs_t*, char*, ocs_textbuf_t*);
81 static void get_active_profile(ocs_t*, char*, ocs_textbuf_t*);
82 static void get_port_protocol(ocs_t*, char*, ocs_textbuf_t*);
83 static void get_driver_version(ocs_t*, char*, ocs_textbuf_t*);
84 static void get_chip_type(ocs_t*, char*, ocs_textbuf_t*);
85 static void get_jumbo_frames(ocs_t*, char*, ocs_textbuf_t*);
86 static void get_gateway(ocs_t*, char*, ocs_textbuf_t*);
87 static void get_data_digest(ocs_t*, char*, ocs_textbuf_t*);
88 static void get_header_digest(ocs_t*, char*, ocs_textbuf_t*);
89 static void get_tcp_window_size(ocs_t*, char*, ocs_textbuf_t*);
90 static void get_tcp_window_scale(ocs_t*, char*, ocs_textbuf_t*);
91 static void get_max_cxns_per_session(ocs_t*, char*, ocs_textbuf_t*);
92 static void get_require_chap(ocs_t*, char*, ocs_textbuf_t*);
93 static void get_linkcfg(ocs_t*, char*, ocs_textbuf_t*);
94 
95 /* Setters */
96 static int set_debug_mq_dump(ocs_t*, char*, char*);
97 static int set_debug_cq_dump(ocs_t*, char*, char*);
98 static int set_debug_wq_dump(ocs_t*, char*, char*);
99 static int set_debug_io_trace(ocs_t*, char*, char*);
100 static int set_debug_sm_trace(ocs_t*, char*, char*);
101 static int set_debug_scsi_tgt_trace(ocs_t*, char*, char*);
102 static int set_mac_address(ocs_t*, char*, char*);
103 static int set_active_profile(ocs_t*, char*, char*);
104 static int set_port_protocol(ocs_t*, char*, char*);
105 static int set_jumbo_frames(ocs_t*, char*, char*);
106 static int set_gateway(ocs_t*, char*, char*);
107 static int set_data_digest(ocs_t*, char*, char*);
108 static int set_header_digest(ocs_t*, char*, char*);
109 static int set_tcp_window_size(ocs_t*, char*, char*);
110 static int set_tcp_window_scale(ocs_t*, char*, char*);
111 static int set_max_cxns_per_session(ocs_t*, char*, char*);
112 static int set_require_chap(ocs_t*, char*, char*);
113 static int set_linkcfg(ocs_t*, char*, char*);
114 
115 /* Executables */
116 static int32_t
117 ocs_mgmt_iclusttgt_entry_add(ocs_t *ocs, char *name,
118  void *buf, uint32_t buf_len,
119  void *arg_out, uint32_t arg_out_length);
120 static int32_t
121 ocs_mgmt_iclusttgt_entry_del(ocs_t *ocs, char *name,
122  void *buf, uint32_t buf_len,
123  void *arg_out, uint32_t arg_out_length);
124 static int32_t
125 ocs_mgmt_iclusttgt_entry_get(ocs_t *ocs, char *name,
126  void *buf, uint32_t buf_len,
127  void *arg_out, uint32_t arg_out_length);
128 static int32_t
129 ocs_mgmt_iclusttgt_clear(ocs_t *ocs, char *name,
130  void *buf, uint32_t buf_len,
131  void *arg_out, uint32_t arg_out_length);
132 static int
133 ocs_mgmt_firmware_write(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void*, uint32_t);
134 static int
135 ocs_mgmt_firmware_reset(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void*, uint32_t);
136 static int32_t
137 ocs_mgmt_ip_add(ocs_t *ocs, char *, void *, uint32_t , void *, uint32_t);
138 static int32_t
139 ocs_mgmt_ip_get(ocs_t *ocs, char *, void *, uint32_t , void *, uint32_t);
140 #if defined(OCS_INCLUDE_RAMD)
141 static int32_t
142 ocs_mgmt_read_phys(ocs_t *ocs, char *, void *, uint32_t , void *, uint32_t);
143 #endif
144 static int32_t
145 ocs_mgmt_ip_remove(ocs_t *ocs, char *, void *, uint32_t , void *, uint32_t);
146 static int32_t
147 ocs_mgmt_chap_add_user(ocs_t *ocs, char *, void *, uint32_t, void *, uint32_t);
148 static int32_t
149 ocs_mgmt_chap_remove_user(ocs_t *ocs, char *, void *, uint32_t, void *, uint32_t);
150 int32_t ocs_iscsi_chap_list_count(ocs_t *ocs);
151 static int32_t
152 ocs_mgmt_chap_show_list(ocs_t *ocs, char *name, void *arg_in,
153  uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length);
154 static int32_t
155 ocs_mgmt_listen_start(ocs_t *ocs, char *, void *, uint32_t, void *, uint32_t);
156 static int32_t
157 ocs_mgmt_listen_stop(ocs_t *ocs, char *, void *, uint32_t, void *, uint32_t);
158 
159 static int32_t
160 ocs_mgmt_route_table_del_entry(ocs_t *ocs, char *name, void *arg_in,
161  uint32_t arg_in_len, void *arg_out,
162  uint32_t arg_out_len);
163 static int32_t
164 ocs_mgmt_route_table_add_entry(ocs_t *ocs, char *name, void *arg_in,
165  uint32_t arg_in_len, void *arg_out,
166  uint32_t arg_out_len);
167 static int32_t
168 ocs_mgmt_route_table_read(ocs_t *ocs, char *name,
169  void *arg_in, uint32_t arg_in_len,
170  void *arg_out, uint32_t arg_out_len);
171 static int32_t
172 ocs_mgmt_vlan_add(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length,
173  void *arg_out, uint32_t arg_out_length);
174 static int32_t
175 ocs_mgmt_vlan_del(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length,
176  void *arg_out, uint32_t arg_out_length);
177 static int32_t
178 ocs_mgmt_vlan_show(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length,
179  void *arg_out, uint32_t arg_out_length);
180 
181 /* Local utility functions */
182 #if defined(OCS_INCLUDE_RAMD)
183 static void* find_address_in_target(ocs_ramdisc_t **ramdisc_array, uint32_t ramdisc_count, uintptr_t target_addr);
184 #endif
185 static void ocs_mgmt_fw_write_cb(int32_t status, uint32_t actual_write_length, void *arg);
186 
188  {"desc", get_desc, NULL, NULL},
189  {"fw_rev", get_fw_rev, NULL, NULL},
190  {"fw_rev2", get_fw_rev2, NULL, NULL},
191  {"ipl", get_ipl, NULL, NULL},
192  {"sn", get_sn, NULL, NULL},
193  {"pn", get_pn, NULL, NULL},
194  {"sli4_intf_reg", get_sli4_intf_reg, NULL, NULL},
195  {"phy_port_num", get_phy_port_num, NULL, NULL},
196  {"asic_id_reg", get_asic_id_reg, NULL, NULL},
197  {"enable_ini", get_enable_ini, NULL, NULL},
198  {"enable_tgt", get_enable_tgt, NULL, NULL},
199  {"enable_sgl_chaining", get_enable_sgl_chaining, NULL, NULL},
200  {"max_sge_size", get_max_sge_size, NULL, NULL},
201  {"num_tgts", get_num_tgts, NULL, NULL},
202  {"local_ip", get_local_ip, NULL, NULL},
203  {"local_subnet", get_local_subnet, NULL, NULL},
204  {"pci_vendor", get_pci_vendor, NULL, NULL},
205  {"pci_device", get_pci_device, NULL, NULL},
206  {"pci_subsystem_vendor", get_pci_subsystem_vendor, NULL, NULL},
207  {"pci_subsystem_device", get_pci_subsystem_device, NULL, NULL},
208  {"businfo", get_businfo, NULL, NULL},
209  {"sfp_a0", get_sfp_a0, NULL, NULL},
210  {"sfp_a2", get_sfp_a2, NULL, NULL},
211  {"profile_list", get_profile_list, NULL, NULL},
212  {"driver_version", get_driver_version, NULL, NULL},
213  {"chip_type", get_chip_type, NULL, NULL},
214  {"debug_mq_dump", get_debug_mq_dump, set_debug_mq_dump, NULL},
215  {"debug_cq_dump", get_debug_cq_dump, set_debug_cq_dump, NULL},
216  {"debug_wq_dump", get_debug_wq_dump, set_debug_wq_dump, NULL},
217  {"debug_io_trace", get_debug_io_trace, set_debug_io_trace, NULL},
218  {"debug_sm_trace", get_debug_sm_trace, set_debug_sm_trace, NULL},
219  {"debug_scsi_tgt_trace", get_debug_scsi_tgt_trace, set_debug_scsi_tgt_trace, NULL},
220  {"mac_address", get_mac_address, set_mac_address, NULL},
221  {"active_profile", get_active_profile, set_active_profile, NULL},
222  {"port_protocol", get_port_protocol, set_port_protocol, NULL},
223  {"jumbo_frames", get_jumbo_frames, set_jumbo_frames, NULL},
224  {"gateway", get_gateway, set_gateway, NULL},
225  {"data_digest", get_data_digest, set_data_digest, NULL},
226  {"header_digest", get_header_digest, set_header_digest, NULL},
227  {"tcp_window_size", get_tcp_window_size, set_tcp_window_size, NULL},
228  {"tcp_window_scale", get_tcp_window_scale, set_tcp_window_scale, NULL},
229  {"max_cxns_per_session", get_max_cxns_per_session, set_max_cxns_per_session, NULL},
230  {"linkcfg", get_linkcfg, set_linkcfg, NULL},
231  {"firmware_write", NULL, NULL, ocs_mgmt_firmware_write},
232  {"firmware_reset", NULL, NULL, ocs_mgmt_firmware_reset},
233 #if defined(OCS_INCLUDE_RAMD)
234  {"read_phys", NULL, NULL, ocs_mgmt_read_phys},
235 #endif
236  {"require_chap", get_require_chap, set_require_chap, NULL},
237  {"add_chap_user", NULL, NULL, ocs_mgmt_chap_add_user},
238  {"remove_chap_user", NULL, NULL, ocs_mgmt_chap_remove_user},
239  {"show_chap_list", NULL, NULL, ocs_mgmt_chap_show_list},
240  {"route_del", NULL, NULL, ocs_mgmt_route_table_del_entry},
241  {"route_add", NULL, NULL, ocs_mgmt_route_table_add_entry},
242  {"route_show", NULL, NULL, ocs_mgmt_route_table_read},
243  {"vlan_del", NULL, NULL, ocs_mgmt_vlan_del},
244  {"vlan_add", NULL, NULL, ocs_mgmt_vlan_add},
245  {"vlan_show", NULL, NULL, ocs_mgmt_vlan_show},
246  {"ip_add", NULL, NULL, ocs_mgmt_ip_add},
247  {"ip_get", NULL, NULL, ocs_mgmt_ip_get},
248  {"ip_remove", NULL, NULL, ocs_mgmt_ip_remove},
249  {"listen_start", NULL, NULL, ocs_mgmt_listen_start},
250  {"listen_stop", NULL, NULL, ocs_mgmt_listen_stop},
251  {"iclusttgt_add", NULL, NULL, ocs_mgmt_iclusttgt_entry_add},
252  {"iclusttgt_del", NULL, NULL, ocs_mgmt_iclusttgt_entry_del},
253  {"iclusttgt_clear", NULL, NULL, ocs_mgmt_iclusttgt_clear},
254  {"iclusttgt_get", NULL, NULL, ocs_mgmt_iclusttgt_entry_get},
255 };
256 
257 /**
258  * @ingroup mgmt
259  * @brief get a list of mgmt items supported by the driver
260  *
261  * This is the top level "get list" handler for the driver. It
262  * will:
263  * - Add entries to the textbuf for any actions supported by this level in the driver
264  * - Call a back end function to add any actions supported by the back end
265  * - Call a function on each child (domain) to recursively add supported actions
266  *
267  * @param ocs pointer to ocs structure
268  * @param textbuf pointer to an ocs_textbuf which is used to accumulate the results
269  *
270  * @return Nothing.
271  */
272 
273 void
274 ocs_mgmt_get_list(ocs_t *ocs, ocs_textbuf_t *textbuf)
275 {
276  uint32_t i;
277  int access;
278 
279  ocs_textbuf_reset(textbuf);
280 
281  ocs_mgmt_start_unnumbered_section(textbuf, "ocs");
282 
283  for (i=0;i<ARRAY_SIZE(mgmt_table);i++) {
284  access = 0;
285  if (mgmt_table[i].get_handler) {
286  access |= MGMT_MODE_RD;
287  }
288  if (mgmt_table[i].set_handler) {
289  access |= MGMT_MODE_WR;
290  }
291  if (mgmt_table[i].action_handler) {
292  access |= MGMT_MODE_EX;
293  }
294  ocs_mgmt_emit_property_name(textbuf, access, mgmt_table[i].name);
295  }
296 
297  if ((ocs->mgmt_functions) && (ocs->mgmt_functions->get_list_handler)) {
298  ocs->mgmt_functions->get_list_handler(textbuf, ocs);
299  }
300 
301  if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->get_list_handler)) {
302  ocs->tgt_mgmt_functions->get_list_handler(textbuf, &(ocs->tgt_ocs));
303  }
304 
305  if ((ocs->domain->mgmt_functions) && (ocs->domain->mgmt_functions->get_list_handler)) {
306  ocs->domain->mgmt_functions->get_list_handler(textbuf, ocs->domain);
307  }
308 
309  ocs_mgmt_end_unnumbered_section(textbuf, "ocs");
310 }
311 
312 /**
313  * @ingroup mgmt
314  * @brief return the value of a mgmt item
315  *
316  * This is the top level "get" handler for the driver. It will:
317  * - Check that the qualifier portion of the name begins with my qualifier (ocs)
318  * - If the remaining part of the name matches a parameter that is known at this level
319  * then the value will be written into textbuf
320  * - If the name is not known the request will be given to the back ends to fulfill if possible
321  * - If the request hasn't been fulfilled by the back end it will be passed to each of the
322  * children (domains) to have them (recursively) try to respond
323  *
324  * In passing the request to other entities the request is considered to be answered
325  * when a response has been written into textbuf, indicated by textbuf->buffer_written
326  * being non-zero.
327  *
328  * @param ocs pointer to ocs structure
329  * @param name the name of the status item to be retrieved
330  * @param textbuf pointer to an ocs_textbuf which is used to return the results
331  *
332  * @return none
333  *
334  */
335 
336 int
337 ocs_mgmt_get(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
338 {
339  char qualifier[6];
340  int retval = -1;
341  uint32_t i;
342 
343  ocs_textbuf_reset(textbuf);
344 
345  ocs_mgmt_start_unnumbered_section(textbuf, "ocs");
346  snprintf(qualifier, sizeof(qualifier), "/ocs");
347 
348  /* See if the name starts with my qualifier. If not then this request isn't for me */
349  if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) {
350  char *unqualified_name = name + strlen(qualifier) + 1;
351 
352  /* See if it's a value I can supply */
353 
354  for (i=0;i<ARRAY_SIZE(mgmt_table);i++) {
355  if (ocs_strcmp(unqualified_name, mgmt_table[i].name) == 0) {
356  if (mgmt_table[i].get_handler) {
357  mgmt_table[i].get_handler(ocs, mgmt_table[i].name, textbuf);
358  }
359 
360  ocs_mgmt_end_unnumbered_section(textbuf, "ocs");
361 
362  return 0;
363  }
364  }
365 
366  if ((ocs->mgmt_functions) && (ocs->mgmt_functions->get_handler)) {
367  retval = ocs->mgmt_functions->get_handler(textbuf, qualifier, name, ocs);
368  }
369 
370  if (retval != 0) {
371  if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->get_handler)) {
372  retval = ocs->tgt_mgmt_functions->get_handler(textbuf, qualifier,
373  name, &(ocs->tgt_ocs));
374  }
375  }
376 
377  /* If I didn't know the value of this status pass the request to each of my children */
378  /* iSCSI has only one domain, not a list */
379 
380  if (retval != 0) {
381  if ((ocs->domain->mgmt_functions) && (ocs->domain->mgmt_functions->get_handler)) {
382  retval = ocs->domain->mgmt_functions->get_handler(textbuf, qualifier, name, ocs->domain);
383  }
384  }
385 
386 
387 
388  }
389 
390  ocs_mgmt_end_unnumbered_section(textbuf, "ocs");
391 
392  return retval;
393 }
394 
395 void
396 ocs_mgmt_get_all(ocs_t *ocs, ocs_textbuf_t *textbuf)
397 {
398  ocs_domain_t *domain;
399  uint32_t i;
400 
401  ocs_mgmt_start_unnumbered_section(textbuf, "ocs");
402 
403  for (i=0;i<ARRAY_SIZE(mgmt_table);i++) {
404  if (mgmt_table[i].get_handler) {
405  mgmt_table[i].get_handler(ocs, mgmt_table[i].name, textbuf);
406  } else if (mgmt_table[i].action_handler) {
407  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, mgmt_table[i].name);
408  }
409  }
410 
411  if ((ocs->mgmt_functions) && (ocs->mgmt_functions->get_all_handler)) {
412  ocs->mgmt_functions->get_all_handler(textbuf, ocs);
413  }
414 
415  if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->get_all_handler)) {
416  ocs->tgt_mgmt_functions->get_all_handler(textbuf, &(ocs->tgt_ocs));
417  }
418 
419  ocs_device_lock(ocs);
420  ocs_list_foreach(&ocs->domain_list, domain) {
421  if ((domain->mgmt_functions) && (domain->mgmt_functions->get_all_handler)) {
422  domain->mgmt_functions->get_all_handler(textbuf, domain);
423  }
424  }
425  ocs_device_unlock(ocs);
426 
427  ocs_mgmt_end_unnumbered_section(textbuf, "ocs");
428 
429 }
430 
431 /**
432  * @ingroup mgmt
433  * @brief set the value of a mgmt item
434  *
435  * This is the top level "set" handler for the driver. It will:
436  * - Check that the qualifier portion of the name begins with my qualifier (ocs)
437  * - If the remaining part of the name matches a parameter that is known at this level
438  * then the correct function will be called to change the configuration
439  * - If the name is not known the request will be given to the back ends to fulfill if possible
440  * - If the request hasn't been fulfilled by the back end it will be passed to each of the
441  * children (domains) to have them (recursively) try to respond
442  *
443  * In passing the request to other entities the request is considered to be handled
444  * if the function returns 0.
445  *
446  * @param ocs pointer to ocs structure
447  * @param name the name of the property to be changed
448  * @param value the requested new value of the property
449  *
450  * @return 0 if the configuration value was updated, -1 if it was not for any reason
451  *
452  *
453  */
454 
455 int
456 ocs_mgmt_set(ocs_t *ocs, char *name, char *value)
457 {
458  int result = -1;
459  char qualifier[80];
460  uint32_t i;
461 
462  snprintf(qualifier, sizeof(qualifier), "/ocs");
463 
464  /* If it doesn't start with my qualifier I don't know what to do with it */
465  if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) {
466  char *unqualified_name = name + strlen(qualifier) +1;
467 
468  /* See if it's a value I can set */
469  for (i=0;i<ARRAY_SIZE(mgmt_table);i++) {
470  if (ocs_strcmp(unqualified_name, mgmt_table[i].name) == 0) {
471  if (mgmt_table[i].set_handler) {
472  return mgmt_table[i].set_handler(ocs, mgmt_table[i].name, value);
473  }
474  }
475  }
476 
477  if ((ocs->mgmt_functions) && (ocs->mgmt_functions->set_handler)) {
478  result = ocs->mgmt_functions->set_handler(qualifier, name, (char *)value, ocs);
479  }
480 
481  if (result != 0) {
482  if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->set_handler)) {
483  result = ocs->tgt_mgmt_functions->set_handler(qualifier, name,
484  (char *)value, &(ocs->tgt_ocs));
485  }
486  }
487 
488  /* If I didn't know how to set this config value pass the request to each of my children */
489 
490  if (result != 0) {
491  if ((ocs->domain->mgmt_functions) && (ocs->domain->mgmt_functions->set_handler)) {
492  result = ocs->domain->mgmt_functions->set_handler(qualifier, name, (char*)value, ocs->domain);
493  }
494  }
495  }
496 
497  return result;
498 }
499 
500 
501 /**
502  * @ingroup mgmt
503  * @brief perform a management action
504  *
505  * This is the top level "do action" handler for the driver.
506  * It will:
507  * - Check that the qualifier portion of the name begins with my qualifier (ocs)
508  * - If the remaining part of the name matches an action that is known at this level
509  * then the correct function will be called to perform the action
510  * - If the name is not known the request will be given to the back ends to fulfill if possible
511  * - If the request hasn't been fulfilled by the back end it will be passed to each of the
512  * children (domains) to have them (recursively) try to respond
513  *
514  * In passing the request to other entities the request is considered to be handled
515  * if the function returns 0.
516  *
517  * @param ocs pointer to ocs structure
518  * @param action the name of the action to be performed
519  * @param arg_in a pointer to an argument being passed to the action
520  * @param arg_in_length the length of the argument pointed to by *arg_in
521  * @param arg_out a pointer to an argument being passed to the action
522  * @param arg_out_length the length of the argument pointed to by *arg_out
523  *
524  * @return 0 if the action was completed, -1 if it was not for any reason
525  *
526  *
527  */
528 
529 int
530 ocs_mgmt_exec(ocs_t *ocs, char *action, void *arg_in, uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length)
531 {
532  int result = -1;
533  char qualifier[80];
534  uint32_t i;
535 
536  snprintf(qualifier, sizeof(qualifier), "/ocs");
537 
538  /* If it doesn't start with my qualifier I don't know what to do with it */
539  if (ocs_strncmp(action, qualifier, strlen(qualifier)) == 0) {
540  char *unqualified_name = action + strlen(qualifier) +1;
541 
542  /* See if it's an action I can perform */
543  for (i=0;i<ARRAY_SIZE(mgmt_table); i++) {
544  if (ocs_strcmp(unqualified_name, mgmt_table[i].name) == 0) {
545  if (mgmt_table[i].action_handler) {
546  return mgmt_table[i].action_handler(ocs, action, arg_in, arg_in_length,
547  arg_out, arg_out_length);
548  }
549 
550  }
551  }
552 
553  if ((ocs->mgmt_functions) && (ocs->mgmt_functions->exec_handler)) {
554  result = ocs->mgmt_functions->exec_handler(qualifier, action, arg_in, arg_in_length,
555  arg_out, arg_out_length, ocs);
556  }
557 
558  if (result != 0) {
559  if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->exec_handler)) {
560  result = ocs->tgt_mgmt_functions->exec_handler(qualifier, action,
561  arg_in, arg_in_length, arg_out, arg_out_length,
562  &(ocs->tgt_ocs));
563  }
564  }
565 
566  /* If I didn't know how to do this action pass the request to each of my children */
567 
568  if (result != 0) {
569  if ((ocs->domain->mgmt_functions) && (ocs->domain->mgmt_functions->exec_handler)) {
570  result = ocs->domain->mgmt_functions->exec_handler(qualifier, action, arg_in, arg_in_length,
571  arg_out, arg_out_length, ocs->domain);
572  }
573  }
574 
575 
576  }
577 
578  return result;
579 }
580 
581 #if defined(OCS_INCLUDE_RAMD)
582 static int32_t
583 ocs_mgmt_read_phys(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length)
584 {
585  uint32_t length;
586  char addr_str[80];
587  uintptr_t target_addr;
588  void* vaddr = NULL;
589  ocs_ramdisc_t **ramdisc_array;
590  uint32_t ramdisc_count;
591  uint32_t sport_idx;
592 
593  if ((arg_in == NULL) ||
594  (arg_in_length == 0) ||
595  (arg_out == NULL) ||
596  (arg_out_length == 0)) {
597  return -1;
598  }
599 
600  if (arg_in_length > 80) {
601  arg_in_length = 80;
602  }
603 
604  if (ocs_copy_from_user(addr_str, arg_in, arg_in_length)) {
605  ocs_log_test(ocs, "Failed to copy addr from user\n");
606  return -EFAULT;
607  }
608 
609  target_addr = (uintptr_t)ocs_strtoul(addr_str, NULL, 0);
610  /* addr_str must be the physical address of a buffer that was reported
611  * in an SGL. Search ramdiscs looking for a segment that contains that
612  * physical address
613  */
614 
615  if (ocs->tgt_ocs.use_global_ramd) {
616  /* Only one target */
617  ramdisc_count = ocs->tgt_ocs.rdisc_count;
618  ramdisc_array = ocs->tgt_ocs.rdisc;
619  vaddr = find_address_in_target(ramdisc_array, ramdisc_count, target_addr);
620  } else {
621  /* Multiple targets. Each target is on a sport */
622  for (sport_idx=0; sport_idx < ocs->iscsi.num_tgts; sport_idx++) {
623  ramdisc_count = ocs->sport[sport_idx].tgt_sport.rdisc_count;
624  ramdisc_array = ocs->sport[sport_idx].tgt_sport.rdisc;
625  vaddr = find_address_in_target(ramdisc_array, ramdisc_count, target_addr);
626 
627  if (vaddr != NULL) {
628  break;
629  }
630  }
631  }
632 
633 
634 
635 
636  length = arg_out_length;
637 
638  if (vaddr != NULL) {
639 
640  if (ocs_copy_to_user(arg_out, vaddr, length)) {
641  ocs_log_test(ocs, "Failed to copy buffer to user\n");
642  return -EFAULT;
643  }
644 
645  return 0;
646  } else {
647 
648  return -EFAULT;
649  }
650 }
651 #endif
652 
653 /*
654  * This function searches a target for a given physical address.
655  * The target is made up of a number of LUNs, each represented by
656  * a ocs_ramdisc_t.
657  */
658 #if defined(OCS_INCLUDE_RAMD)
659 static void* find_address_in_target(ocs_ramdisc_t **ramdisc_array, uint32_t ramdisc_count, uintptr_t target_addr)
660 {
661  void *vaddr = NULL;
662  uint32_t ramdisc_idx;
663 
664  /* Check each ramdisc */
665  for (ramdisc_idx=0; ramdisc_idx<ramdisc_count; ramdisc_idx++) {
666  uint32_t segment_idx;
667  ocs_ramdisc_t *rdisc;
668  rdisc = ramdisc_array[ramdisc_idx];
669  /* Check each segment in the ramdisc */
670  for (segment_idx=0; segment_idx<rdisc->segment_count; segment_idx++) {
671  ramdisc_segment_t *segment = rdisc->segments[segment_idx];
672  uintptr_t segment_start;
673  uintptr_t segment_end;
674  uint32_t offset;
675 
676  segment_start = segment->data_segment.phys;
677  segment_end = segment->data_segment.phys + segment->data_segment.size - 1;
678  if ((target_addr >= segment_start) && (target_addr <= segment_end)) {
679  /* Found the target address */
680  offset = target_addr - segment_start;
681  vaddr = segment->data_segment.virt + offset;
682  }
683 
684  if (rdisc->dif_separate) {
685  segment_start = segment->dif_segment.phys;
686  segment_end = segment->data_segment.phys + segment->dif_segment.size - 1;
687  if ((target_addr >= segment_start) && (target_addr <= segment_end)) {
688  /* Found the target address */
689  offset = target_addr - segment_start;
690  vaddr = segment->dif_segment.virt + offset;
691  }
692  }
693 
694  if (vaddr != NULL) {
695  break;
696  }
697 
698  }
699 
700  if (vaddr != NULL) {
701  break;
702  }
703 
704 
705  }
706 
707  return vaddr;
708 }
709 #endif
710 
711 
712 static int32_t
713 ocs_mgmt_firmware_reset(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length)
714 {
715  int rc = 0;
716  uint8_t bus, dev, func;
717  int index;
718  ocs_t *other_ocs;
719 
720  ocs_log_debug(ocs, "Resetting port\n");
721  if (ocs_hal_reset(&ocs->hal, OCS_HAL_RESET_FIRMWARE)) {
722  ocs_log_test(ocs, "failed to reset port\n");
723  rc = -1;
724  } else {
725  ocs_log_debug(ocs, "successfully reset port\n");
726 
727 
728  /* now flag all functions on the same device as this port as uninitialized */
729  ocs_get_bus_dev_func(ocs, &bus, &dev, &func);
730 
731  index = 0;
732 
733  while ((other_ocs = ocs_get_instance(index++)) != NULL) {
734  uint8_t other_bus, other_dev, other_func;
735 
736  ocs_get_bus_dev_func(other_ocs, &other_bus, &other_dev, &other_func);
737 
738  if ((bus == other_bus) && (dev == other_dev)) {
739  ocs_iscsi_uninitialize(&other_ocs->iscsi);
740  }
741  }
742  }
743 
744  return rc;
745 }
746 
747 
748 #define FW_WRITE_BUFSIZE 64*1024
749 
750 typedef struct ocs_mgmt_fw_write_result {
751  ocs_sem_t semaphore;
752  int32_t status;
753  uint32_t actual_xfer;
755 
756 
757 static int32_t
758 ocs_mgmt_firmware_write(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length)
759 {
760  int rc = 0;
761  uint32_t bytes_left;
762  uint32_t xfer_size;
763  uint32_t offset;
764  uint8_t *userp;
765  ocs_dma_t dma;
766  int last = 0;
768 
769  ocs_sem_init(&(result.semaphore), 0, "fw_write");
770 
771  bytes_left = buf_len;
772  offset = 0;
773  userp = (uint8_t *)buf;
774 
775  if (ocs_dma_alloc(ocs, &dma, FW_WRITE_BUFSIZE, 4096)) {
776  ocs_log_err(ocs, "ocs_mgmt_firmware_write: malloc failed");
777  return -ENOMEM;
778  }
779 
780  while (bytes_left > 0) {
781  if (bytes_left > FW_WRITE_BUFSIZE) {
782  xfer_size = FW_WRITE_BUFSIZE;
783  } else {
784  xfer_size = bytes_left;
785  }
786 
787  // Copy xfer_size bytes from user space to kernel buffer
788  if (ocs_copy_from_user(dma.virt, userp, xfer_size)) {
789  rc = -EFAULT;
790  break;
791  }
792 
793  // See if this is the last block
794  if (bytes_left == xfer_size) {
795  last = 1;
796  }
797 
798  // Send the HAL command
799  ocs_hal_firmware_write(&ocs->hal, &dma, xfer_size, offset, last, ocs_mgmt_fw_write_cb, &result);
800 
801  // Wait for semaphore to be signaled when the command completes
802  // TODO: Should there be a timeout on this? If so, how long?
803  if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
804  // Undefined failure
805  ocs_log_test(ocs, "ocs_sem_p failed\n");
806  rc = -ENXIO;
807  break;
808  }
809 
810  if (result.actual_xfer == 0) {
811  ocs_log_test(ocs, "actual_write_length is %d\n", result.actual_xfer);
812  rc = -EFAULT;
813  break;
814  }
815 
816  // Check status
817  if (result.status != 0) {
818  ocs_log_test(ocs, "write returned status %d\n", result.status);
819  rc = -EFAULT;
820  break;
821  }
822 
823  bytes_left -= result.actual_xfer;
824  offset += result.actual_xfer;
825  userp += result.actual_xfer;
826  }
827 
828  ocs_dma_free(ocs, &dma);
829  return rc;
830 }
831 
832 
833 static void
834 ocs_mgmt_fw_write_cb(int32_t status, uint32_t actual_write_length, void *arg)
835 {
836  ocs_mgmt_fw_write_result_t *result = arg;
837 
838  result->status = status;
839  result->actual_xfer = actual_write_length;
840 
841  ocs_sem_v(&(result->semaphore));
842 }
843 
844 typedef struct ocs_mgmt_get_profile_list_result {
845  ocs_sem_t semaphore;
846  int32_t status;
849 
850 static void
852  int32_t status,
853  uint32_t ext_status,
854  void *params)
855 {
856  ocs_mgmt_get_profile_list_result_t *result = ul_arg;
858 
859  result->status = status;
860  result->list = list;
861 
862  ocs_sem_v(&(result->semaphore));
863 }
864 
865 /**
866  * @brief Get list of profiles
867  * @par Description
868  * This is a management action handler to get the list of
869  * profiles supported by the SLI port. Although the spec says
870  * that all SLI platforms support this, only Skyhawk actually
871  * has a useful implementation.
872  *
873  * @param ocs Pointer to the ocs structure.
874  * @param name Name of the action being performed.
875  * @param textbuf The textbuf to which the result is written.
876  *
877  * @return none
878  */
879 static void
880 get_profile_list(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
881 {
883 
884  ocs_sem_init(&(result.semaphore), 0, "get_profile_list");
885 
887  if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
888  // Undefined failure
889  ocs_log_test(ocs, "ocs_sem_p failed\n");
890  }
891  if (result.status == 0) {
892  // Success.
893 #define MAX_LINE_SIZE 520
894 #define BUFFER_SIZE MAX_LINE_SIZE*40
895  char *result_buf;
896  char result_line[MAX_LINE_SIZE];
897  uint32_t bytes_left;
898  uint32_t i;
899 
900  result_buf = ocs_malloc(ocs, BUFFER_SIZE, OCS_M_ZERO);
901  bytes_left = BUFFER_SIZE;
902 
903  for (i=0; i<result.list->num_descriptors; i++) {
904  sprintf(result_line, "0x%02x:%s\n", result.list->descriptors[i].profile_id,
906  if (strlen(result_line) < bytes_left) {
907  strcat(result_buf, result_line);
908  bytes_left -= strlen(result_line);
909  }
910  }
911 
912  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "profile_list", result_buf);
913 
914  ocs_free(ocs, result_buf, BUFFER_SIZE);
915  ocs_free(ocs, result.list, sizeof(ocs_hal_profile_list_t));
916  } else {
917  ocs_log_test(ocs, "getting profile list status 0x%x\n", result.status);
918  }
919  }
920 }
921 
922 typedef struct ocs_mgmt_get_active_profile_result {
923  ocs_sem_t semaphore;
924  int32_t status;
927 
928 static void
930  int32_t status,
931  uint32_t ext_status,
932  void * params)
933 {
934  ocs_mgmt_get_active_profile_result_t *result = ul_arg;
935  uint32_t *profile_id;
936 
937  profile_id = (uint32_t *)params;
938 
939  result->status = status;
940  result->active_profile_id = *profile_id;
941 
942  ocs_sem_v(&(result->semaphore));
943 }
944 
945 #define MAX_PROFILE_LENGTH 5
946 
947 /**
948  * @brief Get active profile
949  * @par Description
950  * This is a management action handler to get the currently
951  * active profile for an SLI port. Although the spec says that
952  * all SLI platforms support this, only Skyhawk actually has a
953  * useful implementation.
954  *
955  * @param ocs Pointer to the ocs structure.
956  * @param name Name of the action being performed.
957  * @param textbuf The textbuf to which the result is written.
958  *
959  * @return Returns 0 on success, non-zero on failure.
960  */
961 static void
962 get_active_profile(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
963 {
964  char result_string[MAX_PROFILE_LENGTH];
966 
967  ocs_sem_init(&(result.semaphore), 0, "get_active_profile");
968 
970  if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
971  // Undefined failure
972  ocs_log_test(ocs, "ocs_sem_p failed\n");
973  }
974  if (result.status == 0) {
975  // Success.
976  sprintf(result_string, "0x%02x", result.active_profile_id);
977  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "active_profile", result_string);
978  } else {
979  ocs_log_test(ocs, "getting active profile status 0x%x\n", result.status);
980  }
981  }
982 }
983 
984 typedef struct ocs_mgmt_set_active_profile_result {
985  ocs_sem_t semaphore;
986  int32_t status;
988 
989 
990 static void
992  int32_t status,
993  uint32_t ext_status,
994  void * params)
995 {
996  ocs_mgmt_get_profile_list_result_t *result = ul_arg;
997 
998  result->status = status;
999 
1000  ocs_sem_v(&(result->semaphore));
1001 }
1002 
1003 /**
1004  * @brief Set active profile
1005  * @par Description
1006  * This is a management action handler to set the currently
1007  * active profile for an SLI port. Although the spec says that
1008  * all SLI platforms support this, only Skyhawk actually has a
1009  * useful implementation.
1010  *
1011  * @param ocs Pointer to the ocs structure.
1012  * @param name Name of the action being performed.
1013  * @param value New value to set the profile to.
1014  *
1015  * @return Returns 0 on success, non-zero on failure.
1016  */
1017 static int32_t
1018 set_active_profile(ocs_t *ocs, char *name, char *value)
1019 {
1021  int32_t rc = 0;
1022  int32_t new_profile;
1023 
1024  new_profile = ocs_strtoul(value, NULL, 0);
1025 
1026  ocs_sem_init(&(result.semaphore), 0, "set_active_profile");
1027 
1028  rc = ocs_hal_set_active_profile(&ocs->hal, ocs_mgmt_set_active_profile_cb, new_profile, &result);
1029  if (rc == OCS_HAL_RTN_SUCCESS) {
1030  if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
1031  // Undefined failure
1032  ocs_log_test(ocs, "ocs_sem_p failed\n");
1033  rc = -ENXIO;
1034  } else {
1035  if (result.status == 0) {
1036  // Success.
1037  rc = 0;
1038  } else {
1039  rc = -1;
1040  ocs_log_test(ocs, "setting active profile status 0x%x\n", result.status);
1041  }
1042  }
1043  }
1044 
1045  return rc;
1046 }
1047 
1048 typedef struct ocs_mgmt_get_port_protocol_result {
1049  ocs_sem_t semaphore;
1050  int32_t status;
1053 
1054 static void
1056  int32_t status,
1057  uint32_t ext_status,
1058  void * params)
1059 {
1060  ocs_mgmt_get_port_protocol_result_t *result = ul_arg;
1061  uint32_t *port_protocol;
1062 
1063  port_protocol = (uint32_t *)params;
1064 
1065  result->status = status;
1066  result->port_protocol = *port_protocol;
1067 
1068  ocs_sem_v(&(result->semaphore));
1069 }
1070 
1071 static void
1072 get_port_protocol(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1073 {
1075  uint8_t bus;
1076  uint8_t dev;
1077  uint8_t func;
1078 
1079  ocs_get_bus_dev_func(ocs, &bus, &dev, &func);
1080 
1081  ocs_sem_init(&(result.semaphore), 0, "get_port_protocol");
1082 
1084  if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
1085  // Undefined failure
1086  ocs_log_test(ocs, "ocs_sem_p failed\n");
1087  }
1088  if (result.status == 0) {
1089  switch (result.port_protocol) {
1091  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "port_protocol", "iSCSI");
1092  break;
1094  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "port_protocol", "FCoE");
1095  break;
1097  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "port_protocol", "FC");
1098  break;
1100  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "port_protocol", "Other");
1101  break;
1103  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "port_protocol", "Unknown");
1104  break;
1105  }
1106  } else {
1107  ocs_log_test(ocs, "getting port profile status 0x%x\n",
1108  result.status);
1109  }
1110  }
1111 }
1112 
1113 typedef struct ocs_mgmt_set_port_protocol_result {
1114  ocs_sem_t semaphore;
1115  int32_t status;
1117 
1118 
1119 static void
1121  int32_t status,
1122  uint32_t ext_status,
1123  void * params)
1124 {
1125  ocs_mgmt_set_port_protocol_result_t *result = ul_arg;
1126 
1127  result->status = status;
1128 
1129  ocs_sem_v(&(result->semaphore));
1130 }
1131 
1132 /**
1133  * @brief Set port profile
1134  * @par Description
1135  * This is a management action handler to set the current
1136  * port protocol. Input value should be one of iSCSI,
1137  * FC, or FCoE.
1138  *
1139  * @param ocs Pointer to the ocs structure.
1140  * @param name Name of the action being performed.
1141  * @param value The value to be assigned
1142  *
1143  * @return Returns 0 on success, non-zero on failure.
1144  */
1145 static int32_t
1146 set_port_protocol(ocs_t *ocs, char *name, char *value)
1147 {
1149  int32_t rc = 0;
1150  ocs_hal_port_protocol_e new_protocol;
1151  uint8_t bus;
1152  uint8_t dev;
1153  uint8_t func;
1154 
1155  ocs_get_bus_dev_func(ocs, &bus, &dev, &func);
1156 
1157  ocs_sem_init(&(result.semaphore), 0, "set_port_protocol");
1158 
1159  if (ocs_strcasecmp(value, "iscsi") == 0) {
1160  new_protocol = OCS_HAL_PORT_PROTOCOL_ISCSI;
1161  } else if (ocs_strcasecmp(value, "fc") == 0) {
1162  new_protocol = OCS_HAL_PORT_PROTOCOL_FC;
1163  } else if (ocs_strcasecmp(value, "fcoe") == 0) {
1164  new_protocol = OCS_HAL_PORT_PROTOCOL_FCOE;
1165  } else {
1166  return -1;
1167  }
1168 
1169  rc = ocs_hal_set_port_protocol(&ocs->hal, func, new_protocol, ocs_mgmt_set_port_protocol_cb, &result);
1170  if (rc == OCS_HAL_RTN_SUCCESS) {
1171  if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
1172  // Undefined failure
1173  ocs_log_test(ocs, "ocs_sem_p failed\n");
1174  rc = -ENXIO;
1175  } else {
1176  if (result.status == 0) {
1177  // Success.
1178  rc = 0;
1179  } else {
1180  rc = -1;
1181  ocs_log_test(ocs, "setting active profile status 0x%x\n", result.status);
1182  }
1183  }
1184  }
1185 
1186  return rc;
1187 }
1188 
1189 static void
1190 get_jumbo_frames(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1191 {
1192  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "jumbo_frames", ocs->enable_jumbo_frame);
1193 }
1194 
1195 static int32_t
1196 set_jumbo_frames(ocs_t *ocs, char *name, char *value)
1197 {
1198  int32_t result;
1199 
1200  if (ocs_strcasecmp(value, "false") == 0) {
1201  ocs->enable_jumbo_frame = FALSE;
1202  result = ocs_iscsi_mtu_set(ocs, ocs->enable_jumbo_frame);
1203  } else if (ocs_strcasecmp(value, "true") == 0) {
1204  ocs->enable_jumbo_frame = TRUE;
1205  result = ocs_iscsi_mtu_set(ocs, ocs->enable_jumbo_frame);
1206  } else {
1207  ocs_log_test(ocs, "Rejecting invalid jumbo_frames value '%s'\n", value);
1208  result = -1;
1209  }
1210 
1211  return result;
1212 }
1213 
1214 static void
1215 get_data_digest(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1216 {
1217  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "data_digest", ocs->enable_data_digest);
1218 }
1219 
1220 static int32_t
1221 set_data_digest(ocs_t *ocs, char *name, char *value)
1222 {
1223  int32_t result;
1224 
1225  if (ocs_strcasecmp(value, "false") == 0) {
1226  ocs->enable_data_digest = FALSE;
1227  result = 0;
1228  } else if (ocs_strcasecmp(value, "true") == 0) {
1229  ocs->enable_data_digest = TRUE;
1230  result = 0;
1231  } else {
1232  ocs_log_test(ocs, "Rejecting invalid data_digest value '%s'\n", value);
1233  result = -1;
1234  }
1235 
1236  return result;
1237 }
1238 
1239 static void
1240 get_header_digest(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1241 {
1242  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "header_digest", ocs->enable_hdr_digest);
1243 }
1244 
1245 static int32_t
1246 set_header_digest(ocs_t *ocs, char *name, char *value)
1247 {
1248  int32_t result;
1249 
1250  if (ocs_strcasecmp(value, "false") == 0) {
1251  ocs->enable_hdr_digest = FALSE;
1252  result = 0;
1253  } else if (ocs_strcasecmp(value, "true") == 0) {
1254  ocs->enable_hdr_digest = TRUE;
1255  result = 0;
1256  } else {
1257  ocs_log_test(ocs, "Rejecting invalid header_digest value '%s'\n", value);
1258  result = -1;
1259  }
1260 
1261  return result;
1262 }
1263 
1264 static void
1265 get_tcp_window_size(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1266 {
1267  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "tcp_window_size", "%d", ocs->tcp_window_size);
1268 }
1269 
1270 static int32_t
1271 set_tcp_window_size(ocs_t *ocs, char *name, char *value)
1272 {
1273  int32_t window_size;
1274 
1275  window_size = ocs_strtoul(value, NULL, 0);
1276  if ((window_size < 1) || (window_size > 65536)) {
1277  ocs_log_test(ocs, "Rejecting invalid window_size %d\n", window_size);
1278  return -1;
1279  }
1280 
1281  ocs->tcp_window_size = window_size;
1282 
1283  return 0;
1284 }
1285 
1286 static void
1287 get_tcp_window_scale(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1288 {
1289  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "tcp_window_scale", "%d", ocs->tcp_window_scale);
1290 }
1291 
1292 static int32_t
1293 set_tcp_window_scale(ocs_t *ocs, char *name, char *value)
1294 {
1295  int32_t window_scale;
1296 
1297  window_scale = ocs_strtoul(value, NULL, 0);
1298  if ((window_scale < 0) || (window_scale > 14)) {
1299  ocs_log_test(ocs, "Rejecting invalid window_scale %d\n", window_scale);
1300  return -1;
1301  }
1302 
1303  ocs->tcp_window_scale = window_scale;
1304 
1305  return 0;
1306 }
1307 
1308 static void
1309 get_max_cxns_per_session(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1310 {
1311  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "max_cxns_per_session", "%d", ocs->max_cxns_per_session);
1312 }
1313 
1314 static int32_t
1315 set_max_cxns_per_session(ocs_t *ocs, char *name, char *value)
1316 {
1317  int32_t max_cxns;
1318 
1319  max_cxns = ocs_strtoul(value, NULL, 0);
1320  if (max_cxns <= 0) {
1321  ocs_log_test(ocs, "Rejecting invalid max_cxns_per_session %d\n", max_cxns);
1322  return -1;
1323  }
1324 
1325  ocs->max_cxns_per_session = max_cxns;
1326 
1327  return 0;
1328 }
1329 
1330 static void
1331 get_gateway(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1332 {
1333  iscsi_api_t *iscsi_api = ocs->iscsi_api;
1334  char ip_str[40];
1335 
1336  format_ip_address(iscsi_api->gateway.ip_type,
1337  iscsi_api->gateway.ip_address, ip_str, sizeof(ip_str));
1338 
1339  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "gateway", ip_str);
1340 }
1341 
1342 static int32_t
1343 set_gateway(ocs_t *ocs, char *name, char *value)
1344 {
1345  int rc = 0;
1346  ocs_ip_address_t gateway;
1347  iscsi_api_t *iscsi_api = ocs->iscsi_api;
1348 
1349  if (ocs_iscsi_inet_pton4(value, &gateway) == 0) {
1350  /* Success - do nothing */
1351  } else if (ocs_iscsi_inet_pton6(value, &gateway) == 0) {
1352  /* Success - do nothing */
1353  } else {
1354  /* Failed, invalid IP address */
1355  ocs_log_test(ocs, "Rejecting invalid gateway IP address '%s'\n", value);
1356  rc = -1;
1357  }
1358 
1359  if (rc == 0) {
1360  iscsi_api->set_gateway = TRUE;
1361  iscsi_api->gateway = gateway;
1362 
1363  rc = ocs_iscsi_gateway_set(ocs, &iscsi_api->gateway);
1364  if (rc == 0) {
1365  char ip_str[40];
1366  format_ip_address(iscsi_api->gateway.ip_type,
1367  iscsi_api->gateway.ip_address,
1368  ip_str, sizeof(ip_str));
1369  ocs_log_debug(ocs, "Added Gateway address %s\n", ip_str);
1370  } else {
1371  ocs_log_test(ocs, "setting gateway returned status %d\n", rc);
1372  }
1373  }
1374 
1375  return rc;
1376 
1377 }
1378 
1379 static void
1380 get_require_chap(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1381 {
1382  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "require_chap", ocs->require_chap);
1383 }
1384 
1385 static int
1386 set_require_chap(ocs_t *ocs, char *name, char *value)
1387 {
1388  int result;
1389 
1390  if (ocs_strcasecmp(value, "false") == 0) {
1391  ocs->require_chap = FALSE;
1392  result = 0;
1393  } else if (ocs_strcasecmp(value, "true") == 0) {
1394  ocs->require_chap = TRUE;
1395  result = 0;
1396  } else {
1397  result = -1;
1398  }
1399 
1400  return result;
1401 }
1402 
1403 /**
1404  * @brief HAL link config enum to mgmt string value mapping.
1405  *
1406  * This structure provides a mapping from the ocs_hal_linkcfg_e
1407  * enum (enum exposed for the OCS_HAL_PORT_SET_LINK_CONFIG port
1408  * control) to the mgmt string that is passed in by the mgmt application
1409  * (elxsdkutil).
1410  */
1411 typedef struct ocs_mgmt_linkcfg_map_s {
1413  const char *mgmt_str;
1415 
1424 
1425 /**
1426  * @brief Get the HAL linkcfg enum from the mgmt config string.
1427  *
1428  * @param mgmt_str mgmt string value.
1429  *
1430  * @return Returns the HAL linkcfg enum corresponding to clp_str.
1431  */
1432 static ocs_hal_linkcfg_e
1433 ocs_hal_linkcfg_from_mgmt(const char *mgmt_str)
1434 {
1435  uint32_t i;
1436  for (i = 0; i < ARRAY_SIZE(mgmt_linkcfg_map); i++) {
1437  if (ocs_strncmp(mgmt_linkcfg_map[i].mgmt_str,
1438  mgmt_str, ocs_strlen(mgmt_str)) == 0) {
1439  return mgmt_linkcfg_map[i].linkcfg;
1440  }
1441  }
1442  return OCS_HAL_LINKCFG_NA;
1443 }
1444 
1445 /**
1446  * @brief Get the mgmt string value from the HAL linkcfg enum.
1447  *
1448  * @param linkcfg HAL linkcfg enum.
1449  *
1450  * @return Returns the mgmt string value corresponding to the given HAL linkcfg.
1451  */
1452 static const char *
1454 {
1455  uint32_t i;
1456  for (i = 0; i < ARRAY_SIZE(mgmt_linkcfg_map); i++) {
1457  if (mgmt_linkcfg_map[i].linkcfg == linkcfg) {
1458  return mgmt_linkcfg_map[i].mgmt_str;
1459  }
1460  }
1462 }
1463 
1464 /**
1465  * @brief Link configuration callback argument
1466  */
1467 typedef struct ocs_mgmt_linkcfg_arg_s {
1468  ocs_sem_t semaphore;
1469  int32_t status;
1472 
1473 
1474 typedef struct ocs_mgmt_get_linkcfg_result {
1475  ocs_sem_t semaphore;
1476  int32_t status;
1479 
1480 static void
1482  int32_t status,
1483  uint32_t ext_status,
1484  void * params)
1485 {
1486  ocs_mgmt_get_linkcfg_result_t *result = ul_arg;
1487 
1488  result->status = status;
1489  result->config_id = (ocs_hal_linkcfg_e)params;
1490 
1491  ocs_sem_v(&(result->semaphore));
1492 }
1493 
1494 /**
1495  * @brief Get current link configuration
1496  * @par Description
1497  * This is a management action handler to get the current
1498  * slink configuration for an SLI port. Although the spec says that
1499  * all SLI platforms support this, only Skyhawk actually has a
1500  * useful implementation.
1501  *
1502  * @param ocs Pointer to the ocs structure.
1503  * @param name Name of the action being performed.
1504  * @param textbuf The textbuf to which the result is written.
1505  *
1506  * @return Returns 0 on success, non-zero on failure.
1507  */
1508 static void
1509 get_linkcfg(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1510 {
1511  const char *result_string;
1512  ocs_hal_linkcfg_e linkcfg;
1514 
1515  ocs_sem_init(&(result.semaphore), 0, "get_linkcfg");
1516 
1518  if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
1519  // Undefined failure
1520  ocs_log_test(ocs, "ocs_sem_p failed\n");
1521  }
1522  if (result.status == 0) {
1523  // Success.
1524  linkcfg = result.config_id;
1525  result_string = ocs_mgmt_from_hal_linkcfg(linkcfg);
1526  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "linkcfg", result_string);
1527  } else {
1528  ocs_log_test(ocs, "getting linkcfg status 0x%x\n", result.status);
1529  }
1530  }
1531 }
1532 
1533 typedef struct ocs_mgmt_set_linkcfg_result {
1534  ocs_sem_t semaphore;
1535  int32_t status;
1537 
1538 
1539 static void
1541  int32_t status,
1542  uint32_t ext_status,
1543  void * params)
1544 {
1545  ocs_mgmt_set_linkcfg_result_t *result = ul_arg;
1546 
1547  result->status = status;
1548 
1549  ocs_sem_v(&(result->semaphore));
1550 }
1551 
1552 /**
1553  * @brief Set linkcfg config value.
1554  *
1555  * @param ocs Pointer to the ocs structure.
1556  * @param name Not used.
1557  * @param value Value to which the linkcfg is set.
1558  *
1559  * @return Returns 0 on success.
1560  */
1561 static int
1562 set_linkcfg(ocs_t *ocs, char *name, char *value)
1563 {
1565  int32_t rc = 0;
1566  ocs_hal_linkcfg_e new_config;
1567 
1568  new_config = ocs_hal_linkcfg_from_mgmt(value);
1569  if (new_config == OCS_HAL_LINKCFG_NA) {
1570  ocs_log_test(ocs, "undefined linkcfg type %s\n", value);
1571  return -1;
1572  }
1573 
1574  ocs_sem_init(&(result.semaphore), 0, "set_linkcfg");
1575 
1576  rc = ocs_hal_set_linkcfg(&ocs->hal, ocs_mgmt_set_linkcfg_cb, new_config, &result);
1577  if (rc == OCS_HAL_RTN_SUCCESS) {
1578  if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
1579  // Undefined failure
1580  ocs_log_test(ocs, "ocs_sem_p failed\n");
1581  rc = -ENXIO;
1582  } else {
1583  if (result.status == 0) {
1584  // Success.
1585  rc = 0;
1586  } else {
1587  rc = -1;
1588  ocs_log_test(ocs, "setting link configuration status 0x%x\n", result.status);
1589  }
1590  }
1591  }
1592 
1593  return rc;
1594 }
1595 
1596 static int32_t
1597 ocs_mgmt_listen_start(ocs_t *ocs, char *name, void *arg_in,
1598  uint32_t arg_in_length, void *arg_out,
1599  uint32_t arg_out_length)
1600 {
1601  int rc = -1;
1602  ocs_ip_address_t ip;
1603  ocs_iscsi_t *iscsi = &ocs->iscsi;
1604  uint32_t i;
1605  int ip_found = FALSE;
1606  char cmd_params[OCS_ISCSI_MGMT_CMD_PARAMS_LEN];
1607  char *ip_str;
1608 
1609  if (!ocs->enable_tgt) {
1610  /* Can't listen if we're not a target */
1611  ocs_log_info(ocs, "Request not applicable in non-target mode\n");
1612  return rc;
1613  }
1614 
1615  if (arg_in == NULL || !arg_in_length ||
1616  (arg_in_length > OCS_ISCSI_MGMT_CMD_PARAMS_LEN)) {
1617  ocs_log_err(ocs, "Invalid arguments list\n");
1618  return rc;
1619  }
1620 
1621  ocs_memset(cmd_params, 0, OCS_ISCSI_MGMT_CMD_PARAMS_LEN);
1622  if (ocs_copy_from_user(cmd_params, arg_in, arg_in_length)) {
1623  ocs_log_err(ocs, "Copy from user failed\n");
1624  return rc;
1625  }
1626 
1627  ip_str = cmd_params;
1628 
1629  if (ocs_iscsi_inet_pton4(ip_str, &ip) == 0) {
1630  /* Success - do nothing */
1631  } else if (ocs_iscsi_inet_pton6(ip_str, &ip) == 0) {
1632  /* Success - do nothing */
1633  } else {
1634  /* Failed, invalid IP address */
1635  ocs_log_test(ocs, "Rejecting invalid listen IP address '%s'\n", ip_str);
1636  rc = -1;
1637  }
1638 
1639  for (i=0; i<iscsi->num_ips; i++) {
1640  if ((iscsi->ip_info[i].ip.ip_type == ip.ip_type) &&
1641  (ocs_memcmp(iscsi->ip_info[i].ip.ip_address, ip.ip_address,
1642  sizeof(ip.ip_address)) == 0)) {
1643 
1644  ip_found = TRUE;
1645  if (iscsi->ip_info[i].listening) {
1646  ocs_log_test(ocs, "already listening on IP %s\n", ip_str);
1647  rc = 0;
1648  } else {
1649  iscsi->ip_info[i].tcp_port = OCS_ISCSI_TCP_PORT;
1650 
1651  rc = ocs_iscsi_listen_start(ocs,
1652  &iscsi->ip_info[i].ip,
1653  iscsi->ip_info[i].tcp_port);
1654  if (rc == 0) {
1655  ocs_log_debug(ocs, "Listen server started on %s\n",
1656  ip_str);
1657  iscsi->ip_info[i].listening = TRUE;
1658  } else {
1659  ocs_log_test(ocs, "listen returned status %d on %s\n",
1660  rc, ip_str);
1661  }
1662 
1663  break;
1664  }
1665  }
1666  }
1667 
1668  if (!ip_found) {
1669  ocs_log_test(ocs, "Can't listen on IP %s, IP not found\n", ip_str);
1670  }
1671 
1672  return rc;
1673 
1674 }
1675 
1676 static int32_t
1677 ocs_mgmt_listen_stop(ocs_t *ocs, char *name,
1678  void *arg_in, uint32_t arg_in_length,
1679  void *arg_out, uint32_t arg_out_length)
1680 {
1681  int rc = -EFAULT;
1682  ocs_ip_address_t ip;
1683  ocs_iscsi_t *iscsi = &ocs->iscsi;
1684  uint32_t i;
1685  int ip_found = FALSE;
1686  char cmd_params[OCS_ISCSI_MGMT_CMD_PARAMS_LEN];
1687  char *ip_str;
1688 
1689  if (!ocs->enable_tgt) {
1690  /* Can't listen if we're not a target */
1691  ocs_log_info(ocs, "Request not applicable in non-target mode\n");
1692  return rc;
1693  }
1694 
1695  if (arg_in == NULL || !arg_in_length ||
1696  (arg_in_length > OCS_ISCSI_MGMT_CMD_PARAMS_LEN)) {
1697  ocs_log_err(ocs, "Invalid arguments list\n");
1698  return rc;
1699  }
1700 
1701  ocs_memset(cmd_params, 0, OCS_ISCSI_MGMT_CMD_PARAMS_LEN);
1702  if (ocs_copy_from_user(cmd_params, arg_in, arg_in_length)) {
1703  ocs_log_err(ocs, "Copy from user failed\n");
1704  return rc;
1705  }
1706 
1707  ip_str = cmd_params;
1708 
1709  if (ocs_iscsi_inet_pton4(ip_str, &ip) == 0) {
1710  /* Success - do nothing */
1711  } else if (ocs_iscsi_inet_pton6(ip_str, &ip) == 0) {
1712  /* Success - do nothing */
1713  } else {
1714  /* Failed, invalid IP address */
1715  ocs_log_test(ocs, "Rejecting invalid listen IP address '%s'\n", ip_str);
1716  rc = -1;
1717  }
1718 
1719  for (i=0; i<iscsi->num_ips; i++) {
1720  if ((iscsi->ip_info[i].ip.ip_type == ip.ip_type) &&
1721  (ocs_memcmp(iscsi->ip_info[i].ip.ip_address, ip.ip_address, sizeof(ip.ip_address)) == 0)) {
1722  ip_found = TRUE;
1723 
1724  if (iscsi->ip_info[i].listening) {
1725  if (ocs_iscsi_listen_stop(ocs,
1726  &iscsi->ip_info[i].ip,
1727  iscsi->ip_info[i].tcp_port)) {
1728  ocs_log_test(ocs, "failed Stopping Listen on IP %s\n",
1729  ip_str);
1730  rc = -1;
1731  } else {
1732  ocs_log_debug(ocs, "Stopped Listening on IP %s\n", ip_str);
1733  iscsi->ip_info[i].listening = FALSE;
1734  rc = 0;
1735  }
1736  } else {
1737  ocs_log_test(ocs, "Not listening on IP %s\n", ip_str);
1738  rc = 0;
1739  }
1740  break;
1741  }
1742  }
1743 
1744  if (!ip_found) {
1745  ocs_log_test(ocs, "IP %s not found\n", ip_str);
1746  }
1747 
1748  return rc;
1749 }
1750 
1751 
1752 /*
1753  * Adds an Ip address to an adapter.
1754  */
1755 static int32_t
1756 ocs_mgmt_ip_add(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length,
1757  void *arg_out, uint32_t arg_out_length)
1758 {
1759  int rc = -EFAULT;
1760  ocs_hal_portal_t portal;
1761  ocs_ip_address_t ip;
1762  ocs_ip_address_t subnet;
1764  char local_ip[64];
1765  char local_subnet[64];
1766  char cmd_params[OCS_ISCSI_MGMT_CMD_PARAMS_LEN];
1767  char *buf;
1768  char vlan_id_str[32];
1769  uint32_t vlan_id;
1770  char *slash;
1771  uint32_t num_chars;
1772  ocs_iscsi_t *iscsi = &ocs->iscsi;
1773 
1774  /* Make sure there is room before we do anything. */
1775  if (iscsi->num_ips >= OCS_MAX_IP) {
1776  ocs_log_test(ocs, "Internal error - Max IPs already configured\n");
1777  return rc;
1778  }
1779 
1780  if (arg_in == NULL || !arg_in_length ||
1781  (arg_in_length > OCS_ISCSI_MGMT_CMD_PARAMS_LEN)) {
1782  ocs_log_err(ocs, "Invalid IP add input arguments\n");
1783  return rc;
1784  }
1785 
1786  ocs_memset(cmd_params, 0, OCS_ISCSI_MGMT_CMD_PARAMS_LEN);
1787  if (ocs_copy_from_user(cmd_params, arg_in, arg_in_length)) {
1788  ocs_log_err(ocs, "Copy from user buffer failed\n");
1789  return rc;
1790  }
1791 
1792  buf = cmd_params;
1793 
1794  /* Find the '/' character that separates the IP address and subnet */
1795  slash = ocs_strchr(buf, '/');
1796  if (slash == NULL) {
1797  ocs_log_test(ocs, "Internal error - cannot split IP address and subnet\n");
1798  return rc;
1799  }
1800 
1801  num_chars = slash - (char*)buf;
1802  ocs_strncpy(local_ip, (char*)buf, num_chars);
1803  local_ip[num_chars] = '\0';
1804 
1805  ++slash;
1806  buf = slash;
1807  slash = ocs_strchr(buf, '/');
1808  if (slash == NULL) {
1809  ocs_log_test(ocs, "Internal error - cannot split subnet\n");
1810  return rc;
1811  }
1812 
1813  num_chars = slash - (char *)buf;
1814  ocs_strncpy(local_subnet, (char *)buf, num_chars);
1815  local_subnet[num_chars] = '\0';
1816 
1817  ++slash;
1818  num_chars = arg_in_length - (slash - cmd_params);
1819  ocs_strncpy(vlan_id_str, (char *)slash, num_chars);
1820  vlan_id_str[num_chars] = '\0';
1821  vlan_id = ocs_atoi(vlan_id_str);
1822 
1823  if (vlan_id) {
1824  rc = ocs_iscsi_find_portal_from_vlan(ocs, vlan_id, &portal);
1825  if (rc) {
1826  ocs_log_err(ocs, "iSCSI portal is not exists for vlan_id %d\n",
1827  vlan_id);
1828  return rc;
1829  }
1830  } else {
1831  portal = ocs_iscsi_portal_get_default(ocs);
1832  }
1833 
1834  rc = -EFAULT;
1835  if (ocs_iscsi_inet_pton4(local_ip, &ip) == 0) {
1836  /* Convert the subnet */
1837  if (ocs_iscsi_inet_pton4(local_subnet, &subnet) == 0) {
1838  ocs_iscsi_ipsub_combine(&ipsub, &ip, &subnet);
1839  } else {
1840  ocs_log_test(ocs, "IPv4 address supplied, but subnet is not an valid IPv4 subnet\n");
1841  return rc;
1842  }
1843  } else if (ocs_iscsi_inet_pton6(local_ip, &ip) == 0) {
1844  if (ocs_iscsi_inet_pton6(local_subnet, &subnet) == 0) {
1845  ocs_iscsi_ipsub_combine(&ipsub, &ip, &subnet);
1846  } else {
1847  ocs_log_test(ocs, "IPv6 address supplied, but subnet is not an valid IPv6 subnet\n");
1848  return rc;
1849  }
1850  } else {
1851  ocs_log_test(ocs, "ERROR: Local address supplied is not a valid IPv4, IPv6, DHCP or AutoV6\n");
1852  return rc;
1853  }
1854 
1855  rc = ocs_iscsi_ip_address_add(ocs, portal, &ipsub);
1856  if (rc == 0) {
1857  ocs_log_debug(ocs, "Added IP address %s mask %s\n",
1858  local_ip, local_subnet);
1859  } else {
1860  ocs_log_err(ocs, "Add IP failed status %d\n", rc);
1861  rc = -EFAULT;
1862  }
1863 
1864  return rc;
1865 }
1866 
1867 /*
1868  * Check the IP address is in listening mode.
1869  */
1870 static int32_t
1872  ocs_hal_portal_t portal, ocs_ip_address_t *ip)
1873 {
1874  uint32_t i;
1875  int32_t rc = FALSE;
1876 
1877  for (i = 0; i < iscsi->num_ips; i++) {
1878  if ((iscsi->ip_info[i].portal == portal) &&
1879  (iscsi->ip_info[i].ip.ip_type == ip->ip_type) &&
1880  (ocs_memcmp(iscsi->ip_info[i].ip.ip_address, ip->ip_address,
1881  sizeof(ip->ip_address)) == 0)) {
1882  if (iscsi->ip_info[i].listening) {
1883  rc = TRUE;
1884  break;
1885  }
1886  }
1887  }
1888 
1889  return rc;
1890 }
1891 
1892 /*
1893  * Find and read subnet of corresponding ip_address
1894  */
1895 static int32_t
1897  ocs_ip_address_t *subnet,
1898  ocs_ip_address_t *ip)
1899 {
1900  int32_t rc = -EFAULT;
1901  uint32_t i;
1902  for (i = 0; i < iscsi->num_ips; i++) {
1903  if ((iscsi->ip_info[i].portal == portal) &&
1904  (iscsi->ip_info[i].ip.ip_type == ip->ip_type) &&
1905  (ocs_memcmp(iscsi->ip_info[i].ip.ip_address, ip->ip_address,
1906  sizeof(ip->ip_address)) == 0)) {
1907  ocs_memcpy(subnet, &iscsi->ip_info[i].subnet,
1908  sizeof(*subnet));
1909  rc = 0;
1910  break;
1911  }
1912  }
1913 
1914  return rc;
1915 }
1916 
1917 /*
1918  * Remove an IP address from an adapter.
1919  */
1920 static int32_t
1921 ocs_mgmt_ip_remove(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length,
1922  void *arg_out, uint32_t arg_out_length)
1923 {
1924  int rc = -EFAULT;
1925  ocs_iscsi_t *iscsi = &ocs->iscsi;
1926  ocs_hal_portal_t portal;
1927  ocs_ip_address_t ip;
1928  ocs_ip_address_t subnet;
1930  char ipaddr[64];
1931  char *slash;
1932  uint32_t num_chars;
1933  char cmd_params[OCS_ISCSI_MGMT_CMD_PARAMS_LEN];
1934  char *buf;
1935  char vlan_id_str[32];
1936  uint32_t vlan_id;
1937 
1938  if (arg_in == NULL || !arg_in_length ||
1939  (arg_in_length > OCS_ISCSI_MGMT_CMD_PARAMS_LEN)) {
1940  ocs_log_err(ocs, "Invalid IP remove args list\n");
1941  return rc;
1942  }
1943 
1944  if (iscsi->num_ips <= 0) {
1945  ocs_log_debug(ocs, "Internal error - No IPs configured\n");
1946  return rc;
1947  }
1948 
1949  ocs_memset(cmd_params, 0, OCS_ISCSI_MGMT_CMD_PARAMS_LEN);
1950  if (ocs_copy_from_user(cmd_params, arg_in, arg_in_length)) {
1951  ocs_log_err(ocs, "Copy from user buffer failed\n");
1952  return rc;
1953  }
1954 
1955  buf = cmd_params;
1956 
1957  /* Find the '/' character that separates the IP address and vlan_id */
1958  slash = ocs_strchr(buf, '/');
1959  if (slash == NULL) {
1960  ocs_log_test(ocs, "Internal error - cannot split IP address\n");
1961  return rc;
1962  }
1963 
1964  num_chars = slash - (char*)buf;
1965  ocs_strncpy(ipaddr, (char*)buf, num_chars);
1966  ipaddr[num_chars] = '\0';
1967 
1968  num_chars = arg_in_length - ((slash - (char*)buf) + 1);
1969  ocs_strncpy(vlan_id_str, slash + 1, num_chars);
1970  vlan_id_str[num_chars] = '\0';
1971  vlan_id = ocs_atoi(vlan_id_str);
1972 
1973  if (vlan_id) {
1974  rc = ocs_iscsi_find_portal_from_vlan(ocs, vlan_id, &portal);
1975  if (rc) {
1976  ocs_log_err(ocs, "iSCSI portal is not exists for vlan_id %d\n",
1977  vlan_id);
1978  return rc;
1979  }
1980  } else {
1981  portal = ocs_iscsi_portal_get_default(ocs);
1982  }
1983 
1984  rc = -EFAULT;
1985  if (ocs_iscsi_inet_pton4(ipaddr, &ip) != 0) {
1986  /* Not a valid IPV4 address */
1987  if (ocs_iscsi_inet_pton6(ipaddr, &ip) != 0) {
1988  /* Not a valid IPV6 address either */
1989  ocs_log_test(ocs, "IP address supplied is not a valid IPv4, IPv6, DHCP or AutoV6\n");
1990  return rc;
1991  }
1992  }
1993 
1994  if (ocs->enable_tgt && ocs_iscsi_is_ipaddr_listening(iscsi, portal, &ip)) {
1995  ocs_log_debug(ocs, "IP addr %s is in listening mode\n", ipaddr);
1996  return rc;
1997  }
1998 
1999  /* Remove IP doesn't have subnet input, so read subnet for the IP */
2000  ocs_memset(&subnet, 0, sizeof(subnet));
2001  if (ocs_iscsi_get_subnet_ip_address(iscsi, portal, &subnet, &ip)) {
2002  ocs_log_debug(ocs, "Subnet is not found for IP addr %s\n",
2003  (char *)arg_in);
2004  return -EFAULT;
2005  }
2006 
2007  ocs_iscsi_ipsub_combine(&ipsub, &ip, &subnet);
2008  rc = ocs_iscsi_ip_address_remove(ocs, portal, &ipsub);
2009  if (rc == 0) {
2010  ocs_log_debug(ocs, "Removed IP address %s\n", (char *)ipaddr);
2011  } else {
2012  ocs_log_test(ocs, "Remove IP failed status %d\n", rc);
2013  rc = -EFAULT;
2014  }
2015 
2016  return rc;
2017 }
2018 
2019 static int32_t
2020 ocs_iscsi_ip_get_copy_to_user(ocs_t *ocs, char *userbuff, uint32_t userbuff_len,
2021  uint32_t *bytes_copied,
2022  uint32_t num_ips, ocs_ip_address_subnet_t *ipsub)
2023 {
2024  uint32_t index;
2025  int32_t rc = 0;
2026  char ip_str[40];
2027  char subnet_str[40];
2028  uint32_t remain = userbuff_len;
2029  uint32_t len;
2030  uint32_t tot_bytes = 0;
2031  uint32_t bytes_to_copy;
2032 
2033  for (index = 0; index < num_ips; index++) {
2034  format_ip_address(ipsub[index].ip_type,
2035  ipsub[index].ip_address,
2036  ip_str, sizeof(ip_str));
2037 
2038  format_ip_address(ipsub[index].ip_type,
2039  ipsub[index].subnet,
2040  subnet_str, sizeof(subnet_str));
2041 
2042  len = ocs_strlen(ip_str);
2043  bytes_to_copy = (len > remain ? remain : len);
2044  if (ocs_copy_to_user(userbuff, ip_str, bytes_to_copy)) {
2045  rc = -EFAULT;
2046  } else {
2047  userbuff += bytes_to_copy;
2048  remain -= bytes_to_copy;
2049  tot_bytes += bytes_to_copy;
2050  }
2051 
2052  if (remain > 1) {
2053  if (ocs_copy_to_user(userbuff, " ", 1)) {
2054  rc = -EFAULT;
2055  } else {
2056  userbuff += 1;
2057  remain -= 1;
2058  tot_bytes += 1;
2059  }
2060  }
2061 
2062  len = ocs_strlen(subnet_str);
2063  bytes_to_copy = (len > remain ? remain : len);
2064  if (ocs_copy_to_user(userbuff, subnet_str, bytes_to_copy)) {
2065  rc = -EFAULT;
2066  } else {
2067  userbuff += bytes_to_copy;
2068  remain -= bytes_to_copy;
2069  tot_bytes += bytes_to_copy;
2070  }
2071 
2072  if (remain > 1) {
2073  if (ocs_copy_to_user(userbuff, "\n", 1)) {
2074  rc = -EFAULT;
2075  } else {
2076  userbuff += 1;
2077  remain -= 1;
2078  tot_bytes += 1;
2079  }
2080  }
2081  }
2082 
2083  *bytes_copied = tot_bytes;
2084  return rc;
2085 }
2086 
2087 /*
2088  * Retrieves the Ip addresses assigned to an adapter.
2089  */
2090 static int32_t
2091 ocs_mgmt_ip_get(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length,
2092  void *arg_out, uint32_t arg_out_length)
2093 {
2094  int32_t ret = -1;
2095  uint32_t userbuff_remain = 0;
2096  uint32_t bytes_copied = 0;
2097  char *userbuff;
2098  char str[64];
2099  ocs_vlan_portal_info_t *portal_info;
2100  ocs_hal_portal_t portal;
2101  ocs_ip_type_e ip_type;
2102  uint32_t num_ips = 0;
2103  ocs_ip_address_subnet_t *ipsub;
2104  iscsi_api_t *iscsi_api = ocs->iscsi_api;
2105 
2106  if (arg_in == NULL || arg_out == NULL ||
2107  (arg_in_length > sizeof(ip_type))) {
2108  ocs_log_err(ocs, "Invalid arguments list\n");
2109  return ret;
2110  }
2111 
2112  if (ocs_copy_from_user(&ip_type, arg_in, arg_in_length)) {
2113  ocs_log_err(ocs, "Copy from user failed\n");
2114  return ret;
2115  }
2116 
2117  if (ip_type == 4) {
2118  ip_type = OCS_IP_TYPE_V4;
2119  } else if (ip_type == 6) {
2120  ip_type = OCS_IP_TYPE_V6;
2121  } else {
2122  ocs_log_err(ocs, "Invalid request of IP type %d\n", ip_type);
2123  return ret;
2124  }
2125 
2126  ipsub = ocs_malloc(ocs, sizeof(ocs_ip_address_subnet_t) * OCS_MAX_IP,
2127  OCS_M_ZERO | OCS_M_NOWAIT);
2128  if (ipsub == NULL) {
2129  ocs_log_err(ocs, "Failed to allocate ipsub\n");
2130  return ret;
2131  }
2132 
2133  userbuff = (char *)arg_out;
2134  userbuff_remain = arg_out_length;
2135 
2136  /* Query and copy IP's on default interface */
2137  portal = ocs_iscsi_portal_get_default(ocs);
2138  ret = ocs_iscsi_ip_address_query(ocs, portal, ip_type,
2139  OCS_MAX_IP, &num_ips, ipsub);
2140  if (ret) {
2141  ocs_log_err(ocs, "Query IP's on default interface failed\n");
2142  goto exit_err;
2143  }
2144 
2145  if (num_ips > 0) {
2146  snprintf(str, sizeof(str), "\nDefault interface\n");
2147  if (userbuff_remain > ocs_strlen(str)) {
2148  if (ocs_copy_to_user(userbuff, str, ocs_strlen(str))) {
2149  ret = -EFAULT;
2150  goto exit_err;
2151  } else {
2152  userbuff += ocs_strlen(str);
2153  userbuff_remain -= ocs_strlen(str);
2154  }
2155  }
2156 
2157  ret = ocs_iscsi_ip_get_copy_to_user(ocs, userbuff, userbuff_remain,
2158  &bytes_copied, num_ips, ipsub);
2159  if (ret) {
2160  ocs_log_err(ocs, "Failed to copy ip addresses to user buffer\n");
2161  goto exit_err;
2162  }
2163 
2164  userbuff += bytes_copied;
2165  userbuff_remain -= bytes_copied;
2166  } else {
2167  snprintf(str, sizeof(str), "Empty\n");
2168  if (userbuff_remain > ocs_strlen(str)) {
2169  if (ocs_copy_to_user(userbuff, str, ocs_strlen(str))) {
2170  ocs_log_info(ocs, "Copy to user failed\n");
2171  ret = -EFAULT;
2172  goto exit_err;
2173  } else {
2174  userbuff += ocs_strlen(str);
2175  userbuff_remain -= ocs_strlen(str);
2176  }
2177  }
2178  }
2179 
2180  /* Query and copy IP's on additional interfaces created for VLAN */
2181  ocs_memset(ipsub, 0, sizeof(*ipsub));
2182  num_ips = 0;
2183  ocs_list_foreach(&iscsi_api->portal_list, portal_info) {
2184  snprintf(str, sizeof(str), "\nVLAN interface %d\n",
2185  portal_info->vlan_id);
2186  if (userbuff_remain > ocs_strlen(str)) {
2187  if (ocs_copy_to_user(userbuff, str, ocs_strlen(str))) {
2188  ocs_log_err(ocs, "Copy to user failed\n");
2189  ret = -EFAULT;
2190  goto exit_err;
2191  } else {
2192  userbuff += ocs_strlen(str);
2193  userbuff_remain -= ocs_strlen(str);
2194  }
2195  }
2196 
2197  ret = ocs_iscsi_ip_address_query(ocs, portal_info->iface_handle, ip_type,
2198  OCS_MAX_IP, &num_ips, ipsub);
2199  if (ret) {
2200  ocs_log_err(ocs, "Query IP's on iface handle %d failed\n",
2201  portal_info->iface_handle);
2202  goto exit_err;
2203  }
2204 
2205  if (num_ips > 0) {
2206  bytes_copied = 0;
2207  ret = ocs_iscsi_ip_get_copy_to_user(ocs, userbuff, userbuff_remain,
2208  &bytes_copied, num_ips, ipsub);
2209  if (ret < 0) {
2210  ocs_log_err(ocs, "Failed to copy ip addresses to user buffer\n");
2211  goto exit_err;
2212  }
2213 
2214  userbuff += bytes_copied;
2215  userbuff_remain -= bytes_copied;
2216  } else {
2217  snprintf(str, sizeof(str), "Empty\n");
2218  if (userbuff_remain > sizeof(str)) {
2219  if (ocs_copy_to_user(userbuff, str, ocs_strlen(str))) {
2220  ocs_log_err(ocs, "Copy to user failed\n");
2221  ret = -EFAULT;
2222  goto exit_err;
2223  } else {
2224  userbuff += ocs_strlen(str);
2225  userbuff_remain -= ocs_strlen(str);
2226  }
2227  }
2228  }
2229  }
2230 
2231  ret = -EFAULT;
2232  if (userbuff_remain > 1) {
2233  if (!ocs_copy_to_user(userbuff, "\0", 1)) {
2234  ret = 0;
2235  }
2236  }
2237 
2238 exit_err:
2239  ocs_free(ocs, ipsub, sizeof(ocs_ip_address_subnet_t) * OCS_MAX_IP);
2240  return ret;
2241 }
2242 
2243 static int32_t ocs_mgmt_route_parse_params(ocs_t *ocs, char *cmd_params,
2244  uint32_t params_len, char *ip_addr,
2245  char *netmask, char *gateway)
2246 {
2247  char *params;
2248  char *slash;
2249  int num_chars;
2250 
2251  slash = ocs_strchr(cmd_params, '/');
2252  if (slash == NULL) {
2253  ocs_log_err(ocs, "Unexpected data in arg_in\n");
2254  return -EFAULT;
2255  }
2256 
2257  num_chars = slash - (char *)cmd_params;
2258  ocs_strncpy(ip_addr, (char *)cmd_params, num_chars);
2259  ip_addr[num_chars] = '\0';
2260 
2261  params = (char *)(cmd_params + num_chars + 1);
2262  slash = ocs_strchr(params, '/');
2263  if (slash == NULL) {
2264  ocs_log_err(ocs, "Unexpected data in arg_in\n");
2265  return -EFAULT;
2266  }
2267 
2268  num_chars = slash - params;
2269  ocs_strncpy(netmask, params, num_chars);
2270  netmask[num_chars] = '\0';
2271 
2272  num_chars = params_len - ((slash - (char *)cmd_params) + 1);
2273  ocs_strncpy(gateway, slash + 1, num_chars);
2274  gateway[num_chars] = '\0';
2275 
2276  return 0;
2277 }
2278 
2279 static int32_t
2280 ocs_mgmt_route_table_del_entry(ocs_t *ocs, char *name,
2281  void *arg_in, uint32_t arg_in_len,
2282  void *arg_out, uint32_t arg_out_len)
2283 {
2284  char ip_addr[64];
2285  char netmask[64];
2286  char gateway[64];
2287  char cmd_params[256];
2288  int rc = -EFAULT;
2289  ocs_ip_address_t ip;
2290  ocs_ip_address_t subnet;
2291  ocs_ip_address_t gateway_ip;
2293 
2294  if (arg_in == NULL) {
2295  ocs_log_err(ocs, "Route del entry arg missing\n");
2296  return rc;
2297  }
2298 
2299  if (ocs_copy_from_user(cmd_params, arg_in, arg_in_len)) {
2300  ocs_log_err(ocs, "copy from user failed\n");
2301  return rc;
2302  }
2303 
2304  rc = ocs_mgmt_route_parse_params(ocs, cmd_params, arg_in_len,
2305  ip_addr, netmask, gateway);
2306  if (rc) {
2307  ocs_log_err(ocs, "route command params parse error\n");
2308  return rc;
2309  }
2310 
2311  rc = -EFAULT;
2312  if (ocs_iscsi_inet_pton4(ip_addr, &ip) == 0) {
2313  /* Convert the subnet */
2314  if (ocs_iscsi_inet_pton4(netmask, &subnet) == 0) {
2315  ocs_iscsi_ipsub_combine(&ipsub, &ip, &subnet);
2316  } else {
2317  ocs_log_err(ocs, "IPv4 address supplied, but subnet is not an valid IPv4 subnet\n");
2318  return rc;
2319  }
2320 
2321  /* Convert the gateway */
2322  if (ocs_iscsi_inet_pton4(gateway, &gateway_ip)) {
2323  ocs_log_err(ocs, "Gateway address supplied is not a valid IPv4 format\n");
2324  return rc;
2325  }
2326  } else if (ocs_iscsi_inet_pton6(ip_addr, &ip) == 0) {
2327  if (ocs_iscsi_inet_pton6(netmask, &subnet) == 0) {
2328  ocs_iscsi_ipsub_combine(&ipsub, &ip, &subnet);
2329  } else {
2330  ocs_log_test(ocs, "IPv6 address supplied, but subnet is not an valid IPv6 subnet\n");
2331  return rc;
2332  }
2333 
2334  /* Convert the gateway */
2335  if (ocs_iscsi_inet_pton6(gateway, &gateway_ip)) {
2336  ocs_log_err(ocs, "Gateway address supplied is not a valid IPv6 formate\n");
2337  return rc;
2338  }
2339  } else {
2340  ocs_log_test(ocs, "ERROR: IP address supplied is not a valid IPv4/IPv6\n");
2341  return rc;
2342  }
2343 
2344  rc = ocs_iscsi_route_table_del_entry(ocs, &ipsub, &gateway_ip);
2345  ocs_log_err(ocs, "Route table delete entry %s - %s/%s/%s\n",
2346  (rc ? "failed" : "successful"),
2347  ip_addr, netmask, gateway);
2348 
2349  return rc;
2350 }
2351 
2352 static int32_t
2353 ocs_mgmt_route_table_add_entry(ocs_t *ocs, char *name,
2354  void *arg_in, uint32_t arg_in_len,
2355  void *arg_out, uint32_t arg_out_len)
2356 {
2357  char ip_addr[64];
2358  char netmask[64];
2359  char gateway[64];
2360  char cmd_params[256];
2361  int rc = -EFAULT;
2362  ocs_ip_address_t ip;
2363  ocs_ip_address_t subnet;
2364  ocs_ip_address_t gateway_ip;
2366 
2367  if (arg_in == NULL) {
2368  ocs_log_err(ocs, "Route del entry arg missing\n");
2369  return rc;
2370  }
2371 
2372  if (ocs_copy_from_user(cmd_params, arg_in, arg_in_len)) {
2373  ocs_log_err(ocs, "copy from user failed\n");
2374  return rc;
2375  }
2376 
2377  rc = ocs_mgmt_route_parse_params(ocs, cmd_params, arg_in_len,
2378  ip_addr, netmask, gateway);
2379  if (rc) {
2380  ocs_log_err(ocs, "route command params parse error\n");
2381  return rc;
2382  }
2383 
2384  rc = -EFAULT;
2385  if (ocs_iscsi_inet_pton4(ip_addr, &ip) == 0) {
2386  /* Convert the subnet */
2387  if (ocs_iscsi_inet_pton4(netmask, &subnet) == 0) {
2388  ocs_iscsi_ipsub_combine(&ipsub, &ip, &subnet);
2389  } else {
2390  ocs_log_err(ocs, "IPv4 address supplied, but subnet is not an valid IPv4 subnet\n");
2391  return rc;
2392  }
2393 
2394  /* Convert the gateway */
2395  if (ocs_iscsi_inet_pton4(gateway, &gateway_ip)) {
2396  ocs_log_err(ocs, "Gateway address supplied is not a valid IPv4 format\n");
2397  return rc;
2398  }
2399  } else if (ocs_iscsi_inet_pton6(ip_addr, &ip) == 0) {
2400  if (ocs_iscsi_inet_pton6(netmask, &subnet) == 0) {
2401  ocs_iscsi_ipsub_combine(&ipsub, &ip, &subnet);
2402  } else {
2403  ocs_log_test(ocs, "IPv6 address supplied, but subnet is not an valid IPv6 subnet\n");
2404  return rc;
2405  }
2406 
2407  /* Convert the gateway */
2408  if (ocs_iscsi_inet_pton6(gateway, &gateway_ip)) {
2409  ocs_log_err(ocs, "Gateway address supplied is not a valid IPv6 formate\n");
2410  return rc;
2411  }
2412  } else {
2413  ocs_log_test(ocs, "ERROR: IP address supplied is not a valid IPv4/IPv6\n");
2414  return rc;
2415  }
2416 
2417  rc = ocs_iscsi_route_table_add_entry(ocs, &ipsub, &gateway_ip);
2418  ocs_log_err(ocs, "Route table add entry %s - %s/%s/%s\n",
2419  (rc ? "failed" : "successful"),
2420  ip_addr, netmask, gateway);
2421 
2422  return rc;
2423 }
2424 
2425 static int32_t
2426 ocs_mgmt_route_table_read(ocs_t *ocs, char *name,
2427  void *arg_in, uint32_t arg_in_len,
2428  void *arg_out, uint32_t arg_out_len)
2429 {
2430  int32_t rc = -EFAULT;
2431  ocs_route_table_t *route_table;
2432 
2433  if (arg_out == NULL || (arg_out_len < sizeof(ocs_route_table_t))) {
2434  ocs_log_err(ocs, "Insufficient buffer %d, argoutlen %d\n",
2435  sizeof(ocs_route_table_t), arg_out_len);
2436  return rc;
2437  }
2438 
2439  route_table = ocs_malloc(ocs, sizeof(*route_table),
2440  OCS_M_ZERO | OCS_M_NOWAIT);
2441  if (route_table == NULL) {
2442  ocs_log_err(ocs, "Failed to alloc\n");
2443  return -ENOMEM;
2444  }
2445 
2446  rc = ocs_iscsi_route_table_read(ocs, route_table);
2447  if (rc) {
2448  ocs_log_err(ocs, "Get route table failed\n");
2449  ocs_free(ocs, route_table, sizeof(*route_table));
2450  return rc;
2451  }
2452 
2453  rc = ocs_copy_to_user(arg_out, route_table, sizeof(*route_table));
2454  if (rc) {
2455  ocs_log_err(ocs, "Copy to user failed\n");
2456  ocs_free(ocs, route_table, sizeof(*route_table));
2457  return rc;
2458  }
2459 
2460  ocs_log_debug(ocs, "Get route table successful.\n");
2461 
2462  ocs_free(ocs, route_table, sizeof(*route_table));
2463  return rc;
2464 }
2465 /*
2466  * iSCSI discovery list will have other targets within the same
2467  * network entity.
2468  * Add an entry to iSCSI discovery list.
2469  * Parameters:
2470  * add <target-name> <target-address>
2471  */
2472 static int32_t
2473 ocs_mgmt_iclusttgt_entry_add(ocs_t *ocs, char *name,
2474  void *buf, uint32_t buflen,
2475  void *argout, uint32_t argout_len)
2476 {
2477  int32_t rc = 0;
2478  int32_t num_chars;
2479  char *slash;
2480  ocs_iscsi_t *iscsi = &ocs->iscsi;
2482 
2483  /* Find the '/' character that separates target-name and target-address */
2484  slash = ocs_strchr(buf, '/');
2485  if (!slash)
2486  return -EFAULT;
2487 
2488  ctgt = ocs_malloc(ocs, sizeof(*ctgt), OCS_M_NOWAIT|OCS_M_ZERO);
2489  if (!ctgt) {
2490  ocs_log_err(ocs, "Failed to allocate memory\n");
2491  return -ENOMEM;
2492  }
2493 
2494  memset(ctgt, 0, sizeof(*ctgt));
2495  num_chars = slash - (char *)buf;
2496  if (ocs_copy_from_user(ctgt->tgt_name, buf, num_chars)) {
2497  ocs_log_err(ocs, "Cluster target copy name from user failed\n");
2498  rc = -EFAULT;
2499  goto clusttgt_add_err;
2500  }
2501  ctgt->tgt_name[num_chars] = '\0';
2502 
2503  num_chars = buflen - ((slash - (char *)buf) + 1);
2504  if (ocs_copy_from_user(ctgt->tgt_addr, (slash + 1), num_chars)) {
2505  ocs_log_err(ocs, "Cluster target copy addr from user failed\n");
2506  rc = -EFAULT;
2507  goto clusttgt_add_err;
2508  }
2509  ctgt->tgt_addr[num_chars] = '\0';
2510 
2511  ocs_list_add_tail(&iscsi->clusttgt.list, ctgt);
2512  ocs_atomic_add_return(&iscsi->clusttgt.cnt, 1);
2513 
2514  return rc;
2515 
2516 clusttgt_add_err:
2517  if (ctgt)
2518  ocs_free(ocs, ctgt, sizeof(*ctgt));
2519 
2520  return rc;
2521 }
2522 
2523 /*
2524  * iSCSI discovery list will have other targets within the same
2525  * network entity.
2526  * Delete an entry to iSCSI discovery list.
2527  * Parameters:
2528  * del <target-name> <target-address>
2529  */
2530 static int32_t
2531 ocs_mgmt_iclusttgt_entry_del(ocs_t *ocs, char *name,
2532  void *buf, uint32_t buflen,
2533  void *arg_out, uint32_t arg_out_len)
2534 {
2535  ocs_iscsi_t *iscsi = &ocs->iscsi;
2536  ocs_iscsi_cluster_tgt_t *ctgt = NULL;
2538  char *slash;
2539  char tgtname[OCS_MAX_ISCSI_NAME];
2540  char tgtaddr[32];
2541  bool found_target = false;
2542  int32_t num_chars;
2543 
2544  if (!ocs_atomic_read(&iscsi->clusttgt.cnt)) {
2545  ocs_log_debug(ocs, "Cluster target list is empty\n");
2546  return 0;
2547  }
2548 
2549  slash = ocs_strchr(buf, '/');
2550  if (!slash)
2551  return -EFAULT;
2552 
2553  num_chars = slash - (char *)buf;
2554  if (ocs_copy_from_user(tgtname, buf, num_chars)) {
2555  ocs_log_err(ocs, "Cluster target copy name from user failed\n");
2556  return -EFAULT;
2557  }
2558 
2559  tgtname[num_chars] = '\0';
2560  num_chars = buflen - ((slash - (char *)buf) + 1);
2561  if (ocs_copy_from_user(tgtaddr, (slash + 1), num_chars)) {
2562  ocs_log_err(ocs, "Cluster target copy addr from user failed\n");
2563  return -EFAULT;
2564  }
2565 
2566  tgtaddr[num_chars] = '\0';
2567 
2568  ocs_list_foreach_safe(&iscsi->clusttgt.list, ctgt, next) {
2569  if (!ocs_strncmp(ctgt->tgt_name, tgtname, strlen(ctgt->tgt_name)) &&
2570  !ocs_strncmp(ctgt->tgt_addr, tgtaddr, strlen(ctgt->tgt_addr))) {
2571  found_target = true;
2572  break;
2573  }
2574  }
2575 
2576  if (!found_target) {
2577  ocs_log_test(ocs, "Target %s:%s not found\n", tgtname, tgtaddr);
2578  return 0;
2579  }
2580 
2581  ocs_list_remove(&iscsi->clusttgt.list, ctgt);
2582  ocs_free(ocs, ctgt, sizeof(*ctgt));
2583  ocs_atomic_sub_return(&iscsi->clusttgt.cnt, 1);
2584 
2585  return 0;
2586 }
2587 
2588 /*
2589  * iSCSI discovery list will have other targets within the same
2590  * network entity.
2591  * Read an entry to iSCSI discovery list
2592  * Parameters:
2593  * get <index-of-target-entry-inthe-list>
2594  */
2595 static int32_t
2596 ocs_mgmt_iclusttgt_entry_get(ocs_t *ocs, char *name,
2597  void *buf, uint32_t buflen,
2598  void *arg_out, uint32_t arg_out_len)
2599 {
2600  ocs_iscsi_t *iscsi = &ocs->iscsi;
2601  ocs_iscsi_cluster_tgt_t *ctgt = NULL;
2603  char buf_tmp[512];
2604  int32_t inx;
2605  char *userp = (char *)arg_out;
2606  int32_t len_tmp;
2607  int32_t cnt;
2608  bool found = false;
2609 
2610  if (!ocs_atomic_read(&iscsi->clusttgt.cnt)) {
2611  ocs_log_debug(ocs, "Cluster target list is empty\n");
2612  return 0;
2613  }
2614 
2615  memset(buf_tmp, 0, sizeof(buf_tmp));
2616  if (ocs_copy_from_user(buf_tmp, buf, buflen)) {
2617  ocs_log_err(ocs, "Cluster target inx copy from user failed\n");
2618  return -EFAULT;
2619  }
2620 
2621  inx = ocs_strtoul(buf_tmp, NULL, 10);
2622 
2623  /*
2624  * Special case - handle it in first place
2625  * If given for inx == key, return number of targets in cluster list
2626  */
2627  if (inx == OCS_CLUST_TARGET_KEY_RETCNT)
2628  return ocs_atomic_read(&iscsi->clusttgt.cnt);
2629 
2630  if (inx >= ocs_atomic_read(&iscsi->clusttgt.cnt)) {
2631  ocs_log_debug(ocs, "Cluster target index %d not found\n", inx);
2632  return -EFAULT;
2633  }
2634 
2635  cnt = 0;
2636  ocs_list_foreach_safe(&iscsi->clusttgt.list, ctgt, next) {
2637  if (cnt == inx) {
2638  found = true;
2639  break;
2640  }
2641  cnt++;
2642  }
2643 
2644  if (!found) {
2645  ocs_log_debug(ocs, "Cluster target index %d not found\n", inx);
2646  return -EFAULT;
2647  }
2648 
2649  len_tmp = snprintf(buf_tmp, sizeof(buf_tmp), "%s/%s",
2650  ctgt->tgt_name, ctgt->tgt_addr);
2651  if (ocs_copy_to_user(userp, buf_tmp, len_tmp)) {
2652  ocs_log_err(ocs,
2653  "Cluster target copy failed\n");
2654  return -EFAULT;
2655  }
2656 
2657  return 0;
2658 }
2659 
2660 /*
2661  * iSCSI discovery list will have other targets within the same
2662  * network entity.
2663  * Clear iSCSI discovery list
2664  * Parameters:
2665  * clear
2666  */
2667 static int32_t
2668 ocs_mgmt_iclusttgt_clear(ocs_t *ocs, char *name,
2669  void *buf, uint32_t buf_len,
2670  void *arg_out, uint32_t arg_out_length)
2671 {
2672  ocs_iscsi_t *iscsi = &ocs->iscsi;
2673 
2675 
2676  return 0;
2677 }
2678 
2679 static void
2680 get_driver_version(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2681 {
2682  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, name, ocs->driver_version);
2683 }
2684 
2685 static void
2686 get_desc(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2687 {
2688  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "desc", ocs->desc);
2689 }
2690 
2691 static void
2692 get_fw_rev(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2693 {
2694  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "fw_rev", ocs_hal_get_ptr(&ocs->hal, OCS_HAL_FW_REV));
2695 }
2696 
2697 static void
2698 get_fw_rev2(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2699 {
2700  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "fw_rev2", ocs_hal_get_ptr(&ocs->hal, OCS_HAL_FW_REV2));
2701 }
2702 
2703 static void
2704 get_ipl(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2705 {
2706  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "ipl", ocs_hal_get_ptr(&ocs->hal, OCS_HAL_IPL));
2707 }
2708 
2709 static void
2710 get_sn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2711 {
2712  uint8_t *pserial;
2713  uint32_t len;
2714  char sn_buf[256];
2715 
2717 
2718  if (pserial) {
2719  len = *pserial ++;
2720  strncpy(sn_buf, (char*)pserial, len);
2721  sn_buf[len] = '\0';
2722  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "sn", sn_buf);
2723  }
2724 
2725 }
2726 
2727 static void
2728 get_pn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2729 {
2730  uint8_t *pserial;
2731  uint32_t len;
2732  char sn_buf[256];
2733 
2735 
2736  if (pserial) {
2737  len = *pserial ++;
2738  strncpy(sn_buf, (char*)pserial, len);
2739  sn_buf[len] = '\0';
2740  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "pn", sn_buf);
2741  } else {
2742  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "pn", ocs->model);
2743  }
2744 
2745 }
2746 
2747 static void
2748 get_sli4_intf_reg(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2749 {
2750  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "sli4_intf_reg", "0x%04x",
2751  ocs_config_read32(ocs, SLI4_INTF_REG));
2752 }
2753 
2754 static void
2755 get_phy_port_num(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2756 {
2757  char *phy_port = NULL;
2758 
2760  if (phy_port) {
2761  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "phy_port_num", phy_port);
2762  } else {
2763  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "phy_port_num", "unknown");
2764  }
2765 }
2766 
2767 static void
2768 get_asic_id_reg(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2769 {
2770  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "asic_id_reg", "0x%04x",
2771  ocs_config_read32(ocs, SLI4_ASIC_ID_REG));
2772 }
2773 
2774 static void
2775 get_chip_type(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2776 {
2777  uint32_t family;
2778  uint32_t asic_id;
2779  uint32_t asic_gen_num;
2780  uint32_t asic_rev_num;
2781  uint32_t rev_id;
2782  char result_buf[80];
2783  char tmp_buf[80];
2784 
2785  family = (ocs_config_read32(ocs, SLI4_INTF_REG) & 0x00000f00) >> 8;
2786  asic_id = ocs_config_read32(ocs, SLI4_ASIC_ID_REG);
2787  asic_rev_num = asic_id & 0xff;
2788  asic_gen_num = (asic_id & 0xff00) >> 8;
2789 
2790  rev_id = ocs_config_read32(ocs, SLI4_PCI_CLASS_REVISION) & 0xff;
2791 
2792  switch(family) {
2793  case 0x00:
2794  // BE2
2795  ocs_strcpy(result_buf, "BE2 A");
2796  ocs_snprintf(tmp_buf, 2, "%d", rev_id);
2797  strcat(result_buf, tmp_buf);
2798  break;
2799  case 0x01:
2800  // BE3
2801  ocs_strcpy(result_buf, "BE3");
2802  if (rev_id >= 0x10) {
2803  strcat(result_buf, "-R");
2804  }
2805  ocs_snprintf(tmp_buf, 3, " %c", ((rev_id & 0xf0) >> 4) + 'A');
2806  strcat(result_buf, tmp_buf);
2807  ocs_snprintf(tmp_buf, 2, "%d", rev_id & 0x0f);
2808  strcat(result_buf, tmp_buf);
2809  break;
2810  case 0x02:
2811  // Skyhawk A0
2812  strcpy(result_buf, "Skyhawk A0");
2813  break;
2814  case 0x0a:
2815  // Lancer A0
2816  strcpy(result_buf, "Lancer A");
2817  ocs_snprintf(tmp_buf, 2, "%d", rev_id & 0x0f);
2818  strcat(result_buf, tmp_buf);
2819  break;
2820  case 0x0b:
2821  // Lancer B0 or D0
2822  ocs_strcpy(result_buf, "Lancer");
2823  ocs_snprintf(tmp_buf, 3, " %c", ((rev_id & 0xf0) >> 4) + 'A');
2824  strcat(result_buf, tmp_buf);
2825  ocs_snprintf(tmp_buf, 2, "%d", rev_id & 0x0f);
2826  strcat(result_buf, tmp_buf);
2827  break;
2828  case 0x0f:
2829  // Refer to ASIC_ID
2830  switch(asic_gen_num) {
2831  case 0x00:
2832  strcpy(result_buf, "BE2");
2833  break;
2834  case 0x03:
2835  strcpy(result_buf, "BE3-R");
2836  break;
2837  case 0x04:
2838  strcpy(result_buf, "Skyhawk-R");
2839  break;
2840  case 0x05:
2841  strcpy(result_buf, "Corsair");
2842  break;
2843  case 0x0b:
2844  strcpy(result_buf, "Lancer");
2845  break;
2846  default:
2847  strcpy(result_buf, "Unknown");
2848  }
2849  if (ocs_strcmp(result_buf, "Unknown") != 0) {
2850  ocs_snprintf(tmp_buf, 3, " %c", ((asic_rev_num & 0xf0) >> 4) + 'A');
2851  strcat(result_buf, tmp_buf);
2852  ocs_snprintf(tmp_buf, 2, "%d", asic_rev_num & 0x0f);
2853  strcat(result_buf, tmp_buf);
2854  }
2855  break;
2856  default:
2857  strcpy(result_buf, "Unknown");
2858  }
2859 
2860  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, name, result_buf);
2861 
2862 }
2863 
2864 static void
2865 get_pci_vendor(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2866 {
2867  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "pci_vendor", "0x%04x", ocs->pci_vendor);
2868 }
2869 
2870 static void
2871 get_pci_device(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2872 {
2873  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "pci_device", "0x%04x", ocs->pci_device);
2874 }
2875 
2876 static void
2877 get_pci_subsystem_vendor(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2878 {
2879  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "pci_subsystem_vendor", "0x%04x", ocs->pci_subsystem_vendor);
2880 }
2881 
2882 static void
2883 get_pci_subsystem_device(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2884 {
2885  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "pci_subsystem_device", "0x%04x", ocs->pci_subsystem_device);
2886 }
2887 static void
2888 get_businfo(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2889 {
2890  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "businfo", ocs->businfo);
2891 }
2892 
2893 static void
2894 get_enable_ini(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2895 {
2896  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "enable_ini", ocs->enable_ini);
2897 }
2898 
2899 static void
2900 get_enable_tgt(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2901 {
2902  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "enable_tgt", ocs->enable_tgt);
2903 }
2904 
2905 static void
2906 get_enable_sgl_chaining(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2907 {
2908  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "enable_sgl_chaining", ocs->enable_sgl_chaining);
2909 }
2910 
2911 static void
2912 get_max_sge_size(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2913 {
2914  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "max_sge_size", "%d", ocs->max_sge_size);
2915 }
2916 
2917 static void
2918 get_num_tgts(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2919 {
2920  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "num_tgts", "%d", ocs->num_tgts);
2921 }
2922 
2923 static void
2924 get_local_ip(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2925 {
2926  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "local_ip", ocs->local_ip);
2927 }
2928 
2929 static void
2930 get_local_subnet(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2931 {
2932  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "local_subnet", ocs->local_subnet);
2933 }
2934 
2935 #define SFP_BYTES 256
2936 
2937 static void
2938 get_sfp_a0(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2939 {
2940  char buf[(SFP_BYTES*3) + 1];
2941  uint32_t i;
2942  char *d;
2943  uint8_t *s;
2944 
2945  d = buf;
2946  s = ocs_hal_get_ptr(&ocs->hal, OCS_HAL_SFP_A0);
2947  for (i=0;i<SFP_BYTES;i++) {
2948  sprintf(d, "%02x ", *s);
2949  d += 3;
2950  ++s;
2951  }
2952 
2953  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "sfp_a0", buf);
2954 }
2955 
2956 static void
2957 get_sfp_a2(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2958 {
2959  char buf[(SFP_BYTES*3) + 1];
2960  uint32_t i;
2961  char *d;
2962  uint8_t *s;
2963 
2964  d = buf;
2965  s = ocs_hal_get_ptr(&ocs->hal, OCS_HAL_SFP_A2);
2966  for (i=0;i<SFP_BYTES;i++) {
2967  sprintf(d, "%02x ", *s);
2968  d += 3;
2969  ++s;
2970  }
2971 
2972  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "sfp_a2", buf);
2973 }
2974 
2975 static void
2976 get_debug_mq_dump(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2977 {
2978 
2979  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "debug_mq_dump",
2981 }
2982 
2983 static void
2984 get_debug_cq_dump(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2985 {
2986 
2987  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "debug_cq_dump",
2989 }
2990 
2991 static void
2992 get_debug_wq_dump(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2993 {
2994  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "debug_wq_dump",
2996 }
2997 
2998 static void
2999 get_debug_io_trace(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
3000 {
3001  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "debug_io_trace",
3003 }
3004 
3005 static void
3006 get_debug_sm_trace(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
3007 {
3008  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "debug_sm_trace",
3010 }
3011 
3012 static void
3013 get_debug_scsi_tgt_trace(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
3014 {
3015  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "debug_scsi_tgt_trace",
3017 }
3018 
3019 static void
3020 get_mac_address(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
3021 {
3022  uint8_t *mac;
3023  char mac_address[18];
3024 
3025  mac = ocs_iscsi_mac_get(ocs);
3026 
3027  format_mac_address(mac, mac_address, 18);
3028 
3029  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "mac_address", mac_address);
3030 
3031 }
3032 
3033 static int
3034 set_mac_address(ocs_t *ocs, char *name, char *value)
3035 {
3036  uint8_t mac_address[6];
3037  int rc=0;
3038 
3039  rc = parse_mac_address(value, mac_address);
3040 
3041  if (rc == 0) {
3042  rc = ocs_iscsi_mac_set(ocs, mac_address);
3043  }
3044 
3045  return rc;
3046 
3047 }
3048 
3049 
3050 static int
3051 set_debug_mq_dump(ocs_t *ocs, char *name, char *value)
3052 {
3053  int result;
3054 
3055  if (ocs_strcasecmp(value, "false") == 0) {
3057  result = 0;
3058  } else if (ocs_strcasecmp(value, "true") == 0) {
3060  result = 0;
3061  } else {
3062  result = -1;
3063  }
3064 
3065  return result;
3066 }
3067 
3068 static int
3069 set_debug_cq_dump(ocs_t *ocs, char *name, char *value)
3070 {
3071  int result;
3072 
3073  if (ocs_strcasecmp(value, "false") == 0) {
3075  result = 0;
3076  } else if (ocs_strcasecmp(value, "true") == 0) {
3078  result = 0;
3079  } else {
3080  result = -1;
3081  }
3082 
3083  return result;
3084 }
3085 
3086 static int
3087 set_debug_wq_dump(ocs_t *ocs, char *name, char *value)
3088 {
3089  int result;
3090 
3091  if (ocs_strcasecmp(value, "false") == 0) {
3093  result = 0;
3094  } else if (ocs_strcasecmp(value, "true") == 0) {
3096  result = 0;
3097  } else {
3098  result = -1;
3099  }
3100 
3101  return result;
3102 }
3103 
3104 static int
3105 set_debug_io_trace(ocs_t *ocs, char *name, char *value)
3106 {
3107  int result;
3108 
3109  if (ocs_strcasecmp(value, "false") == 0) {
3111  result = 0;
3112  } else if (ocs_strcasecmp(value, "true") == 0) {
3114  result = 0;
3115  } else {
3116  result = -1;
3117  }
3118 
3119  return result;
3120 }
3121 
3122 static int
3123 set_debug_sm_trace(ocs_t *ocs, char *name, char *value)
3124 {
3125  int result;
3126 
3127  if (ocs_strcasecmp(value, "false") == 0) {
3129  result = 0;
3130  } else if (ocs_strcasecmp(value, "true") == 0) {
3132  result = 0;
3133  } else {
3134  result = -1;
3135  }
3136 
3137  return result;
3138 }
3139 
3140 static int
3141 set_debug_scsi_tgt_trace(ocs_t *ocs, char *name, char *value)
3142 {
3143  int result;
3144 
3145  if (ocs_strcasecmp(value, "false") == 0) {
3147  result = 0;
3148  } else if (ocs_strcasecmp(value, "true") == 0) {
3150  result = 0;
3151  } else {
3152  result = -1;
3153  }
3154 
3155  return result;
3156 }
3157 
3158 static int32_t
3159 ocs_mgmt_chap_add_user(ocs_t *ocs, char *name, void *arg_in,
3160  uint32_t arg_in_length, void *arg_out,
3161  uint32_t arg_out_length)
3162 {
3163  ocs_chap_user_buffer_t chap_user_buff;
3164  int rc;
3165 
3166  /* Sanity checks */
3167  if (arg_in_length <= 3) {
3168  return -1;
3169  }
3170 
3171  if (arg_in == NULL) {
3172  return -1;
3173  }
3174 
3175  memset(&chap_user_buff, 0, sizeof(chap_user_buff));
3176  if (ocs_copy_from_user(&chap_user_buff, arg_in, sizeof(chap_user_buff))) {
3177  ocs_log_err(ocs, "copy_from_user failed\n");
3178  return -1;
3179  }
3180 
3181  rc = ocs_iscsi_chap_user_add(ocs, chap_user_buff.username, chap_user_buff.secret,
3182  chap_user_buff.type, chap_user_buff.mode);
3183  return rc;
3184 }
3185 
3186 static int32_t
3187 ocs_mgmt_chap_remove_user(ocs_t *ocs, char *name, void *arg_in,
3188  uint32_t arg_in_length, void *arg_out,
3189  uint32_t arg_out_length)
3190 {
3191  ocs_chap_user_buffer_t chap_user_buff;
3192 
3193  /* Sanity checks */
3194  if (arg_in_length <= 0 || arg_in == NULL) {
3195  ocs_log_err(ocs, "Insufficient input buffers\n");
3196  return -1;
3197  }
3198 
3199  memset(&chap_user_buff, 0, sizeof(chap_user_buff));
3200  if (ocs_copy_from_user(&chap_user_buff, arg_in, sizeof(chap_user_buff))) {
3201  ocs_log_err(ocs, "copy_from_user failed\n");
3202  return -1;
3203  }
3204 
3205  return ocs_iscsi_chap_user_del(ocs, chap_user_buff.username,
3206  chap_user_buff.type,
3207  chap_user_buff.mode);
3208 }
3209 
3210 /**
3211  * @brief Copy the chap_list to user supplied buffer.
3212  *
3213  * Return At first stage (when arg_in and arg_out NULL), return count of
3214  * items in chap_list
3215  * At Second stage, return zero on successful copy, otherwise a negative value.
3216  */
3217 static int32_t
3218 ocs_mgmt_chap_show_list(ocs_t *ocs, char *name, void *arg_in,
3219  uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length)
3220 {
3221  if (arg_in == NULL && arg_out == NULL) {
3222  return ocs_iscsi_chap_list_count(ocs);
3223  }
3224 
3225  if (arg_out == NULL || arg_out_length == 0) {
3226  ocs_log_err(ocs, "Invalid output buffer\n");
3227  return -1;
3228  }
3229 
3230  return ocs_iscsi_chap_list_get(ocs, arg_out, arg_out_length);
3231 }
3232 
3233 /**
3234  * @brief Delete VLAN will actually deletes the interface handle of vlan
3235  * This function first removes the IP addresses configured on the interface
3236  * handle and then delete iface.
3237  *
3238  */
3239 static int32_t
3240 ocs_mgmt_vlan_del(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length,
3241  void *arg_out, uint32_t arg_out_length)
3242 {
3243  uint32_t vlan_id = 0;
3244  ocs_hal_portal_t portal_iface = 0;
3245  int32_t rc = -EFAULT;
3246 
3247  if (arg_in == NULL || (arg_in_length < sizeof(vlan_id))) {
3248  ocs_log_err(ocs, "vlan_id buffer is missing\n");
3249  return rc;
3250  }
3251 
3252  if (ocs_copy_from_user(&vlan_id, arg_in, sizeof(vlan_id))) {
3253  ocs_log_err(ocs, "copy from user failed\n");
3254  return rc;
3255  }
3256 
3257  rc = ocs_iscsi_find_portal_from_vlan(ocs, vlan_id, &portal_iface);
3258  if (rc) {
3259  ocs_log_err(ocs, "iSCSI portal is not exists for vlan id %d\n",
3260  vlan_id);
3261  return rc;
3262  }
3263 
3264  /*
3265  * Remove IP address of this interface
3266  */
3267  rc = ocs_iscsi_portal_remove_ip_addresses(ocs, portal_iface);
3268  if (rc) {
3269  ocs_log_err(ocs, "Failed to remove IP addresses of iface %d\n",
3270  portal_iface);
3271  return rc;
3272  }
3273 
3274  rc = ocs_iscsi_portal_delete(ocs, portal_iface);
3275  if (rc) {
3276  ocs_log_err(ocs, "Delete iface failed\n");
3277  } else {
3278  ocs_log_debug(ocs, "Deleted IFACE handle %d of vlan id %d\n",
3279  portal_iface, vlan_id);
3280  }
3281 
3282  if (rc == 0) {
3283  /* Remove VLAN and portal from vlan_list */
3284  rc = ocs_iscsi_portal_del_vlan(ocs, portal_iface);
3285  if (rc) {
3286  ocs_log_err(ocs, "Failed to delete portal\n");
3287  }
3288  }
3289 
3290  return rc;
3291 }
3292 
3293 /**
3294  * @brief Add VLAN tag will actually creates an interface along with VLAN ID
3295  * Rule 1: Cannot set VLAN on default interface in I+T profile.
3296  * VLAN can only be added by creating an additional interface handle.
3297  * Rule 2: An interface can only has one VLAN
3298  */
3299 static int32_t
3300 ocs_mgmt_vlan_add(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length,
3301  void *arg_out, uint32_t arg_out_length)
3302 {
3303  uint32_t vlan_id = 0;
3304  ocs_hal_portal_t portal_iface = 0;
3305  int32_t rc = -EFAULT;
3306 
3307  if (arg_in == NULL || (arg_in_length < sizeof(vlan_id))) {
3308  ocs_log_err(ocs, "vlan_id buffer is missing\n");
3309  return rc;
3310  }
3311 
3312  if (ocs_copy_from_user(&vlan_id, arg_in, sizeof(vlan_id))) {
3313  ocs_log_err(ocs, "copy from user failed\n");
3314  return rc;
3315  }
3316 
3317  rc = ocs_iscsi_portal_create(ocs, vlan_id, &portal_iface);
3318  if (rc) {
3319  ocs_log_err(ocs, "Create iface failed\n");
3320  } else {
3321  ocs_log_debug(ocs, "Created IFACE handle %d for vlan id %d\n",
3322  portal_iface, vlan_id);
3323  }
3324 
3325  return rc;
3326 }
3327 
3328 static int32_t
3329 ocs_mgmt_vlan_show(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length,
3330  void *arg_out, uint32_t arg_out_length)
3331 {
3332  int32_t ret = -EFAULT;
3333 
3334  if (arg_out == NULL) {
3335  ocs_log_err(ocs, "Insufficient arg_out buffer\n");
3336  return ret;
3337  }
3338 
3339  ret = ocs_iscsi_portal_read_vlan_ids(ocs, arg_out, arg_out_length);
3340  if (ret) {
3341  ocs_log_err(ocs, "Failed to read vlan ids\n");
3342  }
3343 
3344  return ret;
3345 }
3346 
3347 #if 0
3348 static void ocs_mgmt_status_hal(ocs_textbuf_t *textbuf, ocs_hal_t *hal);
3349 static void ocs_mgmt_sli4_queue_status(ocs_textbuf_t *textbuf, const char *name,
3350  sli4_queue_t *q, uint32_t q_count);
3351 
3352 void
3353 ocs_mgmt_get_info(ocs_t *ocs, ocs_textbuf_t *textbuf) {
3354 
3355  ocs_mgmt_start_section(textbuf, "ocs", ocs->ocs_instance);
3356 
3357  /* Dump target and initiator private data */
3358  // ocs_scsi_ini_mgmt_status(textbuf, OCS_SCSI_DDUMP_DEVICE, ocs);
3359  ocs_scsi_tgt_mgmt_status(textbuf, OCS_SCSI_DDUMP_DEVICE, ocs);
3360 
3361  ocs_mgmt_status_hal(textbuf, &ocs->hal);
3362 
3363  ocs_mgmt_end_section(textbuf);
3364 
3365 
3366 }
3367 
3368 static void
3369 ocs_mgmt_status_hal(ocs_textbuf_t *textbuf, ocs_hal_t *hal)
3370 {
3371  ocs_t *ocs = hal->os;
3372 
3373  ocs_assert(ocs);
3374 
3375  ocs_mgmt_start_section(textbuf, "hal", ocs->ocs_instance);
3376 
3377 
3378  ocs_mgmt_sli4_queue_status(textbuf, "wq", hal->wq, 1);
3379  ocs_mgmt_sli4_queue_status(textbuf, "rq", hal->rq, ARRAY_SIZE(hal->rq));
3380  ocs_mgmt_sli4_queue_status(textbuf, "mq", hal->mq, ARRAY_SIZE(hal->mq));
3381  ocs_mgmt_sli4_queue_status(textbuf, "cq", hal->cq, ARRAY_SIZE(hal->cq));
3382  ocs_mgmt_sli4_queue_status(textbuf, "eq", hal->eq, ARRAY_SIZE(hal->eq));
3383 
3384  ocs_mgmt_end_section(textbuf);
3385  //sli4_link_event_t link;
3386 }
3387 
3388 static void
3389 ocs_mgmt_sli4_queue_status(ocs_textbuf_t *textbuf, const char *name, sli4_queue_t *q, uint32_t q_count)
3390 {
3391  uint32_t i;
3392 
3393  for (i = 0; i < q_count; i ++, q ++) {
3394  ocs_mgmt_start_section(textbuf, name, i);
3395  ocs_mgmt_status_int(textbuf, "index", "%d", q->index);
3396  ocs_mgmt_status_int(textbuf, "size", "%d", q->size);
3397  ocs_mgmt_status_int(textbuf, "length", "%d", q->length);
3398  ocs_mgmt_status_int(textbuf, "n_posted", "%d", q->n_posted);
3399  ocs_mgmt_status_int(textbuf, "id", "%d", q->id);
3400  ocs_mgmt_status_int(textbuf, "type", "%d", q->type);
3401  ocs_mgmt_status_int(textbuf, "limit", "%d", q->limit);
3402  ocs_mgmt_end_section(textbuf);
3403  }
3404 }
3405 #endif
3406 
3407 /**
3408  * @page mgmt_api_overview Management APIs
3409  * - @ref mgmt
3410  *
3411  * <div class="overview">
3412  * The management interface provides a mechanism by which a program in user space
3413  * can interact with the running driver. Through the ioctl system call, a user program
3414  * can get a list of the information available, and then read/modify
3415  * individual values. There are three categories of management information:<br/><br/>
3416  *
3417  * - Status - A status is a read-only value. The ocs_mgmt_get_status_list() function
3418  * returns a list of available status properties. The ocs_mgmt_get_status()
3419  * function returns the value of a particular property.
3420  *
3421  * - Configuration - A configuration is a read/write value. The
3422  * ocs_mgmt_get_config_list() function
3423  * returns a list of configuration properties. The ocs_mgmt_get_config() function
3424  * returns the current value of a property. The ocs_mgmt_set_config() function
3425  * changes the value of a property.
3426  *
3427  * - Action - An action allows a user to perform an action in the driver, such as
3428  * updating firmware or bringing a link up/down. The ocs_mgmt_get_action_list()
3429  * function returns a list of available actions. The ocs_mgmt_do_action() function
3430  * invokes a particular action.
3431  *
3432  * </div>
3433  */
structure for storing VLAN id and interface handle together
#define OCS_CONFIG_LINKCFG_4X10G
linkcfg strings
Definition: ocs_ioctl.h:472
#define BUFFER_SIZE
static int set_mac_address(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:3034
static int32_t ocs_iscsi_get_subnet_ip_address(ocs_iscsi_t *iscsi, ocs_hal_portal_t portal, ocs_ip_address_t *subnet, ocs_ip_address_t *ip)
Definition: ocs_mgmt.c:1896
static void get_sn(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2710
static void get_header_digest(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1240
ocs_os_handle_t os
Definition: ocs_hal.h:725
ocs_hal_linkcfg_e linkcfg
Definition: ocs_mgmt.c:1470
#define FW_WRITE_BUFSIZE
Definition: ocs_mgmt.c:748
static int32_t ocs_iscsi_ip_get_copy_to_user(ocs_t *ocs, char *userbuff, uint32_t userbuff_len, uint32_t *bytes_copied, uint32_t num_ips, ocs_ip_address_subnet_t *ipsub)
Definition: ocs_mgmt.c:2020
int32_t ocs_hal_get_active_profile(ocs_hal_t *hal, mgmt_cb_t cb, void *ul_arg)
Get the currently active profile.
Definition: ocs_hal.c:6398
ocs_t * ocs_get_instance(uint32_t index)
Returns a pointer to the ocs structure given the instance index.
Definition: ocs_driver.c:141
static void get_max_sge_size(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2912
ocs_mgmt_action_func action_handler
Definition: ocs_mgmt.h:68
uint16_t size
Definition: sli4.h:2051
static void get_debug_io_trace(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2999
#define OCS_DEBUG_ENABLE_MQ_DUMP
Definition: ocs_debug.h:155
int ocs_mgmt_get(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
return the value of a mgmt item
Definition: ocs_mgmt.c:337
void ocs_iscsi_cluster_tgts_free(ocs_iscsi_t *iscsi)
iscsi cluster targets free
Definition: ocs_iscsi.c:2211
Definition: ocs_mgmt.h:64
#define OCS_DEBUG_ENABLE_SM_TRACE
Definition: ocs_debug.h:159
int32_t parse_mac_address(const char *src, uint8_t *dest)
Parse a string into a MAC address.
Definition: ocs_iscsi.c:737
ocs_mgmt_set_func set_handler
Definition: ocs_mgmt.h:67
int32_t ocs_iscsi_mtu_set(ocs_t *ocs, uint8_t is_jumbo)
Sets the TCP MTU size of the iSCSI device.
Definition: ocs_iscsi.c:2173
int32_t ocs_iscsi_find_portal_from_vlan(ocs_t *ocs, uint32_t vlan_id, ocs_hal_portal_t *iface_handle)
Helper function to find respective interface handle of VLAN id.
Definition: ocs_iscsi.c:2921
static void get_tcp_window_size(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1265
void ocs_mgmt_emit_int(ocs_textbuf_t *textbuf, int mode, const char *name, const char *fmt,...)
Generate a property with an integer value in a management XML document.
int32_t ocs_hal_get_linkcfg(ocs_hal_t *hal, mgmt_cb_t cb, void *ul_arg)
Get the current link configuration.
Definition: ocs_hal.c:6628
static int set_max_cxns_per_session(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:1315
#define OCS_CONFIG_LINKCFG_1X40G
Definition: ocs_ioctl.h:473
static void get_pci_vendor(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2865
static void get_driver_version(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2680
ocs_hal_rtn_e ocs_hal_set_linkcfg(ocs_hal_t *hal, mgmt_cb_t cb, ocs_hal_linkcfg_e value, void *ul_arg)
Set the link configuration (Skyhawk only).
Definition: ocs_hal.c:6716
static void get_jumbo_frames(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1190
ocs_mgmt_get_func get_handler
Definition: ocs_mgmt.h:66
static void get_pn(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2728
int ocs_mgmt_set(ocs_t *ocs, char *name, char *value)
set the value of a mgmt item
Definition: ocs_mgmt.c:456
static void get_debug_sm_trace(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:3006
static int set_require_chap(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:1386
static int set_tcp_window_size(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:1271
uint32_t index
Definition: sli4.h:2050
static int32_t ocs_mgmt_iclusttgt_entry_get(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length)
Definition: ocs_mgmt.c:2596
ocs_hal_rtn_e ocs_hal_set_active_profile(ocs_hal_t *hal, mgmt_cb_t cb, uint32_t profile_id, void *ul_arg)
Set the currently active profile.
Definition: ocs_hal.c:6479
ocs_hal_portal_t portal
Definition: ocs_iscsi.h:278
static void get_debug_wq_dump(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2992
int ocs_mgmt_exec(ocs_t *ocs, char *action, void *arg_in, uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length)
perform a management action
Definition: ocs_mgmt.c:530
#define MGMT_MODE_EX
Definition: ocs_mgmt.h:49
void format_mac_address(uint8_t *address, char *buffer, int size)
Format a MAC address into a string.
Definition: ocs_iscsi.c:711
int32_t ocs_iscsi_listen_start(ocs_t *ocs, ocs_ip_address_t *ip, uint16_t tcp_port)
Starts a TCP listen socket.
Definition: ocs_iscsi.c:3227
static int32_t ocs_mgmt_ip_remove(ocs_t *ocs, char *, void *, uint32_t, void *, uint32_t)
Definition: ocs_mgmt.c:1921
#define OCS_CONFIG_LINKCFG_4X8G
Definition: ocs_ioctl.h:475
void ocs_iscsi_ipsub_combine(ocs_ip_address_subnet_t *ipsub, ocs_ip_address_t *ip, ocs_ip_address_t *subnet)
Combines an iSCSI IP address and subnet into the combined structure.
Definition: ocs_iscsi.c:414
static int32_t ocs_mgmt_vlan_del(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length)
Delete VLAN will actually deletes the interface handle of vlan This function first removes the IP add...
Definition: ocs_mgmt.c:3240
int32_t ocs_iscsi_chap_user_del(ocs_t *ocs, char *username, uint32_t type, uint32_t mode)
Delete CHAP user.
static void ocs_mgmt_get_linkcfg_cb(void *ul_arg, int32_t status, uint32_t ext_status, void *params)
Definition: ocs_mgmt.c:1481
uint32_t segment_count
Definition: ocs_ramdisc.h:107
static void ocs_device_lock(ocs_t *ocs)
Definition: ocs_drv_fc.h:218
#define OCS_DEBUG_ENABLE_SCSI_TGT_TRACE
Definition: ocs_debug.h:160
const char * name
Definition: ocs_ddump.h:54
HAL object.
Definition: ocs_hal.h:724
static int32_t ocs_mgmt_chap_show_list(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length)
Copy the chap_list to user supplied buffer.
Definition: ocs_mgmt.c:3218
static void get_max_cxns_per_session(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1309
#define OCS_ISCSI_MGMT_CMD_PARAMS_LEN
Definition: ocs_mgmt.h:52
static int set_port_protocol(ocs_t *, char *, char *)
Set port profile.
Definition: ocs_mgmt.c:1146
static void get_enable_ini(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2894
static int32_t ocs_mgmt_route_table_add_entry(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_len, void *arg_out, uint32_t arg_out_len)
Definition: ocs_mgmt.c:2353
sli4_queue_t mq[1]
Definition: ocs_hal.h:751
void ocs_mgmt_start_unnumbered_section(ocs_textbuf_t *textbuf, const char *name)
Generate the beginning of an unnumbered section in a management XML document.
ramdisc instance structure
Definition: ocs_ramdisc.h:88
static void get_sfp_a0(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2938
ramdisc segment structure
Definition: ocs_ramdisc.h:79
void ocs_mgmt_start_section(ocs_textbuf_t *textbuf, const char *name, int index)
Generate the beginning of a numbered section in a management XML document.
int const char const char void ocs_mgmt_emit_boolean(ocs_textbuf_t *textbuf, int access, const char *name, const int value)
Generate a property with a boolean value in a management XML document.
static void get_local_subnet(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2930
uint32_t ocs_hal_portal_t
Definition: ocs_common.h:204
static int32_t ocs_mgmt_listen_start(ocs_t *ocs, char *, void *, uint32_t, void *, uint32_t)
Definition: ocs_mgmt.c:1597
static int32_t ocs_mgmt_iclusttgt_clear(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length)
Definition: ocs_mgmt.c:2668
#define SLI4_ASIC_ID_REG
ASIC_ID - SLI ASIC Type and Revision Register.
Definition: sli4.h:101
ocs_hal_port_protocol_e
Port protocols.
Definition: ocs_hal.h:142
ocs_hal_profile_descriptor_t descriptors[OCS_HAL_MAX_PROFILES]
Definition: ocs_hal.h:313
static void ocs_mgmt_set_active_profile_cb(void *ul_arg, int32_t status, uint32_t ext_status, void *params)
Definition: ocs_mgmt.c:991
size_t size
Definition: ocs_ramdisc.h:73
static void * ocs_list_remove(ocs_list_t *list, void *item)
Remove an item from the list.
Definition: ocs_list.h:385
static void get_enable_tgt(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2900
ocs_ip_type_e ip_type
Definition: ocs_iscsi_api.h:75
void ocs_iscsi_uninitialize(ocs_iscsi_t *iscsi)
Indicate that HAL is not initialized.
Definition: ocs_iscsi.c:1904
static int set_debug_wq_dump(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:3087
static void get_require_chap(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1380
void ocs_mgmt_get_list(ocs_t *ocs, ocs_textbuf_t *textbuf)
get a list of mgmt items supported by the driver
Definition: ocs_mgmt.c:274
int32_t ocs_iscsi_route_table_read(ocs_t *ocs, ocs_route_table_t *route_table)
Definition: ocs_iscsi.c:2371
static void get_desc(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2686
uint8_t * ocs_iscsi_mac_get(ocs_t *ocs)
Gets the MAC address of the iSCSI device.
Definition: ocs_iscsi.c:1323
sli4_queue_t rq[OCS_HAL_MAX_NUM_RQ]
Definition: ocs_hal.h:750
#define OCS_CONFIG_LINKCFG_UNKNOWN
Definition: ocs_ioctl.h:479
uint32_t num_descriptors
Definition: ocs_hal.h:312
ocs_hal_rtn_e ocs_hal_reset(ocs_hal_t *hal, ocs_hal_reset_e reset)
Definition: ocs_hal.c:2558
void ocs_mgmt_get_all(ocs_t *ocs, ocs_textbuf_t *textbuf)
Definition: ocs_mgmt.c:396
int32_t ocs_iscsi_chap_user_add(ocs_t *ocs, char *username, char *secret, uint32_t type, uint32_t mode)
Add CHAP user. If CHAP user of same type is already exists, return error.
static int32_t ocs_mgmt_iclusttgt_entry_del(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length)
Definition: ocs_mgmt.c:2531
static int set_data_digest(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:1221
sli4_queue_t eq[OCS_HAL_MAX_NUM_EQ]
Definition: ocs_hal.h:753
static void get_chip_type(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2775
int32_t ocs_iscsi_listen_stop(ocs_t *ocs, ocs_ip_address_t *ip, uint16_t tcp_port)
Stops a TCP listen socket.
Definition: ocs_iscsi.c:3275
static void get_port_protocol(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1072
static void get_fw_rev(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2692
ocs_hal_portal_t ocs_iscsi_portal_get_default(ocs_t *ocs)
Retrieves the default portal.
Definition: ocs_iscsi.c:2816
int32_t ocs_iscsi_ip_address_remove(ocs_t *ocs, ocs_hal_portal_t portal, ocs_ip_address_subnet_t *ipsub)
Remove the IP address to the specified interface.
Definition: ocs_iscsi.c:2510
ramdisc_segment_t ** segments
Definition: ocs_ramdisc.h:106
#define ocs_list_foreach_safe(list, item, nxt)
Iterate a linked list safely.
Definition: ocs_list.h:446
void ocs_mgmt_end_unnumbered_section(ocs_textbuf_t *textbuf, const char *name)
Generate the end of a section in a management XML document.
static void get_pci_device(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2871
static int32_t ocs_mgmt_vlan_add(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length)
Add VLAN tag will actually creates an interface along with VLAN ID Rule 1: Cannot set VLAN on default...
Definition: ocs_mgmt.c:3300
static void ocs_device_unlock(ocs_t *ocs)
Definition: ocs_drv_fc.h:223
static int32_t ocs_mgmt_iclusttgt_entry_add(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length)
Definition: ocs_mgmt.c:2473
static void get_phy_port_num(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2755
#define MAX_PROFILE_LENGTH
Definition: ocs_mgmt.c:945
static int32_t ocs_iscsi_is_ipaddr_listening(ocs_iscsi_t *iscsi, ocs_hal_portal_t portal, ocs_ip_address_t *ip)
Definition: ocs_mgmt.c:1871
int32_t ocs_iscsi_ip_address_query(ocs_t *ocs, ocs_hal_portal_t portal, ocs_ip_type_e ip_type, uint32_t max_entries, uint32_t *num_ips, ocs_ip_address_subnet_t *ipsub)
Queries the IP addresses on the default interface.
Definition: ocs_iscsi.c:2567
ocs_hal_linkcfg_e
Link configurations.
Definition: ocs_hal.h:184
uint8_t ip_address[16]
Definition: ocs_iscsi_api.h:76
uint8_t type
Definition: sli4.h:2059
static int ocs_mgmt_firmware_write(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void *, uint32_t)
Definition: ocs_mgmt.c:758
#define OCS_CLUST_TARGET_KEY_RETCNT
Definition: ocs_iscsi.h:242
#define OCS_CONFIG_LINKCFG_4X1G
Definition: ocs_ioctl.h:476
iSCSI object
Definition: ocs_iscsi.h:293
void ocs_mgmt_end_section(ocs_textbuf_t *textbuf, const char *name, int index)
Generate the indexed end of a section in a management XML document.
ocs_hal_portal_t iface_handle
ocs_hal_profile_list_t * list
Definition: ocs_mgmt.c:847
#define OCS_DEBUG_ENABLE_CQ_DUMP
Definition: ocs_debug.h:156
static void get_local_ip(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2924
static int32_t ocs_mgmt_route_table_read(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_len, void *arg_out, uint32_t arg_out_len)
Definition: ocs_mgmt.c:2426
static ocs_mgmt_linkcfg_map_t mgmt_linkcfg_map[]
Definition: ocs_mgmt.c:1416
static void get_profile_list(ocs_t *, char *, ocs_textbuf_t *)
Get list of profiles.
Definition: ocs_mgmt.c:880
static void get_sfp_a2(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2957
static int32_t ocs_mgmt_vlan_show(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length)
Definition: ocs_mgmt.c:3329
A Profile List.
Definition: ocs_hal.h:311
static void get_fw_rev2(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2698
uint16_t length
Definition: sli4.h:2052
uint16_t id
Definition: sli4.h:2054
#define OCS_DEBUG_ENABLE_IO_TRACE
Definition: ocs_debug.h:158
int32_t ocs_iscsi_chap_list_count(ocs_t *ocs)
Returns the count of chap_list.
ocs_ip_address_t gateway
static int set_debug_io_trace(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:3105
void * virt
Definition: ocs_ramdisc.h:71
uint32_t listening
Definition: ocs_iscsi.h:283
uint16_t tcp_port
Definition: ocs_iscsi.h:281
static void get_enable_sgl_chaining(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2906
static int set_tcp_window_scale(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:1293
static void get_debug_cq_dump(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2984
static void get_num_tgts(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2918
static int set_active_profile(ocs_t *, char *, char *)
Set active profile.
Definition: ocs_mgmt.c:1018
uint16_t n_posted
Definition: sli4.h:2053
static void get_active_profile(ocs_t *, char *, ocs_textbuf_t *)
Get active profile.
Definition: ocs_mgmt.c:962
int32_t ocs_iscsi_portal_del_vlan(ocs_t *ocs, ocs_hal_portal_t iface)
Delete iface handle and VLAN from portal_list.
Definition: ocs_iscsi.c:3011
#define OCS_CONFIG_LINKCFG_2X16G
Definition: ocs_ioctl.h:474
static ocs_hal_linkcfg_e ocs_hal_linkcfg_from_mgmt(const char *mgmt_str)
Get the HAL linkcfg enum from the mgmt config string.
Definition: ocs_mgmt.c:1433
ocs_hal_rtn_e ocs_hal_get_profile_list(ocs_hal_t *hal, mgmt_cb_t mgmt_cb, void *ul_arg)
Get a list of available profiles.
Definition: ocs_hal.c:6304
int32_t ocs_iscsi_portal_delete(ocs_t *ocs, ocs_hal_portal_t portal)
Removes a previously-created portal.
Definition: ocs_iscsi.c:3183
static int set_debug_cq_dump(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:3069
#define MGMT_MODE_RD
Definition: ocs_mgmt.h:47
int32_t ocs_iscsi_portal_read_vlan_ids(ocs_t *ocs, void *arg_out, uint32_t arg_out_length)
Read VLAN IDs to provided buffer.
Definition: ocs_iscsi.c:3041
static int32_t ocs_mgmt_ip_add(ocs_t *ocs, char *, void *, uint32_t, void *, uint32_t)
Definition: ocs_mgmt.c:1756
static void ocs_mgmt_get_active_profile_cb(void *ul_arg, int32_t status, uint32_t ext_status, void *params)
Definition: ocs_mgmt.c:929
int32_t ocs_iscsi_gateway_set(ocs_t *ocs, ocs_ip_address_t *gateway)
Sets the IP gateway address.
Definition: ocs_iscsi.c:2771
static void get_tcp_window_scale(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1287
int32_t ocs_iscsi_mac_set(ocs_t *ocs, uint8_t *mac_address)
Sets the MAC address of the iSCSI device.
Definition: ocs_iscsi.c:1281
static int set_debug_sm_trace(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:3123
static void ocs_list_add_tail(ocs_list_t *list, void *item)
Add an item to the tail of the list.
Definition: ocs_list.h:263
static void ocs_mgmt_set_linkcfg_cb(void *ul_arg, int32_t status, uint32_t ext_status, void *params)
Definition: ocs_mgmt.c:1540
This structure is used to track the SLI4 queues.
Definition: sli4.h:2046
sli4_queue_t * cq
Definition: ocs_hal.h:752
#define SFP_BYTES
Definition: ocs_mgmt.c:2935
structure wrapping an IP address and subnet together with their type.
Definition: ocs_iscsi_api.h:82
#define OCS_CONFIG_LINKCFG_2X10G
Definition: ocs_ioctl.h:477
void format_ip_address(ocs_ip_type_e ip_type, uint8_t *address, char *buffer, int size)
Format an IP address into a string.
Definition: ocs_iscsi.c:460
ocs_iscsi_cluster_sendtargets_t clusttgt
Definition: ocs_iscsi.h:348
static void get_debug_mq_dump(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2976
ocs_hal_linkcfg_e config_id
Definition: ocs_mgmt.c:1477
static int set_debug_scsi_tgt_trace(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:3141
#define SLI4_INTF_REG
SLI_INTF - SLI Interface Definition Register.
Definition: sli4.h:81
static void get_gateway(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1331
int32_t ocs_iscsi_portal_remove_ip_addresses(ocs_t *ocs, ocs_hal_portal_t iface_handle)
Check and remove IP addresses of the corresponding interface.
Definition: ocs_iscsi.c:2862
#define SLI4_PCI_CLASS_REVISION
Definition: sli4.h:68
static int set_gateway(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:1343
ocs_ip_type_e
enum identifying the types of IP addresses.
Definition: ocs_iscsi_api.h:46
static void get_businfo(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2888
static void get_mac_address(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:3020
static int set_linkcfg(ocs_t *, char *, char *)
Set linkcfg config value.
Definition: ocs_mgmt.c:1562
uint8_t dif_separate
Definition: ocs_ramdisc.h:93
int32_t ocs_iscsi_chap_list_get(ocs_t *ocs, char *userbuf, int32_t buflen)
Return CHAP list items.
void ocs_debug_enable(uint32_t mask)
enable debug options
Definition: ocs_debug.c:91
static void get_data_digest(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1215
uintptr_t phys
Definition: ocs_ramdisc.h:72
ocs_hal_port_protocol_e port_protocol
Definition: ocs_mgmt.c:1051
static void ocs_mgmt_set_port_protocol_cb(void *ul_arg, int32_t status, uint32_t ext_status, void *params)
Definition: ocs_mgmt.c:1120
static int set_debug_mq_dump(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:3051
static void get_linkcfg(ocs_t *, char *, ocs_textbuf_t *)
Get current link configuration.
Definition: ocs_mgmt.c:1509
static void get_pci_subsystem_device(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2883
int32_t ocs_iscsi_ip_address_add(ocs_t *ocs, ocs_hal_portal_t portal, ocs_ip_address_subnet_t *ipsub)
Adds the IP address to the specified interface.
Definition: ocs_iscsi.c:2417
static const char * ocs_mgmt_from_hal_linkcfg(ocs_hal_linkcfg_e linkcfg)
Get the mgmt string value from the HAL linkcfg enum.
Definition: ocs_mgmt.c:1453
int32_t ocs_get_bus_dev_func(ocs_t *ocs, uint8_t *bus, uint8_t *dev, uint8_t *func)
#define MAX_LINE_SIZE
int32_t ocs_iscsi_route_table_del_entry(ocs_t *ocs, ocs_ip_address_subnet_t *ipsub, ocs_ip_address_t *gateway)
Deletes an entry from a routing table.
Definition: ocs_iscsi.c:2276
ocs_hal_rtn_e ocs_hal_set_port_protocol(ocs_hal_t *hal, uint32_t pci_func, ocs_hal_port_protocol_e new_protocol, mgmt_cb_t cb, void *ul_arg)
Set the port protocol.
Definition: ocs_hal.c:7116
static void get_debug_scsi_tgt_trace(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:3013
sli4_queue_t * wq
Definition: ocs_hal.h:749
ocs_list_t portal_list
int ocs_debug_is_enabled(uint32_t mask)
return true if debug bits are enabled
Definition: ocs_debug.c:122
Link configuration callback argument.
Definition: ocs_mgmt.c:1467
int32_t ocs_iscsi_inet_pton4(const char *src, ocs_ip_address_t *ip)
Converts an IPv4 address from a string to the IP structure.
Definition: ocs_iscsi.c:513
ocs_ip_address_t ip
Definition: ocs_iscsi.h:279
static void get_asic_id_reg(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2768
#define MGMT_MODE_RW
Definition: ocs_mgmt.h:50
#define MGMT_MODE_WR
Definition: ocs_mgmt.h:48
void ocs_textbuf_reset(ocs_textbuf_t *textbuf)
Definition: ocs_textbuf.c:406
#define OCS_MAX_IP
Definition: ocs_iscsi.h:288
int32_t ocs_hal_get_port_protocol(ocs_hal_t *hal, uint32_t pci_func, mgmt_cb_t cb, void *ul_arg)
Get the current port protocol.
Definition: ocs_hal.c:6846
static int32_t ocs_mgmt_ip_get(ocs_t *ocs, char *, void *, uint32_t, void *, uint32_t)
Definition: ocs_mgmt.c:2091
#define ocs_assert(cond,...)
Definition: ocs_debug.h:163
ocs_ip_address_t subnet
Definition: ocs_iscsi.h:280
#define OCS_MAX_ISCSI_NAME
Definition: ocs_common.h:240
#define OCS_ISCSI_TCP_PORT
ocs_iscsi_tgt_ip_t * ip_info
Definition: ocs_iscsi.h:332
int32_t ocs_iscsi_inet_pton6(const char *src, ocs_ip_address_t *ip)
Converts an IPv6 address from a string to the IP structure.
Definition: ocs_iscsi.c:574
static void ocs_mgmt_fw_write_cb(int32_t status, uint32_t actual_write_length, void *arg)
Definition: ocs_mgmt.c:834
int access
Definition: ocs_mgmt.h:99
static void ocs_mgmt_get_profile_list_cb(void *ul_arg, int32_t status, uint32_t ext_status, void *params)
Definition: ocs_mgmt.c:851
int32_t ocs_iscsi_portal_create(ocs_t *ocs, unsigned int vlan_id, ocs_hal_portal_t *portal)
Creates a portal for a VLAN.
Definition: ocs_iscsi.c:3125
void * ocs_hal_get_ptr(ocs_hal_t *hal, ocs_hal_property_e prop)
Definition: ocs_hal.c:2753
HAL link config enum to mgmt string value mapping.
Definition: ocs_mgmt.c:1411
static void ocs_mgmt_get_port_protocol_cb(void *ul_arg, int32_t status, uint32_t ext_status, void *params)
Definition: ocs_mgmt.c:1055
static int32_t ocs_mgmt_chap_add_user(ocs_t *ocs, char *, void *, uint32_t, void *, uint32_t)
Definition: ocs_mgmt.c:3159
void ocs_mgmt_emit_string(ocs_textbuf_t *textbuf, int access, const char *name, const char *value)
Generate a property with a string value in a management XML document.
ocs_dma_t data_segment
Definition: ocs_ramdisc.h:80
#define ocs_list_foreach(list, item)
Iterate a linked list.
Definition: ocs_list.h:428
static void get_pci_subsystem_vendor(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2877
structure wrapping an IP address together with it&#39;s type.
Definition: ocs_iscsi_api.h:74
static void get_sli4_intf_reg(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2748
char tgt_name[OCS_MAX_ISCSI_NAME]
Definition: ocs_iscsi.h:245
static int set_header_digest(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:1246
static void get_ipl(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2704
static int32_t ocs_mgmt_chap_remove_user(ocs_t *ocs, char *, void *, uint32_t, void *, uint32_t)
Definition: ocs_mgmt.c:3187
void * ocs_scsi_get_property_ptr(ocs_t *ocs, ocs_scsi_property_e prop)
return a property pointer.
Definition: ocs_scsi.c:2119
ocs_hal_linkcfg_e linkcfg
Definition: ocs_mgmt.c:1412
#define OCS_CONFIG_LINKCFG_2X10G_2X8G
Definition: ocs_ioctl.h:478
ocs_difdma_t dif_segment
Definition: ocs_ramdisc.h:81
static int ocs_mgmt_firmware_reset(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void *, uint32_t)
Definition: ocs_mgmt.c:713
ocs_mgmt_table_entry_t mgmt_table[]
Definition: ocs_mgmt.c:187
static int32_t ocs_mgmt_listen_stop(ocs_t *ocs, char *, void *, uint32_t, void *, uint32_t)
Definition: ocs_mgmt.c:1677
int32_t ocs_iscsi_route_table_add_entry(ocs_t *ocs, ocs_ip_address_subnet_t *ipsub, ocs_ip_address_t *gateway)
Adds an entry to a routing table.
Definition: ocs_iscsi.c:2328
void ocs_mgmt_emit_property_name(ocs_textbuf_t *textbuf, int access, const char *name)
Generate a property, with no value, in a management XML document.
const char * mgmt_str
Definition: ocs_mgmt.c:1413
void ocs_debug_disable(uint32_t mask)
disable debug options
Definition: ocs_debug.c:106
static int set_jumbo_frames(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:1196
ocs_hal_rtn_e ocs_hal_firmware_write(ocs_hal_t *hal, ocs_dma_t *dma, uint32_t size, uint32_t offset, int last, ocs_hal_fw_cb_t cb, void *arg)
Write a portion of a firmware image to the device.
Definition: ocs_hal.c:6229
uint32_t num_ips
Definition: ocs_iscsi.h:331
#define OCS_DEBUG_ENABLE_WQ_DUMP
Definition: ocs_debug.h:157
static int32_t ocs_mgmt_route_parse_params(ocs_t *ocs, char *cmd_params, uint32_t params_len, char *ip_addr, char *netmask, char *gateway)
Definition: ocs_mgmt.c:2243
static int32_t ocs_mgmt_route_table_del_entry(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_len, void *arg_out, uint32_t arg_out_len)
Definition: ocs_mgmt.c:2280