xref: /freebsd-src/contrib/ofed/opensm/opensm/osm_qos.c (revision 87181516ef48be852d5e5fee53c6e0dbfc62f21e)
1*d6b92ffaSHans Petter Selasky /*
2*d6b92ffaSHans Petter Selasky  * Copyright (c) 2006-2009 Voltaire, Inc. All rights reserved.
3*d6b92ffaSHans Petter Selasky  * Copyright (c) 2010-2015 Mellanox Technologies LTD. All rights reserved.
4*d6b92ffaSHans Petter Selasky  * Copyright (c) 2009 HNR Consulting. All rights reserved.
5*d6b92ffaSHans Petter Selasky  *
6*d6b92ffaSHans Petter Selasky  * This software is available to you under a choice of one of two
7*d6b92ffaSHans Petter Selasky  * licenses.  You may choose to be licensed under the terms of the GNU
8*d6b92ffaSHans Petter Selasky  * General Public License (GPL) Version 2, available from the file
9*d6b92ffaSHans Petter Selasky  * COPYING in the main directory of this source tree, or the
10*d6b92ffaSHans Petter Selasky  * OpenIB.org BSD license below:
11*d6b92ffaSHans Petter Selasky  *
12*d6b92ffaSHans Petter Selasky  *     Redistribution and use in source and binary forms, with or
13*d6b92ffaSHans Petter Selasky  *     without modification, are permitted provided that the following
14*d6b92ffaSHans Petter Selasky  *     conditions are met:
15*d6b92ffaSHans Petter Selasky  *
16*d6b92ffaSHans Petter Selasky  *      - Redistributions of source code must retain the above
17*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
18*d6b92ffaSHans Petter Selasky  *        disclaimer.
19*d6b92ffaSHans Petter Selasky  *
20*d6b92ffaSHans Petter Selasky  *      - Redistributions in binary form must reproduce the above
21*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
22*d6b92ffaSHans Petter Selasky  *        disclaimer in the documentation and/or other materials
23*d6b92ffaSHans Petter Selasky  *        provided with the distribution.
24*d6b92ffaSHans Petter Selasky  *
25*d6b92ffaSHans Petter Selasky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26*d6b92ffaSHans Petter Selasky  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27*d6b92ffaSHans Petter Selasky  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28*d6b92ffaSHans Petter Selasky  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29*d6b92ffaSHans Petter Selasky  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30*d6b92ffaSHans Petter Selasky  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31*d6b92ffaSHans Petter Selasky  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32*d6b92ffaSHans Petter Selasky  * SOFTWARE.
33*d6b92ffaSHans Petter Selasky  *
34*d6b92ffaSHans Petter Selasky  */
35*d6b92ffaSHans Petter Selasky 
36*d6b92ffaSHans Petter Selasky /*
37*d6b92ffaSHans Petter Selasky  * Abstract:
38*d6b92ffaSHans Petter Selasky  *    Implementation of OpenSM QoS infrastructure primitives
39*d6b92ffaSHans Petter Selasky  */
40*d6b92ffaSHans Petter Selasky 
41*d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
42*d6b92ffaSHans Petter Selasky #  include <config.h>
43*d6b92ffaSHans Petter Selasky #endif				/* HAVE_CONFIG_H */
44*d6b92ffaSHans Petter Selasky 
45*d6b92ffaSHans Petter Selasky #include <stdlib.h>
46*d6b92ffaSHans Petter Selasky #include <string.h>
47*d6b92ffaSHans Petter Selasky 
48*d6b92ffaSHans Petter Selasky #include <iba/ib_types.h>
49*d6b92ffaSHans Petter Selasky #include <complib/cl_qmap.h>
50*d6b92ffaSHans Petter Selasky #include <complib/cl_debug.h>
51*d6b92ffaSHans Petter Selasky #include <opensm/osm_file_ids.h>
52*d6b92ffaSHans Petter Selasky #define FILE_ID OSM_FILE_QOS_C
53*d6b92ffaSHans Petter Selasky #include <opensm/osm_opensm.h>
54*d6b92ffaSHans Petter Selasky #include <opensm/osm_subnet.h>
55*d6b92ffaSHans Petter Selasky #include <opensm/osm_qos_policy.h>
56*d6b92ffaSHans Petter Selasky 
57*d6b92ffaSHans Petter Selasky struct qos_config {
58*d6b92ffaSHans Petter Selasky 	uint8_t max_vls;
59*d6b92ffaSHans Petter Selasky 	uint8_t vl_high_limit;
60*d6b92ffaSHans Petter Selasky 	ib_vl_arb_table_t vlarb_high[2];
61*d6b92ffaSHans Petter Selasky 	ib_vl_arb_table_t vlarb_low[2];
62*d6b92ffaSHans Petter Selasky 	ib_slvl_table_t sl2vl;
63*d6b92ffaSHans Petter Selasky };
64*d6b92ffaSHans Petter Selasky 
65*d6b92ffaSHans Petter Selasky typedef struct qos_mad_item {
66*d6b92ffaSHans Petter Selasky 	cl_list_item_t list_item;
67*d6b92ffaSHans Petter Selasky 	osm_madw_t *p_madw;
68*d6b92ffaSHans Petter Selasky } qos_mad_item_t;
69*d6b92ffaSHans Petter Selasky 
70*d6b92ffaSHans Petter Selasky typedef struct qos_mad_list {
71*d6b92ffaSHans Petter Selasky 	cl_list_item_t list_item;
72*d6b92ffaSHans Petter Selasky 	cl_qlist_t port_mad_list;
73*d6b92ffaSHans Petter Selasky } qos_mad_list_t;
74*d6b92ffaSHans Petter Selasky 
75*d6b92ffaSHans Petter Selasky static void qos_build_config(struct qos_config *cfg,
76*d6b92ffaSHans Petter Selasky 			     osm_qos_options_t * opt,
77*d6b92ffaSHans Petter Selasky 			     osm_qos_options_t * dflt);
78*d6b92ffaSHans Petter Selasky 
79*d6b92ffaSHans Petter Selasky /*
80*d6b92ffaSHans Petter Selasky  * QoS primitives
81*d6b92ffaSHans Petter Selasky  */
82*d6b92ffaSHans Petter Selasky 
osm_qos_mad_create(IN osm_sm_t * sm,IN osm_physp_t * p,IN uint32_t data_size,IN uint8_t * p_data,IN ib_net16_t attr_id,IN uint32_t attr_mod)83*d6b92ffaSHans Petter Selasky static qos_mad_item_t *osm_qos_mad_create(IN osm_sm_t * sm,
84*d6b92ffaSHans Petter Selasky 					  IN osm_physp_t * p,
85*d6b92ffaSHans Petter Selasky 					  IN uint32_t data_size,
86*d6b92ffaSHans Petter Selasky 					  IN uint8_t * p_data,
87*d6b92ffaSHans Petter Selasky 					  IN ib_net16_t attr_id,
88*d6b92ffaSHans Petter Selasky 					  IN uint32_t attr_mod)
89*d6b92ffaSHans Petter Selasky 
90*d6b92ffaSHans Petter Selasky {
91*d6b92ffaSHans Petter Selasky 	qos_mad_item_t *p_mad;
92*d6b92ffaSHans Petter Selasky 	osm_madw_context_t context;
93*d6b92ffaSHans Petter Selasky 	osm_madw_t *p_madw;
94*d6b92ffaSHans Petter Selasky 	osm_node_t *p_node;
95*d6b92ffaSHans Petter Selasky 	osm_physp_t *physp0;
96*d6b92ffaSHans Petter Selasky 	ib_net64_t m_key;
97*d6b92ffaSHans Petter Selasky 
98*d6b92ffaSHans Petter Selasky 	p_node = osm_physp_get_node_ptr(p);
99*d6b92ffaSHans Petter Selasky 	if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH &&
100*d6b92ffaSHans Petter Selasky 	    osm_physp_get_port_num(p) != 0) {
101*d6b92ffaSHans Petter Selasky 		physp0 = osm_node_get_physp_ptr(p_node, 0);
102*d6b92ffaSHans Petter Selasky 		m_key = ib_port_info_get_m_key(&physp0->port_info);
103*d6b92ffaSHans Petter Selasky 	} else
104*d6b92ffaSHans Petter Selasky 		m_key = ib_port_info_get_m_key(&p->port_info);
105*d6b92ffaSHans Petter Selasky 
106*d6b92ffaSHans Petter Selasky 	switch (attr_id){
107*d6b92ffaSHans Petter Selasky 	case IB_MAD_ATTR_SLVL_TABLE:
108*d6b92ffaSHans Petter Selasky 		context.slvl_context.node_guid = osm_node_get_node_guid(p_node);
109*d6b92ffaSHans Petter Selasky 		context.slvl_context.port_guid = osm_physp_get_port_guid(p);
110*d6b92ffaSHans Petter Selasky 		context.slvl_context.set_method = TRUE;
111*d6b92ffaSHans Petter Selasky 		break;
112*d6b92ffaSHans Petter Selasky 	case IB_MAD_ATTR_VL_ARBITRATION:
113*d6b92ffaSHans Petter Selasky 		context.vla_context.node_guid = osm_node_get_node_guid(p_node);
114*d6b92ffaSHans Petter Selasky 		context.vla_context.port_guid = osm_physp_get_port_guid(p);
115*d6b92ffaSHans Petter Selasky 		context.vla_context.set_method = TRUE;
116*d6b92ffaSHans Petter Selasky 		break;
117*d6b92ffaSHans Petter Selasky 	default:
118*d6b92ffaSHans Petter Selasky 		return NULL;
119*d6b92ffaSHans Petter Selasky 	}
120*d6b92ffaSHans Petter Selasky 
121*d6b92ffaSHans Petter Selasky 	p_mad = (qos_mad_item_t *) malloc(sizeof(*p_mad));
122*d6b92ffaSHans Petter Selasky 	if (!p_mad)
123*d6b92ffaSHans Petter Selasky 		return NULL;
124*d6b92ffaSHans Petter Selasky 
125*d6b92ffaSHans Petter Selasky 	memset(p_mad, 0, sizeof(*p_mad));
126*d6b92ffaSHans Petter Selasky 
127*d6b92ffaSHans Petter Selasky 	p_madw = osm_prepare_req_set(sm, osm_physp_get_dr_path_ptr(p),
128*d6b92ffaSHans Petter Selasky 				     p_data, data_size,
129*d6b92ffaSHans Petter Selasky 				     attr_id, cl_hton32(attr_mod),
130*d6b92ffaSHans Petter Selasky 				     FALSE, m_key,
131*d6b92ffaSHans Petter Selasky 				     CL_DISP_MSGID_NONE, &context);
132*d6b92ffaSHans Petter Selasky 
133*d6b92ffaSHans Petter Selasky 	if (p_madw == NULL) {
134*d6b92ffaSHans Petter Selasky 		free(p_mad);
135*d6b92ffaSHans Petter Selasky 		return NULL;
136*d6b92ffaSHans Petter Selasky 	}
137*d6b92ffaSHans Petter Selasky 	p_mad->p_madw = p_madw;
138*d6b92ffaSHans Petter Selasky 	return p_mad;
139*d6b92ffaSHans Petter Selasky }
140*d6b92ffaSHans Petter Selasky 
osm_qos_mad_delete(qos_mad_item_t ** p_item)141*d6b92ffaSHans Petter Selasky static void osm_qos_mad_delete(qos_mad_item_t ** p_item)
142*d6b92ffaSHans Petter Selasky {
143*d6b92ffaSHans Petter Selasky 	free(*p_item);
144*d6b92ffaSHans Petter Selasky 	*p_item = NULL;
145*d6b92ffaSHans Petter Selasky }
146*d6b92ffaSHans Petter Selasky 
vlarb_update_table_block(osm_sm_t * sm,osm_physp_t * p,uint8_t port_num,unsigned force_update,const ib_vl_arb_table_t * table_block,unsigned block_length,unsigned block_num,cl_qlist_t * mad_list)147*d6b92ffaSHans Petter Selasky static ib_api_status_t vlarb_update_table_block(osm_sm_t * sm,
148*d6b92ffaSHans Petter Selasky 						osm_physp_t * p,
149*d6b92ffaSHans Petter Selasky 						uint8_t port_num,
150*d6b92ffaSHans Petter Selasky 						unsigned force_update,
151*d6b92ffaSHans Petter Selasky 						const ib_vl_arb_table_t *
152*d6b92ffaSHans Petter Selasky 						table_block,
153*d6b92ffaSHans Petter Selasky 						unsigned block_length,
154*d6b92ffaSHans Petter Selasky 						unsigned block_num,
155*d6b92ffaSHans Petter Selasky 						cl_qlist_t *mad_list)
156*d6b92ffaSHans Petter Selasky {
157*d6b92ffaSHans Petter Selasky 	struct osm_routing_engine *re = sm->p_subn->p_osm->routing_engine_used;
158*d6b92ffaSHans Petter Selasky 	ib_vl_arb_table_t block;
159*d6b92ffaSHans Petter Selasky 	uint32_t attr_mod;
160*d6b92ffaSHans Petter Selasky 	unsigned vl_mask, i;
161*d6b92ffaSHans Petter Selasky 	qos_mad_item_t *p_mad;
162*d6b92ffaSHans Petter Selasky 	vl_mask = (1 << (ib_port_info_get_op_vls(&p->port_info) - 1)) - 1;
163*d6b92ffaSHans Petter Selasky 
164*d6b92ffaSHans Petter Selasky 	memset(&block, 0, sizeof(block));
165*d6b92ffaSHans Petter Selasky 	memcpy(&block, table_block, block_length * sizeof(block.vl_entry[0]));
166*d6b92ffaSHans Petter Selasky 
167*d6b92ffaSHans Petter Selasky 	if (re && re->update_vlarb)
168*d6b92ffaSHans Petter Selasky 		re->update_vlarb(re->context, p, port_num, &block,
169*d6b92ffaSHans Petter Selasky 				 block_length, block_num);
170*d6b92ffaSHans Petter Selasky 
171*d6b92ffaSHans Petter Selasky 	for (i = 0; i < block_length; i++)
172*d6b92ffaSHans Petter Selasky 		block.vl_entry[i].vl &= vl_mask;
173*d6b92ffaSHans Petter Selasky 
174*d6b92ffaSHans Petter Selasky 	if (!force_update &&
175*d6b92ffaSHans Petter Selasky 	    !memcmp(&p->vl_arb[block_num], &block,
176*d6b92ffaSHans Petter Selasky 		    block_length * sizeof(block.vl_entry[0])))
177*d6b92ffaSHans Petter Selasky 		return IB_SUCCESS;
178*d6b92ffaSHans Petter Selasky 
179*d6b92ffaSHans Petter Selasky 	attr_mod = ((block_num + 1) << 16) | port_num;
180*d6b92ffaSHans Petter Selasky 
181*d6b92ffaSHans Petter Selasky 	p_mad = osm_qos_mad_create(sm,p,sizeof(block),(uint8_t *) & block,
182*d6b92ffaSHans Petter Selasky 				   IB_MAD_ATTR_VL_ARBITRATION, attr_mod);
183*d6b92ffaSHans Petter Selasky 
184*d6b92ffaSHans Petter Selasky 	if (!p_mad)
185*d6b92ffaSHans Petter Selasky 		return IB_INSUFFICIENT_MEMORY;
186*d6b92ffaSHans Petter Selasky 
187*d6b92ffaSHans Petter Selasky 	/*
188*d6b92ffaSHans Petter Selasky 	 * Zero the stored VL Arbitration block, so in case the MAD will
189*d6b92ffaSHans Petter Selasky 	 * end up with error, we will resend it in the next sweep.
190*d6b92ffaSHans Petter Selasky 	 */
191*d6b92ffaSHans Petter Selasky 	memset(&p->vl_arb[block_num], 0,
192*d6b92ffaSHans Petter Selasky 	       block_length * sizeof(block.vl_entry[0]));
193*d6b92ffaSHans Petter Selasky 
194*d6b92ffaSHans Petter Selasky 	cl_qlist_insert_tail(mad_list, &p_mad->list_item);
195*d6b92ffaSHans Petter Selasky 
196*d6b92ffaSHans Petter Selasky 	return IB_SUCCESS;
197*d6b92ffaSHans Petter Selasky }
198*d6b92ffaSHans Petter Selasky 
vlarb_update(osm_sm_t * sm,osm_physp_t * p,uint8_t port_num,unsigned force_update,const struct qos_config * qcfg,cl_qlist_t * mad_list)199*d6b92ffaSHans Petter Selasky static ib_api_status_t vlarb_update(osm_sm_t * sm, osm_physp_t * p,
200*d6b92ffaSHans Petter Selasky 				    uint8_t port_num, unsigned force_update,
201*d6b92ffaSHans Petter Selasky 				    const struct qos_config *qcfg,
202*d6b92ffaSHans Petter Selasky 				    cl_qlist_t *mad_list)
203*d6b92ffaSHans Petter Selasky {
204*d6b92ffaSHans Petter Selasky 	ib_api_status_t status = IB_SUCCESS;
205*d6b92ffaSHans Petter Selasky 	ib_port_info_t *p_pi = &p->port_info;
206*d6b92ffaSHans Petter Selasky 	unsigned len;
207*d6b92ffaSHans Petter Selasky 
208*d6b92ffaSHans Petter Selasky 	if (p_pi->vl_arb_low_cap > 0) {
209*d6b92ffaSHans Petter Selasky 		len = p_pi->vl_arb_low_cap < IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK ?
210*d6b92ffaSHans Petter Selasky 		    p_pi->vl_arb_low_cap : IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK;
211*d6b92ffaSHans Petter Selasky 		if ((status = vlarb_update_table_block(sm, p, port_num,
212*d6b92ffaSHans Petter Selasky 						       force_update,
213*d6b92ffaSHans Petter Selasky 						       &qcfg->vlarb_low[0],
214*d6b92ffaSHans Petter Selasky 						       len, 0,
215*d6b92ffaSHans Petter Selasky 						       mad_list)) != IB_SUCCESS)
216*d6b92ffaSHans Petter Selasky 			return status;
217*d6b92ffaSHans Petter Selasky 	}
218*d6b92ffaSHans Petter Selasky 	if (p_pi->vl_arb_low_cap > IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK) {
219*d6b92ffaSHans Petter Selasky 		len = p_pi->vl_arb_low_cap % IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK;
220*d6b92ffaSHans Petter Selasky 		if ((status = vlarb_update_table_block(sm, p, port_num,
221*d6b92ffaSHans Petter Selasky 						       force_update,
222*d6b92ffaSHans Petter Selasky 						       &qcfg->vlarb_low[1],
223*d6b92ffaSHans Petter Selasky 						       len, 1,
224*d6b92ffaSHans Petter Selasky 						       mad_list)) != IB_SUCCESS)
225*d6b92ffaSHans Petter Selasky 			return status;
226*d6b92ffaSHans Petter Selasky 	}
227*d6b92ffaSHans Petter Selasky 	if (p_pi->vl_arb_high_cap > 0) {
228*d6b92ffaSHans Petter Selasky 		len = p_pi->vl_arb_high_cap < IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK ?
229*d6b92ffaSHans Petter Selasky 		    p_pi->vl_arb_high_cap : IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK;
230*d6b92ffaSHans Petter Selasky 		if ((status = vlarb_update_table_block(sm, p, port_num,
231*d6b92ffaSHans Petter Selasky 						       force_update,
232*d6b92ffaSHans Petter Selasky 						       &qcfg->vlarb_high[0],
233*d6b92ffaSHans Petter Selasky 						       len, 2,
234*d6b92ffaSHans Petter Selasky 						       mad_list)) != IB_SUCCESS)
235*d6b92ffaSHans Petter Selasky 			return status;
236*d6b92ffaSHans Petter Selasky 	}
237*d6b92ffaSHans Petter Selasky 	if (p_pi->vl_arb_high_cap > IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK) {
238*d6b92ffaSHans Petter Selasky 		len = p_pi->vl_arb_high_cap % IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK;
239*d6b92ffaSHans Petter Selasky 		if ((status = vlarb_update_table_block(sm, p, port_num,
240*d6b92ffaSHans Petter Selasky 						       force_update,
241*d6b92ffaSHans Petter Selasky 						       &qcfg->vlarb_high[1],
242*d6b92ffaSHans Petter Selasky 						       len, 3,
243*d6b92ffaSHans Petter Selasky 						       mad_list)) != IB_SUCCESS)
244*d6b92ffaSHans Petter Selasky 			return status;
245*d6b92ffaSHans Petter Selasky 	}
246*d6b92ffaSHans Petter Selasky 
247*d6b92ffaSHans Petter Selasky 	return status;
248*d6b92ffaSHans Petter Selasky }
249*d6b92ffaSHans Petter Selasky 
sl2vl_update_table(osm_sm_t * sm,osm_physp_t * p,uint8_t in_port,uint32_t attr_mod,unsigned force_update,const ib_slvl_table_t * sl2vl_table,cl_qlist_t * mad_list)250*d6b92ffaSHans Petter Selasky static ib_api_status_t sl2vl_update_table(osm_sm_t * sm, osm_physp_t * p,
251*d6b92ffaSHans Petter Selasky 					  uint8_t in_port, uint32_t attr_mod,
252*d6b92ffaSHans Petter Selasky 					  unsigned force_update,
253*d6b92ffaSHans Petter Selasky 					  const ib_slvl_table_t * sl2vl_table,
254*d6b92ffaSHans Petter Selasky 					  cl_qlist_t *mad_list)
255*d6b92ffaSHans Petter Selasky {
256*d6b92ffaSHans Petter Selasky 	ib_slvl_table_t tbl, *p_tbl;
257*d6b92ffaSHans Petter Selasky 	unsigned vl_mask;
258*d6b92ffaSHans Petter Selasky 	uint8_t vl1, vl2;
259*d6b92ffaSHans Petter Selasky 	int i;
260*d6b92ffaSHans Petter Selasky 	qos_mad_item_t *p_mad;
261*d6b92ffaSHans Petter Selasky 
262*d6b92ffaSHans Petter Selasky 	vl_mask = (1 << (ib_port_info_get_op_vls(&p->port_info) - 1)) - 1;
263*d6b92ffaSHans Petter Selasky 
264*d6b92ffaSHans Petter Selasky 	for (i = 0; i < IB_MAX_NUM_VLS / 2; i++) {
265*d6b92ffaSHans Petter Selasky 		vl1 = sl2vl_table->raw_vl_by_sl[i] >> 4;
266*d6b92ffaSHans Petter Selasky 		vl2 = sl2vl_table->raw_vl_by_sl[i] & 0xf;
267*d6b92ffaSHans Petter Selasky 		if (vl1 != 15)
268*d6b92ffaSHans Petter Selasky 			vl1 &= vl_mask;
269*d6b92ffaSHans Petter Selasky 		if (vl2 != 15)
270*d6b92ffaSHans Petter Selasky 			vl2 &= vl_mask;
271*d6b92ffaSHans Petter Selasky 		tbl.raw_vl_by_sl[i] = (vl1 << 4) | vl2;
272*d6b92ffaSHans Petter Selasky 	}
273*d6b92ffaSHans Petter Selasky 
274*d6b92ffaSHans Petter Selasky 	p_tbl = osm_physp_get_slvl_tbl(p, in_port);
275*d6b92ffaSHans Petter Selasky 
276*d6b92ffaSHans Petter Selasky 	if (!force_update && !memcmp(p_tbl, &tbl, sizeof(tbl)))
277*d6b92ffaSHans Petter Selasky 		return IB_SUCCESS;
278*d6b92ffaSHans Petter Selasky 
279*d6b92ffaSHans Petter Selasky 	p_mad = osm_qos_mad_create(sm, p, sizeof(tbl), (uint8_t *) & tbl,
280*d6b92ffaSHans Petter Selasky 				   IB_MAD_ATTR_SLVL_TABLE, attr_mod);
281*d6b92ffaSHans Petter Selasky 	if (!p_mad)
282*d6b92ffaSHans Petter Selasky 		return IB_INSUFFICIENT_MEMORY;
283*d6b92ffaSHans Petter Selasky 
284*d6b92ffaSHans Petter Selasky 	/*
285*d6b92ffaSHans Petter Selasky 	 * Zero the stored SL2VL block, so in case the MAD will
286*d6b92ffaSHans Petter Selasky 	 * end up with error, we will resend it in the next sweep.
287*d6b92ffaSHans Petter Selasky 	 */
288*d6b92ffaSHans Petter Selasky 	memset(p_tbl, 0, sizeof(tbl));
289*d6b92ffaSHans Petter Selasky 
290*d6b92ffaSHans Petter Selasky 	cl_qlist_insert_tail(mad_list, &p_mad->list_item);
291*d6b92ffaSHans Petter Selasky 	return IB_SUCCESS;
292*d6b92ffaSHans Petter Selasky }
293*d6b92ffaSHans Petter Selasky 
qos_extports_setup(osm_sm_t * sm,osm_node_t * node,const struct qos_config * qcfg,cl_qlist_t * port_mad_list)294*d6b92ffaSHans Petter Selasky static int qos_extports_setup(osm_sm_t * sm, osm_node_t *node,
295*d6b92ffaSHans Petter Selasky 			      const struct qos_config *qcfg,
296*d6b92ffaSHans Petter Selasky 			      cl_qlist_t *port_mad_list)
297*d6b92ffaSHans Petter Selasky 
298*d6b92ffaSHans Petter Selasky {
299*d6b92ffaSHans Petter Selasky 	osm_physp_t *p0, *p;
300*d6b92ffaSHans Petter Selasky 	unsigned force_update;
301*d6b92ffaSHans Petter Selasky 	unsigned num_ports = osm_node_get_num_physp(node);
302*d6b92ffaSHans Petter Selasky 	struct osm_routing_engine *re = sm->p_subn->p_osm->routing_engine_used;
303*d6b92ffaSHans Petter Selasky 	int ret = 0;
304*d6b92ffaSHans Petter Selasky 	unsigned in, out;
305*d6b92ffaSHans Petter Selasky 	uint8_t op_vl, common_op_vl = 0, max_num = 0;
306*d6b92ffaSHans Petter Selasky 	uint8_t op_vl_arr[15];
307*d6b92ffaSHans Petter Selasky 
308*d6b92ffaSHans Petter Selasky 	/*
309*d6b92ffaSHans Petter Selasky 	 * Do nothing unless the most recent routing attempt was successful.
310*d6b92ffaSHans Petter Selasky 	 */
311*d6b92ffaSHans Petter Selasky 	if (!re)
312*d6b92ffaSHans Petter Selasky 		return ret;
313*d6b92ffaSHans Petter Selasky 
314*d6b92ffaSHans Petter Selasky 	for (out = 1; out < num_ports; out++) {
315*d6b92ffaSHans Petter Selasky 		p = osm_node_get_physp_ptr(node, out);
316*d6b92ffaSHans Petter Selasky 		if (!p)
317*d6b92ffaSHans Petter Selasky 			continue;
318*d6b92ffaSHans Petter Selasky 		if (ib_port_info_get_port_state(&p->port_info) == IB_LINK_DOWN)
319*d6b92ffaSHans Petter Selasky 			continue;
320*d6b92ffaSHans Petter Selasky 		force_update = p->need_update || sm->p_subn->need_update;
321*d6b92ffaSHans Petter Selasky 		p->vl_high_limit = qcfg->vl_high_limit;
322*d6b92ffaSHans Petter Selasky 		if (vlarb_update(sm, p, p->port_num, force_update, qcfg,
323*d6b92ffaSHans Petter Selasky 				 port_mad_list))
324*d6b92ffaSHans Petter Selasky 			ret = -1;
325*d6b92ffaSHans Petter Selasky 	}
326*d6b92ffaSHans Petter Selasky 
327*d6b92ffaSHans Petter Selasky 	p0 = osm_node_get_physp_ptr(node, 0);
328*d6b92ffaSHans Petter Selasky 	if (!(p0->port_info.capability_mask & IB_PORT_CAP_HAS_SL_MAP))
329*d6b92ffaSHans Petter Selasky 		return ret;
330*d6b92ffaSHans Petter Selasky 
331*d6b92ffaSHans Petter Selasky 	if (ib_switch_info_get_opt_sl2vlmapping(&node->sw->switch_info) &&
332*d6b92ffaSHans Petter Selasky 	    sm->p_subn->opt.use_optimized_slvl && !re->update_sl2vl) {
333*d6b92ffaSHans Petter Selasky 
334*d6b92ffaSHans Petter Selasky 		/* we should find the op_vl that is used by majority of ports */
335*d6b92ffaSHans Petter Selasky 		memset(&op_vl_arr[0], 0, sizeof(op_vl_arr));
336*d6b92ffaSHans Petter Selasky 		p0 = osm_node_get_physp_ptr(node, 1);
337*d6b92ffaSHans Petter Selasky 
338*d6b92ffaSHans Petter Selasky 		for (out = 1; out < num_ports; out++) {
339*d6b92ffaSHans Petter Selasky 			p = osm_node_get_physp_ptr(node, out);
340*d6b92ffaSHans Petter Selasky 			if (!p)
341*d6b92ffaSHans Petter Selasky 				continue;
342*d6b92ffaSHans Petter Selasky 			if (ib_port_info_get_port_state(&p->port_info) ==
343*d6b92ffaSHans Petter Selasky 			    IB_LINK_DOWN)
344*d6b92ffaSHans Petter Selasky 				continue;
345*d6b92ffaSHans Petter Selasky 			op_vl = ib_port_info_get_op_vls(&p->port_info);
346*d6b92ffaSHans Petter Selasky 			op_vl_arr[op_vl]++;
347*d6b92ffaSHans Petter Selasky 			if (op_vl_arr[op_vl] > max_num){
348*d6b92ffaSHans Petter Selasky 				max_num = op_vl_arr[op_vl];
349*d6b92ffaSHans Petter Selasky 				common_op_vl = op_vl;
350*d6b92ffaSHans Petter Selasky 				/* remember the port with most common op_vl */
351*d6b92ffaSHans Petter Selasky 				p0 = p;
352*d6b92ffaSHans Petter Selasky 			}
353*d6b92ffaSHans Petter Selasky 
354*d6b92ffaSHans Petter Selasky 		}
355*d6b92ffaSHans Petter Selasky 		if (!p0)
356*d6b92ffaSHans Petter Selasky 			return -1;
357*d6b92ffaSHans Petter Selasky 		force_update = node->sw->need_update || sm->p_subn->need_update;
358*d6b92ffaSHans Petter Selasky 		if (sl2vl_update_table(sm, p0, p0->port_num, 0x30000, force_update,
359*d6b92ffaSHans Petter Selasky 					&qcfg->sl2vl, port_mad_list))
360*d6b92ffaSHans Petter Selasky 			ret = -1;
361*d6b92ffaSHans Petter Selasky 		/*
362*d6b92ffaSHans Petter Selasky 		 * Overwrite default ALL configuration if port's
363*d6b92ffaSHans Petter Selasky 		 * op_vl is different.
364*d6b92ffaSHans Petter Selasky 		 */
365*d6b92ffaSHans Petter Selasky 		for (out = 1; out < num_ports; out++) {
366*d6b92ffaSHans Petter Selasky 			p = osm_node_get_physp_ptr(node, out);
367*d6b92ffaSHans Petter Selasky 			if (!p)
368*d6b92ffaSHans Petter Selasky 				continue;
369*d6b92ffaSHans Petter Selasky 			if (ib_port_info_get_port_state(&p->port_info) ==
370*d6b92ffaSHans Petter Selasky 			    IB_LINK_DOWN)
371*d6b92ffaSHans Petter Selasky 				continue;
372*d6b92ffaSHans Petter Selasky 
373*d6b92ffaSHans Petter Selasky 			force_update = p->need_update || force_update;
374*d6b92ffaSHans Petter Selasky 			if (ib_port_info_get_op_vls(&p->port_info) !=
375*d6b92ffaSHans Petter Selasky 			    common_op_vl &&
376*d6b92ffaSHans Petter Selasky 			    sl2vl_update_table(sm, p, p->port_num, 0x20000 | out,
377*d6b92ffaSHans Petter Selasky 					       force_update, &qcfg->sl2vl,
378*d6b92ffaSHans Petter Selasky 					       port_mad_list))
379*d6b92ffaSHans Petter Selasky 				ret = -1;
380*d6b92ffaSHans Petter Selasky 		}
381*d6b92ffaSHans Petter Selasky 		return ret;
382*d6b92ffaSHans Petter Selasky 	}
383*d6b92ffaSHans Petter Selasky 
384*d6b92ffaSHans Petter Selasky 	/* non optimized sl2vl configuration */
385*d6b92ffaSHans Petter Selasky 	out = ib_switch_info_is_enhanced_port0(&node->sw->switch_info) ? 0 : 1;
386*d6b92ffaSHans Petter Selasky 	for (; out < num_ports; out++) {
387*d6b92ffaSHans Petter Selasky 		p = osm_node_get_physp_ptr(node, out);
388*d6b92ffaSHans Petter Selasky 		if (!p)
389*d6b92ffaSHans Petter Selasky 			continue;
390*d6b92ffaSHans Petter Selasky 		if (ib_port_info_get_port_state(&p->port_info) == IB_LINK_DOWN)
391*d6b92ffaSHans Petter Selasky 			continue;
392*d6b92ffaSHans Petter Selasky 		force_update = p->need_update || sm->p_subn->need_update;
393*d6b92ffaSHans Petter Selasky 		/* go over all in ports */
394*d6b92ffaSHans Petter Selasky 		for (in = 0; in < num_ports; in++) {
395*d6b92ffaSHans Petter Selasky 			const ib_slvl_table_t *port_sl2vl = &qcfg->sl2vl;
396*d6b92ffaSHans Petter Selasky 			ib_slvl_table_t routing_sl2vl;
397*d6b92ffaSHans Petter Selasky 
398*d6b92ffaSHans Petter Selasky 			if (re->update_sl2vl) {
399*d6b92ffaSHans Petter Selasky 				routing_sl2vl = *port_sl2vl;
400*d6b92ffaSHans Petter Selasky 				re->update_sl2vl(re->context,
401*d6b92ffaSHans Petter Selasky 						 p, in, out, &routing_sl2vl);
402*d6b92ffaSHans Petter Selasky 				port_sl2vl = &routing_sl2vl;
403*d6b92ffaSHans Petter Selasky 			}
404*d6b92ffaSHans Petter Selasky 			if (sl2vl_update_table(sm, p, in, in << 8 | out,
405*d6b92ffaSHans Petter Selasky 					       force_update, port_sl2vl,
406*d6b92ffaSHans Petter Selasky 					       port_mad_list))
407*d6b92ffaSHans Petter Selasky 				ret = -1;
408*d6b92ffaSHans Petter Selasky 		}
409*d6b92ffaSHans Petter Selasky 	}
410*d6b92ffaSHans Petter Selasky 
411*d6b92ffaSHans Petter Selasky 	return ret;
412*d6b92ffaSHans Petter Selasky }
413*d6b92ffaSHans Petter Selasky 
qos_endport_setup(osm_sm_t * sm,osm_physp_t * p,const struct qos_config * qcfg,int vlarb_only,cl_qlist_t * port_mad_list)414*d6b92ffaSHans Petter Selasky static int qos_endport_setup(osm_sm_t * sm, osm_physp_t * p,
415*d6b92ffaSHans Petter Selasky 			     const struct qos_config *qcfg, int vlarb_only,
416*d6b92ffaSHans Petter Selasky 			     cl_qlist_t *port_mad_list)
417*d6b92ffaSHans Petter Selasky {
418*d6b92ffaSHans Petter Selasky 	unsigned force_update = p->need_update || sm->p_subn->need_update;
419*d6b92ffaSHans Petter Selasky 	struct osm_routing_engine *re = sm->p_subn->p_osm->routing_engine_used;
420*d6b92ffaSHans Petter Selasky 	const ib_slvl_table_t *port_sl2vl = &qcfg->sl2vl;
421*d6b92ffaSHans Petter Selasky 	ib_slvl_table_t routing_sl2vl;
422*d6b92ffaSHans Petter Selasky 
423*d6b92ffaSHans Petter Selasky 	p->vl_high_limit = qcfg->vl_high_limit;
424*d6b92ffaSHans Petter Selasky 	if (vlarb_update(sm, p, 0, force_update, qcfg, port_mad_list))
425*d6b92ffaSHans Petter Selasky 		return -1;
426*d6b92ffaSHans Petter Selasky 	if (vlarb_only)
427*d6b92ffaSHans Petter Selasky 		return 0;
428*d6b92ffaSHans Petter Selasky 
429*d6b92ffaSHans Petter Selasky 	if (!(p->port_info.capability_mask & IB_PORT_CAP_HAS_SL_MAP))
430*d6b92ffaSHans Petter Selasky 		return 0;
431*d6b92ffaSHans Petter Selasky 
432*d6b92ffaSHans Petter Selasky 	if (re && re->update_sl2vl) {
433*d6b92ffaSHans Petter Selasky 		routing_sl2vl = *port_sl2vl;
434*d6b92ffaSHans Petter Selasky 		re->update_sl2vl(re->context, p, 0, 0, &routing_sl2vl);
435*d6b92ffaSHans Petter Selasky 		port_sl2vl = &routing_sl2vl;
436*d6b92ffaSHans Petter Selasky 	}
437*d6b92ffaSHans Petter Selasky 	if (sl2vl_update_table(sm, p, 0, 0, force_update, port_sl2vl,
438*d6b92ffaSHans Petter Selasky 			       port_mad_list))
439*d6b92ffaSHans Petter Selasky 		return -1;
440*d6b92ffaSHans Petter Selasky 
441*d6b92ffaSHans Petter Selasky 	return 0;
442*d6b92ffaSHans Petter Selasky }
443*d6b92ffaSHans Petter Selasky 
osm_qos_setup(osm_opensm_t * p_osm)444*d6b92ffaSHans Petter Selasky int osm_qos_setup(osm_opensm_t * p_osm)
445*d6b92ffaSHans Petter Selasky {
446*d6b92ffaSHans Petter Selasky 	struct qos_config ca_config, sw0_config, swe_config, rtr_config;
447*d6b92ffaSHans Petter Selasky 	struct qos_config *cfg;
448*d6b92ffaSHans Petter Selasky 	cl_qmap_t *p_tbl;
449*d6b92ffaSHans Petter Selasky 	cl_map_item_t *p_next;
450*d6b92ffaSHans Petter Selasky 	osm_port_t *p_port;
451*d6b92ffaSHans Petter Selasky 	osm_node_t *p_node;
452*d6b92ffaSHans Petter Selasky 	int ret = 0;
453*d6b92ffaSHans Petter Selasky 	int vlarb_only;
454*d6b92ffaSHans Petter Selasky 	qos_mad_list_t *p_list, *p_list_next;
455*d6b92ffaSHans Petter Selasky 	qos_mad_item_t *p_port_mad;
456*d6b92ffaSHans Petter Selasky 	cl_qlist_t qos_mad_list;
457*d6b92ffaSHans Petter Selasky 
458*d6b92ffaSHans Petter Selasky 	if (!p_osm->subn.opt.qos)
459*d6b92ffaSHans Petter Selasky 		return 0;
460*d6b92ffaSHans Petter Selasky 
461*d6b92ffaSHans Petter Selasky 	OSM_LOG_ENTER(&p_osm->log);
462*d6b92ffaSHans Petter Selasky 
463*d6b92ffaSHans Petter Selasky 	qos_build_config(&ca_config, &p_osm->subn.opt.qos_ca_options,
464*d6b92ffaSHans Petter Selasky 			 &p_osm->subn.opt.qos_options);
465*d6b92ffaSHans Petter Selasky 	qos_build_config(&sw0_config, &p_osm->subn.opt.qos_sw0_options,
466*d6b92ffaSHans Petter Selasky 			 &p_osm->subn.opt.qos_options);
467*d6b92ffaSHans Petter Selasky 	qos_build_config(&swe_config, &p_osm->subn.opt.qos_swe_options,
468*d6b92ffaSHans Petter Selasky 			 &p_osm->subn.opt.qos_options);
469*d6b92ffaSHans Petter Selasky 	qos_build_config(&rtr_config, &p_osm->subn.opt.qos_rtr_options,
470*d6b92ffaSHans Petter Selasky 			 &p_osm->subn.opt.qos_options);
471*d6b92ffaSHans Petter Selasky 
472*d6b92ffaSHans Petter Selasky 	cl_qlist_init(&qos_mad_list);
473*d6b92ffaSHans Petter Selasky 
474*d6b92ffaSHans Petter Selasky 	cl_plock_excl_acquire(&p_osm->lock);
475*d6b92ffaSHans Petter Selasky 
476*d6b92ffaSHans Petter Selasky 	/* read QoS policy config file */
477*d6b92ffaSHans Petter Selasky 	osm_qos_parse_policy_file(&p_osm->subn);
478*d6b92ffaSHans Petter Selasky 	p_tbl = &p_osm->subn.port_guid_tbl;
479*d6b92ffaSHans Petter Selasky 	p_next = cl_qmap_head(p_tbl);
480*d6b92ffaSHans Petter Selasky 	while (p_next != cl_qmap_end(p_tbl)) {
481*d6b92ffaSHans Petter Selasky 		vlarb_only = 0;
482*d6b92ffaSHans Petter Selasky 		p_port = (osm_port_t *) p_next;
483*d6b92ffaSHans Petter Selasky 		p_next = cl_qmap_next(p_next);
484*d6b92ffaSHans Petter Selasky 
485*d6b92ffaSHans Petter Selasky 		p_list = (qos_mad_list_t *) malloc(sizeof(*p_list));
486*d6b92ffaSHans Petter Selasky 		if (!p_list) {
487*d6b92ffaSHans Petter Selasky 			cl_plock_release(&p_osm->lock);
488*d6b92ffaSHans Petter Selasky 			return -1;
489*d6b92ffaSHans Petter Selasky 		}
490*d6b92ffaSHans Petter Selasky 
491*d6b92ffaSHans Petter Selasky 		memset(p_list, 0, sizeof(*p_list));
492*d6b92ffaSHans Petter Selasky 
493*d6b92ffaSHans Petter Selasky 		cl_qlist_init(&p_list->port_mad_list);
494*d6b92ffaSHans Petter Selasky 
495*d6b92ffaSHans Petter Selasky 		p_node = p_port->p_node;
496*d6b92ffaSHans Petter Selasky 		if (p_node->sw) {
497*d6b92ffaSHans Petter Selasky 			if (qos_extports_setup(&p_osm->sm, p_node, &swe_config,
498*d6b92ffaSHans Petter Selasky 					       &p_list->port_mad_list)) {
499*d6b92ffaSHans Petter Selasky 				cl_plock_release(&p_osm->lock);
500*d6b92ffaSHans Petter Selasky 				ret = -1;
501*d6b92ffaSHans Petter Selasky 			}
502*d6b92ffaSHans Petter Selasky 
503*d6b92ffaSHans Petter Selasky 			/* skip base port 0 */
504*d6b92ffaSHans Petter Selasky 			if (!ib_switch_info_is_enhanced_port0
505*d6b92ffaSHans Petter Selasky 			    (&p_node->sw->switch_info))
506*d6b92ffaSHans Petter Selasky 				goto Continue;
507*d6b92ffaSHans Petter Selasky 
508*d6b92ffaSHans Petter Selasky 			if (ib_switch_info_get_opt_sl2vlmapping(&p_node->sw->switch_info) &&
509*d6b92ffaSHans Petter Selasky 			    p_osm->sm.p_subn->opt.use_optimized_slvl &&
510*d6b92ffaSHans Petter Selasky 			    !memcmp(&swe_config.sl2vl, &sw0_config.sl2vl,
511*d6b92ffaSHans Petter Selasky 				    sizeof(swe_config.sl2vl)))
512*d6b92ffaSHans Petter Selasky 				vlarb_only = 1;
513*d6b92ffaSHans Petter Selasky 
514*d6b92ffaSHans Petter Selasky 			cfg = &sw0_config;
515*d6b92ffaSHans Petter Selasky 		} else if (osm_node_get_type(p_node) == IB_NODE_TYPE_ROUTER)
516*d6b92ffaSHans Petter Selasky 			cfg = &rtr_config;
517*d6b92ffaSHans Petter Selasky 		else
518*d6b92ffaSHans Petter Selasky 			cfg = &ca_config;
519*d6b92ffaSHans Petter Selasky 
520*d6b92ffaSHans Petter Selasky 		if (qos_endport_setup(&p_osm->sm, p_port->p_physp, cfg,
521*d6b92ffaSHans Petter Selasky 				      vlarb_only, &p_list->port_mad_list)) {
522*d6b92ffaSHans Petter Selasky 			cl_plock_release(&p_osm->lock);
523*d6b92ffaSHans Petter Selasky 			ret = -1;
524*d6b92ffaSHans Petter Selasky 		}
525*d6b92ffaSHans Petter Selasky Continue:
526*d6b92ffaSHans Petter Selasky 		/* if MAD list is not empty, add it to the global MAD list */
527*d6b92ffaSHans Petter Selasky 		if (cl_qlist_count(&p_list->port_mad_list)) {
528*d6b92ffaSHans Petter Selasky 			cl_qlist_insert_tail(&qos_mad_list, &p_list->list_item);
529*d6b92ffaSHans Petter Selasky 		} else {
530*d6b92ffaSHans Petter Selasky 			free(p_list);
531*d6b92ffaSHans Petter Selasky 		}
532*d6b92ffaSHans Petter Selasky 	}
533*d6b92ffaSHans Petter Selasky 	while (cl_qlist_count(&qos_mad_list)) {
534*d6b92ffaSHans Petter Selasky 		p_list_next = (qos_mad_list_t *) cl_qlist_head(&qos_mad_list);
535*d6b92ffaSHans Petter Selasky 		while (p_list_next !=
536*d6b92ffaSHans Petter Selasky 			(qos_mad_list_t *) cl_qlist_end(&qos_mad_list)) {
537*d6b92ffaSHans Petter Selasky 			p_list = p_list_next;
538*d6b92ffaSHans Petter Selasky 			p_list_next = (qos_mad_list_t *)
539*d6b92ffaSHans Petter Selasky 				      cl_qlist_next(&p_list->list_item);
540*d6b92ffaSHans Petter Selasky 			/* next MAD to send*/
541*d6b92ffaSHans Petter Selasky 			p_port_mad = (qos_mad_item_t *)
542*d6b92ffaSHans Petter Selasky 				     cl_qlist_remove_head(&p_list->port_mad_list);
543*d6b92ffaSHans Petter Selasky 			osm_send_req_mad(&p_osm->sm, p_port_mad->p_madw);
544*d6b92ffaSHans Petter Selasky 			osm_qos_mad_delete(&p_port_mad);
545*d6b92ffaSHans Petter Selasky 			/* remove the QoS MAD from global MAD list */
546*d6b92ffaSHans Petter Selasky 			if (cl_qlist_count(&p_list->port_mad_list) == 0) {
547*d6b92ffaSHans Petter Selasky 				cl_qlist_remove_item(&qos_mad_list, &p_list->list_item);
548*d6b92ffaSHans Petter Selasky 				free(p_list);
549*d6b92ffaSHans Petter Selasky 			}
550*d6b92ffaSHans Petter Selasky 		}
551*d6b92ffaSHans Petter Selasky 	}
552*d6b92ffaSHans Petter Selasky 
553*d6b92ffaSHans Petter Selasky 	cl_plock_release(&p_osm->lock);
554*d6b92ffaSHans Petter Selasky 	OSM_LOG_EXIT(&p_osm->log);
555*d6b92ffaSHans Petter Selasky 
556*d6b92ffaSHans Petter Selasky 	return ret;
557*d6b92ffaSHans Petter Selasky }
558*d6b92ffaSHans Petter Selasky 
559*d6b92ffaSHans Petter Selasky /*
560*d6b92ffaSHans Petter Selasky  *  QoS config stuff
561*d6b92ffaSHans Petter Selasky  */
parse_one_unsigned(const char * str,char delim,unsigned * val)562*d6b92ffaSHans Petter Selasky static int parse_one_unsigned(const char *str, char delim, unsigned *val)
563*d6b92ffaSHans Petter Selasky {
564*d6b92ffaSHans Petter Selasky 	char *end;
565*d6b92ffaSHans Petter Selasky 	*val = strtoul(str, &end, 0);
566*d6b92ffaSHans Petter Selasky 	if (*end)
567*d6b92ffaSHans Petter Selasky 		end++;
568*d6b92ffaSHans Petter Selasky 	return (int)(end - str);
569*d6b92ffaSHans Petter Selasky }
570*d6b92ffaSHans Petter Selasky 
parse_vlarb_entry(const char * str,ib_vl_arb_element_t * e)571*d6b92ffaSHans Petter Selasky static int parse_vlarb_entry(const char *str, ib_vl_arb_element_t * e)
572*d6b92ffaSHans Petter Selasky {
573*d6b92ffaSHans Petter Selasky 	unsigned val;
574*d6b92ffaSHans Petter Selasky 	const char *p = str;
575*d6b92ffaSHans Petter Selasky 	p += parse_one_unsigned(p, ':', &val);
576*d6b92ffaSHans Petter Selasky 	e->vl = val % 15;
577*d6b92ffaSHans Petter Selasky 	p += parse_one_unsigned(p, ',', &val);
578*d6b92ffaSHans Petter Selasky 	e->weight = (uint8_t) val;
579*d6b92ffaSHans Petter Selasky 	return (int)(p - str);
580*d6b92ffaSHans Petter Selasky }
581*d6b92ffaSHans Petter Selasky 
parse_sl2vl_entry(const char * str,uint8_t * raw)582*d6b92ffaSHans Petter Selasky static int parse_sl2vl_entry(const char *str, uint8_t * raw)
583*d6b92ffaSHans Petter Selasky {
584*d6b92ffaSHans Petter Selasky 	unsigned val1, val2;
585*d6b92ffaSHans Petter Selasky 	const char *p = str;
586*d6b92ffaSHans Petter Selasky 	p += parse_one_unsigned(p, ',', &val1);
587*d6b92ffaSHans Petter Selasky 	p += parse_one_unsigned(p, ',', &val2);
588*d6b92ffaSHans Petter Selasky 	*raw = (val1 << 4) | (val2 & 0xf);
589*d6b92ffaSHans Petter Selasky 	return (int)(p - str);
590*d6b92ffaSHans Petter Selasky }
591*d6b92ffaSHans Petter Selasky 
qos_build_config(struct qos_config * cfg,osm_qos_options_t * opt,osm_qos_options_t * dflt)592*d6b92ffaSHans Petter Selasky static void qos_build_config(struct qos_config *cfg, osm_qos_options_t * opt,
593*d6b92ffaSHans Petter Selasky 			     osm_qos_options_t * dflt)
594*d6b92ffaSHans Petter Selasky {
595*d6b92ffaSHans Petter Selasky 	int i;
596*d6b92ffaSHans Petter Selasky 	const char *p;
597*d6b92ffaSHans Petter Selasky 
598*d6b92ffaSHans Petter Selasky 	memset(cfg, 0, sizeof(*cfg));
599*d6b92ffaSHans Petter Selasky 
600*d6b92ffaSHans Petter Selasky 	if (opt->max_vls > 0)
601*d6b92ffaSHans Petter Selasky 		cfg->max_vls = opt->max_vls;
602*d6b92ffaSHans Petter Selasky 	else {
603*d6b92ffaSHans Petter Selasky 		if (dflt->max_vls > 0)
604*d6b92ffaSHans Petter Selasky 			cfg->max_vls = dflt->max_vls;
605*d6b92ffaSHans Petter Selasky 		else
606*d6b92ffaSHans Petter Selasky 			cfg->max_vls = OSM_DEFAULT_QOS_MAX_VLS;
607*d6b92ffaSHans Petter Selasky 	}
608*d6b92ffaSHans Petter Selasky 
609*d6b92ffaSHans Petter Selasky 	if (opt->high_limit >= 0)
610*d6b92ffaSHans Petter Selasky 		cfg->vl_high_limit = (uint8_t) opt->high_limit;
611*d6b92ffaSHans Petter Selasky 	else {
612*d6b92ffaSHans Petter Selasky 		if (dflt->high_limit >= 0)
613*d6b92ffaSHans Petter Selasky 			cfg->vl_high_limit = (uint8_t) dflt->high_limit;
614*d6b92ffaSHans Petter Selasky 		else
615*d6b92ffaSHans Petter Selasky 			cfg->vl_high_limit = (uint8_t) OSM_DEFAULT_QOS_HIGH_LIMIT;
616*d6b92ffaSHans Petter Selasky 	}
617*d6b92ffaSHans Petter Selasky 
618*d6b92ffaSHans Petter Selasky 	if (opt->vlarb_high)
619*d6b92ffaSHans Petter Selasky 		p = opt->vlarb_high;
620*d6b92ffaSHans Petter Selasky 	else {
621*d6b92ffaSHans Petter Selasky 		if (dflt->vlarb_high)
622*d6b92ffaSHans Petter Selasky 			p = dflt->vlarb_high;
623*d6b92ffaSHans Petter Selasky 		else
624*d6b92ffaSHans Petter Selasky 			p = OSM_DEFAULT_QOS_VLARB_HIGH;
625*d6b92ffaSHans Petter Selasky 	}
626*d6b92ffaSHans Petter Selasky 	for (i = 0; i < 2 * IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; i++) {
627*d6b92ffaSHans Petter Selasky 		p += parse_vlarb_entry(p,
628*d6b92ffaSHans Petter Selasky 				       &cfg->vlarb_high[i /
629*d6b92ffaSHans Petter Selasky 							IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK].
630*d6b92ffaSHans Petter Selasky 				       vl_entry[i %
631*d6b92ffaSHans Petter Selasky 						IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK]);
632*d6b92ffaSHans Petter Selasky 	}
633*d6b92ffaSHans Petter Selasky 
634*d6b92ffaSHans Petter Selasky 	if (opt->vlarb_low)
635*d6b92ffaSHans Petter Selasky 		p = opt->vlarb_low;
636*d6b92ffaSHans Petter Selasky 	else {
637*d6b92ffaSHans Petter Selasky 		if (dflt->vlarb_low)
638*d6b92ffaSHans Petter Selasky 			p = dflt->vlarb_low;
639*d6b92ffaSHans Petter Selasky 		else
640*d6b92ffaSHans Petter Selasky 			p = OSM_DEFAULT_QOS_VLARB_LOW;
641*d6b92ffaSHans Petter Selasky 	}
642*d6b92ffaSHans Petter Selasky 	for (i = 0; i < 2 * IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; i++) {
643*d6b92ffaSHans Petter Selasky 		p += parse_vlarb_entry(p,
644*d6b92ffaSHans Petter Selasky 				       &cfg->vlarb_low[i /
645*d6b92ffaSHans Petter Selasky 						       IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK].
646*d6b92ffaSHans Petter Selasky 				       vl_entry[i %
647*d6b92ffaSHans Petter Selasky 						IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK]);
648*d6b92ffaSHans Petter Selasky 	}
649*d6b92ffaSHans Petter Selasky 
650*d6b92ffaSHans Petter Selasky 	p = opt->sl2vl ? opt->sl2vl : dflt->sl2vl;
651*d6b92ffaSHans Petter Selasky 	if (opt->sl2vl)
652*d6b92ffaSHans Petter Selasky 		p = opt->sl2vl;
653*d6b92ffaSHans Petter Selasky 	else {
654*d6b92ffaSHans Petter Selasky 		if (dflt->sl2vl)
655*d6b92ffaSHans Petter Selasky 			p = dflt->sl2vl;
656*d6b92ffaSHans Petter Selasky 		else
657*d6b92ffaSHans Petter Selasky 			p = OSM_DEFAULT_QOS_SL2VL;
658*d6b92ffaSHans Petter Selasky 	}
659*d6b92ffaSHans Petter Selasky 	for (i = 0; i < IB_MAX_NUM_VLS / 2; i++)
660*d6b92ffaSHans Petter Selasky 		p += parse_sl2vl_entry(p, &cfg->sl2vl.raw_vl_by_sl[i]);
661*d6b92ffaSHans Petter Selasky }
662