1 %{
2 /*
3  * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
4  * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
5  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
6  * Copyright (c) 2008 HNR Consulting. All rights reserved.
7  *
8  * This software is available to you under a choice of one of two
9  * licenses.  You may choose to be licensed under the terms of the GNU
10  * General Public License (GPL) Version 2, available from the file
11  * COPYING in the main directory of this source tree, or the
12  * OpenIB.org BSD license below:
13  *
14  *     Redistribution and use in source and binary forms, with or
15  *     without modification, are permitted provided that the following
16  *     conditions are met:
17  *
18  *      - Redistributions of source code must retain the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer.
21  *
22  *      - Redistributions in binary form must reproduce the above
23  *        copyright notice, this list of conditions and the following
24  *        disclaimer in the documentation and/or other materials
25  *        provided with the distribution.
26  *
27  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
31  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
32  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
33  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34  * SOFTWARE.
35  *
36  */
37 
38 /*
39  * Abstract:
40  *    Grammar of OSM QoS parser.
41  *
42  * Environment:
43  *    Linux User Mode
44  *
45  * Author:
46  *    Yevgeny Kliteynik, Mellanox
47  */
48 
49 #include <stdio.h>
50 #include <assert.h>
51 #include <stdarg.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <ctype.h>
55 #include <errno.h>
56 #include <opensm/osm_file_ids.h>
57 #define FILE_ID OSM_FILE_QOS_PARSER_Y_Y
58 #include <opensm/osm_opensm.h>
59 #include <opensm/osm_qos_policy.h>
60 
61 #define OSM_QOS_POLICY_MAX_LINE_LEN         1024*10
62 #define OSM_QOS_POLICY_SL2VL_TABLE_LEN      IB_MAX_NUM_VLS
63 #define OSM_QOS_POLICY_MAX_VL_NUM           IB_MAX_NUM_VLS
64 #define OSM_QOS_POLICY_MAX_RATE             IB_MAX_RATE
65 #define OSM_QOS_POLICY_MIN_RATE             IB_MIN_RATE
66 #define OSM_QOS_POLICY_MAX_MTU              IB_MAX_MTU
67 #define OSM_QOS_POLICY_MIN_MTU              IB_MIN_MTU
68 
69 typedef struct tmp_parser_struct_t_ {
70     char       str[OSM_QOS_POLICY_MAX_LINE_LEN];
71     uint64_t   num_pair[2];
72     cl_list_t  str_list;
73     cl_list_t  num_list;
74     cl_list_t  num_pair_list;
75 } tmp_parser_struct_t;
76 
77 static void __parser_tmp_struct_init();
78 static void __parser_tmp_struct_reset();
79 static void __parser_tmp_struct_destroy();
80 
81 static char * __parser_strip_white(char * str);
82 
83 static void __parser_str2uint64(uint64_t * p_val, char * str);
84 
85 static void __parser_port_group_start();
86 static int __parser_port_group_end();
87 
88 static void __parser_sl2vl_scope_start();
89 static int __parser_sl2vl_scope_end();
90 
91 static void __parser_vlarb_scope_start();
92 static int __parser_vlarb_scope_end();
93 
94 static void __parser_qos_level_start();
95 static int __parser_qos_level_end();
96 
97 static void __parser_match_rule_start();
98 static int __parser_match_rule_end();
99 
100 static void __parser_ulp_match_rule_start();
101 static int __parser_ulp_match_rule_end();
102 
103 static void __pkey_rangelist2rangearr(
104     cl_list_t    * p_list,
105     uint64_t  ** * p_arr,
106     unsigned     * p_arr_len);
107 
108 static void __rangelist2rangearr(
109     cl_list_t    * p_list,
110     uint64_t  ** * p_arr,
111     unsigned     * p_arr_len);
112 
113 static void __merge_rangearr(
114     uint64_t  **   range_arr_1,
115     unsigned       range_len_1,
116     uint64_t  **   range_arr_2,
117     unsigned       range_len_2,
118     uint64_t  ** * p_arr,
119     unsigned     * p_arr_len );
120 
121 static void __parser_add_port_to_port_map(
122     cl_qmap_t   * p_map,
123     osm_physp_t * p_physp);
124 
125 static void __parser_add_guid_range_to_port_map(
126     cl_qmap_t  * p_map,
127     uint64_t  ** range_arr,
128     unsigned     range_len);
129 
130 static void __parser_add_pkey_range_to_port_map(
131     cl_qmap_t  * p_map,
132     uint64_t  ** range_arr,
133     unsigned     range_len);
134 
135 static void __parser_add_partition_list_to_port_map(
136     cl_qmap_t  * p_map,
137     cl_list_t  * p_list);
138 
139 static void __parser_add_map_to_port_map(
140     cl_qmap_t * p_dmap,
141     cl_map_t  * p_smap);
142 
143 static int __validate_pkeys(
144     uint64_t ** range_arr,
145     unsigned    range_len,
146     boolean_t   is_ipoib);
147 
148 static void __setup_simple_qos_levels();
149 static void __clear_simple_qos_levels();
150 static void __setup_ulp_match_rules();
151 static void __process_ulp_match_rules();
152 static void yyerror(const char *format, ...);
153 
154 extern char * yytext;
155 extern int yylex (void);
156 extern FILE * yyin;
157 extern int errno;
158 extern void yyrestart(FILE *input_file);
159 int yyparse();
160 
161 #define RESET_BUFFER  __parser_tmp_struct_reset()
162 
163 tmp_parser_struct_t tmp_parser_struct;
164 
165 int column_num;
166 int line_num;
167 
168 osm_qos_policy_t       * p_qos_policy = NULL;
169 osm_qos_port_group_t   * p_current_port_group = NULL;
170 osm_qos_sl2vl_scope_t  * p_current_sl2vl_scope = NULL;
171 osm_qos_vlarb_scope_t  * p_current_vlarb_scope = NULL;
172 osm_qos_level_t        * p_current_qos_level = NULL;
173 osm_qos_match_rule_t   * p_current_qos_match_rule = NULL;
174 osm_log_t              * p_qos_parser_osm_log;
175 
176 /* 16 Simple QoS Levels - one for each SL */
177 static osm_qos_level_t osm_qos_policy_simple_qos_levels[16];
178 
179 /* Default Simple QoS Level */
180 osm_qos_level_t __default_simple_qos_level;
181 
182 /*
183  * List of match rules that will be generated by the
184  * qos-ulp section. These rules are concatenated to
185  * the end of the usual matching rules list at the
186  * end of parsing.
187  */
188 static cl_list_t __ulp_match_rules;
189 
190 /***************************************************/
191 
192 %}
193 
194 %token TK_NUMBER
195 %token TK_DASH
196 %token TK_DOTDOT
197 %token TK_COMMA
198 %token TK_ASTERISK
199 %token TK_TEXT
200 
201 %token TK_QOS_ULPS_START
202 %token TK_QOS_ULPS_END
203 
204 %token TK_PORT_GROUPS_START
205 %token TK_PORT_GROUPS_END
206 %token TK_PORT_GROUP_START
207 %token TK_PORT_GROUP_END
208 
209 %token TK_QOS_SETUP_START
210 %token TK_QOS_SETUP_END
211 %token TK_VLARB_TABLES_START
212 %token TK_VLARB_TABLES_END
213 %token TK_VLARB_SCOPE_START
214 %token TK_VLARB_SCOPE_END
215 
216 %token TK_SL2VL_TABLES_START
217 %token TK_SL2VL_TABLES_END
218 %token TK_SL2VL_SCOPE_START
219 %token TK_SL2VL_SCOPE_END
220 
221 %token TK_QOS_LEVELS_START
222 %token TK_QOS_LEVELS_END
223 %token TK_QOS_LEVEL_START
224 %token TK_QOS_LEVEL_END
225 
226 %token TK_QOS_MATCH_RULES_START
227 %token TK_QOS_MATCH_RULES_END
228 %token TK_QOS_MATCH_RULE_START
229 %token TK_QOS_MATCH_RULE_END
230 
231 %token TK_NAME
232 %token TK_USE
233 %token TK_PORT_GUID
234 %token TK_PORT_NAME
235 %token TK_PARTITION
236 %token TK_NODE_TYPE
237 %token TK_GROUP
238 %token TK_ACROSS
239 %token TK_VLARB_HIGH
240 %token TK_VLARB_LOW
241 %token TK_VLARB_HIGH_LIMIT
242 %token TK_TO
243 %token TK_FROM
244 %token TK_ACROSS_TO
245 %token TK_ACROSS_FROM
246 %token TK_SL2VL_TABLE
247 %token TK_SL
248 %token TK_MTU_LIMIT
249 %token TK_RATE_LIMIT
250 %token TK_PACKET_LIFE
251 %token TK_PATH_BITS
252 %token TK_QOS_CLASS
253 %token TK_SOURCE
254 %token TK_DESTINATION
255 %token TK_SERVICE_ID
256 %token TK_QOS_LEVEL_NAME
257 %token TK_PKEY
258 
259 %token TK_NODE_TYPE_ROUTER
260 %token TK_NODE_TYPE_CA
261 %token TK_NODE_TYPE_SWITCH
262 %token TK_NODE_TYPE_SELF
263 %token TK_NODE_TYPE_ALL
264 
265 %token TK_ULP_DEFAULT
266 %token TK_ULP_ANY_SERVICE_ID
267 %token TK_ULP_ANY_PKEY
268 %token TK_ULP_ANY_TARGET_PORT_GUID
269 %token TK_ULP_ANY_SOURCE_PORT_GUID
270 %token TK_ULP_ANY_SOURCE_TARGET_PORT_GUID
271 %token TK_ULP_SDP_DEFAULT
272 %token TK_ULP_SDP_PORT
273 %token TK_ULP_RDS_DEFAULT
274 %token TK_ULP_RDS_PORT
275 %token TK_ULP_ISER_DEFAULT
276 %token TK_ULP_ISER_PORT
277 %token TK_ULP_SRP_GUID
278 %token TK_ULP_IPOIB_DEFAULT
279 %token TK_ULP_IPOIB_PKEY
280 
281 %start head
282 
283 %%
284 
285 head:               qos_policy_entries
286                     ;
287 
288 qos_policy_entries: /* empty */
289                     | qos_policy_entries qos_policy_entry
290                     ;
291 
292 qos_policy_entry:     qos_ulps_section
293                     | port_groups_section
294                     | qos_setup_section
295                     | qos_levels_section
296                     | qos_match_rules_section
297                     ;
298 
299     /*
300      * Parsing qos-ulps:
301      * -------------------
302      *  qos-ulps
303      *      default                       : 0 #default SL
304      *      sdp, port-num 30000           : 1 #SL for SDP when destination port is 30000
305      *      sdp, port-num 10000-20000     : 2
306      *      sdp                           : 0 #default SL for SDP
307      *      srp, target-port-guid 0x1234  : 2
308      *      rds, port-num 25000           : 2 #SL for RDS when destination port is 25000
309      *      rds,                          : 0 #default SL for RDS
310      *      iser, port-num 900            : 5 #SL for iSER where target port is 900
311      *      iser                          : 4 #default SL for iSER
312      *      ipoib, pkey 0x0001            : 5 #SL for IPoIB on partition with pkey 0x0001
313      *      ipoib                         : 6 #default IPoIB partition - pkey=0x7FFF
314      *      any, service-id 0x6234        : 2
315      *      any, pkey 0x0ABC              : 3
316      *      any, target-port-guid 0x0ABC-0xFFFFF : 6
317      *      any, source-port-guid 0x1234  : 7
318      *      any, source-target-port-guid 0x5678 : 8
319      *  end-qos-ulps
320      */
321 
322 qos_ulps_section: TK_QOS_ULPS_START qos_ulps TK_QOS_ULPS_END
323                      ;
324 
325 qos_ulps:             qos_ulp
326                     | qos_ulps qos_ulp
327                     ;
328 
329     /*
330      * Parsing port groups:
331      * -------------------
332      *  port-groups
333      *       port-group
334      *          name: Storage
335      *          use: our SRP storage targets
336      *          port-guid: 0x1000000000000001,0x1000000000000002
337      *          ...
338      *          port-name: vs1 HCA-1/P1
339      *          port-name: node_description/P2
340      *          ...
341      *          pkey: 0x00FF-0x0FFF
342      *          ...
343      *          partition: Part1
344      *          ...
345      *          node-type: ROUTER,CA,SWITCH,SELF,ALL
346      *          ...
347      *      end-port-group
348      *      port-group
349      *          ...
350      *      end-port-group
351      *  end-port-groups
352      */
353 
354 
355 port_groups_section: TK_PORT_GROUPS_START port_groups TK_PORT_GROUPS_END
356                      ;
357 
358 port_groups:        port_group
359                     | port_groups port_group
360                     ;
361 
362 port_group:         port_group_start port_group_entries port_group_end
363                     ;
364 
365 port_group_start:   TK_PORT_GROUP_START {
366                         __parser_port_group_start();
367                     }
368                     ;
369 
370 port_group_end:     TK_PORT_GROUP_END {
371                         if ( __parser_port_group_end() )
372                             return 1;
373                     }
374                     ;
375 
376 port_group_entries: /* empty */
377                     | port_group_entries port_group_entry
378                     ;
379 
380 port_group_entry:     port_group_name
381                     | port_group_use
382                     | port_group_port_guid
383                     | port_group_port_name
384                     | port_group_pkey
385                     | port_group_partition
386                     | port_group_node_type
387                     ;
388 
389 
390     /*
391      * Parsing qos setup:
392      * -----------------
393      *  qos-setup
394      *      vlarb-tables
395      *          vlarb-scope
396      *              ...
397      *          end-vlarb-scope
398      *          vlarb-scope
399      *              ...
400      *          end-vlarb-scope
401      *     end-vlarb-tables
402      *     sl2vl-tables
403      *          sl2vl-scope
404      *              ...
405      *         end-sl2vl-scope
406      *         sl2vl-scope
407      *              ...
408      *          end-sl2vl-scope
409      *     end-sl2vl-tables
410      *  end-qos-setup
411      */
412 
413 qos_setup_section:  TK_QOS_SETUP_START qos_setup_items TK_QOS_SETUP_END
414                     ;
415 
416 qos_setup_items:    /* empty */
417                     | qos_setup_items vlarb_tables
418                     | qos_setup_items sl2vl_tables
419                     ;
420 
421     /* Parsing vlarb-tables */
422 
423 vlarb_tables:       TK_VLARB_TABLES_START vlarb_scope_items TK_VLARB_TABLES_END
424                     ;
425 
426 vlarb_scope_items:  /* empty */
427                     | vlarb_scope_items vlarb_scope
428                     ;
429 
430 vlarb_scope:        vlarb_scope_start vlarb_scope_entries vlarb_scope_end
431                     ;
432 
433 vlarb_scope_start:  TK_VLARB_SCOPE_START {
434                         __parser_vlarb_scope_start();
435                     }
436                     ;
437 
438 vlarb_scope_end:    TK_VLARB_SCOPE_END {
439                         if ( __parser_vlarb_scope_end() )
440                             return 1;
441                     }
442                     ;
443 
444 vlarb_scope_entries:/* empty */
445                     | vlarb_scope_entries vlarb_scope_entry
446                     ;
447 
448     /*
449      *          vlarb-scope
450      *              group: Storage
451      *              ...
452      *              across: Storage
453      *              ...
454      *              vlarb-high: 0:255,1:127,2:63,3:31,4:15,5:7,6:3,7:1
455      *              vlarb-low: 8:255,9:127,10:63,11:31,12:15,13:7,14:3
456      *              vl-high-limit: 10
457      *          end-vlarb-scope
458      */
459 
460 vlarb_scope_entry:    vlarb_scope_group
461                     | vlarb_scope_across
462                     | vlarb_scope_vlarb_high
463                     | vlarb_scope_vlarb_low
464                     | vlarb_scope_vlarb_high_limit
465                     ;
466 
467     /* Parsing sl2vl-tables */
468 
469 sl2vl_tables:       TK_SL2VL_TABLES_START sl2vl_scope_items TK_SL2VL_TABLES_END
470                     ;
471 
472 sl2vl_scope_items:  /* empty */
473                     | sl2vl_scope_items sl2vl_scope
474                     ;
475 
476 sl2vl_scope:        sl2vl_scope_start sl2vl_scope_entries sl2vl_scope_end
477                     ;
478 
479 sl2vl_scope_start:  TK_SL2VL_SCOPE_START {
480                         __parser_sl2vl_scope_start();
481                     }
482                     ;
483 
484 sl2vl_scope_end:    TK_SL2VL_SCOPE_END {
485                         if ( __parser_sl2vl_scope_end() )
486                             return 1;
487                     }
488                     ;
489 
490 sl2vl_scope_entries:/* empty */
491                     | sl2vl_scope_entries sl2vl_scope_entry
492                     ;
493 
494     /*
495      *          sl2vl-scope
496      *              group: Part1
497      *              ...
498      *              from: *
499      *              ...
500      *              to: *
501      *              ...
502      *              across-to: Storage2
503      *              ...
504      *              across-from: Storage1
505      *              ...
506      *              sl2vl-table: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7
507      *          end-sl2vl-scope
508      */
509 
510 sl2vl_scope_entry:    sl2vl_scope_group
511                     | sl2vl_scope_across
512                     | sl2vl_scope_across_from
513                     | sl2vl_scope_across_to
514                     | sl2vl_scope_from
515                     | sl2vl_scope_to
516                     | sl2vl_scope_sl2vl_table
517                     ;
518 
519     /*
520      * Parsing qos-levels:
521      * ------------------
522      *  qos-levels
523      *      qos-level
524      *          name: qos_level_1
525      *          use: for the lowest priority communication
526      *          sl: 15
527      *          mtu-limit: 1
528      *          rate-limit: 1
529      *          packet-life: 12
530      *          path-bits: 2,4,8-32
531      *          pkey: 0x00FF-0x0FFF
532      *      end-qos-level
533      *          ...
534      *      qos-level
535      *    end-qos-level
536      *  end-qos-levels
537      */
538 
539 
540 qos_levels_section: TK_QOS_LEVELS_START qos_levels TK_QOS_LEVELS_END
541                     ;
542 
543 qos_levels:         /* empty */
544                     | qos_levels qos_level
545                     ;
546 
547 qos_level:          qos_level_start qos_level_entries qos_level_end
548                     ;
549 
550 qos_level_start:    TK_QOS_LEVEL_START {
551                         __parser_qos_level_start();
552                     }
553                     ;
554 
555 qos_level_end:      TK_QOS_LEVEL_END {
556                         if ( __parser_qos_level_end() )
557                             return 1;
558                     }
559                     ;
560 
561 qos_level_entries:  /* empty */
562                     | qos_level_entries qos_level_entry
563                     ;
564 
565 qos_level_entry:      qos_level_name
566                     | qos_level_use
567                     | qos_level_sl
568                     | qos_level_mtu_limit
569                     | qos_level_rate_limit
570                     | qos_level_packet_life
571                     | qos_level_path_bits
572                     | qos_level_pkey
573                     ;
574 
575     /*
576      * Parsing qos-match-rules:
577      * -----------------------
578      *  qos-match-rules
579      *      qos-match-rule
580      *          use: low latency by class 7-9 or 11 and bla bla
581      *          qos-class: 7-9,11
582      *          qos-level-name: default
583      *          source: Storage
584      *          destination: Storage
585      *          service-id: 22,4719-5000
586      *          pkey: 0x00FF-0x0FFF
587      *      end-qos-match-rule
588      *      qos-match-rule
589      *          ...
590      *      end-qos-match-rule
591      *  end-qos-match-rules
592      */
593 
594 qos_match_rules_section: TK_QOS_MATCH_RULES_START qos_match_rules TK_QOS_MATCH_RULES_END
595                     ;
596 
597 qos_match_rules:    /* empty */
598                     | qos_match_rules qos_match_rule
599                     ;
600 
601 qos_match_rule:     qos_match_rule_start qos_match_rule_entries qos_match_rule_end
602                     ;
603 
604 qos_match_rule_start: TK_QOS_MATCH_RULE_START {
605                         __parser_match_rule_start();
606                     }
607                     ;
608 
609 qos_match_rule_end: TK_QOS_MATCH_RULE_END {
610                         if ( __parser_match_rule_end() )
611                             return 1;
612                     }
613                     ;
614 
615 qos_match_rule_entries: /* empty */
616                     | qos_match_rule_entries qos_match_rule_entry
617                     ;
618 
619 qos_match_rule_entry: qos_match_rule_use
620                     | qos_match_rule_qos_class
621                     | qos_match_rule_qos_level_name
622                     | qos_match_rule_source
623                     | qos_match_rule_destination
624                     | qos_match_rule_service_id
625                     | qos_match_rule_pkey
626                     ;
627 
628 
629     /*
630      * Parsing qos-ulps:
631      * -----------------
632      *   default
633      *   sdp
634      *   sdp with port-num
635      *   rds
636      *   rds with port-num
637      *   srp with target-port-guid
638      *   iser
639      *   iser with port-num
640      *   ipoib
641      *   ipoib with pkey
642      *   any with service-id
643      *   any with pkey
644      *   any with target-port-guid
645      *   any with source-port-guid
646      *   any with source-target-port-guid
647      */
648 
649 qos_ulp:            TK_ULP_DEFAULT single_number {
650                         /* parsing default ulp rule: "default: num" */
651                         cl_list_iterator_t    list_iterator;
652                         uint64_t            * p_tmp_num;
653 
654                         list_iterator = cl_list_head(&tmp_parser_struct.num_list);
655                         p_tmp_num = (uint64_t*)cl_list_obj(list_iterator);
656                         if (*p_tmp_num > 15)
657                         {
658                             yyerror("illegal SL value");
659                             return 1;
660                         }
661                         __default_simple_qos_level.sl = (uint8_t)(*p_tmp_num);
662                         __default_simple_qos_level.sl_set = TRUE;
663                         free(p_tmp_num);
664                         cl_list_remove_all(&tmp_parser_struct.num_list);
665                     }
666 
667                     | qos_ulp_type_any_service list_of_ranges TK_DOTDOT {
668                         /* "any, service-id ... : sl" - one instance of list of ranges */
669                         uint64_t ** range_arr;
670                         unsigned    range_len;
671 
672                         if (!cl_list_count(&tmp_parser_struct.num_pair_list))
673                         {
674                             yyerror("ULP rule doesn't have service ids");
675                             return 1;
676                         }
677 
678                         /* get all the service id ranges */
679                         __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
680                                               &range_arr,
681                                               &range_len );
682 
683                         p_current_qos_match_rule->service_id_range_arr = range_arr;
684                         p_current_qos_match_rule->service_id_range_len = range_len;
685 
686                     } qos_ulp_sl
687 
688                     | qos_ulp_type_any_pkey list_of_ranges TK_DOTDOT {
689                         /* "any, pkey ... : sl" - one instance of list of ranges */
690                         uint64_t ** range_arr;
691                         unsigned    range_len;
692 
693                         if (!cl_list_count(&tmp_parser_struct.num_pair_list))
694                         {
695                             yyerror("ULP rule doesn't have pkeys");
696                             return 1;
697                         }
698 
699                         /* get all the pkey ranges */
700                         __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list,
701                                               &range_arr,
702                                               &range_len );
703 
704                         p_current_qos_match_rule->pkey_range_arr = range_arr;
705                         p_current_qos_match_rule->pkey_range_len = range_len;
706 
707                     } qos_ulp_sl
708 
709                     | qos_ulp_type_any_target_port_guid list_of_ranges TK_DOTDOT {
710                         /* any, target-port-guid ... : sl */
711                         uint64_t ** range_arr;
712                         unsigned    range_len;
713 
714                         if (!cl_list_count(&tmp_parser_struct.num_pair_list))
715                         {
716                             yyerror("ULP rule doesn't have port guids");
717                             return 1;
718                         }
719 
720                         /* create a new port group with these ports */
721                         __parser_port_group_start();
722 
723                         p_current_port_group->name = strdup("_ULP_Targets_");
724                         p_current_port_group->use = strdup("Generated from ULP rules");
725 
726                         __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
727                                               &range_arr,
728                                               &range_len );
729 
730                         __parser_add_guid_range_to_port_map(
731                                               &p_current_port_group->port_map,
732                                               range_arr,
733                                               range_len);
734 
735                         /* add this port group to the destination
736                            groups of the current match rule */
737                         cl_list_insert_tail(&p_current_qos_match_rule->destination_group_list,
738                                             p_current_port_group);
739 
740                         __parser_port_group_end();
741 
742                     } qos_ulp_sl
743 
744 		    | qos_ulp_type_any_source_port_guid list_of_ranges TK_DOTDOT {
745 			/* any, source-port-guid ... : sl */
746 			uint64_t ** range_arr;
747 			unsigned    range_len;
748 
749 			if (!cl_list_count(&tmp_parser_struct.num_pair_list))
750 			{
751 				yyerror("ULP rule doesn't have port guids");
752 				return 1;
753 			}
754 
755                         /* create a new port group with these ports */
756                         __parser_port_group_start();
757 
758                         p_current_port_group->name = strdup("_ULP_Sources_");
759                         p_current_port_group->use = strdup("Generated from ULP rules");
760 
761                         __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
762                                               &range_arr,
763                                               &range_len );
764 
765                         __parser_add_guid_range_to_port_map(
766                                               &p_current_port_group->port_map,
767                                               range_arr,
768                                               range_len);
769 
770                         /* add this port group to the source
771                            groups of the current match rule */
772                         cl_list_insert_tail(&p_current_qos_match_rule->source_group_list,
773                                             p_current_port_group);
774 
775                         __parser_port_group_end();
776 
777 		    } qos_ulp_sl
778 
779 		    | qos_ulp_type_any_source_target_port_guid list_of_ranges TK_DOTDOT {
780 			/* any, source-target-port-guid ... : sl */
781 			uint64_t ** range_arr;
782 			unsigned    range_len;
783 
784 			if (!cl_list_count(&tmp_parser_struct.num_pair_list))
785 			{
786 				yyerror("ULP rule doesn't have port guids");
787 				return 1;
788 			}
789 
790                         /* create a new port group with these ports */
791                         __parser_port_group_start();
792 
793                         p_current_port_group->name = strdup("_ULP_Sources_Targets_");
794                         p_current_port_group->use = strdup("Generated from ULP rules");
795 
796                         __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
797                                               &range_arr,
798                                               &range_len );
799 
800                         __parser_add_guid_range_to_port_map(
801                                               &p_current_port_group->port_map,
802                                               range_arr,
803                                               range_len);
804 
805                         /* add this port group to the source and destination
806                            groups of the current match rule */
807                         cl_list_insert_tail(&p_current_qos_match_rule->source_group_list,
808                                             p_current_port_group);
809 
810                         cl_list_insert_tail(&p_current_qos_match_rule->destination_group_list,
811                                             p_current_port_group);
812 
813                         __parser_port_group_end();
814 
815 		    } qos_ulp_sl
816 
817                     | qos_ulp_type_sdp_default {
818                         /* "sdp : sl" - default SL for SDP */
819                         uint64_t ** range_arr =
820                                (uint64_t **)malloc(sizeof(uint64_t *));
821                         range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t));
822                         range_arr[0][0] = OSM_QOS_POLICY_ULP_SDP_SERVICE_ID;
823                         range_arr[0][1] = OSM_QOS_POLICY_ULP_SDP_SERVICE_ID + 0xFFFF;
824 
825                         p_current_qos_match_rule->service_id_range_arr = range_arr;
826                         p_current_qos_match_rule->service_id_range_len = 1;
827 
828                     } qos_ulp_sl
829 
830                     | qos_ulp_type_sdp_port list_of_ranges TK_DOTDOT {
831                         /* sdp with port numbers */
832                         uint64_t ** range_arr;
833                         unsigned    range_len;
834                         unsigned    i;
835 
836                         if (!cl_list_count(&tmp_parser_struct.num_pair_list))
837                         {
838                             yyerror("SDP ULP rule doesn't have port numbers");
839                             return 1;
840                         }
841 
842                         /* get all the port ranges */
843                         __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
844                                               &range_arr,
845                                               &range_len );
846                         /* now translate these port numbers into service ids */
847                         for (i = 0; i < range_len; i++)
848                         {
849                             if (range_arr[i][0] > 0xFFFF || range_arr[i][1] > 0xFFFF)
850                             {
851                                 yyerror("SDP port number out of range");
852 				free(range_arr);
853                                 return 1;
854                             }
855                             range_arr[i][0] += OSM_QOS_POLICY_ULP_SDP_SERVICE_ID;
856                             range_arr[i][1] += OSM_QOS_POLICY_ULP_SDP_SERVICE_ID;
857                         }
858 
859                         p_current_qos_match_rule->service_id_range_arr = range_arr;
860                         p_current_qos_match_rule->service_id_range_len = range_len;
861 
862                     } qos_ulp_sl
863 
864                     | qos_ulp_type_rds_default {
865                         /* "rds : sl" - default SL for RDS */
866                         uint64_t ** range_arr =
867                                (uint64_t **)malloc(sizeof(uint64_t *));
868                         range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t));
869                         range_arr[0][0] = range_arr[0][1] =
870                            OSM_QOS_POLICY_ULP_RDS_SERVICE_ID + OSM_QOS_POLICY_ULP_RDS_PORT;
871 
872                         p_current_qos_match_rule->service_id_range_arr = range_arr;
873                         p_current_qos_match_rule->service_id_range_len = 1;
874 
875                     } qos_ulp_sl
876 
877                     | qos_ulp_type_rds_port list_of_ranges TK_DOTDOT {
878                         /* rds with port numbers */
879                         uint64_t ** range_arr;
880                         unsigned    range_len;
881                         unsigned    i;
882 
883                         if (!cl_list_count(&tmp_parser_struct.num_pair_list))
884                         {
885                             yyerror("RDS ULP rule doesn't have port numbers");
886                             return 1;
887                         }
888 
889                         /* get all the port ranges */
890                         __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
891                                               &range_arr,
892                                               &range_len );
893                         /* now translate these port numbers into service ids */
894                         for (i = 0; i < range_len; i++)
895                         {
896                             if (range_arr[i][0] > 0xFFFF || range_arr[i][1] > 0xFFFF)
897                             {
898                                 yyerror("SDP port number out of range");
899 				free(range_arr);
900                                 return 1;
901                             }
902                             range_arr[i][0] += OSM_QOS_POLICY_ULP_RDS_SERVICE_ID;
903                             range_arr[i][1] += OSM_QOS_POLICY_ULP_RDS_SERVICE_ID;
904                         }
905 
906                         p_current_qos_match_rule->service_id_range_arr = range_arr;
907                         p_current_qos_match_rule->service_id_range_len = range_len;
908 
909                     } qos_ulp_sl
910 
911                     | qos_ulp_type_iser_default {
912                         /* "iSER : sl" - default SL for iSER */
913                         uint64_t ** range_arr =
914                                (uint64_t **)malloc(sizeof(uint64_t *));
915                         range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t));
916                         range_arr[0][0] = range_arr[0][1] =
917                            OSM_QOS_POLICY_ULP_ISER_SERVICE_ID + OSM_QOS_POLICY_ULP_ISER_PORT;
918 
919                         p_current_qos_match_rule->service_id_range_arr = range_arr;
920                         p_current_qos_match_rule->service_id_range_len = 1;
921 
922                     } qos_ulp_sl
923 
924                     | qos_ulp_type_iser_port list_of_ranges TK_DOTDOT {
925                         /* iser with port numbers */
926                         uint64_t ** range_arr;
927                         unsigned    range_len;
928                         unsigned    i;
929 
930                         if (!cl_list_count(&tmp_parser_struct.num_pair_list))
931                         {
932                             yyerror("iSER ULP rule doesn't have port numbers");
933                             return 1;
934                         }
935 
936                         /* get all the port ranges */
937                         __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
938                                               &range_arr,
939                                               &range_len );
940                         /* now translate these port numbers into service ids */
941                         for (i = 0; i < range_len; i++)
942                         {
943                             if (range_arr[i][0] > 0xFFFF || range_arr[i][1] > 0xFFFF)
944                             {
945                                 yyerror("SDP port number out of range");
946 				free(range_arr);
947                                 return 1;
948                             }
949                             range_arr[i][0] += OSM_QOS_POLICY_ULP_ISER_SERVICE_ID;
950                             range_arr[i][1] += OSM_QOS_POLICY_ULP_ISER_SERVICE_ID;
951                         }
952 
953                         p_current_qos_match_rule->service_id_range_arr = range_arr;
954                         p_current_qos_match_rule->service_id_range_len = range_len;
955 
956                     } qos_ulp_sl
957 
958                     | qos_ulp_type_srp_guid list_of_ranges TK_DOTDOT {
959                         /* srp with target guids - this rule is similar
960                            to writing 'any' ulp with target port guids */
961                         uint64_t ** range_arr;
962                         unsigned    range_len;
963 
964                         if (!cl_list_count(&tmp_parser_struct.num_pair_list))
965                         {
966                             yyerror("SRP ULP rule doesn't have port guids");
967                             return 1;
968                         }
969 
970                         /* create a new port group with these ports */
971                         __parser_port_group_start();
972 
973                         p_current_port_group->name = strdup("_SRP_Targets_");
974                         p_current_port_group->use = strdup("Generated from ULP rules");
975 
976                         __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
977                                               &range_arr,
978                                               &range_len );
979 
980                         __parser_add_guid_range_to_port_map(
981                                               &p_current_port_group->port_map,
982                                               range_arr,
983                                               range_len);
984 
985                         /* add this port group to the destination
986                            groups of the current match rule */
987                         cl_list_insert_tail(&p_current_qos_match_rule->destination_group_list,
988                                             p_current_port_group);
989 
990                         __parser_port_group_end();
991 
992                     } qos_ulp_sl
993 
994                     | qos_ulp_type_ipoib_default {
995                         /* ipoib w/o any pkeys (default pkey) */
996                         uint64_t ** range_arr =
997                                (uint64_t **)malloc(sizeof(uint64_t *));
998                         range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t));
999                         range_arr[0][0] = range_arr[0][1] = 0x7fff;
1000 
1001                         /*
1002                          * Although we know that the default partition exists,
1003                          * we still need to validate it by checking that it has
1004                          * at least two full members. Otherwise IPoIB won't work.
1005                          */
1006                         if (__validate_pkeys(range_arr, 1, TRUE))
1007                             return 1;
1008 
1009                         p_current_qos_match_rule->pkey_range_arr = range_arr;
1010                         p_current_qos_match_rule->pkey_range_len = 1;
1011 
1012                     } qos_ulp_sl
1013 
1014                     | qos_ulp_type_ipoib_pkey list_of_ranges TK_DOTDOT {
1015                         /* ipoib with pkeys */
1016                         uint64_t ** range_arr;
1017                         unsigned    range_len;
1018 
1019                         if (!cl_list_count(&tmp_parser_struct.num_pair_list))
1020                         {
1021                             yyerror("IPoIB ULP rule doesn't have pkeys");
1022                             return 1;
1023                         }
1024 
1025                         /* get all the pkey ranges */
1026                         __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list,
1027                                               &range_arr,
1028                                               &range_len );
1029 
1030                         /*
1031                          * Validate pkeys.
1032                          * For IPoIB pkeys the validation is strict.
1033                          * If some problem would be found, parsing will
1034                          * be aborted with a proper error messages.
1035                          */
1036 			if (__validate_pkeys(range_arr, range_len, TRUE)) {
1037 			    free(range_arr);
1038                             return 1;
1039 			}
1040 
1041                         p_current_qos_match_rule->pkey_range_arr = range_arr;
1042                         p_current_qos_match_rule->pkey_range_len = range_len;
1043 
1044                     } qos_ulp_sl
1045                     ;
1046 
1047 qos_ulp_type_any_service: TK_ULP_ANY_SERVICE_ID
1048                     { __parser_ulp_match_rule_start(); };
1049 
1050 qos_ulp_type_any_pkey: TK_ULP_ANY_PKEY
1051                     { __parser_ulp_match_rule_start(); };
1052 
1053 qos_ulp_type_any_target_port_guid: TK_ULP_ANY_TARGET_PORT_GUID
1054                     { __parser_ulp_match_rule_start(); };
1055 
1056 qos_ulp_type_any_source_port_guid: TK_ULP_ANY_SOURCE_PORT_GUID
1057                     { __parser_ulp_match_rule_start(); };
1058 
1059 qos_ulp_type_any_source_target_port_guid: TK_ULP_ANY_SOURCE_TARGET_PORT_GUID
1060                     { __parser_ulp_match_rule_start(); };
1061 
1062 qos_ulp_type_sdp_default: TK_ULP_SDP_DEFAULT
1063                     { __parser_ulp_match_rule_start(); };
1064 
1065 qos_ulp_type_sdp_port: TK_ULP_SDP_PORT
1066                     { __parser_ulp_match_rule_start(); };
1067 
1068 qos_ulp_type_rds_default: TK_ULP_RDS_DEFAULT
1069                     { __parser_ulp_match_rule_start(); };
1070 
1071 qos_ulp_type_rds_port: TK_ULP_RDS_PORT
1072                     { __parser_ulp_match_rule_start(); };
1073 
1074 qos_ulp_type_iser_default: TK_ULP_ISER_DEFAULT
1075                     { __parser_ulp_match_rule_start(); };
1076 
1077 qos_ulp_type_iser_port: TK_ULP_ISER_PORT
1078                     { __parser_ulp_match_rule_start(); };
1079 
1080 qos_ulp_type_srp_guid: TK_ULP_SRP_GUID
1081                     { __parser_ulp_match_rule_start(); };
1082 
1083 qos_ulp_type_ipoib_default: TK_ULP_IPOIB_DEFAULT
1084                     { __parser_ulp_match_rule_start(); };
1085 
1086 qos_ulp_type_ipoib_pkey: TK_ULP_IPOIB_PKEY
1087                     { __parser_ulp_match_rule_start(); };
1088 
1089 
1090 qos_ulp_sl:   single_number {
1091                         /* get the SL for ULP rules */
1092                         cl_list_iterator_t  list_iterator;
1093                         uint64_t          * p_tmp_num;
1094                         uint8_t             sl;
1095 
1096                         list_iterator = cl_list_head(&tmp_parser_struct.num_list);
1097                         p_tmp_num = (uint64_t*)cl_list_obj(list_iterator);
1098                         if (*p_tmp_num > 15)
1099                         {
1100                             yyerror("illegal SL value");
1101                             return 1;
1102                         }
1103 
1104                         sl = (uint8_t)(*p_tmp_num);
1105                         free(p_tmp_num);
1106                         cl_list_remove_all(&tmp_parser_struct.num_list);
1107 
1108                         p_current_qos_match_rule->p_qos_level =
1109                                  &osm_qos_policy_simple_qos_levels[sl];
1110                         p_current_qos_match_rule->qos_level_name =
1111                                  strdup(osm_qos_policy_simple_qos_levels[sl].name);
1112 
1113                         if (__parser_ulp_match_rule_end())
1114                             return 1;
1115                     }
1116                     ;
1117 
1118     /*
1119      *  port_group_entry values:
1120      *      port_group_name
1121      *      port_group_use
1122      *      port_group_port_guid
1123      *      port_group_port_name
1124      *      port_group_pkey
1125      *      port_group_partition
1126      *      port_group_node_type
1127      */
1128 
1129 port_group_name:        port_group_name_start single_string {
1130                             /* 'name' of 'port-group' - one instance */
1131                             cl_list_iterator_t    list_iterator;
1132                             char                * tmp_str;
1133 
1134                             if (p_current_port_group->name)
1135                             {
1136                                 yyerror("port-group has multiple 'name' tags");
1137                                 cl_list_remove_all(&tmp_parser_struct.str_list);
1138                                 return 1;
1139                             }
1140 
1141                             list_iterator = cl_list_head(&tmp_parser_struct.str_list);
1142                             if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
1143                             {
1144                                 tmp_str = (char*)cl_list_obj(list_iterator);
1145                                 if (tmp_str)
1146                                     p_current_port_group->name = tmp_str;
1147                             }
1148                             cl_list_remove_all(&tmp_parser_struct.str_list);
1149                         }
1150                         ;
1151 
1152 port_group_name_start:  TK_NAME {
1153                             RESET_BUFFER;
1154                         }
1155                         ;
1156 
1157 port_group_use:         port_group_use_start single_string {
1158                             /* 'use' of 'port-group' - one instance */
1159                             cl_list_iterator_t    list_iterator;
1160                             char                * tmp_str;
1161 
1162                             if (p_current_port_group->use)
1163                             {
1164                                 yyerror("port-group has multiple 'use' tags");
1165                                 cl_list_remove_all(&tmp_parser_struct.str_list);
1166                                 return 1;
1167                             }
1168 
1169                             list_iterator = cl_list_head(&tmp_parser_struct.str_list);
1170                             if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
1171                             {
1172                                 tmp_str = (char*)cl_list_obj(list_iterator);
1173                                 if (tmp_str)
1174                                     p_current_port_group->use = tmp_str;
1175                             }
1176                             cl_list_remove_all(&tmp_parser_struct.str_list);
1177                         }
1178                         ;
1179 
1180 port_group_use_start:   TK_USE {
1181                             RESET_BUFFER;
1182                         }
1183                         ;
1184 
1185 port_group_port_name:   port_group_port_name_start string_list {
1186                             /* 'port-name' in 'port-group' - any num of instances */
1187                             cl_list_iterator_t list_iterator;
1188                             osm_node_t * p_node;
1189                             osm_physp_t * p_physp;
1190                             unsigned port_num;
1191                             char * tmp_str;
1192                             char * port_str;
1193 
1194                             /* parsing port name strings */
1195                             for (list_iterator = cl_list_head(&tmp_parser_struct.str_list);
1196                                  list_iterator != cl_list_end(&tmp_parser_struct.str_list);
1197                                  list_iterator = cl_list_next(list_iterator))
1198                             {
1199                                 tmp_str = (char*)cl_list_obj(list_iterator);
1200                                 if (tmp_str)
1201                                 {
1202                                     /* last slash in port name string is a separator
1203                                        between node name and port number */
1204                                     port_str = strrchr(tmp_str, '/');
1205                                     if (!port_str || (strlen(port_str) < 3) ||
1206                                         (port_str[1] != 'p' && port_str[1] != 'P')) {
1207                                         yyerror("'%s' - illegal port name",
1208                                                            tmp_str);
1209                                         free(tmp_str);
1210                                         cl_list_remove_all(&tmp_parser_struct.str_list);
1211                                         return 1;
1212                                     }
1213 
1214                                     if (!(port_num = strtoul(&port_str[2],NULL,0))) {
1215                                         yyerror(
1216                                                "'%s' - illegal port number in port name",
1217                                                tmp_str);
1218                                         free(tmp_str);
1219                                         cl_list_remove_all(&tmp_parser_struct.str_list);
1220                                         return 1;
1221                                     }
1222 
1223                                     /* separate node name from port number */
1224                                     port_str[0] = '\0';
1225 
1226                                     if (st_lookup(p_qos_policy->p_node_hash,
1227                                                   (st_data_t)tmp_str,
1228                                                   (void *)&p_node))
1229                                     {
1230                                         /* we found the node, now get the right port */
1231                                         p_physp = osm_node_get_physp_ptr(p_node, port_num);
1232                                         if (!p_physp) {
1233                                             yyerror(
1234                                                    "'%s' - port number out of range in port name",
1235                                                    tmp_str);
1236                                             free(tmp_str);
1237                                             cl_list_remove_all(&tmp_parser_struct.str_list);
1238                                             return 1;
1239                                         }
1240                                         /* we found the port, now add it to guid table */
1241                                         __parser_add_port_to_port_map(&p_current_port_group->port_map,
1242                                                                       p_physp);
1243                                     }
1244                                     free(tmp_str);
1245                                 }
1246                             }
1247                             cl_list_remove_all(&tmp_parser_struct.str_list);
1248                         }
1249                         ;
1250 
1251 port_group_port_name_start: TK_PORT_NAME {
1252                             RESET_BUFFER;
1253                         }
1254                         ;
1255 
1256 port_group_port_guid:   port_group_port_guid_start list_of_ranges {
1257                             /* 'port-guid' in 'port-group' - any num of instances */
1258                             /* list of guid ranges */
1259                             if (cl_list_count(&tmp_parser_struct.num_pair_list))
1260                             {
1261                                 uint64_t ** range_arr;
1262                                 unsigned range_len;
1263 
1264                                 __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
1265                                                       &range_arr,
1266                                                       &range_len );
1267 
1268                                 __parser_add_guid_range_to_port_map(
1269                                                       &p_current_port_group->port_map,
1270                                                       range_arr,
1271                                                       range_len);
1272                             }
1273                         }
1274                         ;
1275 
1276 port_group_port_guid_start: TK_PORT_GUID {
1277                             RESET_BUFFER;
1278                         }
1279                         ;
1280 
1281 port_group_pkey:        port_group_pkey_start list_of_ranges {
1282                             /* 'pkey' in 'port-group' - any num of instances */
1283                             /* list of pkey ranges */
1284                             if (cl_list_count(&tmp_parser_struct.num_pair_list))
1285                             {
1286                                 uint64_t ** range_arr;
1287                                 unsigned range_len;
1288 
1289                                 __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list,
1290                                                       &range_arr,
1291                                                       &range_len );
1292 
1293                                 __parser_add_pkey_range_to_port_map(
1294                                                       &p_current_port_group->port_map,
1295                                                       range_arr,
1296                                                       range_len);
1297                             }
1298                         }
1299                         ;
1300 
1301 port_group_pkey_start:  TK_PKEY {
1302                             RESET_BUFFER;
1303                         }
1304                         ;
1305 
1306 port_group_partition:  port_group_partition_start string_list {
1307                             /* 'partition' in 'port-group' - any num of instances */
1308                             __parser_add_partition_list_to_port_map(
1309                                                &p_current_port_group->port_map,
1310                                                &tmp_parser_struct.str_list);
1311                         }
1312                         ;
1313 
1314 port_group_partition_start: TK_PARTITION {
1315                             RESET_BUFFER;
1316                         }
1317                         ;
1318 
1319 port_group_node_type:   port_group_node_type_start port_group_node_type_list {
1320                             /* 'node-type' in 'port-group' - any num of instances */
1321                         }
1322                         ;
1323 
1324 port_group_node_type_start: TK_NODE_TYPE {
1325                             RESET_BUFFER;
1326                         }
1327                         ;
1328 
1329 port_group_node_type_list:  node_type_item
1330                         |   port_group_node_type_list TK_COMMA node_type_item
1331                         ;
1332 
1333 node_type_item:           node_type_ca
1334                         | node_type_switch
1335                         | node_type_router
1336                         | node_type_all
1337                         | node_type_self
1338                         ;
1339 
1340 node_type_ca:           TK_NODE_TYPE_CA {
1341                             p_current_port_group->node_types |=
1342                                OSM_QOS_POLICY_NODE_TYPE_CA;
1343                         }
1344                         ;
1345 
1346 node_type_switch:       TK_NODE_TYPE_SWITCH {
1347                             p_current_port_group->node_types |=
1348                                OSM_QOS_POLICY_NODE_TYPE_SWITCH;
1349                         }
1350                         ;
1351 
1352 node_type_router:       TK_NODE_TYPE_ROUTER {
1353                             p_current_port_group->node_types |=
1354                                OSM_QOS_POLICY_NODE_TYPE_ROUTER;
1355                         }
1356                         ;
1357 
1358 node_type_all:          TK_NODE_TYPE_ALL {
1359                             p_current_port_group->node_types |=
1360                                (OSM_QOS_POLICY_NODE_TYPE_CA |
1361                                 OSM_QOS_POLICY_NODE_TYPE_SWITCH |
1362                                 OSM_QOS_POLICY_NODE_TYPE_ROUTER);
1363                         }
1364                         ;
1365 
1366 node_type_self:         TK_NODE_TYPE_SELF {
1367                             osm_port_t * p_osm_port =
1368                                 osm_get_port_by_guid(p_qos_policy->p_subn,
1369                                      p_qos_policy->p_subn->sm_port_guid);
1370                             if (p_osm_port)
1371                                 __parser_add_port_to_port_map(
1372                                    &p_current_port_group->port_map,
1373                                    p_osm_port->p_physp);
1374                         }
1375                         ;
1376 
1377     /*
1378      *  vlarb_scope_entry values:
1379      *      vlarb_scope_group
1380      *      vlarb_scope_across
1381      *      vlarb_scope_vlarb_high
1382      *      vlarb_scope_vlarb_low
1383      *      vlarb_scope_vlarb_high_limit
1384      */
1385 
1386 
1387 
1388 vlarb_scope_group:      vlarb_scope_group_start string_list {
1389                             /* 'group' in 'vlarb-scope' - any num of instances */
1390                             cl_list_iterator_t    list_iterator;
1391                             char                * tmp_str;
1392 
1393                             list_iterator = cl_list_head(&tmp_parser_struct.str_list);
1394                             while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
1395                             {
1396                                 tmp_str = (char*)cl_list_obj(list_iterator);
1397                                 if (tmp_str)
1398                                     cl_list_insert_tail(&p_current_vlarb_scope->group_list,tmp_str);
1399                                 list_iterator = cl_list_next(list_iterator);
1400                             }
1401                             cl_list_remove_all(&tmp_parser_struct.str_list);
1402                         }
1403                         ;
1404 
1405 vlarb_scope_group_start: TK_GROUP {
1406                             RESET_BUFFER;
1407                         }
1408                         ;
1409 
1410 vlarb_scope_across: vlarb_scope_across_start string_list {
1411                             /* 'across' in 'vlarb-scope' - any num of instances */
1412                             cl_list_iterator_t    list_iterator;
1413                             char                * tmp_str;
1414 
1415                             list_iterator = cl_list_head(&tmp_parser_struct.str_list);
1416                             while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
1417                             {
1418                                 tmp_str = (char*)cl_list_obj(list_iterator);
1419                                 if (tmp_str)
1420                                     cl_list_insert_tail(&p_current_vlarb_scope->across_list,tmp_str);
1421                                 list_iterator = cl_list_next(list_iterator);
1422                             }
1423                             cl_list_remove_all(&tmp_parser_struct.str_list);
1424                         }
1425                         ;
1426 
1427 vlarb_scope_across_start: TK_ACROSS {
1428                             RESET_BUFFER;
1429                         }
1430                         ;
1431 
1432 vlarb_scope_vlarb_high_limit:  vlarb_scope_vlarb_high_limit_start single_number {
1433                             /* 'vl-high-limit' in 'vlarb-scope' - one instance of one number */
1434                             cl_list_iterator_t    list_iterator;
1435                             uint64_t            * p_tmp_num;
1436 
1437                             list_iterator = cl_list_head(&tmp_parser_struct.num_list);
1438                             p_tmp_num = (uint64_t*)cl_list_obj(list_iterator);
1439                             if (p_tmp_num)
1440                             {
1441                                 p_current_vlarb_scope->vl_high_limit = (uint32_t)(*p_tmp_num);
1442                                 p_current_vlarb_scope->vl_high_limit_set = TRUE;
1443                                 free(p_tmp_num);
1444                             }
1445 
1446                             cl_list_remove_all(&tmp_parser_struct.num_list);
1447                         }
1448                         ;
1449 
1450 vlarb_scope_vlarb_high_limit_start: TK_VLARB_HIGH_LIMIT {
1451                             RESET_BUFFER;
1452                         }
1453                         ;
1454 
1455 vlarb_scope_vlarb_high: vlarb_scope_vlarb_high_start num_list_with_dotdot {
1456                             /* 'vlarb-high' in 'vlarb-scope' - list of pairs of numbers with ':' and ',' */
1457                             cl_list_iterator_t    list_iterator;
1458                             uint64_t            * num_pair;
1459 
1460                             list_iterator = cl_list_head(&tmp_parser_struct.num_pair_list);
1461                             while( list_iterator != cl_list_end(&tmp_parser_struct.num_pair_list) )
1462                             {
1463                                 num_pair = (uint64_t*)cl_list_obj(list_iterator);
1464                                 if (num_pair)
1465                                     cl_list_insert_tail(&p_current_vlarb_scope->vlarb_high_list,num_pair);
1466                                 list_iterator = cl_list_next(list_iterator);
1467                             }
1468                             cl_list_remove_all(&tmp_parser_struct.num_pair_list);
1469                         }
1470                         ;
1471 
1472 vlarb_scope_vlarb_high_start: TK_VLARB_HIGH {
1473                             RESET_BUFFER;
1474                         }
1475                         ;
1476 
1477 vlarb_scope_vlarb_low:  vlarb_scope_vlarb_low_start num_list_with_dotdot {
1478                             /* 'vlarb-low' in 'vlarb-scope' - list of pairs of numbers with ':' and ',' */
1479                             cl_list_iterator_t    list_iterator;
1480                             uint64_t            * num_pair;
1481 
1482                             list_iterator = cl_list_head(&tmp_parser_struct.num_pair_list);
1483                             while( list_iterator != cl_list_end(&tmp_parser_struct.num_pair_list) )
1484                             {
1485                                 num_pair = (uint64_t*)cl_list_obj(list_iterator);
1486                                 if (num_pair)
1487                                     cl_list_insert_tail(&p_current_vlarb_scope->vlarb_low_list,num_pair);
1488                                 list_iterator = cl_list_next(list_iterator);
1489                             }
1490                             cl_list_remove_all(&tmp_parser_struct.num_pair_list);
1491                         }
1492                         ;
1493 
1494 vlarb_scope_vlarb_low_start: TK_VLARB_LOW {
1495                             RESET_BUFFER;
1496                         }
1497                         ;
1498 
1499     /*
1500      *  sl2vl_scope_entry values:
1501      *      sl2vl_scope_group
1502      *      sl2vl_scope_across
1503      *      sl2vl_scope_across_from
1504      *      sl2vl_scope_across_to
1505      *      sl2vl_scope_from
1506      *      sl2vl_scope_to
1507      *      sl2vl_scope_sl2vl_table
1508      */
1509 
1510 sl2vl_scope_group:      sl2vl_scope_group_start string_list {
1511                             /* 'group' in 'sl2vl-scope' - any num of instances */
1512                             cl_list_iterator_t    list_iterator;
1513                             char                * tmp_str;
1514 
1515                             list_iterator = cl_list_head(&tmp_parser_struct.str_list);
1516                             while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
1517                             {
1518                                 tmp_str = (char*)cl_list_obj(list_iterator);
1519                                 if (tmp_str)
1520                                     cl_list_insert_tail(&p_current_sl2vl_scope->group_list,tmp_str);
1521                                 list_iterator = cl_list_next(list_iterator);
1522                             }
1523                             cl_list_remove_all(&tmp_parser_struct.str_list);
1524                         }
1525                         ;
1526 
1527 sl2vl_scope_group_start: TK_GROUP {
1528                             RESET_BUFFER;
1529                         }
1530                         ;
1531 
1532 sl2vl_scope_across:     sl2vl_scope_across_start string_list {
1533                             /* 'across' in 'sl2vl-scope' - any num of instances */
1534                             cl_list_iterator_t    list_iterator;
1535                             char                * tmp_str;
1536 
1537                             list_iterator = cl_list_head(&tmp_parser_struct.str_list);
1538                             while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
1539                             {
1540                                 tmp_str = (char*)cl_list_obj(list_iterator);
1541                                 if (tmp_str) {
1542                                     cl_list_insert_tail(&p_current_sl2vl_scope->across_from_list,tmp_str);
1543                                     cl_list_insert_tail(&p_current_sl2vl_scope->across_to_list,strdup(tmp_str));
1544                                 }
1545                                 list_iterator = cl_list_next(list_iterator);
1546                             }
1547                             cl_list_remove_all(&tmp_parser_struct.str_list);
1548                         }
1549                         ;
1550 
1551 sl2vl_scope_across_start: TK_ACROSS {
1552                             RESET_BUFFER;
1553                         }
1554                         ;
1555 
1556 sl2vl_scope_across_from:  sl2vl_scope_across_from_start string_list {
1557                             /* 'across-from' in 'sl2vl-scope' - any num of instances */
1558                             cl_list_iterator_t    list_iterator;
1559                             char                * tmp_str;
1560 
1561                             list_iterator = cl_list_head(&tmp_parser_struct.str_list);
1562                             while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
1563                             {
1564                                 tmp_str = (char*)cl_list_obj(list_iterator);
1565                                 if (tmp_str)
1566                                     cl_list_insert_tail(&p_current_sl2vl_scope->across_from_list,tmp_str);
1567                                 list_iterator = cl_list_next(list_iterator);
1568                             }
1569                             cl_list_remove_all(&tmp_parser_struct.str_list);
1570                         }
1571                         ;
1572 
1573 sl2vl_scope_across_from_start: TK_ACROSS_FROM {
1574                             RESET_BUFFER;
1575                         }
1576                         ;
1577 
1578 sl2vl_scope_across_to:  sl2vl_scope_across_to_start string_list {
1579                             /* 'across-to' in 'sl2vl-scope' - any num of instances */
1580                             cl_list_iterator_t    list_iterator;
1581                             char                * tmp_str;
1582 
1583                             list_iterator = cl_list_head(&tmp_parser_struct.str_list);
1584                             while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
1585                             {
1586                                 tmp_str = (char*)cl_list_obj(list_iterator);
1587                                 if (tmp_str) {
1588                                     cl_list_insert_tail(&p_current_sl2vl_scope->across_to_list,tmp_str);
1589                                 }
1590                                 list_iterator = cl_list_next(list_iterator);
1591                             }
1592                             cl_list_remove_all(&tmp_parser_struct.str_list);
1593                         }
1594                         ;
1595 
1596 sl2vl_scope_across_to_start: TK_ACROSS_TO {
1597                             RESET_BUFFER;
1598                         }
1599                         ;
1600 
1601 sl2vl_scope_from:       sl2vl_scope_from_start sl2vl_scope_from_list_or_asterisk {
1602                             /* 'from' in 'sl2vl-scope' - any num of instances */
1603                         }
1604                         ;
1605 
1606 sl2vl_scope_from_start: TK_FROM {
1607                             RESET_BUFFER;
1608                         }
1609                         ;
1610 
1611 sl2vl_scope_to:         sl2vl_scope_to_start sl2vl_scope_to_list_or_asterisk {
1612                             /* 'to' in 'sl2vl-scope' - any num of instances */
1613                         }
1614                         ;
1615 
1616 sl2vl_scope_to_start:   TK_TO {
1617                             RESET_BUFFER;
1618                         }
1619                         ;
1620 
1621 sl2vl_scope_from_list_or_asterisk:  sl2vl_scope_from_asterisk
1622                                   | sl2vl_scope_from_list_of_ranges
1623                                   ;
1624 
1625 sl2vl_scope_from_asterisk: TK_ASTERISK {
1626                             int i;
1627                             for (i = 0; i < OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH; i++)
1628                                 p_current_sl2vl_scope->from[i] = TRUE;
1629                         }
1630                         ;
1631 
1632 sl2vl_scope_to_list_or_asterisk:  sl2vl_scope_to_asterisk
1633                                 | sl2vl_scope_to_list_of_ranges
1634                                   ;
1635 
1636 sl2vl_scope_to_asterisk: TK_ASTERISK {
1637                             int i;
1638                             for (i = 0; i < OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH; i++)
1639                                 p_current_sl2vl_scope->to[i] = TRUE;
1640                         }
1641                         ;
1642 
1643 sl2vl_scope_from_list_of_ranges: list_of_ranges {
1644                             int i;
1645                             cl_list_iterator_t    list_iterator;
1646                             uint64_t            * num_pair;
1647                             uint8_t               num1, num2;
1648 
1649                             list_iterator = cl_list_head(&tmp_parser_struct.num_pair_list);
1650                             while( list_iterator != cl_list_end(&tmp_parser_struct.num_pair_list) )
1651                             {
1652                                 num_pair = (uint64_t*)cl_list_obj(list_iterator);
1653                                 if (num_pair)
1654                                 {
1655                                     if ( num_pair[1] >= OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH )
1656                                     {
1657                                         yyerror("port number out of range 'from' list");
1658                                         free(num_pair);
1659                                         cl_list_remove_all(&tmp_parser_struct.num_pair_list);
1660                                         return 1;
1661                                     }
1662                                     num1 = (uint8_t)num_pair[0];
1663                                     num2 = (uint8_t)num_pair[1];
1664                                     free(num_pair);
1665                                     for (i = num1; i <= num2; i++)
1666                                         p_current_sl2vl_scope->from[i] = TRUE;
1667                                 }
1668                                 list_iterator = cl_list_next(list_iterator);
1669                             }
1670                             cl_list_remove_all(&tmp_parser_struct.num_pair_list);
1671                         }
1672                         ;
1673 
1674 sl2vl_scope_to_list_of_ranges: list_of_ranges {
1675                             int i;
1676                             cl_list_iterator_t    list_iterator;
1677                             uint64_t            * num_pair;
1678                             uint8_t               num1, num2;
1679 
1680                             list_iterator = cl_list_head(&tmp_parser_struct.num_pair_list);
1681                             while( list_iterator != cl_list_end(&tmp_parser_struct.num_pair_list) )
1682                             {
1683                                 num_pair = (uint64_t*)cl_list_obj(list_iterator);
1684                                 if (num_pair)
1685                                 {
1686                                     if ( num_pair[1] >= OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH )
1687                                     {
1688                                         yyerror("port number out of range 'to' list");
1689                                         free(num_pair);
1690                                         cl_list_remove_all(&tmp_parser_struct.num_pair_list);
1691                                         return 1;
1692                                     }
1693                                     num1 = (uint8_t)num_pair[0];
1694                                     num2 = (uint8_t)num_pair[1];
1695                                     free(num_pair);
1696                                     for (i = num1; i <= num2; i++)
1697                                         p_current_sl2vl_scope->to[i] = TRUE;
1698                                 }
1699                                 list_iterator = cl_list_next(list_iterator);
1700                             }
1701                             cl_list_remove_all(&tmp_parser_struct.num_pair_list);
1702                         }
1703                         ;
1704 
1705 
1706 sl2vl_scope_sl2vl_table:  sl2vl_scope_sl2vl_table_start num_list {
1707                             /* 'sl2vl-table' - one instance of exactly
1708                                OSM_QOS_POLICY_SL2VL_TABLE_LEN numbers */
1709                             cl_list_iterator_t    list_iterator;
1710                             uint64_t              num;
1711                             uint64_t            * p_num;
1712                             int                   i = 0;
1713 
1714                             if (p_current_sl2vl_scope->sl2vl_table_set)
1715                             {
1716                                 yyerror("sl2vl-scope has more than one sl2vl-table");
1717                                 cl_list_remove_all(&tmp_parser_struct.num_list);
1718                                 return 1;
1719                             }
1720 
1721                             if (cl_list_count(&tmp_parser_struct.num_list) != OSM_QOS_POLICY_SL2VL_TABLE_LEN)
1722                             {
1723                                 yyerror("wrong number of values in 'sl2vl-table' (should be 16)");
1724                                 cl_list_remove_all(&tmp_parser_struct.num_list);
1725                                 return 1;
1726                             }
1727 
1728                             list_iterator = cl_list_head(&tmp_parser_struct.num_list);
1729                             while( list_iterator != cl_list_end(&tmp_parser_struct.num_list) )
1730                             {
1731                                 p_num = (uint64_t*)cl_list_obj(list_iterator);
1732                                 num = *p_num;
1733                                 free(p_num);
1734                                 if (num >= OSM_QOS_POLICY_MAX_VL_NUM)
1735                                 {
1736                                     yyerror("wrong VL value in 'sl2vl-table' (should be 0 to 15)");
1737                                     cl_list_remove_all(&tmp_parser_struct.num_list);
1738                                     return 1;
1739                                 }
1740 
1741                                 p_current_sl2vl_scope->sl2vl_table[i++] = (uint8_t)num;
1742                                 list_iterator = cl_list_next(list_iterator);
1743                             }
1744                             p_current_sl2vl_scope->sl2vl_table_set = TRUE;
1745                             cl_list_remove_all(&tmp_parser_struct.num_list);
1746                         }
1747                         ;
1748 
1749 sl2vl_scope_sl2vl_table_start: TK_SL2VL_TABLE {
1750                             RESET_BUFFER;
1751                         }
1752                         ;
1753 
1754     /*
1755      *  qos_level_entry values:
1756      *      qos_level_name
1757      *      qos_level_use
1758      *      qos_level_sl
1759      *      qos_level_mtu_limit
1760      *      qos_level_rate_limit
1761      *      qos_level_packet_life
1762      *      qos_level_path_bits
1763      *      qos_level_pkey
1764      */
1765 
1766 qos_level_name:         qos_level_name_start single_string {
1767                             /* 'name' of 'qos-level' - one instance */
1768                             cl_list_iterator_t    list_iterator;
1769                             char                * tmp_str;
1770 
1771                             if (p_current_qos_level->name)
1772                             {
1773                                 yyerror("qos-level has multiple 'name' tags");
1774                                 cl_list_remove_all(&tmp_parser_struct.str_list);
1775                                 return 1;
1776                             }
1777 
1778                             list_iterator = cl_list_head(&tmp_parser_struct.str_list);
1779                             if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
1780                             {
1781                                 tmp_str = (char*)cl_list_obj(list_iterator);
1782                                 if (tmp_str)
1783                                     p_current_qos_level->name = tmp_str;
1784                             }
1785                             cl_list_remove_all(&tmp_parser_struct.str_list);
1786                         }
1787                         ;
1788 
1789 qos_level_name_start:   TK_NAME {
1790                             RESET_BUFFER;
1791                         }
1792                         ;
1793 
1794 qos_level_use:          qos_level_use_start single_string {
1795                             /* 'use' of 'qos-level' - one instance */
1796                             cl_list_iterator_t    list_iterator;
1797                             char                * tmp_str;
1798 
1799                             if (p_current_qos_level->use)
1800                             {
1801                                 yyerror("qos-level has multiple 'use' tags");
1802                                 cl_list_remove_all(&tmp_parser_struct.str_list);
1803                                 return 1;
1804                             }
1805 
1806                             list_iterator = cl_list_head(&tmp_parser_struct.str_list);
1807                             if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
1808                             {
1809                                 tmp_str = (char*)cl_list_obj(list_iterator);
1810                                 if (tmp_str)
1811                                     p_current_qos_level->use = tmp_str;
1812                             }
1813                             cl_list_remove_all(&tmp_parser_struct.str_list);
1814                         }
1815                         ;
1816 
1817 qos_level_use_start:    TK_USE {
1818                             RESET_BUFFER;
1819                         }
1820                         ;
1821 
1822 qos_level_sl:           qos_level_sl_start single_number {
1823                             /* 'sl' in 'qos-level' - one instance */
1824                             cl_list_iterator_t   list_iterator;
1825                             uint64_t           * p_num;
1826 
1827                             if (p_current_qos_level->sl_set)
1828                             {
1829                                 yyerror("'qos-level' has multiple 'sl' tags");
1830                                 cl_list_remove_all(&tmp_parser_struct.num_list);
1831                                 return 1;
1832                             }
1833                             list_iterator = cl_list_head(&tmp_parser_struct.num_list);
1834                             p_num = (uint64_t*)cl_list_obj(list_iterator);
1835                             p_current_qos_level->sl = (uint8_t)(*p_num);
1836                             free(p_num);
1837                             p_current_qos_level->sl_set = TRUE;
1838                             cl_list_remove_all(&tmp_parser_struct.num_list);
1839                         }
1840                         ;
1841 
1842 qos_level_sl_start:     TK_SL {
1843                             RESET_BUFFER;
1844                         }
1845                         ;
1846 
1847 qos_level_mtu_limit:    qos_level_mtu_limit_start single_number {
1848                             /* 'mtu-limit' in 'qos-level' - one instance */
1849                             cl_list_iterator_t   list_iterator;
1850                             uint64_t           * p_num;
1851 
1852                             if (p_current_qos_level->mtu_limit_set)
1853                             {
1854                                 yyerror("'qos-level' has multiple 'mtu-limit' tags");
1855                                 cl_list_remove_all(&tmp_parser_struct.num_list);
1856                                 return 1;
1857                             }
1858                             list_iterator = cl_list_head(&tmp_parser_struct.num_list);
1859                             p_num = (uint64_t*)cl_list_obj(list_iterator);
1860                             if (*p_num > OSM_QOS_POLICY_MAX_MTU || *p_num < OSM_QOS_POLICY_MIN_MTU)
1861                             {
1862                                 yyerror("mtu limit is out of range, value: %d", *p_num);
1863                                 free(p_num);
1864                                 cl_list_remove_all(&tmp_parser_struct.num_list);
1865                                 return 1;
1866                             }
1867                             p_current_qos_level->mtu_limit = (uint8_t)(*p_num);
1868                             free(p_num);
1869                             p_current_qos_level->mtu_limit_set = TRUE;
1870                             cl_list_remove_all(&tmp_parser_struct.num_list);
1871                         }
1872                         ;
1873 
1874 qos_level_mtu_limit_start: TK_MTU_LIMIT {
1875                             /* 'mtu-limit' in 'qos-level' - one instance */
1876                             RESET_BUFFER;
1877                         }
1878                         ;
1879 
1880 qos_level_rate_limit:    qos_level_rate_limit_start single_number {
1881                             /* 'rate-limit' in 'qos-level' - one instance */
1882                             cl_list_iterator_t   list_iterator;
1883                             uint64_t           * p_num;
1884 
1885                             if (p_current_qos_level->rate_limit_set)
1886                             {
1887                                 yyerror("'qos-level' has multiple 'rate-limit' tags");
1888                                 cl_list_remove_all(&tmp_parser_struct.num_list);
1889                                 return 1;
1890                             }
1891                             list_iterator = cl_list_head(&tmp_parser_struct.num_list);
1892                             p_num = (uint64_t*)cl_list_obj(list_iterator);
1893                             if (*p_num > OSM_QOS_POLICY_MAX_RATE || *p_num < OSM_QOS_POLICY_MIN_RATE)
1894                             {
1895                                 yyerror("rate limit is out of range, value: %d", *p_num);
1896                                 free(p_num);
1897                                 cl_list_remove_all(&tmp_parser_struct.num_list);
1898                                 return 1;
1899                             }
1900                             p_current_qos_level->rate_limit = (uint8_t)(*p_num);
1901                             free(p_num);
1902                             p_current_qos_level->rate_limit_set = TRUE;
1903                             cl_list_remove_all(&tmp_parser_struct.num_list);
1904                         }
1905                         ;
1906 
1907 qos_level_rate_limit_start: TK_RATE_LIMIT {
1908                             /* 'rate-limit' in 'qos-level' - one instance */
1909                             RESET_BUFFER;
1910                         }
1911                         ;
1912 
1913 qos_level_packet_life:  qos_level_packet_life_start single_number {
1914                             /* 'packet-life' in 'qos-level' - one instance */
1915                             cl_list_iterator_t   list_iterator;
1916                             uint64_t           * p_num;
1917 
1918                             if (p_current_qos_level->pkt_life_set)
1919                             {
1920                                 yyerror("'qos-level' has multiple 'packet-life' tags");
1921                                 cl_list_remove_all(&tmp_parser_struct.num_list);
1922                                 return 1;
1923                             }
1924                             list_iterator = cl_list_head(&tmp_parser_struct.num_list);
1925                             p_num = (uint64_t*)cl_list_obj(list_iterator);
1926                             p_current_qos_level->pkt_life = (uint8_t)(*p_num);
1927                             free(p_num);
1928                             p_current_qos_level->pkt_life_set= TRUE;
1929                             cl_list_remove_all(&tmp_parser_struct.num_list);
1930                         }
1931                         ;
1932 
1933 qos_level_packet_life_start: TK_PACKET_LIFE {
1934                             /* 'packet-life' in 'qos-level' - one instance */
1935                             RESET_BUFFER;
1936                         }
1937                         ;
1938 
1939 qos_level_path_bits:    qos_level_path_bits_start list_of_ranges {
1940                             /* 'path-bits' in 'qos-level' - any num of instances */
1941                             /* list of path bit ranges */
1942 
1943                             if (cl_list_count(&tmp_parser_struct.num_pair_list))
1944                             {
1945                                 uint64_t ** range_arr;
1946                                 unsigned range_len;
1947 
1948                                 __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
1949                                                       &range_arr,
1950                                                       &range_len );
1951 
1952                                 if ( !p_current_qos_level->path_bits_range_len )
1953                                 {
1954                                     p_current_qos_level->path_bits_range_arr = range_arr;
1955                                     p_current_qos_level->path_bits_range_len = range_len;
1956                                 }
1957                                 else
1958                                 {
1959                                     uint64_t ** new_range_arr;
1960                                     unsigned new_range_len;
1961                                     __merge_rangearr( p_current_qos_level->path_bits_range_arr,
1962                                                       p_current_qos_level->path_bits_range_len,
1963                                                       range_arr,
1964                                                       range_len,
1965                                                       &new_range_arr,
1966                                                       &new_range_len );
1967                                     p_current_qos_level->path_bits_range_arr = new_range_arr;
1968                                     p_current_qos_level->path_bits_range_len = new_range_len;
1969                                 }
1970                             }
1971                         }
1972                         ;
1973 
1974 qos_level_path_bits_start: TK_PATH_BITS {
1975                             RESET_BUFFER;
1976                         }
1977                         ;
1978 
1979 qos_level_pkey:         qos_level_pkey_start list_of_ranges {
1980                             /* 'pkey' in 'qos-level' - num of instances of list of ranges */
1981                             if (cl_list_count(&tmp_parser_struct.num_pair_list))
1982                             {
1983                                 uint64_t ** range_arr;
1984                                 unsigned range_len;
1985 
1986                                 __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list,
1987                                                       &range_arr,
1988                                                       &range_len );
1989 
1990                                 if ( !p_current_qos_level->pkey_range_len )
1991                                 {
1992                                     p_current_qos_level->pkey_range_arr = range_arr;
1993                                     p_current_qos_level->pkey_range_len = range_len;
1994                                 }
1995                                 else
1996                                 {
1997                                     uint64_t ** new_range_arr;
1998                                     unsigned new_range_len;
1999                                     __merge_rangearr( p_current_qos_level->pkey_range_arr,
2000                                                       p_current_qos_level->pkey_range_len,
2001                                                       range_arr,
2002                                                       range_len,
2003                                                       &new_range_arr,
2004                                                       &new_range_len );
2005                                     p_current_qos_level->pkey_range_arr = new_range_arr;
2006                                     p_current_qos_level->pkey_range_len = new_range_len;
2007                                 }
2008                             }
2009                         }
2010                         ;
2011 
2012 qos_level_pkey_start:   TK_PKEY {
2013                             RESET_BUFFER;
2014                         }
2015                         ;
2016 
2017     /*
2018      *  qos_match_rule_entry values:
2019      *      qos_match_rule_use
2020      *      qos_match_rule_qos_class
2021      *      qos_match_rule_qos_level_name
2022      *      qos_match_rule_source
2023      *      qos_match_rule_destination
2024      *      qos_match_rule_service_id
2025      *      qos_match_rule_pkey
2026      */
2027 
2028 
2029 qos_match_rule_use:     qos_match_rule_use_start single_string {
2030                             /* 'use' of 'qos-match-rule' - one instance */
2031                             cl_list_iterator_t    list_iterator;
2032                             char                * tmp_str;
2033 
2034                             if (p_current_qos_match_rule->use)
2035                             {
2036                                 yyerror("'qos-match-rule' has multiple 'use' tags");
2037                                 cl_list_remove_all(&tmp_parser_struct.str_list);
2038                                 return 1;
2039                             }
2040 
2041                             list_iterator = cl_list_head(&tmp_parser_struct.str_list);
2042                             if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
2043                             {
2044                                 tmp_str = (char*)cl_list_obj(list_iterator);
2045                                 if (tmp_str)
2046                                     p_current_qos_match_rule->use = tmp_str;
2047                             }
2048                             cl_list_remove_all(&tmp_parser_struct.str_list);
2049                         }
2050                         ;
2051 
2052 qos_match_rule_use_start: TK_USE {
2053                             RESET_BUFFER;
2054                         }
2055                         ;
2056 
2057 qos_match_rule_qos_class: qos_match_rule_qos_class_start list_of_ranges {
2058                             /* 'qos-class' in 'qos-match-rule' - num of instances of list of ranges */
2059                             /* list of class ranges (QoS Class is 12-bit value) */
2060                             if (cl_list_count(&tmp_parser_struct.num_pair_list))
2061                             {
2062                                 uint64_t ** range_arr;
2063                                 unsigned range_len;
2064 
2065                                 __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
2066                                                       &range_arr,
2067                                                       &range_len );
2068 
2069                                 if ( !p_current_qos_match_rule->qos_class_range_len )
2070                                 {
2071                                     p_current_qos_match_rule->qos_class_range_arr = range_arr;
2072                                     p_current_qos_match_rule->qos_class_range_len = range_len;
2073                                 }
2074                                 else
2075                                 {
2076                                     uint64_t ** new_range_arr;
2077                                     unsigned new_range_len;
2078                                     __merge_rangearr( p_current_qos_match_rule->qos_class_range_arr,
2079                                                       p_current_qos_match_rule->qos_class_range_len,
2080                                                       range_arr,
2081                                                       range_len,
2082                                                       &new_range_arr,
2083                                                       &new_range_len );
2084                                     p_current_qos_match_rule->qos_class_range_arr = new_range_arr;
2085                                     p_current_qos_match_rule->qos_class_range_len = new_range_len;
2086                                 }
2087                             }
2088                         }
2089                         ;
2090 
2091 qos_match_rule_qos_class_start: TK_QOS_CLASS {
2092                             RESET_BUFFER;
2093                         }
2094                         ;
2095 
2096 qos_match_rule_source:  qos_match_rule_source_start string_list {
2097                             /* 'source' in 'qos-match-rule' - text */
2098                             cl_list_iterator_t    list_iterator;
2099                             char                * tmp_str;
2100 
2101                             list_iterator = cl_list_head(&tmp_parser_struct.str_list);
2102                             while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
2103                             {
2104                                 tmp_str = (char*)cl_list_obj(list_iterator);
2105                                 if (tmp_str)
2106                                     cl_list_insert_tail(&p_current_qos_match_rule->source_list,tmp_str);
2107                                 list_iterator = cl_list_next(list_iterator);
2108                             }
2109                             cl_list_remove_all(&tmp_parser_struct.str_list);
2110                         }
2111                         ;
2112 
2113 qos_match_rule_source_start: TK_SOURCE {
2114                             RESET_BUFFER;
2115                         }
2116                         ;
2117 
2118 qos_match_rule_destination: qos_match_rule_destination_start string_list {
2119                             /* 'destination' in 'qos-match-rule' - text */
2120                             cl_list_iterator_t    list_iterator;
2121                             char                * tmp_str;
2122 
2123                             list_iterator = cl_list_head(&tmp_parser_struct.str_list);
2124                             while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
2125                             {
2126                                 tmp_str = (char*)cl_list_obj(list_iterator);
2127                                 if (tmp_str)
2128                                     cl_list_insert_tail(&p_current_qos_match_rule->destination_list,tmp_str);
2129                                 list_iterator = cl_list_next(list_iterator);
2130                             }
2131                             cl_list_remove_all(&tmp_parser_struct.str_list);
2132                         }
2133                         ;
2134 
2135 qos_match_rule_destination_start: TK_DESTINATION {
2136                             RESET_BUFFER;
2137                         }
2138                         ;
2139 
2140 qos_match_rule_qos_level_name:  qos_match_rule_qos_level_name_start single_string {
2141                             /* 'qos-level-name' in 'qos-match-rule' - single string */
2142                             cl_list_iterator_t   list_iterator;
2143                             char               * tmp_str;
2144 
2145                             if (p_current_qos_match_rule->qos_level_name)
2146                             {
2147                                 yyerror("qos-match-rule has multiple 'qos-level-name' tags");
2148                                 cl_list_remove_all(&tmp_parser_struct.num_list);
2149                                 return 1;
2150                             }
2151 
2152                             list_iterator = cl_list_head(&tmp_parser_struct.str_list);
2153                             if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) )
2154                             {
2155                                 tmp_str = (char*)cl_list_obj(list_iterator);
2156                                 if (tmp_str)
2157                                     p_current_qos_match_rule->qos_level_name = tmp_str;
2158                             }
2159                             cl_list_remove_all(&tmp_parser_struct.str_list);
2160                         }
2161                         ;
2162 
2163 qos_match_rule_qos_level_name_start: TK_QOS_LEVEL_NAME {
2164                             RESET_BUFFER;
2165                         }
2166                         ;
2167 
2168 qos_match_rule_service_id: qos_match_rule_service_id_start list_of_ranges {
2169                             /* 'service-id' in 'qos-match-rule' - num of instances of list of ranges */
2170                             if (cl_list_count(&tmp_parser_struct.num_pair_list))
2171                             {
2172                                 uint64_t ** range_arr;
2173                                 unsigned range_len;
2174 
2175                                 __rangelist2rangearr( &tmp_parser_struct.num_pair_list,
2176                                                       &range_arr,
2177                                                       &range_len );
2178 
2179                                 if ( !p_current_qos_match_rule->service_id_range_len )
2180                                 {
2181                                     p_current_qos_match_rule->service_id_range_arr = range_arr;
2182                                     p_current_qos_match_rule->service_id_range_len = range_len;
2183                                 }
2184                                 else
2185                                 {
2186                                     uint64_t ** new_range_arr;
2187                                     unsigned new_range_len;
2188                                     __merge_rangearr( p_current_qos_match_rule->service_id_range_arr,
2189                                                       p_current_qos_match_rule->service_id_range_len,
2190                                                       range_arr,
2191                                                       range_len,
2192                                                       &new_range_arr,
2193                                                       &new_range_len );
2194                                     p_current_qos_match_rule->service_id_range_arr = new_range_arr;
2195                                     p_current_qos_match_rule->service_id_range_len = new_range_len;
2196                                 }
2197                             }
2198                         }
2199                         ;
2200 
2201 qos_match_rule_service_id_start: TK_SERVICE_ID {
2202                             RESET_BUFFER;
2203                         }
2204                         ;
2205 
2206 qos_match_rule_pkey:    qos_match_rule_pkey_start list_of_ranges {
2207                             /* 'pkey' in 'qos-match-rule' - num of instances of list of ranges */
2208                             if (cl_list_count(&tmp_parser_struct.num_pair_list))
2209                             {
2210                                 uint64_t ** range_arr;
2211                                 unsigned range_len;
2212 
2213                                 __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list,
2214                                                       &range_arr,
2215                                                       &range_len );
2216 
2217                                 if ( !p_current_qos_match_rule->pkey_range_len )
2218                                 {
2219                                     p_current_qos_match_rule->pkey_range_arr = range_arr;
2220                                     p_current_qos_match_rule->pkey_range_len = range_len;
2221                                 }
2222                                 else
2223                                 {
2224                                     uint64_t ** new_range_arr;
2225                                     unsigned new_range_len;
2226                                     __merge_rangearr( p_current_qos_match_rule->pkey_range_arr,
2227                                                       p_current_qos_match_rule->pkey_range_len,
2228                                                       range_arr,
2229                                                       range_len,
2230                                                       &new_range_arr,
2231                                                       &new_range_len );
2232                                     p_current_qos_match_rule->pkey_range_arr = new_range_arr;
2233                                     p_current_qos_match_rule->pkey_range_len = new_range_len;
2234                                 }
2235                             }
2236                         }
2237                         ;
2238 
2239 qos_match_rule_pkey_start: TK_PKEY {
2240                             RESET_BUFFER;
2241                         }
2242                         ;
2243 
2244 
2245     /*
2246      * Common part
2247      */
2248 
2249 
2250 single_string:      single_string_elems {
2251                         cl_list_insert_tail(&tmp_parser_struct.str_list,
2252                                             strdup(__parser_strip_white(tmp_parser_struct.str)));
2253                         tmp_parser_struct.str[0] = '\0';
2254                     }
2255                     ;
2256 
2257 single_string_elems:  single_string_element
2258                     | single_string_elems single_string_element
2259                     ;
2260 
2261 single_string_element: TK_TEXT {
2262                         strcat(tmp_parser_struct.str,$1);
2263                         free($1);
2264                     }
2265                     ;
2266 
2267 
2268 string_list:        single_string
2269                     | string_list TK_COMMA single_string
2270                     ;
2271 
2272 
2273 
2274 single_number:      number
2275                     ;
2276 
2277 num_list:             number
2278                     | num_list TK_COMMA number
2279                     ;
2280 
2281 number:             TK_NUMBER {
2282                         uint64_t * p_num = (uint64_t*)malloc(sizeof(uint64_t));
2283                         __parser_str2uint64(p_num,$1);
2284                         free($1);
2285                         cl_list_insert_tail(&tmp_parser_struct.num_list, p_num);
2286                     }
2287                     ;
2288 
2289 num_list_with_dotdot: number_from_pair_1 TK_DOTDOT number_from_pair_2 {
2290                         uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2);
2291                         num_pair[0] = tmp_parser_struct.num_pair[0];
2292                         num_pair[1] = tmp_parser_struct.num_pair[1];
2293                         cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair);
2294                     }
2295                     | num_list_with_dotdot TK_COMMA number_from_pair_1 TK_DOTDOT number_from_pair_2 {
2296                         uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2);
2297                         num_pair[0] = tmp_parser_struct.num_pair[0];
2298                         num_pair[1] = tmp_parser_struct.num_pair[1];
2299                         cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair);
2300                     }
2301                     ;
2302 
2303 number_from_pair_1:   TK_NUMBER {
2304                         __parser_str2uint64(&tmp_parser_struct.num_pair[0],$1);
2305                         free($1);
2306                     }
2307                     ;
2308 
2309 number_from_pair_2:   TK_NUMBER {
2310                         __parser_str2uint64(&tmp_parser_struct.num_pair[1],$1);
2311                         free($1);
2312                     }
2313                     ;
2314 
2315 list_of_ranges:     num_list_with_dash
2316                     ;
2317 
2318 num_list_with_dash:   single_number_from_range {
2319                         uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2);
2320                         num_pair[0] = tmp_parser_struct.num_pair[0];
2321                         num_pair[1] = tmp_parser_struct.num_pair[1];
2322                         cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair);
2323                     }
2324                     | number_from_range_1 TK_DASH number_from_range_2 {
2325                         uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2);
2326                         if (tmp_parser_struct.num_pair[0] <= tmp_parser_struct.num_pair[1]) {
2327                             num_pair[0] = tmp_parser_struct.num_pair[0];
2328                             num_pair[1] = tmp_parser_struct.num_pair[1];
2329                         }
2330                         else {
2331                             num_pair[1] = tmp_parser_struct.num_pair[0];
2332                             num_pair[0] = tmp_parser_struct.num_pair[1];
2333                         }
2334                         cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair);
2335                     }
2336                     | num_list_with_dash TK_COMMA number_from_range_1 TK_DASH number_from_range_2 {
2337                         uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2);
2338                         if (tmp_parser_struct.num_pair[0] <= tmp_parser_struct.num_pair[1]) {
2339                             num_pair[0] = tmp_parser_struct.num_pair[0];
2340                             num_pair[1] = tmp_parser_struct.num_pair[1];
2341                         }
2342                         else {
2343                             num_pair[1] = tmp_parser_struct.num_pair[0];
2344                             num_pair[0] = tmp_parser_struct.num_pair[1];
2345                         }
2346                         cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair);
2347                     }
2348                     | num_list_with_dash TK_COMMA single_number_from_range {
2349                         uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2);
2350                         num_pair[0] = tmp_parser_struct.num_pair[0];
2351                         num_pair[1] = tmp_parser_struct.num_pair[1];
2352                         cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair);
2353                     }
2354                     ;
2355 
2356 single_number_from_range:  TK_NUMBER {
2357                         __parser_str2uint64(&tmp_parser_struct.num_pair[0],$1);
2358                         __parser_str2uint64(&tmp_parser_struct.num_pair[1],$1);
2359                         free($1);
2360                     }
2361                     ;
2362 
2363 number_from_range_1:  TK_NUMBER {
2364                         __parser_str2uint64(&tmp_parser_struct.num_pair[0],$1);
2365                         free($1);
2366                     }
2367                     ;
2368 
2369 number_from_range_2:  TK_NUMBER {
2370                         __parser_str2uint64(&tmp_parser_struct.num_pair[1],$1);
2371                         free($1);
2372                     }
2373                     ;
2374 
2375 %%
2376 
2377 /***************************************************
2378  ***************************************************/
2379 
2380 int osm_qos_parse_policy_file(IN osm_subn_t * p_subn)
2381 {
2382     int res = 0;
2383     static boolean_t first_time = TRUE;
2384     p_qos_parser_osm_log = &p_subn->p_osm->log;
2385 
2386     OSM_LOG_ENTER(p_qos_parser_osm_log);
2387 
2388     osm_qos_policy_destroy(p_subn->p_qos_policy);
2389     p_subn->p_qos_policy = NULL;
2390 
2391     yyin = fopen (p_subn->opt.qos_policy_file, "r");
2392     if (!yyin)
2393     {
2394         if (strcmp(p_subn->opt.qos_policy_file,OSM_DEFAULT_QOS_POLICY_FILE)) {
2395             OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC01: "
2396                     "Failed opening QoS policy file %s - %s\n",
2397                     p_subn->opt.qos_policy_file, strerror(errno));
2398             res = 1;
2399         }
2400         else
2401             OSM_LOG(p_qos_parser_osm_log, OSM_LOG_VERBOSE,
2402                     "QoS policy file not found (%s)\n",
2403                     p_subn->opt.qos_policy_file);
2404 
2405         goto Exit;
2406     }
2407 
2408     if (first_time)
2409     {
2410         first_time = FALSE;
2411         __setup_simple_qos_levels();
2412         __setup_ulp_match_rules();
2413         OSM_LOG(p_qos_parser_osm_log, OSM_LOG_INFO,
2414 		"Loading QoS policy file (%s)\n",
2415                 p_subn->opt.qos_policy_file);
2416     }
2417     else
2418         /*
2419          * ULP match rules list was emptied at the end of
2420          * previous parsing iteration.
2421          * What's left is to clear simple QoS levels.
2422          */
2423         __clear_simple_qos_levels();
2424 
2425     column_num = 1;
2426     line_num = 1;
2427 
2428     p_subn->p_qos_policy = osm_qos_policy_create(p_subn);
2429 
2430     __parser_tmp_struct_init();
2431     p_qos_policy = p_subn->p_qos_policy;
2432 
2433     res = yyparse();
2434 
2435     __parser_tmp_struct_destroy();
2436 
2437     if (res != 0)
2438     {
2439         OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC03: "
2440                 "Failed parsing QoS policy file (%s)\n",
2441                 p_subn->opt.qos_policy_file);
2442         osm_qos_policy_destroy(p_subn->p_qos_policy);
2443         p_subn->p_qos_policy = NULL;
2444         res = 1;
2445         goto Exit;
2446     }
2447 
2448     /* add generated ULP match rules to the usual match rules */
2449     __process_ulp_match_rules();
2450 
2451     if (osm_qos_policy_validate(p_subn->p_qos_policy,p_qos_parser_osm_log))
2452     {
2453         OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC04: "
2454                 "Error(s) in QoS policy file (%s)\n",
2455                 p_subn->opt.qos_policy_file);
2456         fprintf(stderr, "Error(s) in QoS policy file (%s)\n",
2457                 p_subn->opt.qos_policy_file);
2458         osm_qos_policy_destroy(p_subn->p_qos_policy);
2459         p_subn->p_qos_policy = NULL;
2460         res = 1;
2461         goto Exit;
2462     }
2463 
2464   Exit:
2465     if (yyin)
2466     {
2467         yyrestart(yyin);
2468         fclose(yyin);
2469     }
2470     OSM_LOG_EXIT(p_qos_parser_osm_log);
2471     return res;
2472 }
2473 
2474 /***************************************************
2475  ***************************************************/
2476 
2477 int yywrap()
2478 {
2479     return(1);
2480 }
2481 
2482 /***************************************************
2483  ***************************************************/
2484 
2485 static void yyerror(const char *format, ...)
2486 {
2487     char s[256];
2488     va_list pvar;
2489 
2490     OSM_LOG_ENTER(p_qos_parser_osm_log);
2491 
2492     va_start(pvar, format);
2493     vsnprintf(s, sizeof(s), format, pvar);
2494     va_end(pvar);
2495 
2496     OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC05: "
2497             "Syntax error (line %d:%d): %s\n",
2498             line_num, column_num, s);
2499     fprintf(stderr, "Error in QoS Policy File (line %d:%d): %s.\n",
2500             line_num, column_num, s);
2501     OSM_LOG_EXIT(p_qos_parser_osm_log);
2502 }
2503 
2504 /***************************************************
2505  ***************************************************/
2506 
2507 static char * __parser_strip_white(char * str)
2508 {
2509 	char *p;
2510 
2511 	while (isspace(*str))
2512 		str++;
2513 	if (!*str)
2514 		return str;
2515 	p = str + strlen(str) - 1;
2516 	while (isspace(*p))
2517 		*p-- = '\0';
2518 
2519 	return str;
2520 }
2521 
2522 /***************************************************
2523  ***************************************************/
2524 
2525 static void __parser_str2uint64(uint64_t * p_val, char * str)
2526 {
2527    *p_val = strtoull(str, NULL, 0);
2528 }
2529 
2530 /***************************************************
2531  ***************************************************/
2532 
2533 static void __parser_port_group_start()
2534 {
2535     p_current_port_group = osm_qos_policy_port_group_create();
2536 }
2537 
2538 /***************************************************
2539  ***************************************************/
2540 
2541 static int __parser_port_group_end()
2542 {
2543     if(!p_current_port_group->name)
2544     {
2545         yyerror("port-group validation failed - no port group name specified");
2546         return -1;
2547     }
2548 
2549     cl_list_insert_tail(&p_qos_policy->port_groups,
2550                         p_current_port_group);
2551     p_current_port_group = NULL;
2552     return 0;
2553 }
2554 
2555 /***************************************************
2556  ***************************************************/
2557 
2558 static void __parser_vlarb_scope_start()
2559 {
2560     p_current_vlarb_scope = osm_qos_policy_vlarb_scope_create();
2561 }
2562 
2563 /***************************************************
2564  ***************************************************/
2565 
2566 static int __parser_vlarb_scope_end()
2567 {
2568     if ( !cl_list_count(&p_current_vlarb_scope->group_list) &&
2569          !cl_list_count(&p_current_vlarb_scope->across_list) )
2570     {
2571         yyerror("vlarb-scope validation failed - no port groups specified by 'group' or by 'across'");
2572         return -1;
2573     }
2574 
2575     cl_list_insert_tail(&p_qos_policy->vlarb_tables,
2576                         p_current_vlarb_scope);
2577     p_current_vlarb_scope = NULL;
2578     return 0;
2579 }
2580 
2581 /***************************************************
2582  ***************************************************/
2583 
2584 static void __parser_sl2vl_scope_start()
2585 {
2586     p_current_sl2vl_scope = osm_qos_policy_sl2vl_scope_create();
2587 }
2588 
2589 /***************************************************
2590  ***************************************************/
2591 
2592 static int __parser_sl2vl_scope_end()
2593 {
2594     if (!p_current_sl2vl_scope->sl2vl_table_set)
2595     {
2596         yyerror("sl2vl-scope validation failed - no sl2vl table specified");
2597         return -1;
2598     }
2599     if ( !cl_list_count(&p_current_sl2vl_scope->group_list) &&
2600          !cl_list_count(&p_current_sl2vl_scope->across_to_list) &&
2601          !cl_list_count(&p_current_sl2vl_scope->across_from_list) )
2602     {
2603         yyerror("sl2vl-scope validation failed - no port groups specified by 'group', 'across-to' or 'across-from'");
2604         return -1;
2605     }
2606 
2607     cl_list_insert_tail(&p_qos_policy->sl2vl_tables,
2608                         p_current_sl2vl_scope);
2609     p_current_sl2vl_scope = NULL;
2610     return 0;
2611 }
2612 
2613 /***************************************************
2614  ***************************************************/
2615 
2616 static void __parser_qos_level_start()
2617 {
2618     p_current_qos_level = osm_qos_policy_qos_level_create();
2619 }
2620 
2621 /***************************************************
2622  ***************************************************/
2623 
2624 static int __parser_qos_level_end()
2625 {
2626     if (!p_current_qos_level->sl_set)
2627     {
2628         yyerror("qos-level validation failed - no 'sl' specified");
2629         return -1;
2630     }
2631     if (!p_current_qos_level->name)
2632     {
2633         yyerror("qos-level validation failed - no 'name' specified");
2634         return -1;
2635     }
2636 
2637     cl_list_insert_tail(&p_qos_policy->qos_levels,
2638                         p_current_qos_level);
2639     p_current_qos_level = NULL;
2640     return 0;
2641 }
2642 
2643 /***************************************************
2644  ***************************************************/
2645 
2646 static void __parser_match_rule_start()
2647 {
2648     p_current_qos_match_rule = osm_qos_policy_match_rule_create();
2649 }
2650 
2651 /***************************************************
2652  ***************************************************/
2653 
2654 static int __parser_match_rule_end()
2655 {
2656     if (!p_current_qos_match_rule->qos_level_name)
2657     {
2658         yyerror("match-rule validation failed - no 'qos-level-name' specified");
2659         return -1;
2660     }
2661 
2662     cl_list_insert_tail(&p_qos_policy->qos_match_rules,
2663                         p_current_qos_match_rule);
2664     p_current_qos_match_rule = NULL;
2665     return 0;
2666 }
2667 
2668 /***************************************************
2669  ***************************************************/
2670 
2671 static void __parser_ulp_match_rule_start()
2672 {
2673     p_current_qos_match_rule = osm_qos_policy_match_rule_create();
2674 }
2675 
2676 /***************************************************
2677  ***************************************************/
2678 
2679 static int __parser_ulp_match_rule_end()
2680 {
2681     CL_ASSERT(p_current_qos_match_rule->p_qos_level);
2682     cl_list_insert_tail(&__ulp_match_rules,
2683                         p_current_qos_match_rule);
2684     p_current_qos_match_rule = NULL;
2685     return 0;
2686 }
2687 
2688 /***************************************************
2689  ***************************************************/
2690 
2691 static void __parser_tmp_struct_init()
2692 {
2693     tmp_parser_struct.str[0] = '\0';
2694     cl_list_construct(&tmp_parser_struct.str_list);
2695     cl_list_init(&tmp_parser_struct.str_list, 10);
2696     cl_list_construct(&tmp_parser_struct.num_list);
2697     cl_list_init(&tmp_parser_struct.num_list, 10);
2698     cl_list_construct(&tmp_parser_struct.num_pair_list);
2699     cl_list_init(&tmp_parser_struct.num_pair_list, 10);
2700 }
2701 
2702 /***************************************************
2703  ***************************************************/
2704 
2705 /*
2706  * Do NOT free objects from the temp struct.
2707  * Either they are inserted into the parse tree data
2708  * structure, or they are already freed when copying
2709  * their values to the parse tree data structure.
2710  */
2711 static void __parser_tmp_struct_reset()
2712 {
2713     tmp_parser_struct.str[0] = '\0';
2714     cl_list_remove_all(&tmp_parser_struct.str_list);
2715     cl_list_remove_all(&tmp_parser_struct.num_list);
2716     cl_list_remove_all(&tmp_parser_struct.num_pair_list);
2717 }
2718 
2719 /***************************************************
2720  ***************************************************/
2721 
2722 static void __parser_tmp_struct_destroy()
2723 {
2724     __parser_tmp_struct_reset();
2725     cl_list_destroy(&tmp_parser_struct.str_list);
2726     cl_list_destroy(&tmp_parser_struct.num_list);
2727     cl_list_destroy(&tmp_parser_struct.num_pair_list);
2728 }
2729 
2730 /***************************************************
2731  ***************************************************/
2732 
2733 #define __SIMPLE_QOS_LEVEL_NAME "SimpleQoSLevel_SL"
2734 #define __SIMPLE_QOS_LEVEL_DEFAULT_NAME "SimpleQoSLevel_DEFAULT"
2735 
2736 static void __setup_simple_qos_levels()
2737 {
2738     uint8_t i;
2739     char tmp_buf[30];
2740     memset(osm_qos_policy_simple_qos_levels, 0,
2741            sizeof(osm_qos_policy_simple_qos_levels));
2742     for (i = 0; i < 16; i++)
2743     {
2744         osm_qos_policy_simple_qos_levels[i].sl = i;
2745         osm_qos_policy_simple_qos_levels[i].sl_set = TRUE;
2746         sprintf(tmp_buf, "%s%u", __SIMPLE_QOS_LEVEL_NAME, i);
2747         osm_qos_policy_simple_qos_levels[i].name = strdup(tmp_buf);
2748     }
2749 
2750     memset(&__default_simple_qos_level, 0,
2751            sizeof(__default_simple_qos_level));
2752     __default_simple_qos_level.name =
2753            strdup(__SIMPLE_QOS_LEVEL_DEFAULT_NAME);
2754 }
2755 
2756 /***************************************************
2757  ***************************************************/
2758 
2759 static void __clear_simple_qos_levels()
2760 {
2761     /*
2762      * Simple QoS levels are static.
2763      * What's left is to invalidate default simple QoS level.
2764      */
2765     __default_simple_qos_level.sl_set = FALSE;
2766 }
2767 
2768 /***************************************************
2769  ***************************************************/
2770 
2771 static void __setup_ulp_match_rules()
2772 {
2773     cl_list_construct(&__ulp_match_rules);
2774     cl_list_init(&__ulp_match_rules, 10);
2775 }
2776 
2777 /***************************************************
2778  ***************************************************/
2779 
2780 static void __process_ulp_match_rules()
2781 {
2782     cl_list_iterator_t list_iterator;
2783     osm_qos_match_rule_t *p_qos_match_rule = NULL;
2784 
2785     list_iterator = cl_list_head(&__ulp_match_rules);
2786     while (list_iterator != cl_list_end(&__ulp_match_rules))
2787     {
2788         p_qos_match_rule = (osm_qos_match_rule_t *) cl_list_obj(list_iterator);
2789         if (p_qos_match_rule)
2790             cl_list_insert_tail(&p_qos_policy->qos_match_rules,
2791                                 p_qos_match_rule);
2792         list_iterator = cl_list_next(list_iterator);
2793     }
2794     cl_list_remove_all(&__ulp_match_rules);
2795 }
2796 
2797 /***************************************************
2798  ***************************************************/
2799 
2800 static int __cmp_num_range(const void * p1, const void * p2)
2801 {
2802     uint64_t * pair1 = *((uint64_t **)p1);
2803     uint64_t * pair2 = *((uint64_t **)p2);
2804 
2805     if (pair1[0] < pair2[0])
2806         return -1;
2807     if (pair1[0] > pair2[0])
2808         return 1;
2809 
2810     if (pair1[1] < pair2[1])
2811         return -1;
2812     if (pair1[1] > pair2[1])
2813         return 1;
2814 
2815     return 0;
2816 }
2817 
2818 /***************************************************
2819  ***************************************************/
2820 
2821 static void __sort_reduce_rangearr(
2822     uint64_t  **   arr,
2823     unsigned       arr_len,
2824     uint64_t  ** * p_res_arr,
2825     unsigned     * p_res_arr_len )
2826 {
2827     unsigned i = 0;
2828     unsigned j = 0;
2829     unsigned last_valid_ind = 0;
2830     unsigned valid_cnt = 0;
2831     uint64_t ** res_arr;
2832     boolean_t * is_valid_arr;
2833 
2834     *p_res_arr = NULL;
2835     *p_res_arr_len = 0;
2836 
2837     qsort(arr, arr_len, sizeof(uint64_t*), __cmp_num_range);
2838 
2839     is_valid_arr = (boolean_t *)malloc(arr_len * sizeof(boolean_t));
2840     is_valid_arr[last_valid_ind] = TRUE;
2841     valid_cnt++;
2842     for (i = 1; i < arr_len; i++)
2843     {
2844         if (arr[i][0] <= arr[last_valid_ind][1])
2845         {
2846             if (arr[i][1] > arr[last_valid_ind][1])
2847                 arr[last_valid_ind][1] = arr[i][1];
2848             free(arr[i]);
2849             arr[i] = NULL;
2850             is_valid_arr[i] = FALSE;
2851         }
2852         else if ((arr[i][0] - 1) == arr[last_valid_ind][1])
2853         {
2854             arr[last_valid_ind][1] = arr[i][1];
2855             free(arr[i]);
2856             arr[i] = NULL;
2857             is_valid_arr[i] = FALSE;
2858         }
2859         else
2860         {
2861             is_valid_arr[i] = TRUE;
2862             last_valid_ind = i;
2863             valid_cnt++;
2864         }
2865     }
2866 
2867     res_arr = (uint64_t **)malloc(valid_cnt * sizeof(uint64_t *));
2868     for (i = 0; i < arr_len; i++)
2869     {
2870         if (is_valid_arr[i])
2871             res_arr[j++] = arr[i];
2872     }
2873     free(is_valid_arr);
2874     free(arr);
2875 
2876     *p_res_arr = res_arr;
2877     *p_res_arr_len = valid_cnt;
2878 }
2879 
2880 /***************************************************
2881  ***************************************************/
2882 
2883 static void __pkey_rangelist2rangearr(
2884     cl_list_t    * p_list,
2885     uint64_t  ** * p_arr,
2886     unsigned     * p_arr_len)
2887 {
2888     uint64_t   tmp_pkey;
2889     uint64_t * p_pkeys;
2890     cl_list_iterator_t list_iterator;
2891 
2892     list_iterator= cl_list_head(p_list);
2893     while( list_iterator != cl_list_end(p_list) )
2894     {
2895        p_pkeys = (uint64_t *)cl_list_obj(list_iterator);
2896        p_pkeys[0] &= 0x7fff;
2897        p_pkeys[1] &= 0x7fff;
2898        if (p_pkeys[0] > p_pkeys[1])
2899        {
2900            tmp_pkey = p_pkeys[1];
2901            p_pkeys[1] = p_pkeys[0];
2902            p_pkeys[0] = tmp_pkey;
2903        }
2904        list_iterator = cl_list_next(list_iterator);
2905     }
2906 
2907     __rangelist2rangearr(p_list, p_arr, p_arr_len);
2908 }
2909 
2910 /***************************************************
2911  ***************************************************/
2912 
2913 static void __rangelist2rangearr(
2914     cl_list_t    * p_list,
2915     uint64_t  ** * p_arr,
2916     unsigned     * p_arr_len)
2917 {
2918     cl_list_iterator_t list_iterator;
2919     unsigned len = cl_list_count(p_list);
2920     unsigned i = 0;
2921     uint64_t ** tmp_arr;
2922     uint64_t ** res_arr = NULL;
2923     unsigned res_arr_len = 0;
2924 
2925     tmp_arr = (uint64_t **)malloc(len * sizeof(uint64_t *));
2926 
2927     list_iterator = cl_list_head(p_list);
2928     while( list_iterator != cl_list_end(p_list) )
2929     {
2930        tmp_arr[i++] = (uint64_t *)cl_list_obj(list_iterator);
2931        list_iterator = cl_list_next(list_iterator);
2932     }
2933     cl_list_remove_all(p_list);
2934 
2935     __sort_reduce_rangearr( tmp_arr,
2936                             len,
2937                             &res_arr,
2938                             &res_arr_len );
2939     *p_arr = res_arr;
2940     *p_arr_len = res_arr_len;
2941 }
2942 
2943 /***************************************************
2944  ***************************************************/
2945 
2946 static void __merge_rangearr(
2947     uint64_t  **   range_arr_1,
2948     unsigned       range_len_1,
2949     uint64_t  **   range_arr_2,
2950     unsigned       range_len_2,
2951     uint64_t  ** * p_arr,
2952     unsigned     * p_arr_len )
2953 {
2954     unsigned i = 0;
2955     unsigned j = 0;
2956     unsigned len = range_len_1 + range_len_2;
2957     uint64_t ** tmp_arr;
2958     uint64_t ** res_arr = NULL;
2959     unsigned res_arr_len = 0;
2960 
2961     *p_arr = NULL;
2962     *p_arr_len = 0;
2963 
2964     tmp_arr = (uint64_t **)malloc(len * sizeof(uint64_t *));
2965 
2966     for (i = 0; i < range_len_1; i++)
2967        tmp_arr[j++] = range_arr_1[i];
2968     for (i = 0; i < range_len_2; i++)
2969        tmp_arr[j++] = range_arr_2[i];
2970     free(range_arr_1);
2971     free(range_arr_2);
2972 
2973     __sort_reduce_rangearr( tmp_arr,
2974                             len,
2975                             &res_arr,
2976                             &res_arr_len );
2977     *p_arr = res_arr;
2978     *p_arr_len = res_arr_len;
2979 }
2980 
2981 /***************************************************
2982  ***************************************************/
2983 
2984 static void __parser_add_port_to_port_map(
2985     cl_qmap_t   * p_map,
2986     osm_physp_t * p_physp)
2987 {
2988     if (cl_qmap_get(p_map, cl_ntoh64(osm_physp_get_port_guid(p_physp))) ==
2989         cl_qmap_end(p_map))
2990     {
2991         osm_qos_port_t * p_port = osm_qos_policy_port_create(p_physp);
2992         if (p_port)
2993             cl_qmap_insert(p_map,
2994                            cl_ntoh64(osm_physp_get_port_guid(p_physp)),
2995                            &p_port->map_item);
2996     }
2997 }
2998 
2999 /***************************************************
3000  ***************************************************/
3001 
3002 static void __parser_add_guid_range_to_port_map(
3003     cl_qmap_t  * p_map,
3004     uint64_t  ** range_arr,
3005     unsigned     range_len)
3006 {
3007     unsigned i;
3008     uint64_t guid_ho;
3009     osm_port_t * p_osm_port;
3010 
3011     if (!range_arr || !range_len)
3012         return;
3013 
3014     for (i = 0; i < range_len; i++) {
3015          for (guid_ho = range_arr[i][0]; guid_ho <= range_arr[i][1]; guid_ho++) {
3016              p_osm_port =
3017                 osm_get_port_by_guid(p_qos_policy->p_subn, cl_hton64(guid_ho));
3018              if (p_osm_port)
3019                  __parser_add_port_to_port_map(p_map, p_osm_port->p_physp);
3020          }
3021          free(range_arr[i]);
3022     }
3023     free(range_arr);
3024 }
3025 
3026 /***************************************************
3027  ***************************************************/
3028 
3029 static void __parser_add_pkey_range_to_port_map(
3030     cl_qmap_t  * p_map,
3031     uint64_t  ** range_arr,
3032     unsigned     range_len)
3033 {
3034     unsigned i;
3035     uint64_t pkey_64;
3036     ib_net16_t pkey;
3037     osm_prtn_t * p_prtn;
3038 
3039     if (!range_arr || !range_len)
3040         return;
3041 
3042     for (i = 0; i < range_len; i++) {
3043          for (pkey_64 = range_arr[i][0]; pkey_64 <= range_arr[i][1]; pkey_64++) {
3044              pkey = cl_hton16((uint16_t)(pkey_64 & 0x7fff));
3045              p_prtn = (osm_prtn_t *)
3046                  cl_qmap_get(&p_qos_policy->p_subn->prtn_pkey_tbl, pkey);
3047              if (p_prtn != (osm_prtn_t *)cl_qmap_end(
3048                    &p_qos_policy->p_subn->prtn_pkey_tbl)) {
3049                  __parser_add_map_to_port_map(p_map, &p_prtn->part_guid_tbl);
3050                  __parser_add_map_to_port_map(p_map, &p_prtn->full_guid_tbl);
3051              }
3052          }
3053          free(range_arr[i]);
3054     }
3055     free(range_arr);
3056 }
3057 
3058 /***************************************************
3059  ***************************************************/
3060 
3061 static void __parser_add_partition_list_to_port_map(
3062     cl_qmap_t  * p_map,
3063     cl_list_t  * p_list)
3064 {
3065     cl_list_iterator_t    list_iterator;
3066     char                * tmp_str;
3067     osm_prtn_t          * p_prtn;
3068 
3069     /* extract all the ports from the partition
3070        to the port map of this port group */
3071     list_iterator = cl_list_head(p_list);
3072     while(list_iterator != cl_list_end(p_list)) {
3073         tmp_str = (char*)cl_list_obj(list_iterator);
3074         if (tmp_str) {
3075             p_prtn = osm_prtn_find_by_name(p_qos_policy->p_subn, tmp_str);
3076             if (p_prtn) {
3077                 __parser_add_map_to_port_map(p_map, &p_prtn->part_guid_tbl);
3078                 __parser_add_map_to_port_map(p_map, &p_prtn->full_guid_tbl);
3079             }
3080             free(tmp_str);
3081         }
3082         list_iterator = cl_list_next(list_iterator);
3083     }
3084     cl_list_remove_all(p_list);
3085 }
3086 
3087 /***************************************************
3088  ***************************************************/
3089 
3090 static void __parser_add_map_to_port_map(
3091     cl_qmap_t * p_dmap,
3092     cl_map_t  * p_smap)
3093 {
3094     cl_map_iterator_t map_iterator;
3095     osm_physp_t * p_physp;
3096 
3097     if (!p_dmap || !p_smap)
3098         return;
3099 
3100     map_iterator = cl_map_head(p_smap);
3101     while (map_iterator != cl_map_end(p_smap)) {
3102         p_physp = (osm_physp_t*)cl_map_obj(map_iterator);
3103         __parser_add_port_to_port_map(p_dmap, p_physp);
3104         map_iterator = cl_map_next(map_iterator);
3105     }
3106 }
3107 
3108 /***************************************************
3109  ***************************************************/
3110 
3111 static int __validate_pkeys( uint64_t ** range_arr,
3112                              unsigned    range_len,
3113                              boolean_t   is_ipoib)
3114 {
3115     unsigned i;
3116     uint64_t pkey_64;
3117     ib_net16_t pkey;
3118     osm_prtn_t * p_prtn;
3119 
3120     if (!range_arr || !range_len)
3121         return 0;
3122 
3123     for (i = 0; i < range_len; i++) {
3124         for (pkey_64 = range_arr[i][0]; pkey_64 <= range_arr[i][1]; pkey_64++) {
3125             pkey = cl_hton16((uint16_t)(pkey_64 & 0x7fff));
3126             p_prtn = (osm_prtn_t *)
3127                 cl_qmap_get(&p_qos_policy->p_subn->prtn_pkey_tbl, pkey);
3128 
3129             if (p_prtn == (osm_prtn_t *)cl_qmap_end(
3130                   &p_qos_policy->p_subn->prtn_pkey_tbl))
3131                 p_prtn = NULL;
3132 
3133             if (is_ipoib) {
3134                 /*
3135                  * Be very strict for IPoIB partition:
3136                  *  - the partition for the pkey have to exist
3137                  *  - it has to have at least 2 full members
3138                  */
3139                 if (!p_prtn) {
3140                     yyerror("IPoIB partition, pkey 0x%04X - "
3141                                        "partition doesn't exist",
3142                                        cl_ntoh16(pkey));
3143                     return 1;
3144                 }
3145                 else if (cl_map_count(&p_prtn->full_guid_tbl) < 2) {
3146                     yyerror("IPoIB partition, pkey 0x%04X - "
3147                                        "partition has less than two full members",
3148                                        cl_ntoh16(pkey));
3149                     return 1;
3150                 }
3151             }
3152             else if (!p_prtn) {
3153                 /*
3154                  * For non-IPoIB pkey we just want to check that
3155                  * the relevant partition exists.
3156                  * And even if it doesn't, don't exit - just print
3157                  * error message and continue.
3158                  */
3159                  OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC02: "
3160 			 "pkey 0x%04X - partition doesn't exist",
3161                          cl_ntoh16(pkey));
3162             }
3163         }
3164     }
3165     return 0;
3166 }
3167 
3168 /***************************************************
3169  ***************************************************/
3170