]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ofed/management/opensm/opensm/osm_prtn_config.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / ofed / management / opensm / opensm / osm_prtn_config.c
1 /*
2  * Copyright (c) 2006-2007 Voltaire, Inc. All rights reserved.
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, available from the file
7  * COPYING in the main directory of this source tree, or the
8  * OpenIB.org BSD license below:
9  *
10  *     Redistribution and use in source and binary forms, with or
11  *     without modification, are permitted provided that the following
12  *     conditions are met:
13  *
14  *      - Redistributions of source code must retain the above
15  *        copyright notice, this list of conditions and the following
16  *        disclaimer.
17  *
18  *      - Redistributions in binary form must reproduce the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer in the documentation and/or other materials
21  *        provided with the distribution.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30  * SOFTWARE.
31  *
32  */
33
34 /*
35  * Abstract:
36  *    Implementation of opensm partition management configuration
37  */
38
39 #if HAVE_CONFIG_H
40 #  include <config.h>
41 #endif                          /* HAVE_CONFIG_H */
42
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <string.h>
46 #include <errno.h>
47 #include <ctype.h>
48
49 #include <iba/ib_types.h>
50 #include <opensm/osm_base.h>
51 #include <opensm/osm_partition.h>
52 #include <opensm/osm_subnet.h>
53 #include <opensm/osm_log.h>
54
55 #include <complib/cl_byteswap.h>
56
57 struct part_conf {
58         osm_log_t *p_log;
59         osm_subn_t *p_subn;
60         osm_prtn_t *p_prtn;
61         unsigned is_ipoib, mtu, rate, sl, scope_mask;
62         boolean_t full;
63 };
64
65 extern osm_prtn_t *osm_prtn_make_new(osm_log_t * p_log, osm_subn_t * p_subn,
66                                      const char *name, uint16_t pkey);
67 extern ib_api_status_t osm_prtn_add_all(osm_log_t * p_log,
68                                         osm_subn_t * p_subn,
69                                         osm_prtn_t * p, boolean_t full);
70 extern ib_api_status_t osm_prtn_add_port(osm_log_t * p_log,
71                                          osm_subn_t * p_subn, osm_prtn_t * p,
72                                          ib_net64_t guid, boolean_t full);
73 extern ib_api_status_t osm_prtn_add_mcgroup(osm_log_t * p_log,
74                                             osm_subn_t * p_subn, osm_prtn_t * p,
75                                             uint8_t rate,
76                                             uint8_t mtu, uint8_t scope);
77
78 static int partition_create(unsigned lineno, struct part_conf *conf,
79                             char *name, char *id, char *flag, char *flag_val)
80 {
81         uint16_t pkey;
82         unsigned int scope;
83
84         if (!id && name && isdigit(*name)) {
85                 id = name;
86                 name = NULL;
87         }
88
89         if (id) {
90                 char *end;
91
92                 pkey = (uint16_t) strtoul(id, &end, 0);
93                 if (end == id || *end)
94                         return -1;
95         } else
96                 pkey = 0;
97
98         conf->p_prtn = osm_prtn_make_new(conf->p_log, conf->p_subn,
99                                          name, cl_hton16(pkey));
100         if (!conf->p_prtn)
101                 return -1;
102
103         if (!conf->p_subn->opt.qos && conf->sl != OSM_DEFAULT_SL) {
104                 OSM_LOG(conf->p_log, OSM_LOG_DEBUG, "Overriding SL %d"
105                         " to default SL %d on partition %s"
106                         " as QoS is not enabled.\n",
107                         conf->sl, OSM_DEFAULT_SL, name);
108                 conf->sl = OSM_DEFAULT_SL;
109         }
110         conf->p_prtn->sl = (uint8_t) conf->sl;
111
112         if (!conf->is_ipoib)
113                 return 0;
114
115         if (!conf->scope_mask) {
116                 osm_prtn_add_mcgroup(conf->p_log, conf->p_subn, conf->p_prtn,
117                                      (uint8_t) conf->rate,
118                                      (uint8_t) conf->mtu,
119                                      0);
120                 return 0;
121         }
122
123         for (scope = 0; scope < 16; scope++) {
124                 if (((1<<scope) & conf->scope_mask) == 0)
125                         continue;
126
127                 osm_prtn_add_mcgroup(conf->p_log, conf->p_subn, conf->p_prtn,
128                                      (uint8_t) conf->rate,
129                                      (uint8_t) conf->mtu,
130                                      (uint8_t) scope);
131         }
132         return 0;
133 }
134
135 static int partition_add_flag(unsigned lineno, struct part_conf *conf,
136                               char *flag, char *val)
137 {
138         int len = strlen(flag);
139         if (!strncmp(flag, "ipoib", len)) {
140                 conf->is_ipoib = 1;
141         } else if (!strncmp(flag, "mtu", len)) {
142                 if (!val || (conf->mtu = strtoul(val, NULL, 0)) == 0)
143                         OSM_LOG(conf->p_log, OSM_LOG_VERBOSE,
144                                 "PARSE WARN: line %d: "
145                                 "flag \'mtu\' requires valid value"
146                                 " - skipped\n", lineno);
147         } else if (!strncmp(flag, "rate", len)) {
148                 if (!val || (conf->rate = strtoul(val, NULL, 0)) == 0)
149                         OSM_LOG(conf->p_log, OSM_LOG_VERBOSE,
150                                 "PARSE WARN: line %d: "
151                                 "flag \'rate\' requires valid value"
152                                 " - skipped\n", lineno);
153         } else if (!strncmp(flag, "scope", len)) {
154                 unsigned int scope;
155                 if (!val || (scope = strtoul(val, NULL, 0)) == 0 || scope > 0xF)
156                         OSM_LOG(conf->p_log, OSM_LOG_VERBOSE,
157                                 "PARSE WARN: line %d: "
158                                 "flag \'scope\' requires valid value"
159                                 " - skipped\n", lineno);
160                 else
161                         conf->scope_mask |= (1<<scope);
162         } else if (!strncmp(flag, "sl", len)) {
163                 unsigned sl;
164                 char *end;
165
166                 if (!val || !*val || (sl = strtoul(val, &end, 0)) > 15 ||
167                     (*end && !isspace(*end)))
168                         OSM_LOG(conf->p_log, OSM_LOG_VERBOSE,
169                                 "PARSE WARN: line %d: "
170                                 "flag \'sl\' requires valid value"
171                                 " - skipped\n", lineno);
172                 else
173                         conf->sl = sl;
174         } else if (!strncmp(flag, "defmember", len)) {
175                 if (!val || (strncmp(val, "limited", strlen(val))
176                              && strncmp(val, "full", strlen(val))))
177                         OSM_LOG(conf->p_log, OSM_LOG_VERBOSE,
178                                 "PARSE WARN: line %d: "
179                                 "flag \'defmember\' requires valid value (limited or full)"
180                                 " - skipped\n", lineno);
181                 else
182                         conf->full = strncmp(val, "full", strlen(val)) == 0;
183         } else {
184                 OSM_LOG(conf->p_log, OSM_LOG_VERBOSE,
185                         "PARSE WARN: line %d: "
186                         "unrecognized partition flag \'%s\'"
187                         " - ignored\n", lineno, flag);
188         }
189         return 0;
190 }
191
192 static int partition_add_port(unsigned lineno, struct part_conf *conf,
193                               char *name, char *flag)
194 {
195         osm_prtn_t *p = conf->p_prtn;
196         ib_net64_t guid;
197         boolean_t full = conf->full;
198
199         if (!name || !*name || !strncmp(name, "NONE", strlen(name)))
200                 return 0;
201
202         if (flag) {
203                 /* reset default membership to limited */
204                 full = FALSE;
205                 if (!strncmp(flag, "full", strlen(flag)))
206                         full = TRUE;
207                 else if (strncmp(flag, "limited", strlen(flag))) {
208                         OSM_LOG(conf->p_log, OSM_LOG_VERBOSE,
209                                 "PARSE WARN: line %d: "
210                                 "unrecognized port flag \'%s\'."
211                                 " Assume \'limited\'\n", lineno, flag);
212                 }
213         }
214
215         if (!strncmp(name, "ALL", strlen(name))) {
216                 return osm_prtn_add_all(conf->p_log, conf->p_subn, p,
217                                         full) == IB_SUCCESS ? 0 : -1;
218         } else if (!strncmp(name, "SELF", strlen(name))) {
219                 guid = cl_ntoh64(conf->p_subn->sm_port_guid);
220         } else {
221                 char *end;
222                 guid = strtoull(name, &end, 0);
223                 if (!guid || *end)
224                         return -1;
225         }
226
227         if (osm_prtn_add_port(conf->p_log, conf->p_subn, p,
228                               cl_hton64(guid), full) != IB_SUCCESS)
229                 return -1;
230
231         return 0;
232 }
233
234 /* conf file parser */
235
236 #define STRIP_HEAD_SPACES(p) while (*(p) == ' ' || *(p) == '\t' || \
237                 *(p) == '\n') { (p)++; }
238 #define STRIP_TAIL_SPACES(p) { char *q = (p) + strlen(p); \
239                                 while ( q != (p) && ( *q == '\0' || \
240                                         *q == ' ' || *q == '\t' || \
241                                         *q == '\n')) { *q-- = '\0'; }; }
242
243 static int parse_name_token(char *str, char **name, char **val)
244 {
245         int len = 0;
246         char *p, *q;
247
248         *name = *val = NULL;
249
250         p = str;
251
252         while (*p == ' ' || *p == '\t' || *p == '\n')
253                 p++;
254
255         q = strchr(p, '=');
256         if (q)
257                 *q++ = '\0';
258
259         len = strlen(str) + 1;
260         str = q;
261
262         q = p + strlen(p);
263         while (q != p && (*q == '\0' || *q == ' ' || *q == '\t' || *q == '\n'))
264                 *q-- = '\0';
265
266         *name = p;
267
268         p = str;
269         if (!p)
270                 return len;
271
272         while (*p == ' ' || *p == '\t' || *p == '\n')
273                 p++;
274
275         q = p + strlen(p);
276         len += (int)(q - str) + 1;
277         while (q != p && (*q == '\0' || *q == ' ' || *q == '\t' || *q == '\n'))
278                 *q-- = '\0';
279         *val = p;
280
281         return len;
282 }
283
284 static struct part_conf *new_part_conf(osm_log_t * p_log, osm_subn_t * p_subn)
285 {
286         static struct part_conf part;
287         struct part_conf *conf = &part;
288
289         memset(conf, 0, sizeof(*conf));
290         conf->p_log = p_log;
291         conf->p_subn = p_subn;
292         conf->p_prtn = NULL;
293         conf->is_ipoib = 0;
294         conf->sl = OSM_DEFAULT_SL;
295         conf->full = FALSE;
296         return conf;
297 }
298
299 static int flush_part_conf(struct part_conf *conf)
300 {
301         memset(conf, 0, sizeof(*conf));
302         return 0;
303 }
304
305 static int parse_part_conf(struct part_conf *conf, char *str, int lineno)
306 {
307         int ret, len = 0;
308         char *name, *id, *flag, *flval;
309         char *q, *p;
310
311         p = str;
312         if (*p == '\t' || *p == '\0' || *p == '\n')
313                 p++;
314
315         len += (int)(p - str);
316         str = p;
317
318         if (conf->p_prtn)
319                 goto skip_header;
320
321         q = strchr(p, ':');
322         if (!q) {
323                 OSM_LOG(conf->p_log, OSM_LOG_ERROR, "PARSE ERROR: line %d: "
324                         "no partition definition found\n", lineno);
325                 fprintf(stderr, "\nPARSE ERROR: line %d: "
326                         "no partition definition found\n", lineno);
327                 return -1;
328         }
329
330         *q++ = '\0';
331         str = q;
332
333         name = id = flag = flval = NULL;
334
335         q = strchr(p, ',');
336         if (q)
337                 *q = '\0';
338
339         ret = parse_name_token(p, &name, &id);
340         p += ret;
341         len += ret;
342
343         while (q) {
344                 flag = flval = NULL;
345                 q = strchr(p, ',');
346                 if (q)
347                         *q++ = '\0';
348                 ret = parse_name_token(p, &flag, &flval);
349                 if (!flag) {
350                         OSM_LOG(conf->p_log, OSM_LOG_ERROR,
351                                 "PARSE ERROR: line %d: "
352                                 "bad partition flags\n", lineno);
353                         fprintf(stderr, "\nPARSE ERROR: line %d: "
354                                 "bad partition flags\n", lineno);
355                         return -1;
356                 }
357                 p += ret;
358                 len += ret;
359                 partition_add_flag(lineno, conf, flag, flval);
360         }
361
362         if (p != str || (partition_create(lineno, conf,
363                                           name, id, flag, flval) < 0)) {
364                 OSM_LOG(conf->p_log, OSM_LOG_ERROR, "PARSE ERROR: line %d: "
365                         "bad partition definition\n", lineno);
366                 fprintf(stderr, "\nPARSE ERROR: line %d: "
367                         "bad partition definition\n", lineno);
368                 return -1;
369         }
370
371 skip_header:
372         do {
373                 name = flag = NULL;
374                 q = strchr(p, ',');
375                 if (q)
376                         *q++ = '\0';
377                 ret = parse_name_token(p, &name, &flag);
378                 if (partition_add_port(lineno, conf, name, flag) < 0) {
379                         OSM_LOG(conf->p_log, OSM_LOG_ERROR,
380                                 "PARSE ERROR: line %d: "
381                                 "bad PortGUID\n", lineno);
382                         fprintf(stderr, "PARSE ERROR: line %d: "
383                                 "bad PortGUID\n", lineno);
384                         return -1;
385                 }
386                 p += ret;
387                 len += ret;
388         } while (q);
389
390         return len;
391 }
392
393 int osm_prtn_config_parse_file(osm_log_t * p_log, osm_subn_t * p_subn,
394                                const char *file_name)
395 {
396         char line[1024];
397         struct part_conf *conf = NULL;
398         FILE *file;
399         int lineno;
400
401         file = fopen(file_name, "r");
402         if (!file) {
403                 OSM_LOG(p_log, OSM_LOG_VERBOSE,
404                         "Cannot open config file \'%s\': %s\n",
405                         file_name, strerror(errno));
406                 return -1;
407         }
408
409         lineno = 0;
410
411         while (fgets(line, sizeof(line) - 1, file) != NULL) {
412                 char *q, *p = line;
413
414                 lineno++;
415
416                 p = line;
417
418                 q = strchr(p, '#');
419                 if (q)
420                         *q = '\0';
421
422                 do {
423                         int len;
424                         while (*p == ' ' || *p == '\t' || *p == '\n')
425                                 p++;
426                         if (*p == '\0')
427                                 break;
428
429                         if (!conf && !(conf = new_part_conf(p_log, p_subn))) {
430                                 OSM_LOG(conf->p_log, OSM_LOG_ERROR,
431                                         "PARSE ERROR: line %d: "
432                                         "internal: cannot create config\n",
433                                         lineno);
434                                 fprintf(stderr,
435                                         "PARSE ERROR: line %d: "
436                                         "internal: cannot create config\n",
437                                         lineno);
438                                 break;
439                         }
440
441                         q = strchr(p, ';');
442                         if (q)
443                                 *q = '\0';
444
445                         len = parse_part_conf(conf, p, lineno);
446                         if (len < 0) {
447                                 break;
448                         }
449
450                         p += len;
451
452                         if (q) {
453                                 flush_part_conf(conf);
454                                 conf = NULL;
455                         }
456                 } while (q);
457         }
458
459         fclose(file);
460
461         return 0;
462 }