diff options
author | Ramaswamy Tummala <Ramaswamy.Tummala@Sun.COM> | 2010-04-14 10:26:18 -0700 |
---|---|---|
committer | Ramaswamy Tummala <Ramaswamy.Tummala@Sun.COM> | 2010-04-14 10:26:18 -0700 |
commit | 1cfa752f4e24c34133009b0f6c139127a5c461de (patch) | |
tree | 6ffe378521988d12eb5fb895e53549460bf2a47c /usr/src/lib/libdladm | |
parent | 97689f66b4d49d8e41fb47ce04dd38217fba0acb (diff) | |
download | illumos-joyent-1cfa752f4e24c34133009b0f6c139127a5c461de.tar.gz |
PSARC 2010/085 IPoIB Administration Enhancement
6837574 IPoIB Administration Enhancement - PSARC 2010/085
6864899 IB datalink names need to be consistent between cluster controllers
6855737 cfgadm status for ibd attachment points gets to inconsistent state
6883212 ibd: add Brussels framework support
6927048 IBD driver should be hardened to handle late HCA port initialization issue
6827237 Fix warlock errors in ibnex
--HG--
rename : usr/src/uts/common/io/ib/clients/ibd/ibd.conf => usr/src/uts/common/io/ib/clients/ibd/ibp.conf
rename : usr/src/uts/intel/ibd/Makefile => usr/src/uts/intel/ibp/Makefile
rename : usr/src/uts/sparc/ibd/Makefile => usr/src/uts/sparc/ibp/Makefile
Diffstat (limited to 'usr/src/lib/libdladm')
-rw-r--r-- | usr/src/lib/libdladm/Makefile | 9 | ||||
-rw-r--r-- | usr/src/lib/libdladm/Makefile.com | 5 | ||||
-rw-r--r-- | usr/src/lib/libdladm/common/libdladm.c | 27 | ||||
-rw-r--r-- | usr/src/lib/libdladm/common/libdladm.h | 9 | ||||
-rw-r--r-- | usr/src/lib/libdladm/common/libdladm_impl.h | 8 | ||||
-rw-r--r-- | usr/src/lib/libdladm/common/libdlib.c | 732 | ||||
-rw-r--r-- | usr/src/lib/libdladm/common/libdlib.h | 78 | ||||
-rw-r--r-- | usr/src/lib/libdladm/common/libdllink.c | 24 | ||||
-rw-r--r-- | usr/src/lib/libdladm/common/linkprop.c | 50 | ||||
-rw-r--r-- | usr/src/lib/libdladm/common/llib-ldladm | 4 | ||||
-rw-r--r-- | usr/src/lib/libdladm/common/mapfile-vers | 10 |
11 files changed, 935 insertions, 21 deletions
diff --git a/usr/src/lib/libdladm/Makefile b/usr/src/lib/libdladm/Makefile index 3e5457f227..92de14cc8a 100644 --- a/usr/src/lib/libdladm/Makefile +++ b/usr/src/lib/libdladm/Makefile @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. # # @@ -29,7 +28,8 @@ include $(SRC)/lib/Makefile.lib HDRS = libdladm.h libdladm_impl.h libdllink.h libdlaggr.h \ libdlwlan.h libdlwlan_impl.h libdlvnic.h libdlvlan.h \ libdlmgmt.h libdlflow.h libdlflow_impl.h libdlstat.h \ - libdlether.h libdlsim.h libdlbridge.h libdliptun.h + libdlether.h libdlsim.h libdlbridge.h libdliptun.h \ + libdlib.h HDRDIR = common @@ -45,7 +45,8 @@ MSGFILES = common/libdladm.c common/linkprop.c common/secobj.c \ common/propfuncs.c common/libdlflow.c \ common/libdlstat.c common/flowattr.c \ common/libdlether.c common/libdlsim.c \ - common/libdlbridge.c common/libdliptun.c + common/libdlbridge.c common/libdliptun.c\ + common/libdlib.c XGETFLAGS = -a -x libdladm.xcl diff --git a/usr/src/lib/libdladm/Makefile.com b/usr/src/lib/libdladm/Makefile.com index 791a1e65dc..5c61d566bc 100644 --- a/usr/src/lib/libdladm/Makefile.com +++ b/usr/src/lib/libdladm/Makefile.com @@ -19,14 +19,13 @@ # CDDL HEADER END # # -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. # LIBRARY = libdladm.a VERS = .1 OBJECTS = libdladm.o secobj.o linkprop.o libdllink.o libdlaggr.o \ - libdlwlan.o libdlvnic.o libdlmgmt.o libdlvlan.o \ + libdlwlan.o libdlvnic.o libdlmgmt.o libdlvlan.o libdlib.o\ flowattr.o flowprop.o propfuncs.o libdlflow.o libdlstat.o \ usage.o libdlether.o libdlsim.o libdlbridge.o libdliptun.o diff --git a/usr/src/lib/libdladm/common/libdladm.c b/usr/src/lib/libdladm/common/libdladm.c index 7531a5c368..e2613402c9 100644 --- a/usr/src/lib/libdladm/common/libdladm.c +++ b/usr/src/lib/libdladm/common/libdladm.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <unistd.h> @@ -385,6 +384,27 @@ dladm_status2str(dladm_status_t status, char *buf) case DLADM_STATUS_POOLCPU: s = "pool and cpus property are mutually exclusive"; break; + case DLADM_STATUS_INVALID_PORT_INSTANCE: + s = "invalid IB phys link"; + break; + case DLADM_STATUS_PORT_IS_DOWN: + s = "port is down"; + break; + case DLADM_STATUS_PARTITION_EXISTS: + s = "partition already exists"; + break; + case DLADM_STATUS_PKEY_NOT_PRESENT: + s = "PKEY is not present on the port"; + break; + case DLADM_STATUS_INVALID_PKEY: + s = "invalid PKEY"; + break; + case DLADM_STATUS_NO_IB_HW_RESOURCE: + s = "IB internal resource not available"; + break; + case DLADM_STATUS_INVALID_PKEY_TBL_SIZE: + s = "invalid PKEY table size"; + break; default: s = "<unknown error>"; break; @@ -618,6 +638,9 @@ dladm_class2str(datalink_class_t class, char *buf) case DATALINK_CLASS_BRIDGE: s = "bridge"; break; + case DATALINK_CLASS_PART: + s = "part"; + break; default: s = "unknown"; break; diff --git a/usr/src/lib/libdladm/common/libdladm.h b/usr/src/lib/libdladm/common/libdladm.h index 3c0adea5ff..0d82640e71 100644 --- a/usr/src/lib/libdladm/common/libdladm.h +++ b/usr/src/lib/libdladm/common/libdladm.h @@ -161,7 +161,14 @@ typedef enum { DLADM_STATUS_NO_HWRINGS, DLADM_STATUS_PERMONLY, DLADM_STATUS_OPTMISSING, - DLADM_STATUS_POOLCPU + DLADM_STATUS_POOLCPU, + DLADM_STATUS_INVALID_PORT_INSTANCE, + DLADM_STATUS_PORT_IS_DOWN, + DLADM_STATUS_PKEY_NOT_PRESENT, + DLADM_STATUS_PARTITION_EXISTS, + DLADM_STATUS_INVALID_PKEY, + DLADM_STATUS_NO_IB_HW_RESOURCE, + DLADM_STATUS_INVALID_PKEY_TBL_SIZE } dladm_status_t; typedef enum { diff --git a/usr/src/lib/libdladm/common/libdladm_impl.h b/usr/src/lib/libdladm/common/libdladm_impl.h index 47bb94b5f7..07937f2c04 100644 --- a/usr/src/lib/libdladm/common/libdladm_impl.h +++ b/usr/src/lib/libdladm/common/libdladm_impl.h @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _LIBDLADM_IMPL_H @@ -103,6 +102,11 @@ extern void dladm_free_args(dladm_arg_list_t *); #define FSIMNETPEER "simnetpeer" /* uint64_t */ /* + * Set for IB partitions only + */ +#define FPORTPKEY "pkey" /* uint64_t */ + +/* * Common fields */ #define FMACADDR "macaddr" /* string */ diff --git a/usr/src/lib/libdladm/common/libdlib.c b/usr/src/lib/libdladm/common/libdlib.c new file mode 100644 index 0000000000..a58e509af8 --- /dev/null +++ b/usr/src/lib/libdladm/common/libdlib.c @@ -0,0 +1,732 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + */ + +#include <stdio.h> +#include <libdevinfo.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <stropts.h> +#include <stdlib.h> +#include <errno.h> +#include <strings.h> +#include <libintl.h> +#include <net/if_types.h> +#include <net/if_dl.h> +#include <sys/dld.h> +#include <sys/ib/ib_types.h> +#include <sys/ibpart.h> +#include <libdllink.h> +#include <libdladm.h> +#include <libdlib.h> +#include <libdladm_impl.h> + +/* + * IP over IB administration API; see PSARC/2010/085 + */ + +/* + * Function prototypes + */ +dladm_status_t dladm_part_create(dladm_handle_t, datalink_id_t, ib_pkey_t, + uint32_t, char *, datalink_id_t *, dladm_arg_list_t *); +static int dladm_ibd_get_instance(char *); +static dladm_status_t i_dladm_part_create(dladm_handle_t, + dladm_part_attr_t *); +dladm_status_t dladm_part_persist_conf(dladm_handle_t, dladm_part_attr_t *); +static dladm_status_t i_dladm_part_delete(dladm_handle_t, datalink_id_t); +dladm_status_t dladm_part_delete(dladm_handle_t, datalink_id_t, int); +static int i_dladm_part_up(dladm_handle_t, datalink_id_t, void *); +dladm_status_t dladm_part_up(dladm_handle_t, datalink_id_t, uint32_t); + +/* + * Convert a error status returned by the IP over IB kernel driver to a + * valid dladm status. + */ +static dladm_status_t +dladm_ib_ioctl_err2status(int err) +{ + switch (err) { + case 0: + return (DLADM_STATUS_OK); + case IBD_INVALID_PORT_INST: + return (DLADM_STATUS_INVALID_PORT_INSTANCE); + case IBD_PORT_IS_DOWN: + return (DLADM_STATUS_PORT_IS_DOWN); + case IBD_PKEY_NOT_PRESENT: + return (DLADM_STATUS_PKEY_NOT_PRESENT); + case IBD_PARTITION_EXISTS: + return (DLADM_STATUS_PARTITION_EXISTS); + case IBD_INVALID_PKEY: + return (DLADM_STATUS_INVALID_PKEY); + case IBD_NO_HW_RESOURCE: + return (DLADM_STATUS_NO_IB_HW_RESOURCE); + case IBD_INVALID_PKEY_TBL_SIZE: + return (DLADM_STATUS_INVALID_PKEY_TBL_SIZE); + default: + return (DLADM_STATUS_FAILED); + } +} + +static dladm_status_t +i_dladm_ib_ioctl(dladm_handle_t handle, int ioccmd, ibd_ioctl_t *iocp) +{ + if (ioctl(dladm_dld_fd(handle), ioccmd, iocp) == 0) + return (DLADM_STATUS_OK); + + if (iocp->ioc_status == 0) + return (dladm_errno2status(errno)); + + return (dladm_ib_ioctl_err2status(iocp->ioc_status)); +} + +/* + * Get the active configuration information for the partition given by + * the 'linkid'. + */ +static dladm_status_t +i_dladm_part_info_active(dladm_handle_t handle, datalink_id_t linkid, + dladm_part_attr_t *attrp) +{ + ibpart_ioctl_t ioc; + dladm_status_t status = DLADM_STATUS_OK; + + bzero(&ioc, sizeof (ioc)); + bzero(attrp, sizeof (*attrp)); + /* + * The ioc_linkid here will contain the data link id of the IB partition + * object. + */ + ioc.ibdioc.ioc_linkid = linkid; + ioc.ibdioc.ioc_info_cmd = IBD_INFO_CMD_IBPART; + + status = i_dladm_ib_ioctl(handle, IBD_INFO_IBPART, (ibd_ioctl_t *)&ioc); + if (status != DLADM_STATUS_OK) + goto bail; + + /* + * On return from the ioctl ioc_linkid field contains the IB port's + * linkid. + */ + attrp->dia_physlinkid = ioc.ibdioc.ioc_linkid; + attrp->dia_partlinkid = ioc.ioc_partid; + attrp->dia_pkey = ioc.ioc_pkey; + attrp->dia_portnum = ioc.ibdioc.ioc_portnum; + attrp->dia_hca_guid = ioc.ibdioc.ioc_hcaguid; + attrp->dia_port_guid = ioc.ibdioc.ioc_portguid; + attrp->dia_instance = ioc.ibdioc.ioc_port_inst; + + /* + * If the IP over IB driver reports that this partition was created + * forcibly, then set the force create flag. + */ + if (ioc.ioc_force_create) + attrp->dia_flags |= DLADM_IBPART_FORCE_CREATE; + +bail: + return (status); +} + +/* + * Get the configuration information about the IB partition 'linkid' from the + * persistent configuration. + */ +static dladm_status_t +i_dladm_part_info_persist(dladm_handle_t handle, datalink_id_t linkid, + dladm_part_attr_t *attrp) +{ + dladm_conf_t conf; + dladm_status_t status; + char linkover[MAXLINKNAMELEN]; + datalink_class_t class; + boolean_t force = B_FALSE; + + /* Get the IB partition's datalink ID */ + if ((status = dladm_datalink_id2info(handle, linkid, NULL, &class, + NULL, NULL, 0)) != DLADM_STATUS_OK) + goto done; + + bzero(attrp, sizeof (*attrp)); + attrp->dia_partlinkid = linkid; + if ((status = dladm_read_conf(handle, linkid, &conf)) != + DLADM_STATUS_OK) + return (status); + + /* + * Get the name of the IB Phys link over which IB partition was + * created. + */ + status = dladm_get_conf_field(handle, conf, FLINKOVER, linkover, + sizeof (linkover)); + if (status != DLADM_STATUS_OK) { + attrp->dia_physlinkid = DATALINK_INVALID_LINKID; + goto done; + } else { + /* Get the IB Phys link's datalink ID */ + if ((status = dladm_name2info(handle, linkover, + &attrp->dia_physlinkid, NULL, NULL, NULL)) != + DLADM_STATUS_OK) + goto done; + } + + /* Get the IB partition's P_Key */ + status = dladm_get_conf_field(handle, conf, FPORTPKEY, + &attrp->dia_pkey, sizeof (uint64_t)); + if (status != DLADM_STATUS_OK) + goto done; + + if (class != DATALINK_CLASS_PART) { + status = DLADM_STATUS_BADARG; + goto done; + } + + /* + * If the FFORCE field is set in the persistent configuration database + * set the force create flag in the partition attributes. + */ + status = dladm_get_conf_field(handle, conf, FFORCE, &force, + sizeof (boolean_t)); + if (status != DLADM_STATUS_OK) { + if (status != DLADM_STATUS_NOTFOUND) + goto done; + } else if (force == B_TRUE) { + attrp->dia_flags |= DLADM_IBPART_FORCE_CREATE; + } + + status = DLADM_STATUS_OK; +done: + dladm_destroy_conf(handle, conf); + return (status); +} + +/* + * Get the configuration information for the IB partition given by the datalink + * ID 'linkid'. Based on the 'flags' field the information is either from the + * active system (DLADM_OPT_ACTIVE) or from the persistent configuration + * database. + */ +dladm_status_t +dladm_part_info(dladm_handle_t handle, datalink_id_t linkid, + dladm_part_attr_t *attrp, uint32_t flags) +{ + if (flags == DLADM_OPT_ACTIVE) + return (i_dladm_part_info_active(handle, linkid, attrp)); + else if (flags == DLADM_OPT_PERSIST) + return (i_dladm_part_info_persist(handle, linkid, attrp)); + else + return (DLADM_STATUS_BADARG); +} + +/* + * Get the configuration information for the IB Phys link given by the datalink + * ID 'linkid'. + */ +/* ARGSUSED */ +dladm_status_t +dladm_ib_info(dladm_handle_t handle, datalink_id_t linkid, + dladm_ib_attr_t *attrp, uint32_t flags) +{ + int instance; + ibport_ioctl_t ioc; + dladm_phys_attr_t dpa; + dladm_status_t status = DLADM_STATUS_OK; + + /* + * We need to get the device name of the IB Phys link to get the + * correct instance number of the IP over IB driver instance. + */ + if (dladm_phys_info(handle, linkid, &dpa, DLADM_OPT_ACTIVE) + != DLADM_STATUS_OK) + return (DLADM_STATUS_BADARG); + + /* + * Get the instance number of the IP over IB driver instance which + * represents this IB Phys link. + */ + instance = dladm_ibd_get_instance(dpa.dp_dev); + if (instance == -1) + return (DLADM_STATUS_FAILED); + + bzero(&ioc, sizeof (ioc)); + /* + * The ioc_linkid here will contain IB port linkid here. We make the + * first ioctl call to get the P_Key table size for this HCA port. + */ + ioc.ibdioc.ioc_linkid = linkid; + ioc.ibdioc.ioc_info_cmd = IBD_INFO_CMD_PKEYTBLSZ; + ioc.ioc_pkey_tbl_sz = 0; + ioc.ibdioc.ioc_port_inst = instance; + + status = i_dladm_ib_ioctl(handle, IBD_INFO_IBPART, (ibd_ioctl_t *)&ioc); + if (status != DLADM_STATUS_OK) + return (status); + + /* + * Now allocate the memory for the P_Key table based on the table size + * return by the ioctl. + */ + ioc.ioc_pkeys = calloc(sizeof (ib_pkey_t), ioc.ioc_pkey_tbl_sz); + if (ioc.ioc_pkeys == NULL) { + status = dladm_errno2status(errno); + goto bail; + } + + /* + * Call the ioctl again to get the P_Key table and other IB Phys link + * attributes. + */ + ioc.ibdioc.ioc_linkid = linkid; + ioc.ibdioc.ioc_port_inst = instance; + ioc.ibdioc.ioc_info_cmd = IBD_INFO_CMD_IBPORT; + + status = i_dladm_ib_ioctl(handle, IBD_INFO_IBPART, (ibd_ioctl_t *)&ioc); + if (status != DLADM_STATUS_OK) + goto bail; + + attrp->dia_physlinkid = ioc.ibdioc.ioc_linkid; + attrp->dia_portnum = ioc.ibdioc.ioc_portnum; + attrp->dia_port_pkey_tbl_sz = ioc.ioc_pkey_tbl_sz; + attrp->dia_port_pkeys = ioc.ioc_pkeys; + attrp->dia_hca_guid = ioc.ibdioc.ioc_hcaguid; + attrp->dia_port_guid = ioc.ibdioc.ioc_portguid; + attrp->dia_instance = ioc.ibdioc.ioc_port_inst; + return (status); +bail: + free(ioc.ioc_pkeys); + return (status); +} + +/* + * Free the memory allocated for the IB HCA port's P_Key table by + * dladm_ib_info library call. + */ +void +dladm_free_ib_info(dladm_ib_attr_t *attr) +{ + if (attr && attr->dia_port_pkeys) + free(attr->dia_port_pkeys); +} + +/* + * Call into the IP over IB driver to create a partition object. + */ +static dladm_status_t +i_dladm_part_create(dladm_handle_t handle, dladm_part_attr_t *pattr) +{ + ibpart_ioctl_t ioc; + dladm_status_t status = DLADM_STATUS_OK; + + bzero(&ioc, sizeof (ioc)); + + /* IB Physical datalink ID */ + ioc.ibdioc.ioc_linkid = pattr->dia_physlinkid; + /* IB Partition datalink ID */ + ioc.ioc_partid = pattr->dia_partlinkid; + ioc.ioc_pkey = pattr->dia_pkey; + ioc.ibdioc.ioc_port_inst = pattr->dia_instance; + ioc.ioc_force_create = ((pattr->dia_flags & DLADM_OPT_FORCE) + != 0); + + status = i_dladm_ib_ioctl(handle, IBD_CREATE_IBPART, + (ibd_ioctl_t *)&ioc); + return (status); +} + +/* + * Create an entry in the dladm persistent configuration database for the + * partition specified by pattr. + */ +dladm_status_t +dladm_part_persist_conf(dladm_handle_t handle, dladm_part_attr_t *pattr) +{ + + dladm_conf_t conf; + dladm_status_t status; + char linkover[MAXLINKNAMELEN]; + uint64_t u64; + + status = dladm_create_conf(handle, pattr->dia_pname, + pattr->dia_partlinkid, DATALINK_CLASS_PART, DL_IB, &conf); + + if (status != DLADM_STATUS_OK) + return (status); + + /* + * Get the name of the IB Phys link over which this partition was + * created. + */ + status = dladm_datalink_id2info(handle, pattr->dia_physlinkid, + NULL, NULL, NULL, linkover, sizeof (linkover)); + if (status != DLADM_STATUS_OK) + return (status); + + /* Store IB Phys link name (linkover) */ + status = dladm_set_conf_field(handle, conf, FLINKOVER, DLADM_TYPE_STR, + linkover); + if (status != DLADM_STATUS_OK) + return (status); + + u64 = pattr->dia_pkey; + + /* Store the IB Partitions P_Key */ + status = dladm_set_conf_field(handle, conf, FPORTPKEY, + DLADM_TYPE_UINT64, &u64); + if (status != DLADM_STATUS_OK) + return (status); + + if (pattr->dia_flags & DLADM_OPT_FORCE) { + boolean_t force = B_TRUE; + /* Store the force create flag. */ + status = dladm_set_conf_field(handle, conf, FFORCE, + DLADM_TYPE_BOOLEAN, &force); + if (status != DLADM_STATUS_OK) + goto done; + } + + status = dladm_write_conf(handle, conf); + if (status != DLADM_STATUS_OK) + return (status); + + dladm_destroy_conf(handle, conf); +done: + return (status); +} + +/* + * Create a new IB Partition datalink of name 'pname' over the IB Physical link + * given in 'physlinkid' with the P_key 'pkey' and return the datalink ID in + * 'partlinkid'. If the 'force' option is set in the 'flags' argument, the + * partition will be created even if the P_Key 'pkey' does not exist or if the + * HCA port represented by the IB Phys link is down. If the 'temporary' flag is + * set, then the configuration information is not added to the persistent + * database. + */ +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) +{ + int i; + dladm_status_t status; + uint_t media; + boolean_t part_created = B_FALSE; + boolean_t conf_set = B_FALSE; + dladm_phys_attr_t dpa; + dladm_part_attr_t pattr; + + pattr.dia_pkey = pkey; + pattr.dia_physlinkid = physlinkid; /* IB Phys link's datalink id */ + pattr.dia_flags = flags; + pattr.dia_pname = pname; + + flags &= ~DLADM_OPT_FORCE; + + /* + * Check whether the PKEY is valid. If not, return immediately + * Only full members are allowed as per the IPoIB specification + */ + if (pattr.dia_pkey <= IB_PKEY_INVALID_FULL) + return (DLADM_STATUS_INVALID_PKEY); + + /* + * Get the media type of the Phys link datalink ID provided and + * make sure that it is Infiniband media DL_IB) + */ + if ((status = dladm_datalink_id2info(handle, pattr.dia_physlinkid, NULL, + NULL, &media, NULL, 0)) != DLADM_STATUS_OK) + return (status); + + if (media != DL_IB) + return (dladm_errno2status(ENOTSUP)); + + /* + * Get the instance number of the IP over IB driver instance which the + * IB Phys link 'physlinkid' over which we will be creating our IB + * partition. + */ + if ((status = dladm_phys_info(handle, pattr.dia_physlinkid, &dpa, + DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) + return (status); + + pattr.dia_instance = dladm_ibd_get_instance(dpa.dp_dev); + if (pattr.dia_instance == -1) + return (DLADM_STATUS_FAILED); + + + if ((status = dladm_create_datalink_id(handle, pattr.dia_pname, + DATALINK_CLASS_PART, DL_IB, flags, &pattr.dia_partlinkid)) != + DLADM_STATUS_OK) + return (status); + + /* + * Create the IB partition object. + */ + status = i_dladm_part_create(handle, &pattr); + if (status != DLADM_STATUS_OK) + goto done; + + part_created = B_TRUE; + + /* + * If the persist flag is set then write this partition information + * to the persistent configuration. + */ + if (pattr.dia_flags & DLADM_OPT_PERSIST) { + status = dladm_part_persist_conf(handle, &pattr); + if (status != DLADM_STATUS_OK) + goto done; + conf_set = B_TRUE; + } + + /* + * If the name-value pair list of properties were provided set those + * properties over the datalink. + */ + if (proplist != NULL) { + for (i = 0; i < proplist->al_count; i++) { + dladm_arg_info_t *aip = &proplist->al_info[i]; + + status = dladm_set_linkprop(handle, + pattr.dia_partlinkid, aip->ai_name, aip->ai_val, + aip->ai_count, pattr.dia_flags); + if (status != DLADM_STATUS_OK) + break; + } + } +done: + if (status != DLADM_STATUS_OK) { + if (conf_set) + (void) dladm_remove_conf(handle, pattr.dia_partlinkid); + if (part_created) + (void) i_dladm_part_delete(handle, + pattr.dia_partlinkid); + (void) dladm_destroy_datalink_id(handle, pattr.dia_partlinkid, + flags); + } + + if (partlinkid != NULL) + *partlinkid = pattr.dia_partlinkid; + + return (status); +} + +/* + * Call into the IP over IB driver to delete the IB partition and free up all + * the resources allocated for it. + */ +static dladm_status_t +i_dladm_part_delete(dladm_handle_t handle, datalink_id_t partid) +{ + ibpart_ioctl_t ioc; + dladm_status_t status = DLADM_STATUS_OK; + + bzero(&ioc, sizeof (ioc)); + ioc.ioc_partid = partid; + status = i_dladm_ib_ioctl(handle, IBD_DELETE_IBPART, + (ibd_ioctl_t *)&ioc); + return (status); +} + +/* + * Delete an IB partition if 'flags' contains the active flag. Update the + * persistent configuration if 'flags' contains the persist flag. + */ +dladm_status_t +dladm_part_delete(dladm_handle_t handle, datalink_id_t partid, int flags) +{ + dladm_status_t status = DLADM_STATUS_OK; + datalink_class_t class; + + if (flags == 0) + return (DLADM_STATUS_BADARG); + + /* + * Make sure that the datalinkid provided is an IB partition class + * datalink ID. + */ + if ((dladm_datalink_id2info(handle, partid, NULL, &class, NULL, NULL, 0) + != DLADM_STATUS_OK)) + return (DLADM_STATUS_BADARG); + + if (class != DATALINK_CLASS_PART) + return (DLADM_STATUS_BADARG); + + if ((flags & DLADM_OPT_ACTIVE) != 0) { + status = i_dladm_part_delete(handle, partid); + if (status == DLADM_STATUS_OK) { + (void) dladm_set_linkprop(handle, partid, NULL, NULL, 0, + DLADM_OPT_ACTIVE); + (void) dladm_destroy_datalink_id(handle, partid, + DLADM_OPT_ACTIVE); + } else if (status != DLADM_STATUS_NOTFOUND || + !(flags & DLADM_OPT_PERSIST)) { + return (status); + } + } + + if ((flags & DLADM_OPT_PERSIST) != 0) { + dladm_status_t db_status; + db_status = dladm_remove_conf(handle, partid); + + /* + * A partition could have been temporarily deleted in which + * case the delete of the active partition above would have + * failed. In that case, we update the status to be returned + * to that of the status returned for deleting the persistent + * database entry. + */ + if (status == DLADM_STATUS_NOTFOUND) + status = db_status; + + (void) dladm_destroy_datalink_id(handle, partid, + DLADM_OPT_PERSIST); + } + + return (status); +} + +/* + * Call into the IP over IB driver to create the active instances of one or all + * IB partitions present in the persistent configuration. + */ +/* ARGSUSED */ +static int +i_dladm_part_up(dladm_handle_t handle, datalink_id_t plinkid, void *arg) +{ + dladm_conf_t conf; + datalink_id_t linkid; + ib_pkey_t pkey; + uint64_t u64; + char linkover[MAXLINKNAMELEN]; + dladm_status_t status; + dladm_phys_attr_t dpa; + dladm_part_attr_t pattr; + + /* + * plinkid is the IB partition datalink's ID. Get an handle to the + * persistent configuration entry for this datalink ID. If this datalink + * ID is not present in the persistent configuration return. + */ + if ((status = dladm_read_conf(handle, plinkid, &conf)) != + DLADM_STATUS_OK) + return (status); + + /* + * Get the name of the IB Phys link over which this partition was + * created. + */ + status = dladm_get_conf_field(handle, conf, FLINKOVER, linkover, + sizeof (linkover)); + if (status != DLADM_STATUS_OK) + goto done; + + if ((status = dladm_name2info(handle, linkover, &linkid, NULL, NULL, + NULL)) != DLADM_STATUS_OK) + goto done; + + /* + * Get the phys attribute of the IB Phys link to get the device name + * associated with the phys link. We need this to get the IP over IB + * driver instance number. + */ + if (dladm_phys_info(handle, linkid, &dpa, DLADM_OPT_ACTIVE) + != DLADM_STATUS_OK) + goto done; + + /* Get the IB partition's P_key */ + status = dladm_get_conf_field(handle, conf, FPORTPKEY, &u64, + sizeof (u64)); + if (status != DLADM_STATUS_OK) + goto done; + + pkey = (ib_pkey_t)u64; + + /* + * We always set the force flag during dladm_part_up because we want + * the partition creation to succeed even if the IB HCA port over which + * the partition is being created is still down. Since dladm_part_up + * is usually invoked during early boot sequence, it is possible under + * some IB subnet configurations for dladm_up_part to be called before + * the IB link negotiation is completed and port state is set to active + * and P_Key table is updated. + */ + pattr.dia_flags = DLADM_OPT_FORCE | DLADM_OPT_ACTIVE | + DLADM_OPT_PERSIST; + /* IB Phys link's datalink ID. */ + pattr.dia_physlinkid = linkid; + /* IB Partition's datalink ID. */ + pattr.dia_partlinkid = plinkid; + pattr.dia_pkey = pkey; + pattr.dia_instance = dladm_ibd_get_instance(dpa.dp_dev); + if (pattr.dia_instance == -1) + return (DLADM_WALK_CONTINUE); + + /* Create the active IB Partition object. */ + if (i_dladm_part_create(handle, &pattr) == DLADM_STATUS_OK && + dladm_up_datalink_id(handle, plinkid) != DLADM_STATUS_OK) + (void) i_dladm_part_delete(handle, linkid); + +done: + dladm_destroy_conf(handle, conf); + return (DLADM_WALK_CONTINUE); +} + +/* + * Bring up one or all IB partition(s) present in the persistent configuration + * database. If we need to bring up one IB Partition, its datalink ID is + * provided in 'linkid'. + */ +/* ARGSUSED */ +dladm_status_t +dladm_part_up(dladm_handle_t handle, datalink_id_t linkid, uint32_t flags) +{ + dladm_status_t status = DLADM_STATUS_OK; + + if (linkid == DATALINK_ALL_LINKID) { + (void) dladm_walk_datalink_id(i_dladm_part_up, handle, + &status, DATALINK_CLASS_PART, DATALINK_ANY_MEDIATYPE, + DLADM_OPT_PERSIST); + return (DLADM_STATUS_OK); + } else { + (void) i_dladm_part_up(handle, linkid, &status); + return (status); + } +} + +static int +dladm_ibd_get_instance(char *devname) +{ + int instance; + + /* + * The devname contains the driver name followed by the instance + * number. Lets just skip the driver name and get the instance. We use + * strlen of ibp here to get the driver name length. + */ + instance = atoi(devname + strlen("ibp")); + + return (instance); +} diff --git a/usr/src/lib/libdladm/common/libdlib.h b/usr/src/lib/libdladm/common/libdlib.h new file mode 100644 index 0000000000..f2b0af52da --- /dev/null +++ b/usr/src/lib/libdladm/common/libdlib.h @@ -0,0 +1,78 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + */ + +#ifndef _LIBDLIB_H +#define _LIBDLIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/types.h> +#include <sys/ib/ib_types.h> + +#define MAXPKEYSTRSZ 968 +#define MAXPKEYLEN 6 +#define IBGUIDSTRLEN 16 +#define IBPORTSTRLEN 5 + +#define DLADM_IBPART_FORCE_CREATE 0x1 + +typedef struct dladm_ib_attr_s { + datalink_id_t dia_physlinkid; /* IB Phys link datalink ID */ + datalink_id_t dia_partlinkid; /* IB Partition datalink ID */ + ib_pkey_t dia_pkey; /* IB partitions P_Key */ + uint32_t dia_flags; + char *dia_devname; /* IB Phys link's device name */ + char *dia_pname; /* IB partition's name */ + uint_t dia_portnum; /* IB Phys link's HCA port number */ + int dia_instance; /* IP over IB driver instance number */ + ib_guid_t dia_hca_guid; /* IB HCA GUID */ + ib_guid_t dia_port_guid; /* IB HCA Port GUID */ + uint_t dia_port_pkey_tbl_sz; + ib_pkey_t *dia_port_pkeys; /* Ptr to the P_Key table */ +} dladm_ib_attr_t; + +typedef struct dladm_ib_attr_s dladm_part_attr_t; + +typedef enum { + DLADM_IBPART_UD_MODE = 0, + DLADM_IBPART_CM_MODE +} dladm_ibpart_linkmode_t; + +extern dladm_status_t dladm_part_create(dladm_handle_t, datalink_id_t, + ib_pkey_t, uint32_t, char *, datalink_id_t *, dladm_arg_list_t *); +extern dladm_status_t dladm_part_delete(dladm_handle_t, datalink_id_t, int); +extern dladm_status_t dladm_part_up(dladm_handle_t, datalink_id_t, uint32_t); +extern dladm_status_t dladm_part_info(dladm_handle_t, datalink_id_t, + dladm_part_attr_t *, uint32_t); +extern dladm_status_t dladm_ib_info(dladm_handle_t, datalink_id_t, + dladm_ib_attr_t *, uint32_t); +extern void dladm_free_ib_info(dladm_ib_attr_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBDLIB_H */ diff --git a/usr/src/lib/libdladm/common/libdllink.c b/usr/src/lib/libdladm/common/libdllink.c index 7bf18ceed5..159df78068 100644 --- a/usr/src/lib/libdladm/common/libdllink.c +++ b/usr/src/lib/libdladm/common/libdllink.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/types.h> @@ -40,6 +39,7 @@ #include <libdlaggr.h> #include <libdlvlan.h> #include <libdlvnic.h> +#include <libdlib.h> #include <libdllink.h> #include <libdlmgmt.h> #include <libdladm_impl.h> @@ -691,6 +691,22 @@ i_dladm_vlan_link_del(dladm_handle_t handle, datalink_id_t vlanid, void *arg) } static int +i_dladm_part_link_del(dladm_handle_t handle, datalink_id_t partid, void *arg) +{ + consumer_del_phys_arg_t *del_arg = arg; + dladm_part_attr_t pinfo; + dladm_status_t status; + + status = dladm_part_info(handle, partid, &pinfo, DLADM_OPT_PERSIST); + if (status != DLADM_STATUS_OK) + return (DLADM_WALK_CONTINUE); + + if (pinfo.dia_physlinkid == del_arg->linkid) + (void) dladm_part_delete(handle, partid, DLADM_OPT_PERSIST); + return (DLADM_WALK_CONTINUE); +} + +static int i_dladm_aggr_link_del(dladm_handle_t handle, datalink_id_t aggrid, void *arg) { consumer_del_phys_arg_t *del_arg = arg; @@ -766,6 +782,10 @@ i_dladm_phys_delete(dladm_handle_t handle, datalink_id_t linkid, void *arg) (void) dladm_walk_datalink_id(i_dladm_vlan_link_del, handle, &del_arg, DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST); + } else if (media == DL_IB) { + del_arg.linkid = linkid; + (void) dladm_walk_datalink_id(i_dladm_part_link_del, handle, + &del_arg, DATALINK_CLASS_PART, DL_IB, DLADM_OPT_PERSIST); } (void) dladm_remove_conf(handle, linkid); diff --git a/usr/src/lib/libdladm/common/linkprop.c b/usr/src/lib/libdladm/common/linkprop.c index 50e79616c0..031c61ebf4 100644 --- a/usr/src/lib/libdladm/common/linkprop.c +++ b/usr/src/lib/libdladm/common/linkprop.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <stdlib.h> @@ -42,6 +41,7 @@ #include <libdlwlan.h> #include <libdlvlan.h> #include <libdlvnic.h> +#include <libdlib.h> #include <libintl.h> #include <dlfcn.h> #include <link.h> @@ -150,7 +150,7 @@ static pd_getf_t get_zone, get_autopush, get_rate_mod, get_rate, get_bridge_pvid, get_protection, get_rxrings, get_txrings, get_cntavail, get_allowedips, get_allowedcids, get_pool, - get_rings_range; + get_rings_range, get_linkmode_prop; static pd_setf_t set_zone, set_rate, set_powermode, set_radio, set_public_prop, set_resource, set_stp_prop, @@ -360,6 +360,8 @@ static link_attr_t link_attr[] = { { MAC_PROP_MAX_TXHWCLNT_AVAIL, sizeof (uint_t), "txhwclnt-available"}, + { MAC_PROP_IB_LINKMODE, sizeof (uint32_t), "linkmode"}, + { MAC_PROP_PRIVATE, 0, "driver-private"} }; @@ -431,6 +433,11 @@ static val_desc_t stp_p2p_vals[] = { { "auto", P2P_AUTO } }; +static val_desc_t dladm_ibpart_linkmode_vals[] = { + { "cm", DLADM_IBPART_CM_MODE }, + { "ud", DLADM_IBPART_UD_MODE }, +}; + #define VALCNT(vals) (sizeof ((vals)) / sizeof (val_desc_t)) #define RESET_VAL ((uintptr_t)-1) #define UNSPEC_VAL ((uintptr_t)-2) @@ -453,6 +460,11 @@ static prop_desc_t prop_table[] = { get_radio, NULL, 0, DATALINK_CLASS_PHYS, DL_WIFI }, + { "linkmode", { "cm", DLADM_IBPART_CM_MODE }, + dladm_ibpart_linkmode_vals, VALCNT(dladm_ibpart_linkmode_vals), + set_public_prop, NULL, get_linkmode_prop, NULL, 0, + DATALINK_CLASS_PART, DL_IB }, + { "speed", { "", 0 }, NULL, 0, set_rate, get_rate_mod, get_rate, check_rate, 0, @@ -4436,3 +4448,35 @@ done: free(buf); return (status); } + +/* ARGSUSED */ +static dladm_status_t +get_linkmode_prop(dladm_handle_t handle, prop_desc_t *pdp, + datalink_id_t linkid, char **prop_val, uint_t *val_cnt, + datalink_media_t media, uint_t flags, uint_t *perm_flags) +{ + char *s; + uint32_t v; + dladm_status_t status; + + status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags, + perm_flags, &v, sizeof (v)); + if (status != DLADM_STATUS_OK) + return (status); + + switch (v) { + case DLADM_IBPART_CM_MODE: + s = "cm"; + break; + case DLADM_IBPART_UD_MODE: + s = "ud"; + break; + default: + s = ""; + break; + } + (void) snprintf(prop_val[0], DLADM_STRSIZE, "%s", s); + + *val_cnt = 1; + return (DLADM_STATUS_OK); +} diff --git a/usr/src/lib/libdladm/common/llib-ldladm b/usr/src/lib/libdladm/common/llib-ldladm index 1020605a3c..8e5eac0614 100644 --- a/usr/src/lib/libdladm/common/llib-ldladm +++ b/usr/src/lib/libdladm/common/llib-ldladm @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. */ /*LINTLIBRARY*/ @@ -31,6 +30,7 @@ #include <libdlwlan.h> #include <libdlvnic.h> #include <libdlvlan.h> +#include <libdlib.h> #include <libdliptun.h> #include <libdlmgmt.h> #include <libdlflow.h> diff --git a/usr/src/lib/libdladm/common/mapfile-vers b/usr/src/lib/libdladm/common/mapfile-vers index 429355e6a0..114f7ffa8b 100644 --- a/usr/src/lib/libdladm/common/mapfile-vers +++ b/usr/src/lib/libdladm/common/mapfile-vers @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # # @@ -256,6 +255,13 @@ SUNWprivate_1.1 { dladm_flow_stat_free; dladm_flow_stat_query_all; dladm_flow_stat_query_all_free; + + dladm_part_create; + dladm_part_delete; + dladm_part_info; + dladm_part_up; + dladm_ib_info; + dladm_free_ib_info; local: *; }; |