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
63typedef 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
71static void __parser_tmp_struct_init();
72static void __parser_tmp_struct_reset();
73static void __parser_tmp_struct_destroy();
74
75static char * __parser_strip_white(char * str);
76
77static void __parser_str2uint64(uint64_t * p_val, char * str);
78
79static void __parser_port_group_start();
80static int __parser_port_group_end();
81
82static void __parser_sl2vl_scope_start();
83static int __parser_sl2vl_scope_end();
84
85static void __parser_vlarb_scope_start();
86static int __parser_vlarb_scope_end();
87
88static void __parser_qos_level_start();
89static int __parser_qos_level_end();
90
91static void __parser_match_rule_start();
92static int __parser_match_rule_end();
93
94static void __parser_ulp_match_rule_start();
95static int __parser_ulp_match_rule_end();
96
97static void __pkey_rangelist2rangearr(
98    cl_list_t    * p_list,
99    uint64_t  ** * p_arr,
100    unsigned     * p_arr_len);
101
102static void __rangelist2rangearr(
103    cl_list_t    * p_list,
104    uint64_t  ** * p_arr,
105    unsigned     * p_arr_len);
106
107static 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
115static void __parser_add_port_to_port_map(
116    cl_qmap_t   * p_map,
117    osm_physp_t * p_physp);
118
119static void __parser_add_guid_range_to_port_map(
120    cl_qmap_t  * p_map,
121    uint64_t  ** range_arr,
122    unsigned     range_len);
123
124static void __parser_add_pkey_range_to_port_map(
125    cl_qmap_t  * p_map,
126    uint64_t  ** range_arr,
127    unsigned     range_len);
128
129static void __parser_add_partition_list_to_port_map(
130    cl_qmap_t  * p_map,
131    cl_list_t  * p_list);
132
133static void __parser_add_map_to_port_map(
134    cl_qmap_t * p_dmap,
135    cl_map_t  * p_smap);
136
137static int __validate_pkeys(
138    uint64_t ** range_arr,
139    unsigned    range_len,
140    boolean_t   is_ipoib);
141
142static void __setup_simple_qos_levels();
143static void __clear_simple_qos_levels();
144static void __setup_ulp_match_rules();
145static void __process_ulp_match_rules();
146static void yyerror(const char *format, ...);
147
148extern char * yytext;
149extern int yylex (void);
150extern FILE * yyin;
151extern int errno;
152int yyparse();
153
154#define RESET_BUFFER  __parser_tmp_struct_reset()
155
156tmp_parser_struct_t tmp_parser_struct;
157
158int column_num;
159int line_num;
160
161osm_qos_policy_t       * p_qos_policy = NULL;
162osm_qos_port_group_t   * p_current_port_group = NULL;
163osm_qos_sl2vl_scope_t  * p_current_sl2vl_scope = NULL;
164osm_qos_vlarb_scope_t  * p_current_vlarb_scope = NULL;
165osm_qos_level_t        * p_current_qos_level = NULL;
166osm_qos_match_rule_t   * p_current_qos_match_rule = NULL;
167osm_log_t              * p_qos_parser_osm_log;
168
169/* 16 Simple QoS Levels - one for each SL */
170static osm_qos_level_t osm_qos_policy_simple_qos_levels[16];
171
172/* Default Simple QoS Level */
173osm_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 */
181static 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
276head:               qos_policy_entries
277                    ;
278
279qos_policy_entries: /* empty */
280                    | qos_policy_entries qos_policy_entry
281                    ;
282
283qos_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
311qos_ulps_section: TK_QOS_ULPS_START qos_ulps TK_QOS_ULPS_END
312                     ;
313
314qos_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
344port_groups_section: TK_PORT_GROUPS_START port_groups TK_PORT_GROUPS_END
345                     ;
346
347port_groups:        port_group
348                    | port_groups port_group
349                    ;
350
351port_group:         port_group_start port_group_entries port_group_end
352                    ;
353
354port_group_start:   TK_PORT_GROUP_START {
355                        __parser_port_group_start();
356                    }
357                    ;
358
359port_group_end:     TK_PORT_GROUP_END {
360                        if ( __parser_port_group_end() )
361                            return 1;
362                    }
363                    ;
364
365port_group_entries: /* empty */
366                    | port_group_entries port_group_entry
367                    ;
368
369port_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
402qos_setup_section:  TK_QOS_SETUP_START qos_setup_items TK_QOS_SETUP_END
403                    ;
404
405qos_setup_items:    /* empty */
406                    | qos_setup_items vlarb_tables
407                    | qos_setup_items sl2vl_tables
408                    ;
409
410    /* Parsing vlarb-tables */
411
412vlarb_tables:       TK_VLARB_TABLES_START vlarb_scope_items TK_VLARB_TABLES_END
413                    ;
414
415vlarb_scope_items:  /* empty */
416                    | vlarb_scope_items vlarb_scope
417                    ;
418
419vlarb_scope:        vlarb_scope_start vlarb_scope_entries vlarb_scope_end
420                    ;
421
422vlarb_scope_start:  TK_VLARB_SCOPE_START {
423                        __parser_vlarb_scope_start();
424                    }
425                    ;
426
427vlarb_scope_end:    TK_VLARB_SCOPE_END {
428                        if ( __parser_vlarb_scope_end() )
429                            return 1;
430                    }
431                    ;
432
433vlarb_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
449vlarb_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
458sl2vl_tables:       TK_SL2VL_TABLES_START sl2vl_scope_items TK_SL2VL_TABLES_END
459                    ;
460
461sl2vl_scope_items:  /* empty */
462                    | sl2vl_scope_items sl2vl_scope
463                    ;
464
465sl2vl_scope:        sl2vl_scope_start sl2vl_scope_entries sl2vl_scope_end
466                    ;
467
468sl2vl_scope_start:  TK_SL2VL_SCOPE_START {
469                        __parser_sl2vl_scope_start();
470                    }
471                    ;
472
473sl2vl_scope_end:    TK_SL2VL_SCOPE_END {
474                        if ( __parser_sl2vl_scope_end() )
475                            return 1;
476                    }
477                    ;
478
479sl2vl_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
499sl2vl_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
529qos_levels_section: TK_QOS_LEVELS_START qos_levels TK_QOS_LEVELS_END
530                    ;
531
532qos_levels:         /* empty */
533                    | qos_levels qos_level
534                    ;
535
536qos_level:          qos_level_start qos_level_entries qos_level_end
537                    ;
538
539qos_level_start:    TK_QOS_LEVEL_START {
540                        __parser_qos_level_start();
541                    }
542                    ;
543
544qos_level_end:      TK_QOS_LEVEL_END {
545                        if ( __parser_qos_level_end() )
546                            return 1;
547                    }
548                    ;
549
550qos_level_entries:  /* empty */
551                    | qos_level_entries qos_level_entry
552                    ;
553
554qos_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
583qos_match_rules_section: TK_QOS_MATCH_RULES_START qos_match_rules TK_QOS_MATCH_RULES_END
584                    ;
585
586qos_match_rules:    /* empty */
587                    | qos_match_rules qos_match_rule
588                    ;
589
590qos_match_rule:     qos_match_rule_start qos_match_rule_entries qos_match_rule_end
591                    ;
592
593qos_match_rule_start: TK_QOS_MATCH_RULE_START {
594                        __parser_match_rule_start();
595                    }
596                    ;
597
598qos_match_rule_end: TK_QOS_MATCH_RULE_END {
599                        if ( __parser_match_rule_end() )
600                            return 1;
601                    }
602                    ;
603
604qos_match_rule_entries: /* empty */
605                    | qos_match_rule_entries qos_match_rule_entry
606                    ;
607
608qos_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
636qos_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
956qos_ulp_type_any_service: TK_ULP_ANY_SERVICE_ID
957                    { __parser_ulp_match_rule_start(); };
958
959qos_ulp_type_any_pkey: TK_ULP_ANY_PKEY
960                    { __parser_ulp_match_rule_start(); };
961
962qos_ulp_type_any_target_port_guid: TK_ULP_ANY_TARGET_PORT_GUID
963                    { __parser_ulp_match_rule_start(); };
964
965qos_ulp_type_sdp_default: TK_ULP_SDP_DEFAULT
966                    { __parser_ulp_match_rule_start(); };
967
968qos_ulp_type_sdp_port: TK_ULP_SDP_PORT
969                    { __parser_ulp_match_rule_start(); };
970
971qos_ulp_type_rds_default: TK_ULP_RDS_DEFAULT
972                    { __parser_ulp_match_rule_start(); };
973
974qos_ulp_type_rds_port: TK_ULP_RDS_PORT
975                    { __parser_ulp_match_rule_start(); };
976
977qos_ulp_type_iser_default: TK_ULP_ISER_DEFAULT
978                    { __parser_ulp_match_rule_start(); };
979
980qos_ulp_type_iser_port: TK_ULP_ISER_PORT
981                    { __parser_ulp_match_rule_start(); };
982
983qos_ulp_type_srp_guid: TK_ULP_SRP_GUID
984                    { __parser_ulp_match_rule_start(); };
985
986qos_ulp_type_ipoib_default: TK_ULP_IPOIB_DEFAULT
987                    { __parser_ulp_match_rule_start(); };
988
989qos_ulp_type_ipoib_pkey: TK_ULP_IPOIB_PKEY
990                    { __parser_ulp_match_rule_start(); };
991
992
993qos_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
1032port_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
1055port_group_name_start:  TK_NAME {
1056                            RESET_BUFFER;
1057                        }
1058                        ;
1059
1060port_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
1083port_group_use_start:   TK_USE {
1084                            RESET_BUFFER;
1085                        }
1086                        ;
1087
1088port_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
1154port_group_port_name_start: TK_PORT_NAME {
1155                            RESET_BUFFER;
1156                        }
1157                        ;
1158
1159port_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
1179port_group_port_guid_start: TK_PORT_GUID {
1180                            RESET_BUFFER;
1181                        }
1182                        ;
1183
1184port_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
1204port_group_pkey_start:  TK_PKEY {
1205                            RESET_BUFFER;
1206                        }
1207                        ;
1208
1209port_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
1217port_group_partition_start: TK_PARTITION {
1218                            RESET_BUFFER;
1219                        }
1220                        ;
1221
1222port_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
1227port_group_node_type_start: TK_NODE_TYPE {
1228                            RESET_BUFFER;
1229                        }
1230                        ;
1231
1232port_group_node_type_list:  node_type_item
1233                        |   port_group_node_type_list TK_COMMA node_type_item
1234                        ;
1235
1236node_type_item:           node_type_ca
1237                        | node_type_switch
1238                        | node_type_router
1239                        | node_type_all
1240                        | node_type_self
1241                        ;
1242
1243node_type_ca:           TK_NODE_TYPE_CA {
1244                            p_current_port_group->node_types |=
1245                               OSM_QOS_POLICY_NODE_TYPE_CA;
1246                        }
1247                        ;
1248
1249node_type_switch:       TK_NODE_TYPE_SWITCH {
1250                            p_current_port_group->node_types |=
1251                               OSM_QOS_POLICY_NODE_TYPE_SWITCH;
1252                        }
1253                        ;
1254
1255node_type_router:       TK_NODE_TYPE_ROUTER {
1256                            p_current_port_group->node_types |=
1257                               OSM_QOS_POLICY_NODE_TYPE_ROUTER;
1258                        }
1259                        ;
1260
1261node_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
1269node_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
1291vlarb_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
1308vlarb_scope_group_start: TK_GROUP {
1309                            RESET_BUFFER;
1310                        }
1311                        ;
1312
1313vlarb_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
1330vlarb_scope_across_start: TK_ACROSS {
1331                            RESET_BUFFER;
1332                        }
1333                        ;
1334
1335vlarb_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
1353vlarb_scope_vlarb_high_limit_start: TK_VLARB_HIGH_LIMIT {
1354                            RESET_BUFFER;
1355                        }
1356                        ;
1357
1358vlarb_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
1375vlarb_scope_vlarb_high_start: TK_VLARB_HIGH {
1376                            RESET_BUFFER;
1377                        }
1378                        ;
1379
1380vlarb_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
1397vlarb_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
1413sl2vl_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
1430sl2vl_scope_group_start: TK_GROUP {
1431                            RESET_BUFFER;
1432                        }
1433                        ;
1434
1435sl2vl_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
1454sl2vl_scope_across_start: TK_ACROSS {
1455                            RESET_BUFFER;
1456                        }
1457                        ;
1458
1459sl2vl_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
1476sl2vl_scope_across_from_start: TK_ACROSS_FROM {
1477                            RESET_BUFFER;
1478                        }
1479                        ;
1480
1481sl2vl_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
1499sl2vl_scope_across_to_start: TK_ACROSS_TO {
1500                            RESET_BUFFER;
1501                        }
1502                        ;
1503
1504sl2vl_scope_from:       sl2vl_scope_from_start sl2vl_scope_from_list_or_asterisk {
1505                            /* 'from' in 'sl2vl-scope' - any num of instances */
1506                        }
1507                        ;
1508
1509sl2vl_scope_from_start: TK_FROM {
1510                            RESET_BUFFER;
1511                        }
1512                        ;
1513
1514sl2vl_scope_to:         sl2vl_scope_to_start sl2vl_scope_to_list_or_asterisk {
1515                            /* 'to' in 'sl2vl-scope' - any num of instances */
1516                        }
1517                        ;
1518
1519sl2vl_scope_to_start:   TK_TO {
1520                            RESET_BUFFER;
1521                        }
1522                        ;
1523
1524sl2vl_scope_from_list_or_asterisk:  sl2vl_scope_from_asterisk
1525                                  | sl2vl_scope_from_list_of_ranges
1526                                  ;
1527
1528sl2vl_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
1535sl2vl_scope_to_list_or_asterisk:  sl2vl_scope_to_asterisk
1536                                | sl2vl_scope_to_list_of_ranges
1537                                  ;
1538
1539sl2vl_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
1546sl2vl_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
1578sl2vl_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
1611sl2vl_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
1654sl2vl_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
1671qos_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
1694qos_level_name_start:   TK_NAME {
1695                            RESET_BUFFER;
1696                        }
1697                        ;
1698
1699qos_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
1722qos_level_use_start:    TK_USE {
1723                            RESET_BUFFER;
1724                        }
1725                        ;
1726
1727qos_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
1747qos_level_sl_start:     TK_SL {
1748                            RESET_BUFFER;
1749                        }
1750                        ;
1751
1752qos_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
1772qos_level_mtu_limit_start: TK_MTU_LIMIT {
1773                            /* 'mtu-limit' in 'qos-level' - one instance */
1774                            RESET_BUFFER;
1775                        }
1776                        ;
1777
1778qos_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
1798qos_level_rate_limit_start: TK_RATE_LIMIT {
1799                            /* 'rate-limit' in 'qos-level' - one instance */
1800                            RESET_BUFFER;
1801                        }
1802                        ;
1803
1804qos_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
1824qos_level_packet_life_start: TK_PACKET_LIFE {
1825                            /* 'packet-life' in 'qos-level' - one instance */
1826                            RESET_BUFFER;
1827                        }
1828                        ;
1829
1830qos_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
1865qos_level_path_bits_start: TK_PATH_BITS {
1866                            RESET_BUFFER;
1867                        }
1868                        ;
1869
1870qos_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
1903qos_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
1920qos_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
1943qos_match_rule_use_start: TK_USE {
1944                            RESET_BUFFER;
1945                        }
1946                        ;
1947
1948qos_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
1982qos_match_rule_qos_class_start: TK_QOS_CLASS {
1983                            RESET_BUFFER;
1984                        }
1985                        ;
1986
1987qos_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
2004qos_match_rule_source_start: TK_SOURCE {
2005                            RESET_BUFFER;
2006                        }
2007                        ;
2008
2009qos_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
2026qos_match_rule_destination_start: TK_DESTINATION {
2027                            RESET_BUFFER;
2028                        }
2029                        ;
2030
2031qos_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
2054qos_match_rule_qos_level_name_start: TK_QOS_LEVEL_NAME {
2055                            RESET_BUFFER;
2056                        }
2057                        ;
2058
2059qos_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
2092qos_match_rule_service_id_start: TK_SERVICE_ID {
2093                            RESET_BUFFER;
2094                        }
2095                        ;
2096
2097qos_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
2130qos_match_rule_pkey_start: TK_PKEY {
2131                            RESET_BUFFER;
2132                        }
2133                        ;
2134
2135
2136    /*
2137     * Common part
2138     */
2139
2140
2141single_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
2148single_string_elems:  single_string_element
2149                    | single_string_elems single_string_element
2150                    ;
2151
2152single_string_element: TK_TEXT {
2153                        strcat(tmp_parser_struct.str,$1);
2154                        free($1);
2155                    }
2156                    ;
2157
2158
2159string_list:        single_string
2160                    | string_list TK_COMMA single_string
2161                    ;
2162
2163
2164
2165single_number:      number
2166                    ;
2167
2168num_list:             number
2169                    | num_list TK_COMMA number
2170                    ;
2171
2172number:             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
2180num_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
2194number_from_pair_1:   TK_NUMBER {
2195                        __parser_str2uint64(&tmp_parser_struct.num_pair[0],$1);
2196                        free($1);
2197                    }
2198                    ;
2199
2200number_from_pair_2:   TK_NUMBER {
2201                        __parser_str2uint64(&tmp_parser_struct.num_pair[1],$1);
2202                        free($1);
2203                    }
2204                    ;
2205
2206list_of_ranges:     num_list_with_dash
2207                    ;
2208
2209num_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
2247single_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
2254number_from_range_1:  TK_NUMBER {
2255                        __parser_str2uint64(&tmp_parser_struct.num_pair[0],$1);
2256                        free($1);
2257                    }
2258                    ;
2259
2260number_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
2271int 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
2365int yywrap()
2366{
2367    return(1);
2368}
2369
2370/***************************************************
2371 ***************************************************/
2372
2373static 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
2395static 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
2416static void __parser_str2uint64(uint64_t * p_val, char * str)
2417{
2418   *p_val = strtoull(str, NULL, 0);
2419}
2420
2421/***************************************************
2422 ***************************************************/
2423
2424static void __parser_port_group_start()
2425{
2426    p_current_port_group = osm_qos_policy_port_group_create();
2427}
2428
2429/***************************************************
2430 ***************************************************/
2431
2432static 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
2449static void __parser_vlarb_scope_start()
2450{
2451    p_current_vlarb_scope = osm_qos_policy_vlarb_scope_create();
2452}
2453
2454/***************************************************
2455 ***************************************************/
2456
2457static 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
2475static void __parser_sl2vl_scope_start()
2476{
2477    p_current_sl2vl_scope = osm_qos_policy_sl2vl_scope_create();
2478}
2479
2480/***************************************************
2481 ***************************************************/
2482
2483static 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
2507static void __parser_qos_level_start()
2508{
2509    p_current_qos_level = osm_qos_policy_qos_level_create();
2510}
2511
2512/***************************************************
2513 ***************************************************/
2514
2515static 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
2537static void __parser_match_rule_start()
2538{
2539    p_current_qos_match_rule = osm_qos_policy_match_rule_create();
2540}
2541
2542/***************************************************
2543 ***************************************************/
2544
2545static 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
2562static void __parser_ulp_match_rule_start()
2563{
2564    p_current_qos_match_rule = osm_qos_policy_match_rule_create();
2565}
2566
2567/***************************************************
2568 ***************************************************/
2569
2570static 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
2582static 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 */
2602static 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
2613static 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
2627static 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
2650static 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
2662static 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
2671static 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
2691static 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
2715static 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
2777static 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
2807static 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
2840static 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
2878static 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
2896static 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
2923static 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
2955static 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
2984static 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
3005static 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 ***************************************************/
3064