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