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