1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 #include <stdio.h>
26 #include <libdevinfo.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <string.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <stropts.h>
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <strings.h>
36 #include <libintl.h>
37 #include <net/if_types.h>
38 #include <net/if_dl.h>
39 #include <sys/dld.h>
40 #include <sys/ib/ib_types.h>
41 #include <sys/ibpart.h>
42 #include <libdllink.h>
43 #include <libdladm.h>
44 #include <libdlib.h>
45 #include <libdladm_impl.h>
46
47 /*
48 * IP over IB administration API; see PSARC/2010/085
49 */
50
51 /*
52 * Function prototypes
53 */
54 dladm_status_t dladm_part_create(dladm_handle_t, datalink_id_t, ib_pkey_t,
55 uint32_t, char *, datalink_id_t *, dladm_arg_list_t *);
56 static dladm_status_t i_dladm_part_create(dladm_handle_t,
57 dladm_part_attr_t *);
58 static dladm_status_t dladm_part_persist_conf(dladm_handle_t, const char *,
59 dladm_part_attr_t *);
60 static dladm_status_t i_dladm_part_delete(dladm_handle_t, datalink_id_t);
61 dladm_status_t dladm_part_delete(dladm_handle_t, datalink_id_t, int);
62 static int i_dladm_part_up(dladm_handle_t, datalink_id_t, void *);
63 dladm_status_t dladm_part_up(dladm_handle_t, datalink_id_t, uint32_t);
64
65 /*
66 * Convert a error status returned by the IP over IB kernel driver to a
67 * valid dladm status.
68 */
69 static dladm_status_t
dladm_ib_ioctl_err2status(int err)70 dladm_ib_ioctl_err2status(int err)
71 {
72 switch (err) {
73 case 0:
74 return (DLADM_STATUS_OK);
75 case IBD_INVALID_PORT_INST:
76 return (DLADM_STATUS_INVALID_PORT_INSTANCE);
77 case IBD_PORT_IS_DOWN:
78 return (DLADM_STATUS_PORT_IS_DOWN);
79 case IBD_PKEY_NOT_PRESENT:
80 return (DLADM_STATUS_PKEY_NOT_PRESENT);
81 case IBD_PARTITION_EXISTS:
82 return (DLADM_STATUS_PARTITION_EXISTS);
83 case IBD_INVALID_PKEY:
84 return (DLADM_STATUS_INVALID_PKEY);
85 case IBD_NO_HW_RESOURCE:
86 return (DLADM_STATUS_NO_IB_HW_RESOURCE);
87 case IBD_INVALID_PKEY_TBL_SIZE:
88 return (DLADM_STATUS_INVALID_PKEY_TBL_SIZE);
89 default:
90 return (DLADM_STATUS_FAILED);
91 }
92 }
93
94 static dladm_status_t
i_dladm_ib_ioctl(dladm_handle_t handle,int ioccmd,ibd_ioctl_t * iocp)95 i_dladm_ib_ioctl(dladm_handle_t handle, int ioccmd, ibd_ioctl_t *iocp)
96 {
97 if (ioctl(dladm_dld_fd(handle), ioccmd, iocp) == 0)
98 return (DLADM_STATUS_OK);
99
100 if (iocp->ioc_status == 0)
101 return (dladm_errno2status(errno));
102
103 return (dladm_ib_ioctl_err2status(iocp->ioc_status));
104 }
105
106 /*
107 * Get the active configuration information for the partition given by
108 * the 'linkid'.
109 */
110 static dladm_status_t
i_dladm_part_info_active(dladm_handle_t handle,datalink_id_t linkid,dladm_part_attr_t * attrp)111 i_dladm_part_info_active(dladm_handle_t handle, datalink_id_t linkid,
112 dladm_part_attr_t *attrp)
113 {
114 ibpart_ioctl_t ioc;
115 dladm_status_t status = DLADM_STATUS_OK;
116
117 bzero(&ioc, sizeof (ioc));
118 bzero(attrp, sizeof (*attrp));
119 /*
120 * The ioc_linkid here will contain the data link id of the IB partition
121 * object.
122 */
123 ioc.ibdioc.ioc_linkid = linkid;
124 ioc.ibdioc.ioc_info_cmd = IBD_INFO_CMD_IBPART;
125
126 status = i_dladm_ib_ioctl(handle, IBD_INFO_IBPART, (ibd_ioctl_t *)&ioc);
127 if (status != DLADM_STATUS_OK)
128 goto bail;
129
130 /*
131 * On return from the ioctl ioc_linkid field contains the IB port's
132 * linkid.
133 */
134 attrp->dia_physlinkid = ioc.ibdioc.ioc_linkid;
135 attrp->dia_partlinkid = ioc.ioc_partid;
136 attrp->dia_pkey = ioc.ioc_pkey;
137 attrp->dia_portnum = ioc.ibdioc.ioc_portnum;
138 attrp->dia_hca_guid = ioc.ibdioc.ioc_hcaguid;
139 attrp->dia_port_guid = ioc.ibdioc.ioc_portguid;
140 attrp->dia_instance = ioc.ibdioc.ioc_port_inst;
141
142 /*
143 * If the IP over IB driver reports that this partition was created
144 * forcibly, then set the force create flag.
145 */
146 if (ioc.ioc_force_create)
147 attrp->dia_flags |= DLADM_PART_FORCE_CREATE;
148
149 bail:
150 return (status);
151 }
152
153 /*
154 * Get the configuration information about the IB partition 'linkid' from the
155 * persistent configuration.
156 */
157 static dladm_status_t
i_dladm_part_info_persist(dladm_handle_t handle,datalink_id_t linkid,dladm_part_attr_t * attrp)158 i_dladm_part_info_persist(dladm_handle_t handle, datalink_id_t linkid,
159 dladm_part_attr_t *attrp)
160 {
161 dladm_conf_t conf;
162 dladm_status_t status;
163 char linkover[MAXLINKNAMELEN];
164 datalink_class_t class;
165 boolean_t force = B_FALSE;
166
167 conf.ds_readonly = B_FALSE;
168 conf.ds_confid = DLADM_INVALID_CONF;
169
170 /* Get the IB partition's datalink ID */
171 if ((status = dladm_datalink_id2info(handle, linkid, NULL, &class,
172 NULL, NULL, 0)) != DLADM_STATUS_OK)
173 goto done;
174
175 bzero(attrp, sizeof (*attrp));
176 attrp->dia_partlinkid = linkid;
177 if ((status = dladm_getsnap_conf(handle, linkid, &conf)) !=
178 DLADM_STATUS_OK)
179 return (status);
180
181 /*
182 * Get the name of the IB Phys link over which IB partition was
183 * created.
184 */
185 status = dladm_get_conf_field(handle, conf, FLINKOVER, linkover,
186 sizeof (linkover));
187 if (status != DLADM_STATUS_OK) {
188 attrp->dia_physlinkid = DATALINK_INVALID_LINKID;
189 goto done;
190 } else {
191 /* Get the IB Phys link's datalink ID */
192 if ((status = dladm_name2info(handle, linkover,
193 &attrp->dia_physlinkid, NULL, NULL, NULL)) !=
194 DLADM_STATUS_OK)
195 goto done;
196 }
197
198 /* Get the IB partition's P_Key */
199 status = dladm_get_conf_field(handle, conf, FPORTPKEY,
200 &attrp->dia_pkey, sizeof (uint64_t));
201 if (status != DLADM_STATUS_OK)
202 goto done;
203
204 if (class != DATALINK_CLASS_PART) {
205 status = DLADM_STATUS_BADARG;
206 goto done;
207 }
208
209 /*
210 * If the FFORCE field is set in the persistent configuration database
211 * set the force create flag in the partition attributes.
212 */
213 status = dladm_get_conf_field(handle, conf, FFORCE, &force,
214 sizeof (boolean_t));
215 if (status != DLADM_STATUS_OK) {
216 if (status != DLADM_STATUS_NOTFOUND)
217 goto done;
218 } else if (force == B_TRUE) {
219 attrp->dia_flags |= DLADM_PART_FORCE_CREATE;
220 }
221
222 status = DLADM_STATUS_OK;
223 done:
224 dladm_destroy_conf(handle, conf);
225 return (status);
226 }
227
228 /*
229 * Get the configuration information for the IB partition given by the datalink
230 * ID 'linkid'. Based on the 'flags' field the information is either from the
231 * active system (DLADM_OPT_ACTIVE) or from the persistent configuration
232 * database.
233 */
234 dladm_status_t
dladm_part_info(dladm_handle_t handle,datalink_id_t linkid,dladm_part_attr_t * attrp,uint32_t flags)235 dladm_part_info(dladm_handle_t handle, datalink_id_t linkid,
236 dladm_part_attr_t *attrp, uint32_t flags)
237 {
238 if (flags == DLADM_OPT_ACTIVE)
239 return (i_dladm_part_info_active(handle, linkid, attrp));
240 else if (flags == DLADM_OPT_PERSIST)
241 return (i_dladm_part_info_persist(handle, linkid, attrp));
242 else
243 return (DLADM_STATUS_BADARG);
244 }
245
246 /*
247 * Get the configuration information for the IB Phys link given by the datalink
248 * ID 'linkid'.
249 */
250 dladm_status_t
dladm_ib_info(dladm_handle_t handle,datalink_id_t linkid,dladm_ib_attr_t * attrp,uint32_t flags __unused)251 dladm_ib_info(dladm_handle_t handle, datalink_id_t linkid,
252 dladm_ib_attr_t *attrp, uint32_t flags __unused)
253 {
254 uint_t instance;
255 ibport_ioctl_t ioc;
256 dladm_phys_attr_t dpa;
257 dladm_status_t status = DLADM_STATUS_OK;
258
259 /*
260 * We need to get the device name of the IB Phys link to get the
261 * correct instance number of the IP over IB driver instance.
262 */
263 if (dladm_phys_info(handle, linkid, &dpa, DLADM_OPT_ACTIVE)
264 != DLADM_STATUS_OK)
265 return (DLADM_STATUS_BADARG);
266
267 /*
268 * Get the instance number of the IP over IB driver instance which
269 * represents this IB Phys link.
270 */
271 if (dladm_parselink(dpa.dp_dev, NULL, &instance) != DLADM_STATUS_OK)
272 return (DLADM_STATUS_FAILED);
273
274 bzero(&ioc, sizeof (ioc));
275 /*
276 * The ioc_linkid here will contain IB port linkid here. We make the
277 * first ioctl call to get the P_Key table size for this HCA port.
278 */
279 ioc.ibdioc.ioc_linkid = linkid;
280 ioc.ibdioc.ioc_info_cmd = IBD_INFO_CMD_PKEYTBLSZ;
281 ioc.ioc_pkey_tbl_sz = 0;
282 ioc.ibdioc.ioc_port_inst = instance;
283
284 status = i_dladm_ib_ioctl(handle, IBD_INFO_IBPART, (ibd_ioctl_t *)&ioc);
285 if (status != DLADM_STATUS_OK)
286 return (status);
287
288 /*
289 * Now allocate the memory for the P_Key table based on the table size
290 * return by the ioctl.
291 */
292 ioc.ioc_pkeys = calloc(sizeof (ib_pkey_t), ioc.ioc_pkey_tbl_sz);
293 if (ioc.ioc_pkeys == NULL) {
294 status = dladm_errno2status(errno);
295 goto bail;
296 }
297
298 /*
299 * Call the ioctl again to get the P_Key table and other IB Phys link
300 * attributes.
301 */
302 ioc.ibdioc.ioc_linkid = linkid;
303 ioc.ibdioc.ioc_port_inst = instance;
304 ioc.ibdioc.ioc_info_cmd = IBD_INFO_CMD_IBPORT;
305
306 status = i_dladm_ib_ioctl(handle, IBD_INFO_IBPART, (ibd_ioctl_t *)&ioc);
307 if (status != DLADM_STATUS_OK)
308 goto bail;
309
310 attrp->dia_physlinkid = ioc.ibdioc.ioc_linkid;
311 attrp->dia_portnum = ioc.ibdioc.ioc_portnum;
312 attrp->dia_port_pkey_tbl_sz = ioc.ioc_pkey_tbl_sz;
313 attrp->dia_port_pkeys = ioc.ioc_pkeys;
314 attrp->dia_hca_guid = ioc.ibdioc.ioc_hcaguid;
315 attrp->dia_port_guid = ioc.ibdioc.ioc_portguid;
316 attrp->dia_instance = ioc.ibdioc.ioc_port_inst;
317 return (status);
318 bail:
319 free(ioc.ioc_pkeys);
320 return (status);
321 }
322
323 /*
324 * Free the memory allocated for the IB HCA port's P_Key table by
325 * dladm_ib_info library call.
326 */
327 void
dladm_free_ib_info(dladm_ib_attr_t * attr)328 dladm_free_ib_info(dladm_ib_attr_t *attr)
329 {
330 if (attr && attr->dia_port_pkeys)
331 free(attr->dia_port_pkeys);
332 }
333
334 /*
335 * Call into the IP over IB driver to create a partition object.
336 */
337 static dladm_status_t
i_dladm_part_create(dladm_handle_t handle,dladm_part_attr_t * pattr)338 i_dladm_part_create(dladm_handle_t handle, dladm_part_attr_t *pattr)
339 {
340 ibpart_ioctl_t ioc;
341
342 bzero(&ioc, sizeof (ioc));
343
344 /* IB Physical datalink ID */
345 ioc.ibdioc.ioc_linkid = pattr->dia_physlinkid;
346 /* IB Partition datalink ID */
347 ioc.ioc_partid = pattr->dia_partlinkid;
348 ioc.ioc_pkey = pattr->dia_pkey;
349 ioc.ibdioc.ioc_port_inst = pattr->dia_instance;
350 ioc.ioc_force_create = ((pattr->dia_flags & DLADM_OPT_FORCE)
351 != 0);
352
353 return (i_dladm_ib_ioctl(handle, IBD_CREATE_IBPART, &ioc.ibdioc));
354 }
355
356 /*
357 * Create an entry in the dladm persistent configuration database for the
358 * partition specified by pattr.
359 */
360 dladm_status_t
dladm_part_persist_conf(dladm_handle_t handle,const char * pname,dladm_part_attr_t * pattr)361 dladm_part_persist_conf(dladm_handle_t handle, const char *pname,
362 dladm_part_attr_t *pattr)
363 {
364
365 dladm_conf_t conf;
366 dladm_status_t status;
367 char linkover[MAXLINKNAMELEN];
368 uint64_t u64;
369
370 status = dladm_create_conf(handle, pname, pattr->dia_partlinkid,
371 DATALINK_CLASS_PART, DL_IB, &conf);
372 if (status != DLADM_STATUS_OK)
373 return (status);
374
375 /*
376 * Get the name of the IB Phys link over which this partition was
377 * created.
378 */
379 status = dladm_datalink_id2info(handle, pattr->dia_physlinkid,
380 NULL, NULL, NULL, linkover, sizeof (linkover));
381 if (status != DLADM_STATUS_OK)
382 return (status);
383
384 /* Store IB Phys link name (linkover) */
385 status = dladm_set_conf_field(handle, conf, FLINKOVER, DLADM_TYPE_STR,
386 linkover);
387 if (status != DLADM_STATUS_OK)
388 return (status);
389
390 u64 = pattr->dia_pkey;
391
392 /* Store the IB Partitions P_Key */
393 status = dladm_set_conf_field(handle, conf, FPORTPKEY,
394 DLADM_TYPE_UINT64, &u64);
395 if (status != DLADM_STATUS_OK)
396 return (status);
397
398 if (pattr->dia_flags & DLADM_OPT_FORCE) {
399 boolean_t force = B_TRUE;
400 /* Store the force create flag. */
401 status = dladm_set_conf_field(handle, conf, FFORCE,
402 DLADM_TYPE_BOOLEAN, &force);
403 if (status != DLADM_STATUS_OK)
404 goto done;
405 }
406
407 status = dladm_write_conf(handle, conf);
408 if (status != DLADM_STATUS_OK)
409 return (status);
410
411 dladm_destroy_conf(handle, conf);
412 done:
413 return (status);
414 }
415
416 /*
417 * Create a new IB Partition datalink of name 'pname' over the IB Physical link
418 * given in 'physlinkid' with the P_key 'pkey' and return the datalink ID in
419 * 'partlinkid'. If the 'force' option is set in the 'flags' argument, the
420 * partition will be created even if the P_Key 'pkey' does not exist or if the
421 * HCA port represented by the IB Phys link is down. If the 'temporary' flag is
422 * set, then the configuration information is not added to the persistent
423 * database.
424 */
425 dladm_status_t
dladm_part_create(dladm_handle_t handle,datalink_id_t physlinkid,ib_pkey_t pkey,uint32_t flags,char * pname,datalink_id_t * partlinkid,dladm_arg_list_t * proplist)426 dladm_part_create(dladm_handle_t handle, datalink_id_t physlinkid,
427 ib_pkey_t pkey, uint32_t flags, char *pname, datalink_id_t *partlinkid,
428 dladm_arg_list_t *proplist)
429 {
430 uint_t i;
431 dladm_status_t status;
432 uint_t media;
433 boolean_t part_created = B_FALSE;
434 boolean_t conf_set = B_FALSE;
435 dladm_phys_attr_t dpa;
436 dladm_part_attr_t pattr;
437
438 pattr.dia_pkey = pkey;
439 pattr.dia_physlinkid = physlinkid; /* IB Phys link's datalink id */
440 pattr.dia_flags = flags;
441
442 flags &= ~DLADM_OPT_FORCE;
443
444 /*
445 * Check whether the PKEY is valid. If not, return immediately
446 * Only full members are allowed as per the IPoIB specification
447 */
448 if (pattr.dia_pkey <= IB_PKEY_INVALID_FULL)
449 return (DLADM_STATUS_INVALID_PKEY);
450
451 /*
452 * Get the media type of the Phys link datalink ID provided and
453 * make sure that it is Infiniband media DL_IB)
454 */
455 if ((status = dladm_datalink_id2info(handle, pattr.dia_physlinkid, NULL,
456 NULL, &media, NULL, 0)) != DLADM_STATUS_OK)
457 return (status);
458
459 if (media != DL_IB)
460 return (dladm_errno2status(ENOTSUP));
461
462 /*
463 * Get the instance number of the IP over IB driver instance which the
464 * IB Phys link 'physlinkid' over which we will be creating our IB
465 * partition.
466 */
467 if ((status = dladm_phys_info(handle, pattr.dia_physlinkid, &dpa,
468 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK)
469 return (status);
470
471 if (dladm_parselink(dpa.dp_dev, NULL, (uint_t *)&pattr.dia_instance) !=
472 DLADM_STATUS_OK)
473 return (DLADM_STATUS_FAILED);
474
475
476 if ((status = dladm_create_datalink_id(handle, pname,
477 DATALINK_CLASS_PART, DL_IB, flags, &pattr.dia_partlinkid)) !=
478 DLADM_STATUS_OK)
479 return (status);
480
481 /*
482 * Create the IB partition object.
483 */
484 status = i_dladm_part_create(handle, &pattr);
485 if (status != DLADM_STATUS_OK)
486 goto done;
487
488 part_created = B_TRUE;
489
490 /*
491 * If the persist flag is set then write this partition information
492 * to the persistent configuration.
493 */
494 if (pattr.dia_flags & DLADM_OPT_PERSIST) {
495 status = dladm_part_persist_conf(handle, pname, &pattr);
496 if (status != DLADM_STATUS_OK)
497 goto done;
498 conf_set = B_TRUE;
499 }
500
501 /*
502 * If the name-value pair list of properties were provided set those
503 * properties over the datalink.
504 */
505 if (proplist != NULL) {
506 for (i = 0; i < proplist->al_count; i++) {
507 dladm_arg_info_t *aip = &proplist->al_info[i];
508
509 status = dladm_set_linkprop(handle,
510 pattr.dia_partlinkid, aip->ai_name, aip->ai_val,
511 aip->ai_count, pattr.dia_flags);
512 if (status != DLADM_STATUS_OK)
513 break;
514 }
515 }
516 done:
517 if (status != DLADM_STATUS_OK) {
518 if (conf_set)
519 (void) dladm_remove_conf(handle, pattr.dia_partlinkid);
520 if (part_created)
521 (void) i_dladm_part_delete(handle,
522 pattr.dia_partlinkid);
523 (void) dladm_destroy_datalink_id(handle, pattr.dia_partlinkid,
524 flags);
525 }
526
527 if (partlinkid != NULL)
528 *partlinkid = pattr.dia_partlinkid;
529
530 return (status);
531 }
532
533 /*
534 * Call into the IP over IB driver to delete the IB partition and free up all
535 * the resources allocated for it.
536 */
537 static dladm_status_t
i_dladm_part_delete(dladm_handle_t handle,datalink_id_t partid)538 i_dladm_part_delete(dladm_handle_t handle, datalink_id_t partid)
539 {
540 ibpart_ioctl_t ioc;
541
542 bzero(&ioc, sizeof (ioc));
543 ioc.ioc_partid = partid;
544 return (i_dladm_ib_ioctl(handle, IBD_DELETE_IBPART, &ioc.ibdioc));
545 }
546
547 /*
548 * Delete an IB partition if 'flags' contains the active flag. Update the
549 * persistent configuration if 'flags' contains the persist flag.
550 */
551 dladm_status_t
dladm_part_delete(dladm_handle_t handle,datalink_id_t partid,int flags)552 dladm_part_delete(dladm_handle_t handle, datalink_id_t partid, int flags)
553 {
554 dladm_status_t status = DLADM_STATUS_OK;
555 datalink_class_t class;
556
557 if (flags == 0)
558 return (DLADM_STATUS_BADARG);
559
560 /*
561 * Make sure that the datalinkid provided is an IB partition class
562 * datalink ID.
563 */
564 if ((dladm_datalink_id2info(handle, partid, NULL, &class, NULL, NULL, 0)
565 != DLADM_STATUS_OK))
566 return (DLADM_STATUS_BADARG);
567
568 if (class != DATALINK_CLASS_PART)
569 return (DLADM_STATUS_BADARG);
570
571 if ((flags & DLADM_OPT_ACTIVE) != 0) {
572 status = i_dladm_part_delete(handle, partid);
573 if (status == DLADM_STATUS_OK) {
574 (void) dladm_set_linkprop(handle, partid, NULL, NULL, 0,
575 DLADM_OPT_ACTIVE);
576 (void) dladm_destroy_datalink_id(handle, partid,
577 DLADM_OPT_ACTIVE);
578 } else if (status != DLADM_STATUS_NOTFOUND ||
579 !(flags & DLADM_OPT_PERSIST)) {
580 return (status);
581 }
582 }
583
584 if ((flags & DLADM_OPT_PERSIST) != 0) {
585 dladm_status_t db_status;
586 db_status = dladm_remove_conf(handle, partid);
587
588 /*
589 * A partition could have been temporarily deleted in which
590 * case the delete of the active partition above would have
591 * failed. In that case, we update the status to be returned
592 * to that of the status returned for deleting the persistent
593 * database entry.
594 */
595 if (status == DLADM_STATUS_NOTFOUND)
596 status = db_status;
597
598 (void) dladm_destroy_datalink_id(handle, partid,
599 DLADM_OPT_PERSIST);
600 }
601
602 return (status);
603 }
604
605 /*
606 * Call into the IP over IB driver to create the active instances of one or all
607 * IB partitions present in the persistent configuration.
608 */
609 static int
i_dladm_part_up(dladm_handle_t handle,datalink_id_t plinkid,void * arg __unused)610 i_dladm_part_up(dladm_handle_t handle, datalink_id_t plinkid,
611 void *arg __unused)
612 {
613 dladm_conf_t conf;
614 datalink_id_t linkid;
615 ib_pkey_t pkey;
616 uint64_t u64;
617 char linkover[MAXLINKNAMELEN];
618 dladm_status_t status;
619 dladm_phys_attr_t dpa;
620 dladm_part_attr_t pattr;
621
622 /*
623 * plinkid is the IB partition datalink's ID. Get an handle to the
624 * persistent configuration entry for this datalink ID. If this datalink
625 * ID is not present in the persistent configuration return.
626 */
627 if ((status = dladm_getsnap_conf(handle, plinkid, &conf)) !=
628 DLADM_STATUS_OK)
629 return (status);
630
631 /*
632 * Get the name of the IB Phys link over which this partition was
633 * created.
634 */
635 status = dladm_get_conf_field(handle, conf, FLINKOVER, linkover,
636 sizeof (linkover));
637 if (status != DLADM_STATUS_OK)
638 goto done;
639
640 if ((status = dladm_name2info(handle, linkover, &linkid, NULL, NULL,
641 NULL)) != DLADM_STATUS_OK)
642 goto done;
643
644 /*
645 * Get the phys attribute of the IB Phys link to get the device name
646 * associated with the phys link. We need this to get the IP over IB
647 * driver instance number.
648 */
649 if (dladm_phys_info(handle, linkid, &dpa, DLADM_OPT_ACTIVE)
650 != DLADM_STATUS_OK)
651 goto done;
652
653 /* Get the IB partition's P_key */
654 status = dladm_get_conf_field(handle, conf, FPORTPKEY, &u64,
655 sizeof (u64));
656 if (status != DLADM_STATUS_OK)
657 goto done;
658
659 pkey = (ib_pkey_t)u64;
660
661 /*
662 * We always set the force flag during dladm_part_up because we want
663 * the partition creation to succeed even if the IB HCA port over which
664 * the partition is being created is still down. Since dladm_part_up
665 * is usually invoked during early boot sequence, it is possible under
666 * some IB subnet configurations for dladm_up_part to be called before
667 * the IB link negotiation is completed and port state is set to active
668 * and P_Key table is updated.
669 */
670 pattr.dia_flags = DLADM_OPT_FORCE | DLADM_OPT_ACTIVE |
671 DLADM_OPT_PERSIST;
672 /* IB Phys link's datalink ID. */
673 pattr.dia_physlinkid = linkid;
674 /* IB Partition's datalink ID. */
675 pattr.dia_partlinkid = plinkid;
676 pattr.dia_pkey = pkey;
677 if (dladm_parselink(dpa.dp_dev, NULL, (uint_t *)&pattr.dia_instance) !=
678 DLADM_STATUS_OK)
679 return (DLADM_WALK_CONTINUE);
680
681 /* Create the active IB Partition object. */
682 if (i_dladm_part_create(handle, &pattr) == DLADM_STATUS_OK &&
683 dladm_up_datalink_id(handle, plinkid) != DLADM_STATUS_OK)
684 (void) i_dladm_part_delete(handle, linkid);
685
686 done:
687 dladm_destroy_conf(handle, conf);
688 return (DLADM_WALK_CONTINUE);
689 }
690
691 /*
692 * Bring up one or all IB partition(s) present in the persistent configuration
693 * database. If we need to bring up one IB Partition, its datalink ID is
694 * provided in 'linkid'.
695 */
696 dladm_status_t
dladm_part_up(dladm_handle_t handle,datalink_id_t linkid,uint32_t flags __unused)697 dladm_part_up(dladm_handle_t handle, datalink_id_t linkid,
698 uint32_t flags __unused)
699 {
700 dladm_status_t status = DLADM_STATUS_OK;
701
702 if (linkid == DATALINK_ALL_LINKID) {
703 (void) dladm_walk_datalink_id(i_dladm_part_up, handle,
704 &status, DATALINK_CLASS_PART, DATALINK_ANY_MEDIATYPE,
705 DLADM_OPT_PERSIST);
706 return (DLADM_STATUS_OK);
707 } else {
708 (void) i_dladm_part_up(handle, linkid, &status);
709 return (status);
710 }
711 }
712