openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

hashing.c (104379B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        hashing.c
      8  * Purpose:     GH2-Hash calcualtions for trunk and ECMP packets.
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <soc/drv.h>
     14 #include <soc/hash.h>
     15 #include <bcm/switch.h>
     16 #include <bcm/error.h>
     17 
     18 #include <bcm_int/esw_dispatch.h>
     19 #include <bcm_int/esw/firebolt.h>
     20 #include <bcm_int/esw/port.h>
     21 #include <bcm_int/esw/stack.h>
     22 #include <bcm_int/esw/switch.h>
     23 
     24 typedef struct bcm_rtag7_base_hash_s {
     25     uint32 rtag7_hash16_value_a_0;      /* hash a0 result */
     26     uint32 rtag7_hash16_value_a_1;      /* hash a1 result */
     27     uint32 rtag7_hash16_value_b_0;      /* hash b0 result */
     28     uint32 rtag7_hash16_value_b_1;      /* hash b1 result */
     29     uint32 rtag7_macro_flow_id;         /* hash micro flow result */
     30     uint32 rtag7_port_lbn;              /* port LBN value from the port table*/
     31     uint32 rtag7_lbid_hash;             /* LBID hash calculation*/
     32     bcm_port_t dev_src_port;            /* Local source port */
     33     bcm_port_t src_port;                /* System source port */
     34     bcm_module_t src_modid;             /* System source modid */
     35     uint8 is_nonuc;                     /* Non-unicast */
     36     uint8 hash_a_valid;                 /* Hash A result use valid input */
     37     uint8 hash_b_valid;                 /* Hash B result use valid input */
     38     uint8 lbid_hash_valid;              /* LBID Hash value is valid */
     39 } bcm_rtag7_base_hash_t;
     40 
     41 #define   ETHERTYPE_IPV6 0x86dd /* ipv6 ethertype */
     42 #define   ETHERTYPE_IPV4 0x0800 /* ipv4 ethertype */
     43 #define   ETHERTYPE_MIN  0x0600 /* minimum ethertype for hashing */
     44 
     45 #define   IP_PROT_TCP 0x6  /* TCP protocol number */
     46 #define   IP_PROT_UDP 0x11 /* TCP protocol number */
     47 
     48 #define RTAG7_L2_ONLY         0x0
     49 #define RTAG7_UNKNOWN_HIGIG   0x1
     50 #define RTAG7_MPLS            0x2
     51 #define RTAG7_MIM             0x3
     52 #define RTAG7_IPV4            0x4
     53 #define RTAG7_IPV6            0x5
     54 #define RTAG7_FCOE            0x6
     55 #define RTAG7_TRILL           0x7
     56 
     57 /* Valid RTAG7 hash value mask for unicast and non-unicast trunk resolution */
     58 #define GH2_RTAG7_HASH_TRUNK_UC_MASK  0xff
     59 #define GH2_RTAG7_HASH_TRUNK_NUC_MASK 0xf
     60 
     61 /* fields from TRUNK_GROUPm */
     62 STATIC soc_field_t _gh2_portf[8] = {
     63     PORT0f, PORT1f, PORT2f, PORT3f,
     64     PORT4f, PORT5f, PORT6f, PORT7f
     65 };
     66 
     67 STATIC soc_field_t _gh2_modulef[8] = {
     68     MODULE0f, MODULE1f, MODULE2f, MODULE3f,
     69     MODULE4f, MODULE5f, MODULE6f, MODULE7f
     70 };
     71 
     72 STATIC soc_field_t _gh2_hg_portf[8] = {
     73     HIGIG_TRUNK_PORT0f, HIGIG_TRUNK_PORT1f,
     74     HIGIG_TRUNK_PORT2f, HIGIG_TRUNK_PORT3f,
     75     HIGIG_TRUNK_PORT4f, HIGIG_TRUNK_PORT5f,
     76     HIGIG_TRUNK_PORT6f, HIGIG_TRUNK_PORT7f
     77 };
     78 
     79 #define HASH_VALUE_64_COMPUTE(subfield,offset,width) do { \
     80         uint64 sf; \
     81         COMPILER_64_ZERO(sf); \
     82         COMPILER_64_ADD_64(sf, subfield); \
     83         COMPILER_64_SHR(subfield, offset); \
     84         COMPILER_64_SHL(sf, (width - offset)); \
     85         COMPILER_64_OR(subfield, sf); \
     86     } while(0)
     87 
     88 #define HASH_VALUE_32_COMPUTE(hash_value_32, hash_value_64) do { \
     89         COMPILER_64_TO_32_LO(hash_value_32, hash_value_64); \
     90     } while(0)
     91 
     92 
     93 /*
     94  * Function:
     95  *          main_gh2_do_rtag7_hashing
     96  * Description:
     97  *          Read hash control register values and
     98  *          set hash_res' fields
     99  * Parameters:
    100  *          unit - StrataSwitch PCI device unit number (driver internal).
    101  *          pkt_info - ptr to data that has packet information
    102  *          hash_res - internal data where hashing informaiton is stored 
    103  * Returns:
    104  *      BCM_E_xxxx
    105  */
    106 STATIC int
    107 main_gh2_do_rtag7_hashing(int unit,
    108                        bcm_switch_pkt_info_t *pkt_info,
    109                        bcm_rtag7_base_hash_t *hash_res)
    110 {
    111     /* Regular var declaration */
    112     uint32      hash_src_port;
    113     uint32      hash_src_modid;
    114     uint32      rtag7_a_sel;
    115     bcm_ip_t            sip_a;       /* Source IPv4 address. */
    116     bcm_ip_t            dip_a;       /* Destination IPv4 address. */
    117     uint32      rtag7_b_sel;
    118     bcm_ip_t            sip_b;       /* Source IPv4 address. */
    119     bcm_ip_t            dip_b;       /* Destination IPv4 address. */
    120     uint32      hash_field_bmap_a;   /* block A chosen bitmap*/
    121     uint32      hash_field_bmap_b;   /* block B chosen bitmap*/
    122 
    123     uint32 hash_word[7];
    124     uint32 hash[13];
    125     int    elem, elem_bit;
    126     uint32 hash_element_valid_bits;
    127     /* int    ip6_addrs = FALSE, ip4_addrs = FALSE; */
    128     int    sip_valid = FALSE, dip_valid = FALSE;
    129     uint32 macro_flow_id;
    130 
    131     uint32 hash_crc16_bisync;
    132     uint32 hash_crc16_ccitt;
    133     uint32 hash_crc32;
    134     uint32 hash_xor16;
    135     uint32 hash_xor8;
    136     uint32 hash_xor4;
    137     uint32 hash_xor2;
    138     uint32 hash_xor1;
    139     uint32 xor32;
    140 
    141     /* register var declaration */
    142     uint8 rtag7_disable_hash_ipv4_a;
    143     uint8 rtag7_disable_hash_ipv6_a;  
    144     uint8 rtag7_disable_hash_ipv4_b;
    145     uint8 rtag7_disable_hash_ipv6_b;
    146     uint8 rtag7_ipv6_addr_use_lsb_a;
    147     uint8 rtag7_ipv6_addr_use_lsb_b;    
    148     uint8 rtag7_pre_processing_enable_a;
    149     uint8 rtag7_pre_processing_enable_b;    
    150     uint8 rtag7_en_flow_label_ipv6_a;
    151     uint8 rtag7_en_flow_label_ipv6_b;   
    152     uint8 rtag7_en_bin_12_overlay_a;
    153     uint8 rtag7_en_bin_12_overlay_b;    
    154     uint32 rtag7_hash_seed_a;
    155     uint32 rtag7_hash_seed_b;   
    156     uint32 rtag7_hash_a0_function_select;
    157     uint32 rtag7_hash_a1_function_select;   
    158     uint32 rtag7_hash_b0_function_select;
    159     uint32 rtag7_hash_b1_function_select;   
    160     uint32 rtag7_macro_flow_hash_function_select;
    161     uint8 rtag7_macro_flow_hash_byte_sel;
    162 
    163     uint64 rtag7_hash_control;
    164     uint32 rtag7_hash_control_2, rtag7_hash_control_3;
    165     uint32 rtag7_hash_seed_a_reg, rtag7_hash_seed_b_reg;
    166     soc_reg_t sc_reg;
    167     soc_field_t sc_field;
    168     uint32 sc_val;
    169     int symmetric_hash_control_mask = 0;
    170     int symmetric_hash_need_swap_ip6 = 0;
    171     int symmetric_hash_need_swap_ip4 = 0;
    172 
    173     SOC_IF_ERROR_RETURN
    174         (READ_RTAG7_HASH_CONTROLr(unit, &rtag7_hash_control));
    175     SOC_IF_ERROR_RETURN
    176         (READ_RTAG7_HASH_CONTROL_2r(unit, &rtag7_hash_control_2));
    177 
    178     SOC_IF_ERROR_RETURN
    179         (READ_RTAG7_HASH_CONTROL_3r(unit, &rtag7_hash_control_3));
    180     SOC_IF_ERROR_RETURN
    181         (READ_RTAG7_HASH_SEED_Ar(unit, &rtag7_hash_seed_a_reg));
    182     SOC_IF_ERROR_RETURN
    183         (READ_RTAG7_HASH_SEED_Br(unit, &rtag7_hash_seed_b_reg));
    184 
    185     /* RTAG7 hash registers */
    186     rtag7_disable_hash_ipv4_a =
    187         soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control,
    188                           DISABLE_HASH_IPV4_Af);
    189     rtag7_disable_hash_ipv6_a =
    190         soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control,
    191                           DISABLE_HASH_IPV6_Af);
    192     rtag7_disable_hash_ipv4_b =
    193         soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control,
    194                           DISABLE_HASH_IPV4_Bf);
    195     rtag7_disable_hash_ipv6_b =
    196         soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control,
    197                           DISABLE_HASH_IPV6_Bf);
    198     rtag7_ipv6_addr_use_lsb_a =
    199         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, rtag7_hash_control_2,
    200                           IPV6_COLLAPSED_ADDR_SELECT_Af);
    201     rtag7_ipv6_addr_use_lsb_b =
    202         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, rtag7_hash_control_2,
    203                           IPV6_COLLAPSED_ADDR_SELECT_Bf);
    204 
    205     rtag7_pre_processing_enable_a =
    206         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3,
    207                           HASH_PRE_PROCESSING_ENABLE_Af);
    208     rtag7_pre_processing_enable_b =
    209         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3,
    210                           HASH_PRE_PROCESSING_ENABLE_Bf);
    211     rtag7_hash_a0_function_select =
    212         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3,
    213                           HASH_A0_FUNCTION_SELECTf);
    214     rtag7_hash_a1_function_select =
    215         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3,
    216                           HASH_A1_FUNCTION_SELECTf);
    217     rtag7_hash_b0_function_select =
    218         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3,
    219                           HASH_B0_FUNCTION_SELECTf);
    220     rtag7_hash_b1_function_select =
    221         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3,
    222                           HASH_B1_FUNCTION_SELECTf);
    223     
    224     if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROLr,
    225                             ENABLE_FLOW_LABEL_IPV6_Af)) {
    226         rtag7_en_flow_label_ipv6_a =
    227             soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr,
    228                                   rtag7_hash_control,
    229                                   ENABLE_FLOW_LABEL_IPV6_Af);
    230     } else {
    231         rtag7_en_flow_label_ipv6_a = 0; /* A0 bincomp value */
    232     }
    233     if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROLr,
    234                             ENABLE_FLOW_LABEL_IPV6_Bf)) {
    235         rtag7_en_flow_label_ipv6_b =
    236             soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr,
    237                                   rtag7_hash_control,
    238                                   ENABLE_FLOW_LABEL_IPV6_Bf);
    239     } else {
    240         rtag7_en_flow_label_ipv6_b = 0; /* A0 bincomp value */
    241     }
    242     rtag7_en_bin_12_overlay_a =
    243         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, rtag7_hash_control_2,
    244                           ENABLE_BIN_12_OVERLAY_Af);
    245     rtag7_en_bin_12_overlay_b =
    246         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, rtag7_hash_control_2,
    247                           ENABLE_BIN_12_OVERLAY_Bf);
    248     if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r,
    249                             MACRO_FLOW_HASH_FUNC_SELf)) {
    250         rtag7_macro_flow_hash_function_select =
    251             soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r,
    252                               rtag7_hash_control_2,
    253                               MACRO_FLOW_HASH_FUNC_SELf);
    254     } else {
    255         rtag7_macro_flow_hash_function_select = 0; /* A0 bincomp value */
    256     }
    257     if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r,
    258                             MACRO_FLOW_HASH_BYTE_SELf)) {
    259         rtag7_macro_flow_hash_byte_sel =
    260             soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r,
    261                               rtag7_hash_control_2,
    262                               MACRO_FLOW_HASH_BYTE_SELf);
    263     } else {
    264         rtag7_macro_flow_hash_byte_sel = 0; /* A0 bincomp value */
    265     }
    266 
    267     rtag7_hash_seed_a =
    268         soc_reg_field_get(unit, RTAG7_HASH_SEED_Ar, rtag7_hash_seed_a_reg,
    269                           HASH_SEED_Af);
    270     rtag7_hash_seed_b =
    271         soc_reg_field_get(unit, RTAG7_HASH_SEED_Br, rtag7_hash_seed_b_reg,
    272                           HASH_SEED_Bf);
    273 
    274     if (BCM_SUCCESS(bcm_esw_switch_control_get(unit,
    275             bcmSwitchSymmetricHashControl, &symmetric_hash_control_mask))) {
    276         if (symmetric_hash_control_mask & 
    277             (BCM_SYMMETRIC_HASH_0_IP6_ENABLE | BCM_SYMMETRIC_HASH_1_IP6_ENABLE)) {
    278             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6) && 
    279                 _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6) &&
    280                 (sal_memcmp(pkt_info->sip6, pkt_info->dip6, BCM_IP6_ADDRLEN) < 0)) {
    281                 symmetric_hash_need_swap_ip6 = 1;
    282             }
    283         }
    284         if (symmetric_hash_control_mask & 
    285             (BCM_SYMMETRIC_HASH_0_IP4_ENABLE | BCM_SYMMETRIC_HASH_1_IP4_ENABLE)) {
    286             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IP) && 
    287                 _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IP) &&
    288                 (pkt_info->sip < pkt_info->dip)) {
    289                 symmetric_hash_need_swap_ip4 = 1;
    290             }
    291         }
    292     }
    293 
    294     /* 
    295      * RTAG7 tables:
    296      * - The first step is to choose the paket type and to fold the ipv6
    297      * addresses in case of IPv6 packet
    298      */
    299 
    300     /* option A ip folding for rtag 7 */
    301     if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) &&
    302          (pkt_info->ethertype == ETHERTYPE_IPV6)) &&
    303                (rtag7_disable_hash_ipv6_a == 0)) {
    304         /* ip6_addrs = TRUE; */
    305         rtag7_a_sel = RTAG7_IPV6;
    306         
    307         /*
    308          * This section will fold the Ipv6 address to single 32 bit address
    309          * by using of of the methose LSB or xor
    310          */
    311         if (rtag7_ipv6_addr_use_lsb_a) {
    312             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) {
    313                 sip_a = (pkt_info->sip6[12] << 24) |
    314                     (pkt_info->sip6[13] << 16) |
    315                     (pkt_info->sip6[14] << 8) |
    316                     (pkt_info->sip6[15]);
    317                 sip_valid = TRUE;
    318             } else {
    319                 sip_a = 0;
    320             }
    321             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) {
    322                 dip_a = (pkt_info->dip6[12] << 24) |
    323                     (pkt_info->dip6[13] << 16) |
    324                     (pkt_info->dip6[14] << 8) |
    325                     (pkt_info->dip6[15]);
    326                 dip_valid = TRUE;
    327             } else {
    328                 dip_a = 0;
    329             }
    330         } else {   
    331             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) {
    332                 sip_a =
    333                     ((pkt_info->sip6[12] << 24) |
    334                      (pkt_info->sip6[13] << 16) |
    335                      (pkt_info->sip6[14] << 8) |
    336                      (pkt_info->sip6[15])) ^
    337                     ((pkt_info->sip6[8] << 24) |
    338                      (pkt_info->sip6[9] << 16) |
    339                      (pkt_info->sip6[10] << 8) |
    340                      (pkt_info->sip6[11])) ^
    341                     ((pkt_info->sip6[4] << 24) |
    342                      (pkt_info->sip6[5] << 16) |
    343                      (pkt_info->sip6[6] << 8) |
    344                      (pkt_info->sip6[7])) ^
    345                     ((pkt_info->sip6[0] << 24) |
    346                      (pkt_info->sip6[1] << 16) |
    347                      (pkt_info->sip6[2] << 8) |
    348                      (pkt_info->sip6[3]));
    349                 sip_valid = TRUE;
    350             } else {
    351                 sip_a = 0;
    352             }
    353 
    354             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) {
    355                 dip_a =
    356                     ((pkt_info->dip6[12] << 24) |
    357                      (pkt_info->dip6[13] << 16) |
    358                      (pkt_info->dip6[14] << 8) |
    359                      (pkt_info->dip6[15])) ^
    360                     ((pkt_info->dip6[8] << 24) |
    361                      (pkt_info->dip6[9] << 16) |
    362                      (pkt_info->dip6[10] << 8) |
    363                      (pkt_info->dip6[11])) ^
    364                     ((pkt_info->dip6[4] << 24) |
    365                      (pkt_info->dip6[5] << 16) |
    366                      (pkt_info->dip6[6] << 8) |
    367                      (pkt_info->dip6[7])) ^
    368                     ((pkt_info->dip6[0] << 24) |
    369                      (pkt_info->dip6[1] << 16) |
    370                      (pkt_info->dip6[2] << 8) |
    371                      (pkt_info->dip6[3]));
    372                 dip_valid = TRUE;
    373             } else {
    374                 dip_a = 0;
    375             }
    376         }
    377     } else if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) &&
    378                 (pkt_info->ethertype == ETHERTYPE_IPV4)) && 
    379                (rtag7_disable_hash_ipv4_a == 0)) {
    380         /* ip4_addrs = TRUE; */
    381         rtag7_a_sel = RTAG7_IPV4;
    382 
    383         /* only one IPv4 hdr */
    384         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IP)) {
    385             sip_a = pkt_info->sip;
    386             sip_valid = TRUE;
    387         } else {
    388             sip_a = 0;
    389         }
    390         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IP)) {
    391             dip_a = pkt_info->dip;
    392             dip_valid = TRUE;
    393         } else {
    394             dip_a = 0;
    395         }
    396     } else {
    397         rtag7_a_sel = RTAG7_L2_ONLY;
    398         sip_a = dip_a = 0;
    399     }
    400     /* End of option A ip folding for rtag 7 */
    401 
    402     /* option B ip folding for rtag 7 */
    403     if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) &&
    404          (pkt_info->ethertype == ETHERTYPE_IPV6)) &&
    405                (rtag7_disable_hash_ipv6_b == 0)) {
    406         /* ip6_addrs = TRUE; */
    407         rtag7_b_sel = RTAG7_IPV6;
    408         
    409         /*
    410          * This section will fold the Ipv6 address to single 32 bit address
    411          * by using of of the methose LSB or xor
    412          */
    413         if (rtag7_ipv6_addr_use_lsb_b) {
    414             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) {
    415                 sip_b = (pkt_info->sip6[12] << 24) |
    416                     (pkt_info->sip6[13] << 16) |
    417                     (pkt_info->sip6[14] << 8) |
    418                     (pkt_info->sip6[15]);
    419                 sip_valid = TRUE;
    420             } else {
    421                 sip_b = 0;
    422             }
    423             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) {
    424                 dip_b = (pkt_info->dip6[12] << 24) |
    425                     (pkt_info->dip6[13] << 16) |
    426                     (pkt_info->dip6[14] << 8) |
    427                     (pkt_info->dip6[15]);
    428                 dip_valid = TRUE;
    429             } else {
    430                 dip_b = 0;
    431             }
    432         } else {   
    433             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) {
    434                 sip_b =
    435                     ((pkt_info->sip6[12] << 24) |
    436                      (pkt_info->sip6[13] << 16) |
    437                      (pkt_info->sip6[14] << 8) |
    438                      (pkt_info->sip6[15])) ^
    439                     ((pkt_info->sip6[8] << 24) |
    440                      (pkt_info->sip6[9] << 16) |
    441                      (pkt_info->sip6[10] << 8) |
    442                      (pkt_info->sip6[11])) ^
    443                     ((pkt_info->sip6[4] << 24) |
    444                      (pkt_info->sip6[5] << 16) |
    445                      (pkt_info->sip6[6] << 8) |
    446                      (pkt_info->sip6[7])) ^
    447                     ((pkt_info->sip6[0] << 24) |
    448                      (pkt_info->sip6[1] << 16) |
    449                      (pkt_info->sip6[2] << 8) |
    450                      (pkt_info->sip6[3]));
    451                 sip_valid = TRUE;
    452             } else {
    453                 sip_b = 0;
    454             }
    455 
    456             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) {
    457                 dip_b =
    458                     ((pkt_info->dip6[12] << 24) |
    459                      (pkt_info->dip6[13] << 16) |
    460                      (pkt_info->dip6[14] << 8) |
    461                      (pkt_info->dip6[15])) ^
    462                     ((pkt_info->dip6[8] << 24) |
    463                      (pkt_info->dip6[9] << 16) |
    464                      (pkt_info->dip6[10] << 8) |
    465                      (pkt_info->dip6[11])) ^
    466                     ((pkt_info->dip6[4] << 24) |
    467                      (pkt_info->dip6[5] << 16) |
    468                      (pkt_info->dip6[6] << 8) |
    469                      (pkt_info->dip6[7])) ^
    470                     ((pkt_info->dip6[0] << 24) |
    471                      (pkt_info->dip6[1] << 16) |
    472                      (pkt_info->dip6[2] << 8) |
    473                      (pkt_info->dip6[3]));
    474                 dip_valid = TRUE;
    475             } else {
    476                 dip_b = 0;
    477             }
    478         }      
    479     } else if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) &&
    480                 (pkt_info->ethertype == ETHERTYPE_IPV4)) && 
    481                (rtag7_disable_hash_ipv4_b == 0)) {
    482         /* ip4_addrs = TRUE; */
    483         rtag7_b_sel = RTAG7_IPV4;
    484 
    485         /* only one IPv4 hdr */
    486         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IP)) {
    487             sip_b = pkt_info->sip;
    488             sip_valid = TRUE;
    489         } else {
    490             sip_b = 0;
    491         }
    492         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IP)) {
    493             dip_b = pkt_info->dip;
    494             dip_valid = TRUE;
    495         } else {
    496             dip_b = 0;
    497         }
    498     } else {    
    499         rtag7_b_sel = RTAG7_L2_ONLY;
    500         sip_b = dip_b = 0;
    501     }
    502     /* End of option B ip folding for rtag 7 */
    503 
    504     /*
    505      * =============
    506      * RTAG7 HASHING 
    507      * =============
    508      */
    509 
    510     /* The inputs to the RTAG7 hash function were reduced in the begining
    511      * of this function.  
    512      * This logic takes the hash inputs and computes both A and B RTAG7
    513      * hash values.
    514      */
    515 
    516     /* Change source modid/port to PORT32 space for hashing */
    517     hash_src_port  = hash_res->src_port;
    518     hash_src_modid = hash_res->src_modid;
    519 
    520     /* Only if the packet was sourced by this chip, make sure to use
    521      * PORT32 space modid and port if dual modid is enabled
    522      * Need to do this because of front panel ports.
    523      *
    524      * Already handled by API gport resolve */
    525 
    526     /* initialize the variables */   
    527     sal_memset(hash,0x0,(sizeof(uint32))*13);
    528     sal_memset(hash_word,0x0,(sizeof(uint32))*7);
    529     
    530     hash_crc16_bisync = 0;
    531     hash_crc16_ccitt = 0;
    532     hash_crc32      = 0;
    533     hash_xor16      = 0;
    534     hash_xor8       = 0;
    535     hash_xor4       = 0;
    536     hash_xor2       = 0;
    537     hash_xor1       = 0;
    538     xor32           = 0;
    539 
    540     hash[12] = 0;   
    541     hash[3] = hash_src_port;
    542     hash[2] = hash_src_modid & 0xff;
    543     hash[1] = 0;
    544     hash[0] = 0;
    545 
    546     hash_element_valid_bits = 0x1fff; /* Init to valid fields above */
    547 
    548     /* option A hash calculation for rtag 7 */
    549     if ((rtag7_a_sel == RTAG7_IPV6) || (rtag7_a_sel == RTAG7_IPV4)) {
    550         if (sip_valid) {
    551             hash[11] = (sip_a >> 16) & 0xffff;
    552             hash[10] =  sip_a & 0xffff;
    553         } else {
    554             hash_element_valid_bits &= ~0xc00;
    555         }
    556         if (dip_valid) {
    557             hash[9]  = (dip_a >> 16) & 0xffff;
    558             hash[8]  =  dip_a & 0xffff;
    559         } else {
    560             hash_element_valid_bits &= ~0x300;
    561         }
    562 
    563         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) {
    564             hash[7]  = pkt_info->vid & 0xfff;
    565         } else {
    566             hash_element_valid_bits &= ~0x80;
    567         }
    568         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT)) {
    569             hash[6]  = pkt_info->src_l4_port;
    570         } else {
    571             hash_element_valid_bits &= ~0x40;
    572         }
    573         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT)) {
    574             hash[5]  = pkt_info->dst_l4_port;
    575         } else {
    576             hash_element_valid_bits &= ~0x20;
    577         }
    578         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL)) {
    579             hash[4]  = pkt_info->protocol;
    580         } else {
    581             hash_element_valid_bits &= ~0x10;
    582         }
    583 
    584         /* Symmetric hash swap src/dst ipaddr/l4_port for option A */
    585         if (((rtag7_a_sel == RTAG7_IPV6) && 
    586             symmetric_hash_need_swap_ip6 && 
    587             (symmetric_hash_control_mask & BCM_SYMMETRIC_HASH_0_IP6_ENABLE)) 
    588             ||
    589             ((rtag7_a_sel == RTAG7_IPV4) && 
    590             symmetric_hash_need_swap_ip4 && 
    591             (symmetric_hash_control_mask & BCM_SYMMETRIC_HASH_0_IP4_ENABLE))) {
    592 
    593             uint32 temp;
    594             temp = hash[11]; hash[11] = hash[9]; hash[9] = temp;
    595             temp = hash[10]; hash[10] = hash[8]; hash[8] = temp;
    596             temp = hash[6]; hash[6] = hash[5]; hash[5] = temp;
    597             LOG_VERBOSE(BSL_LS_BCM_COMMON,
    598                         (BSL_META_U(unit,
    599                                     "Symmetric hash swap for hash A calculation.\n")));
    600         }
    601 
    602         if ((rtag7_a_sel == RTAG7_IPV6) && rtag7_en_flow_label_ipv6_a) {
    603             LOG_VERBOSE(BSL_LS_BCM_COMMON,
    604                         (BSL_META_U(unit,
    605                                     "Hash calculation: The system is set to use ipv6 flow label" 
    606                                      " and the code can't get this info\n")));
    607         }
    608 
    609         if (rtag7_a_sel == RTAG7_IPV4) {  /* Use IPv4 BITMAPs */
    610             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) &&
    611                 ((pkt_info->protocol == IP_PROT_TCP) ||
    612                 (pkt_info->protocol == IP_PROT_UDP))) { 
    613                 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) &&
    614                     _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) &&
    615                     (pkt_info->src_l4_port == pkt_info->dst_l4_port)) {
    616                     sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_1r;
    617                     sc_field = IPV4_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Af;
    618                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
    619                                 (BSL_META_U(unit,
    620                                             "Hash calculation: Bitmap is block A IPv4 TCP=UDP\n")));
    621                 } else {
    622                     sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_2r;
    623                     sc_field = IPV4_TCP_UDP_FIELD_BITMAP_Af;
    624                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
    625                                 (BSL_META_U(unit,
    626                                             "Hash calculation: Bitmap is block A IPv4 L4 tcp/udp\n")));
    627                 }
    628             } else {
    629                 sc_reg = RTAG7_HASH_FIELD_BMAP_1r;
    630                 sc_field = IPV4_FIELD_BITMAP_Af;
    631                 LOG_VERBOSE(BSL_LS_BCM_COMMON,
    632                             (BSL_META_U(unit,
    633                                         "Hash calculation: Bitmap is block A IPv4 \n")));
    634             }
    635 
    636         } else { /* Use IPv6 BITMAPs */
    637             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) &&
    638                 ((pkt_info->protocol == IP_PROT_TCP) ||
    639                 (pkt_info->protocol == IP_PROT_UDP))) { 
    640                 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) &&
    641                     _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) &&
    642                     (pkt_info->src_l4_port == pkt_info->dst_l4_port)) {
    643                     sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_1r;
    644                     sc_field = IPV6_TCP_UDP_SCTP_SRC_EQ_DST_FIELD_BITMAP_Af;
    645                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
    646                                 (BSL_META_U(unit,
    647                                             "Hash calculation: Bitmap is block A IPv6 TCP=UDP\n")));
    648                 } else {
    649                     sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_2r;
    650                     sc_field = IPV6_TCP_UDP_SCTP_FIELD_BITMAP_Af;
    651                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
    652                                 (BSL_META_U(unit,
    653                                             "Hash calculation: Bitmap is block A IPv6 L4 tcp/udp\n")));
    654                 }
    655             } else {
    656                 sc_reg = RTAG7_HASH_FIELD_BMAP_2r;
    657                 sc_field = IPV6_FIELD_BITMAP_Af;
    658                 LOG_VERBOSE(BSL_LS_BCM_COMMON,
    659                             (BSL_META_U(unit,
    660                                         "Hash calculation: Bitmap is block A IPv6 \n")));
    661             }
    662         }
    663         
    664     } else { /* Catch-all for RTAG7_L2_ONLY */
    665 
    666         /* L2 only hash key */
    667         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_MAC)) {
    668             hash[11] = (pkt_info->src_mac[0] << 8) | pkt_info->src_mac[1];
    669             hash[10] = (pkt_info->src_mac[2] << 8) | pkt_info->src_mac[3];
    670             hash[9] = (pkt_info->src_mac[4] << 8) | pkt_info->src_mac[5];
    671         } else {
    672             hash_element_valid_bits &= ~0xe00;
    673         }
    674         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_MAC)) {
    675             hash[8] = (pkt_info->dst_mac[0] << 8) | pkt_info->dst_mac[1];
    676             hash[7] = (pkt_info->dst_mac[2] << 8) | pkt_info->dst_mac[3];
    677             hash[6] = (pkt_info->dst_mac[4] << 8) | pkt_info->dst_mac[5];
    678         } else {
    679             hash_element_valid_bits &= ~0x1c0;
    680         }
    681 
    682         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE)) {
    683             hash[5] = (pkt_info->ethertype >= ETHERTYPE_MIN) ?
    684                 pkt_info->ethertype : 0;
    685         } else {
    686             hash_element_valid_bits &= ~0x20;
    687         }
    688 
    689         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) {
    690             hash[4] = pkt_info->vid & 0xfff;
    691         } else {
    692             hash_element_valid_bits &= ~0x10;
    693         }
    694 
    695         sc_reg = RTAG7_HASH_FIELD_BMAP_3r;
    696         sc_field = L2_FIELD_BITMAP_Af;
    697         LOG_VERBOSE(BSL_LS_BCM_COMMON,
    698                     (BSL_META_U(unit,
    699                                 "Hash calculation: Bitmap is block A L2\n")));
    700     }
    701 
    702     BCM_IF_ERROR_RETURN
    703         (soc_reg32_get(unit, sc_reg, REG_PORT_ANY, 0, &sc_val));
    704     hash_field_bmap_a = soc_reg_field_get(unit, sc_reg, sc_val, sc_field);
    705 
    706     /* Pre-Processing */
    707     if (rtag7_pre_processing_enable_a) {
    708         hash[12] = hash[12] ^ (hash[12] >> 3) ^ (hash[12] << 2);
    709         hash[11] = hash[11] ^ (hash[11] >> 3) ^ (hash[11] << 2);
    710         hash[10] = hash[10] ^ (hash[10] >> 3) ^ (hash[10] << 2);
    711         hash[9] = hash[9] ^ (hash[9] >> 3) ^ (hash[9] << 2);
    712         hash[8] = hash[8] ^ (hash[8] >> 3) ^ (hash[8] << 2);
    713         hash[7] = hash[7] ^ (hash[7] >> 3) ^ (hash[7] << 2);
    714         hash[6] = hash[6] ^ (hash[6] >> 3) ^ (hash[6] << 2);
    715         hash[5] = hash[5] ^ (hash[5] >> 3) ^ (hash[5] << 2);
    716         hash[4] = hash[4] ^ (hash[4] >> 3) ^ (hash[4] << 2);
    717         hash[3] = hash[3] ^ (hash[3] >> 3) ^ (hash[3] << 2);
    718         hash[2] = hash[2] ^ (hash[2] >> 3) ^ (hash[2] << 2);
    719         hash[1] = hash[1] ^ (hash[1] >> 3) ^ (hash[1] << 2);
    720         hash[0] = hash[0] ^ (hash[0] >> 3) ^ (hash[0] << 2);
    721     }
    722 
    723     if (((hash_field_bmap_a >> 12) & 0x1) == 0) {
    724         hash[12] = 0;
    725     }    
    726 
    727     if (rtag7_en_bin_12_overlay_a) {
    728         hash_word[6] = (rtag7_hash_seed_a & 0xffff0000) | (hash[12] & 0xffff);
    729     } else {
    730         hash_word[6] = rtag7_hash_seed_a;
    731     }    
    732 
    733     hash_res->hash_a_valid = TRUE;
    734     for (elem = 11; elem >= 0; elem--) {
    735         elem_bit = 1 << elem;
    736         if (0 != (hash_field_bmap_a & elem_bit)) {
    737             if (0 != (hash_element_valid_bits & elem_bit)) {
    738                 hash_word[elem/2] |=
    739                     ((hash[elem] & 0xffff) << (16 * (elem % 2)));
    740             } else {
    741                 hash_res->hash_a_valid = FALSE;
    742                 break;
    743             }
    744         }
    745     }
    746 
    747     /*Calculation*/
    748     xor32 = hash_word[6] ^ hash_word[5] ^ hash_word[4] ^ hash_word[3] ^
    749         hash_word[2] ^ hash_word[1] ^ hash_word[0];
    750 
    751     hash_xor16 = (xor32 & 0xffff) ^ ((xor32 >> 16) & 0xffff);  
    752     hash_xor8 = (hash_xor16 & 0xff) ^ ((hash_xor16 >> 8) & 0xff);
    753     hash_xor4 = (hash_xor8 & 0xf) ^ ((hash_xor8 >> 4) & 0xf);
    754     hash_xor2 = (hash_xor4 & 0x3) ^ ((hash_xor4 >> 2) & 0x3);
    755     hash_xor1 = (hash_xor2 & 0x1) ^ ((hash_xor2 >> 1) & 0x1);
    756 
    757     hash_crc16_bisync = _shr_crc16_draco_array(hash_word, 28);
    758     hash_crc16_ccitt =  _shr_crc16_ccitt_array(hash_word, 28);
    759     hash_crc32 =        _shr_crc32_castagnoli_array(hash_word, 28);
    760 
    761     switch (rtag7_hash_a0_function_select) {
    762     case 0: /* reserved */
    763         hash_res->rtag7_hash16_value_a_0 = 0;
    764         break;
    765     case 1: /* reserved */
    766         hash_res->rtag7_hash16_value_a_0 = 0;
    767         break;
    768     case 2: /* reserved */
    769         hash_res->rtag7_hash16_value_a_0 = 0;
    770         break;
    771     case 3: /* CRC16 BISYNC */
    772         hash_res->rtag7_hash16_value_a_0 = hash_crc16_bisync;
    773         break;
    774     case 4: /* CRC16_XOR1 */ 
    775         hash_res->rtag7_hash16_value_a_0 = hash_xor1 & 0x1;
    776         hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    777         break;
    778     case 5: /* CRC16_XOR2 */
    779         hash_res->rtag7_hash16_value_a_0 = hash_xor2 & 0x3;
    780         hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    781         break;
    782     case 6: /* CRC16_XOR4 */ 
    783         hash_res->rtag7_hash16_value_a_0 = hash_xor4 & 0xf;
    784         hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    785         break;
    786     case 7: /* CRC16_XOR8 */
    787         hash_res->rtag7_hash16_value_a_0 = hash_xor8 & 0xff;
    788         hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    789         break;
    790     case 8: /* XOR16 */
    791         hash_res->rtag7_hash16_value_a_0 = hash_xor16;
    792         break;
    793     case 9: /* CRC16_CCITT */
    794         hash_res->rtag7_hash16_value_a_0 = hash_crc16_ccitt;
    795         break;
    796     case 10: /* CRC32_LO */
    797         hash_res->rtag7_hash16_value_a_0 = hash_crc32 & 0xffff;
    798         break;
    799     case 11: /* CRC32_HI */
    800         hash_res->rtag7_hash16_value_a_0 = (hash_crc32 >> 16) & 0xffff;
    801         break;
    802     default: /* reserved */
    803         hash_res->rtag7_hash16_value_a_0 = 0;
    804         break;
    805     }
    806 
    807     switch (rtag7_hash_a1_function_select) {
    808     case 0: /* reserved */
    809         hash_res->rtag7_hash16_value_a_1 = 0;
    810         break;
    811     case 1: /* reserved */
    812         hash_res->rtag7_hash16_value_a_1 = 0;
    813         break;
    814     case 2: /* reserved */
    815         hash_res->rtag7_hash16_value_a_1 = 0;
    816         break;
    817     case 3: /* CRC16 BISYNC */
    818         hash_res->rtag7_hash16_value_a_1 = hash_crc16_bisync;
    819         break;
    820     case 4: /* CRC16_XOR1 */ 
    821         hash_res->rtag7_hash16_value_a_1 = hash_xor1 & 0x1;
    822         hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    823         break;
    824     case 5: /* CRC16_XOR2 */
    825         hash_res->rtag7_hash16_value_a_1 = hash_xor2 & 0x3;
    826         hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    827         break;
    828     case 6: /* CRC16_XOR4 */ 
    829         hash_res->rtag7_hash16_value_a_1 = hash_xor4 & 0xf;
    830         hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    831         break;
    832     case 7: /* CRC16_XOR8 */
    833         hash_res->rtag7_hash16_value_a_1 = hash_xor8 & 0xff;
    834         hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    835         break;
    836     case 8: /* XOR16 */
    837         hash_res->rtag7_hash16_value_a_1 = hash_xor16;
    838         break;
    839     case 9: /* CRC16_CCITT */
    840         hash_res->rtag7_hash16_value_a_1 = hash_crc16_ccitt;
    841         break;
    842     case 10: /* CRC32_LO */
    843         hash_res->rtag7_hash16_value_a_1 = hash_crc32 & 0xffff;
    844         break;
    845     case 11: /* CRC32_HI */
    846         hash_res->rtag7_hash16_value_a_1 = (hash_crc32 >> 16) & 0xffff;
    847         break;
    848     default: /* reserved */
    849         hash_res->rtag7_hash16_value_a_1 = 0;
    850         break;
    851     }
    852 
    853     /* End of option A hash calculation for rtag 7 */
    854 
    855     /* Generation of Macro Flow Based HASH Select */
    856     /* This is used for Macro flow based Hash function selection for all consumers of RTAG7 HASH */
    857     /* Macro flow based hash function selection improves distribution among members */
    858     /* Refer Each application (ECMP, LAG, HG-TRUNK) on how this is being used */
    859     switch (rtag7_macro_flow_hash_function_select) {
    860     case 0: /* reserved */
    861         macro_flow_id = 0;
    862         break;
    863     case 1: /* reserved */
    864         macro_flow_id = 0;
    865         break;
    866     case 2: /* reserved */
    867         macro_flow_id = 0;
    868         break;
    869     case 3: /* CRC16 BISYNC */
    870         macro_flow_id = hash_crc16_bisync;
    871         break;
    872     case 4: /* CRC16_XOR1 */ 
    873         macro_flow_id = hash_xor1 & 0x1;
    874         macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    875         break;
    876     case 5: /* CRC16_XOR2 */
    877         macro_flow_id = hash_xor2 & 0x3;
    878         macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    879         break;
    880     case 6: /* CRC16_XOR4 */ 
    881         macro_flow_id = hash_xor4 & 0xf;
    882         macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    883         break;
    884     case 7: /* CRC16_XOR8 */
    885         macro_flow_id = hash_xor8 & 0xff;
    886         macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    887         break;
    888     case 8: /* XOR16 */
    889         macro_flow_id = hash_xor16;
    890         break;
    891     case 9: /* CRC16_CCITT */
    892         macro_flow_id = hash_crc16_ccitt;
    893         break;
    894     case 10: /* CRC32_LO */
    895         macro_flow_id = hash_crc32 & 0xffff;
    896         break;
    897     case 11: /* CRC32_HI */
    898         macro_flow_id = (hash_crc32 >> 16) & 0xffff;
    899         break;
    900     default: /* reserved */
    901         macro_flow_id = 0;
    902         break;
    903     }
    904     hash_res->rtag7_macro_flow_id = (rtag7_macro_flow_hash_byte_sel) ?  
    905         ((macro_flow_id >> 8) & 0xff) : (macro_flow_id & 0xff);
    906 
    907     /* option B hash calculation for rtag 7 */
    908 
    909     /* initialize the variables */   
    910     
    911     sal_memset(hash,0x0,(sizeof(uint32))*13);
    912     sal_memset(hash_word,0x0,(sizeof(uint32))*7);
    913     
    914     hash_crc16_bisync = 0;
    915     hash_crc16_ccitt = 0;
    916     hash_crc32      = 0;
    917     hash_xor16      = 0;
    918     hash_xor8       = 0;
    919     hash_xor4       = 0;
    920     hash_xor2       = 0;
    921     hash_xor1       = 0;
    922     xor32           = 0;
    923  
    924     hash[12] = 0;   
    925     hash[3] = hash_src_port;
    926     hash[2] = hash_src_modid & 0xff;
    927     hash[1] = 0;
    928     hash[0] = 0; 
    929 
    930     hash_element_valid_bits = 0x1fff; /* Init to valid fields above */
    931 
    932     /* option B hash calculation for rtag 7 */
    933     
    934     if ((rtag7_b_sel == RTAG7_IPV6) || (rtag7_b_sel == RTAG7_IPV4)) {
    935         if (sip_valid) {
    936             hash[11] = (sip_b >> 16) & 0xffff;
    937             hash[10] =  sip_b & 0xffff;
    938         } else {
    939             hash_element_valid_bits &= ~0xc00;
    940         }
    941         if (dip_valid) {
    942             hash[9]  = (dip_b >> 16) & 0xffff;
    943             hash[8]  =  dip_b & 0xffff;
    944         } else {
    945             hash_element_valid_bits &= ~0x300;
    946         }
    947 
    948         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) {
    949             hash[7]  = pkt_info->vid & 0xfff;
    950         } else {
    951             hash_element_valid_bits &= ~0x80;
    952         }
    953         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT)) {
    954             hash[6]  = pkt_info->src_l4_port;
    955         } else {
    956             hash_element_valid_bits &= ~0x40;
    957         }
    958         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT)) {
    959             hash[5]  = pkt_info->dst_l4_port;
    960         } else {
    961             hash_element_valid_bits &= ~0x20;
    962         }
    963         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL)) {
    964             hash[4]  = pkt_info->protocol;
    965         } else {
    966             hash_element_valid_bits &= ~0x10;
    967         }
    968 
    969         /* Symmetric hash swap src/dst ipaddr/l4_port for option B */
    970         if (((rtag7_b_sel == RTAG7_IPV6) && 
    971             symmetric_hash_need_swap_ip6 && 
    972             (symmetric_hash_control_mask & BCM_SYMMETRIC_HASH_1_IP6_ENABLE)) 
    973             ||
    974             ((rtag7_b_sel == RTAG7_IPV4) && 
    975             symmetric_hash_need_swap_ip4 && 
    976             (symmetric_hash_control_mask & BCM_SYMMETRIC_HASH_1_IP4_ENABLE))) {
    977 
    978             uint32 temp;
    979             temp = hash[11]; hash[11] = hash[9]; hash[9] = temp;
    980             temp = hash[10]; hash[10] = hash[8]; hash[8] = temp;
    981             temp = hash[6]; hash[6] = hash[5]; hash[5] = temp;
    982             LOG_VERBOSE(BSL_LS_BCM_COMMON,
    983                         (BSL_META_U(unit,
    984                                     "Symmetric hash swap for hash B calculation.\n")));
    985         }
    986 
    987         if ((rtag7_b_sel == RTAG7_IPV6) && rtag7_en_flow_label_ipv6_b) {
    988             LOG_VERBOSE(BSL_LS_BCM_COMMON,
    989                         (BSL_META_U(unit,
    990                                     "Hash calculation: The system is set to use ipv6 flow label" 
    991                                      " and the code can't get this info\n")));
    992         }
    993 
    994         if (rtag7_b_sel == RTAG7_IPV4) {  /* Use IPv4 BITMAPs */
    995             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) &&
    996                 ((pkt_info->protocol == IP_PROT_TCP) ||
    997                 (pkt_info->protocol == IP_PROT_UDP))) { 
    998                 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) &&
    999                     _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) &&
   1000                     (pkt_info->src_l4_port == pkt_info->dst_l4_port)) {
   1001                     sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_1r;
   1002                     sc_field = IPV4_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Bf;
   1003                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1004                                 (BSL_META_U(unit,
   1005                                             "Hash calculation: Bitmap is block B IPv4 TCP=UDP\n")));
   1006                 } else {
   1007                     sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_2r;
   1008                     sc_field = IPV4_TCP_UDP_FIELD_BITMAP_Bf;
   1009                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1010                                 (BSL_META_U(unit,
   1011                                             "Hash calculation: Bitmap is block B IPv4 L4 tcp/udp\n")));
   1012                 }
   1013             } else {
   1014                 sc_reg = RTAG7_HASH_FIELD_BMAP_1r;
   1015                 sc_field = IPV4_FIELD_BITMAP_Bf;
   1016                 LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1017                             (BSL_META_U(unit,
   1018                                         "Hash calculation: Bitmap is block B IPv4\n")));
   1019             }
   1020 
   1021         } else { /* Use IPv6 BITMAPs */
   1022 
   1023             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) &&
   1024                 ((pkt_info->protocol == IP_PROT_TCP) ||
   1025                 (pkt_info->protocol == IP_PROT_UDP))) { 
   1026                 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) &&
   1027                     _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) &&
   1028                     (pkt_info->src_l4_port == pkt_info->dst_l4_port)) {
   1029                     sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_1r;
   1030                     sc_field = IPV6_TCP_UDP_SCTP_SRC_EQ_DST_FIELD_BITMAP_Bf;
   1031                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1032                                 (BSL_META_U(unit,
   1033                                             "Hash calculation: Bitmap is block B IPv6 TCP=UDP\n")));
   1034                 } else {
   1035                     sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_2r;
   1036                     sc_field = IPV6_TCP_UDP_SCTP_FIELD_BITMAP_Bf;
   1037                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1038                                 (BSL_META_U(unit,
   1039                                             "Hash calculation: Bitmap is block B IPv6 TCP=UDP\n")));
   1040                 }
   1041             } else {
   1042                 sc_reg = RTAG7_HASH_FIELD_BMAP_2r;
   1043                 sc_field = IPV6_FIELD_BITMAP_Bf;
   1044                 LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1045                             (BSL_META_U(unit,
   1046                                         "Hash calculation: Bitmap is block B IPv6\n")));
   1047             }
   1048         }
   1049     } else { /* Catch-all for RTAG7_L2_ONLY */
   1050 
   1051         /* L2 only hash key */
   1052         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_MAC)) {
   1053             hash[11] = (pkt_info->src_mac[0] << 8) | pkt_info->src_mac[1];
   1054             hash[10] = (pkt_info->src_mac[2] << 8) | pkt_info->src_mac[3];
   1055             hash[9] = (pkt_info->src_mac[4] << 8) | pkt_info->src_mac[5];
   1056         } else {
   1057             hash_element_valid_bits &= ~0xe00;
   1058         }
   1059         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_MAC)) {
   1060             hash[8] = (pkt_info->dst_mac[0] << 8) | pkt_info->dst_mac[1];
   1061             hash[7] = (pkt_info->dst_mac[2] << 8) | pkt_info->dst_mac[3];
   1062             hash[6] = (pkt_info->dst_mac[4] << 8) | pkt_info->dst_mac[5];
   1063         } else {
   1064             hash_element_valid_bits &= ~0x1c0;
   1065         }
   1066 
   1067         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE)) {
   1068             hash[5] = (pkt_info->ethertype >= ETHERTYPE_MIN) ?
   1069                 pkt_info->ethertype : 0;
   1070         } else {
   1071             hash_element_valid_bits &= ~0x20;
   1072         }
   1073 
   1074         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) {
   1075             hash[4] = pkt_info->vid & 0xfff;
   1076         } else {
   1077             hash_element_valid_bits &= ~0x10;
   1078         }
   1079 
   1080         sc_reg = RTAG7_HASH_FIELD_BMAP_3r;
   1081         sc_field = L2_FIELD_BITMAP_Bf;
   1082         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1083                     (BSL_META_U(unit,
   1084                                 "Hash calculation: Bitmap is block B L2\n")));
   1085     }
   1086 
   1087     BCM_IF_ERROR_RETURN
   1088         (soc_reg32_get(unit, sc_reg, REG_PORT_ANY, 0, &sc_val));
   1089     hash_field_bmap_b = soc_reg_field_get(unit, sc_reg, sc_val, sc_field);
   1090     /* Pre-Processing */
   1091 
   1092     if (rtag7_pre_processing_enable_b) {
   1093         hash[12] = hash[12] ^ (hash[12] >> 3) ^ (hash[12] << 2);
   1094         hash[11] = hash[11] ^ (hash[11] >> 3) ^ (hash[11] << 2);
   1095         hash[10] = hash[10] ^ (hash[10] >> 3) ^ (hash[10] << 2);
   1096         hash[9] = hash[9] ^ (hash[9] >> 3) ^ (hash[9] << 2);
   1097         hash[8] = hash[8] ^ (hash[8] >> 3) ^ (hash[8] << 2);
   1098         hash[7] = hash[7] ^ (hash[7] >> 3) ^ (hash[7] << 2);
   1099         hash[6] = hash[6] ^ (hash[6] >> 3) ^ (hash[6] << 2);
   1100         hash[5] = hash[5] ^ (hash[5] >> 3) ^ (hash[5] << 2);
   1101         hash[4] = hash[4] ^ (hash[4] >> 3) ^ (hash[4] << 2);
   1102         hash[3] = hash[3] ^ (hash[3] >> 3) ^ (hash[3] << 2);
   1103         hash[2] = hash[2] ^ (hash[2] >> 3) ^ (hash[2] << 2);
   1104         hash[1] = hash[1] ^ (hash[1] >> 3) ^ (hash[1] << 2);
   1105         hash[0] = hash[0] ^ (hash[0] >> 3) ^ (hash[0] << 2);
   1106     }
   1107 
   1108     if (((hash_field_bmap_b >> 12) & 0x1) == 0) {
   1109         hash[12] = 0;
   1110     }    
   1111 
   1112     if (rtag7_en_bin_12_overlay_b) {
   1113         hash_word[6] = (rtag7_hash_seed_b & 0xffff0000) | (hash[12] & 0xffff);
   1114     } else {
   1115         hash_word[6] = rtag7_hash_seed_b;
   1116     }    
   1117 
   1118     hash_res->hash_b_valid = TRUE;
   1119     for (elem = 11; elem >= 0; elem--) {
   1120         elem_bit = 1 << elem;
   1121         if (0 != (hash_field_bmap_b & elem_bit)) {
   1122             if (0 != (hash_element_valid_bits & elem_bit)) {
   1123                 hash_word[elem/2] |=
   1124                     ((hash[elem] & 0xffff) << (16 * (elem % 2)));
   1125             } else {
   1126                 hash_res->hash_b_valid = FALSE;
   1127                 break;
   1128             }
   1129         }
   1130     }
   1131 
   1132     xor32 = hash_word[6] ^ hash_word[5] ^ hash_word[4] ^ hash_word[3] ^ hash_word[2] ^ hash_word[1] ^ hash_word[0];
   1133     hash_xor16 = (xor32 & 0xffff) ^ ((xor32 >> 16) & 0xffff);  
   1134     hash_xor8 = (hash_xor16 & 0xff) ^ ((hash_xor16 >> 8) & 0xff);
   1135     hash_xor4 = (hash_xor8 & 0xf) ^ ((hash_xor8 >> 4) & 0xf);
   1136     hash_xor2 = (hash_xor4 & 0x3) ^ ((hash_xor4 >> 2) & 0x3);
   1137     hash_xor1 = (hash_xor2 & 0x1) ^ ((hash_xor2 >> 1) & 0x1);
   1138 
   1139     hash_crc16_bisync = _shr_crc16_draco_array(hash_word, 28);
   1140     hash_crc16_ccitt =  _shr_crc16_ccitt_array(hash_word, 28);
   1141     hash_crc32 =        _shr_crc32_castagnoli_array(hash_word, 28);
   1142 
   1143     switch (rtag7_hash_b0_function_select) {
   1144     case 0: /* reserved */
   1145         hash_res->rtag7_hash16_value_b_0 = 0;
   1146         break;
   1147     case 1: /* reserved */
   1148         hash_res->rtag7_hash16_value_b_0 = 0;
   1149         break;
   1150     case 2: /* reserved */
   1151         hash_res->rtag7_hash16_value_b_0 = 0;
   1152         break;
   1153     case 3: /* CRC16 BISYNC */
   1154         hash_res->rtag7_hash16_value_b_0 = hash_crc16_bisync;
   1155         break;
   1156     case 4: /* CRC16_XOR1 */ 
   1157         hash_res->rtag7_hash16_value_b_0 = hash_xor1 & 0x1;
   1158         hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1159         break;
   1160     case 5: /* CRC16_XOR2 */
   1161         hash_res->rtag7_hash16_value_b_0 = hash_xor2 & 0x3;
   1162         hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1163         break;
   1164     case 6: /* CRC16_XOR4 */ 
   1165         hash_res->rtag7_hash16_value_b_0 = hash_xor4 & 0xf;
   1166         hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1167         break;
   1168     case 7: /* CRC16_XOR8 */
   1169         hash_res->rtag7_hash16_value_b_0 = hash_xor8 & 0xff;
   1170         hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1171         break;
   1172     case 8: /* XOR16 */
   1173         hash_res->rtag7_hash16_value_b_0 = hash_xor16;
   1174         break;
   1175     case 9: /* CRC16_CCITT */
   1176         hash_res->rtag7_hash16_value_b_0 = hash_crc16_ccitt;
   1177         break;
   1178     case 10: /* CRC32_LO */
   1179         hash_res->rtag7_hash16_value_b_0 = hash_crc32 & 0xffff;
   1180         break;
   1181     case 11: /* CRC32_HI */
   1182         hash_res->rtag7_hash16_value_b_0 = (hash_crc32 >> 16) & 0xffff;
   1183         break;
   1184     default: /* reserved */
   1185         hash_res->rtag7_hash16_value_b_0 = 0;
   1186         break;
   1187     }
   1188 
   1189     switch (rtag7_hash_b1_function_select) {
   1190     case 0: /* reserved */
   1191         hash_res->rtag7_hash16_value_b_1 = 0;
   1192         break;
   1193     case 1: /* reserved */
   1194         hash_res->rtag7_hash16_value_b_1 = 0;
   1195         break;
   1196     case 2: /* reserved */
   1197         hash_res->rtag7_hash16_value_b_1 = 0;
   1198         break;
   1199     case 3: /* CRC16 BISYNC */
   1200         hash_res->rtag7_hash16_value_b_1 = hash_crc16_bisync;
   1201         break;
   1202     case 4: /* CRC16_XOR1 */ 
   1203         hash_res->rtag7_hash16_value_b_1 = hash_xor1 & 0x1;
   1204         hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1205         break;
   1206     case 5: /* CRC16_XOR2 */
   1207         hash_res->rtag7_hash16_value_b_1 = hash_xor2 & 0x3;
   1208         hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1209         break;
   1210     case 6: /* CRC16_XOR4 */ 
   1211         hash_res->rtag7_hash16_value_b_1 = hash_xor4 & 0xf;
   1212         hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1213         break;
   1214     case 7: /* CRC16_XOR8 */
   1215         hash_res->rtag7_hash16_value_b_1 = hash_xor8 & 0xff;
   1216         hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1217         break;
   1218     case 8: /* XOR16 */
   1219         hash_res->rtag7_hash16_value_b_1 = hash_xor16;
   1220         break;
   1221     case 9: /* CRC16_CCITT */
   1222         hash_res->rtag7_hash16_value_b_1 = hash_crc16_ccitt;
   1223         break;
   1224     case 10: /* CRC32_LO */
   1225         hash_res->rtag7_hash16_value_b_1 = hash_crc32 & 0xffff;
   1226         break;
   1227     case 11: /* CRC32_HI */
   1228         hash_res->rtag7_hash16_value_b_1 = (hash_crc32 >> 16) & 0xffff;
   1229         break;
   1230     default: /* reserved */
   1231         hash_res->rtag7_hash16_value_b_1 = 0;
   1232         break;
   1233     }
   1234 
   1235     /* End of option B hash calculation for rtag 7 */
   1236     return BCM_E_NONE;
   1237 }
   1238 
   1239 /*
   1240  * Function:
   1241  *          select_gh2_hash_subfield
   1242  * Description:
   1243  *          read hashing values of hash A0,A1,B0,B1,LBID
   1244  *          from sub_sel_block pointed by hash_sub_sel
   1245  * Parameters:
   1246  *          concat - tell whether is in concatenated mode or not
   1247  *          hash_sub_sel - tell which hash sub to choose
   1248  *          seleted_subfiled - saves subfield value
   1249  *          hash_Base - internal data where hashing informaiton is stored
   1250  * Returns:
   1251  *      BCM_E_xxxx
   1252  * Note: if hash_sub_sel and hash_Base->hash_x_valid mismatches, 
   1253  *       it will return BCM_E_PARAM
   1254  */
   1255 STATIC int
   1256 select_gh2_hash_subfield(uint32 concat, int hash_sub_sel, uint64 *selected_subfield,
   1257                      bcm_rtag7_base_hash_t *hash_Base)
   1258 {
   1259     int rv = BCM_E_NONE;
   1260 
   1261     switch (hash_sub_sel) {
   1262         case 0: /* select pkt hash A */
   1263             if (concat) {
   1264                 COMPILER_64_SET(*selected_subfield,
   1265                     (hash_Base->rtag7_hash16_value_b_1 << 16 | hash_Base->rtag7_hash16_value_b_0),
   1266                     (hash_Base->rtag7_hash16_value_a_1 << 16 | hash_Base->rtag7_hash16_value_a_0));
   1267                 if (!hash_Base->hash_a_valid || !hash_Base->hash_b_valid) {
   1268                     /* Missing paramter in input */
   1269                     rv = BCM_E_PARAM;
   1270                 }
   1271             } else {
   1272                 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_hash16_value_a_0);
   1273                 if (!hash_Base->hash_a_valid) {
   1274                     /* Missing paramter in input */
   1275                     rv = BCM_E_PARAM;
   1276                 }
   1277             }
   1278             break;
   1279 
   1280         case 1: /* select pkt hash B */
   1281             if (concat) {
   1282                 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_port_lbn);
   1283             } else {
   1284                 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_hash16_value_b_0);
   1285                 if (!hash_Base->hash_b_valid) {
   1286                     /* Missing paramter in input */
   1287                     rv = BCM_E_PARAM;
   1288                 }
   1289             }
   1290             break;
   1291 
   1292         case 2: /* select port LBN */
   1293             COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_port_lbn);
   1294             break;
   1295 
   1296         case 3: /* select destination port id or hash A */
   1297             if (concat) {
   1298                 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_port_lbn);
   1299             } else {
   1300                 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_hash16_value_a_0);
   1301                 if (!hash_Base->hash_a_valid) {
   1302                     /* Missing paramter in input */
   1303                     rv = BCM_E_PARAM;
   1304                 }
   1305             }
   1306             break;
   1307 
   1308         case 4: /* select LBID from module header or from SW1 stage */ 
   1309             COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_lbid_hash);
   1310             if (!hash_Base->lbid_hash_valid) {
   1311                 /* LBID setting isn't RTAG7 */
   1312                 rv = BCM_E_CONFIG;
   1313             }
   1314             break;
   1315 
   1316         case 5: /* select LBID from SW1 stage */
   1317             COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_lbid_hash);
   1318             if (!hash_Base->lbid_hash_valid) {
   1319                 /* LBID setting isn't RTAG7 */
   1320                 rv = BCM_E_CONFIG;
   1321             }
   1322             break;
   1323 
   1324         case 6:
   1325             if (concat) {
   1326                 COMPILER_64_ZERO(*selected_subfield);
   1327             } else {
   1328                 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_hash16_value_a_1);
   1329                 if (!hash_Base->hash_a_valid) {
   1330                     /* Missing paramter in input */
   1331                     rv = BCM_E_PARAM;
   1332                 }
   1333             }
   1334             break;
   1335 
   1336         case 7: 
   1337             if (concat) {
   1338                 COMPILER_64_ZERO(*selected_subfield);
   1339             } else {
   1340                 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_hash16_value_b_1);
   1341                 if (!hash_Base->hash_b_valid) {
   1342                     /* Missing paramter in input */
   1343                     rv = BCM_E_PARAM;
   1344                 }
   1345             }
   1346             break;
   1347 
   1348         default:
   1349             return BCM_E_PARAM;
   1350     }
   1351 
   1352     return rv;
   1353 }
   1354 
   1355 /*
   1356  * Function:
   1357  *          main_gh2_compute_lbid
   1358  * Description:
   1359  *     get lbid value that is used in hashing calculation
   1360  *     if flow hash is used, get SUB_SEL_LBID_OR_ENTROPYf and 
   1361  *        OFFSET_LBID_OR_ENTROPYf from RTAG7_FLOW_BASED_HASHm 
   1362  *     if flow hash is not used, get SUB_SEL_LBID_(non)UCf and 
   1363  *        OFFSET_LBID_(non)UCf from RTAG7_PORT_BASED_HASHm 
   1364  * Parameters:
   1365  *          unit - StrataSwitch PCI device unit number (driver internal).
   1366  *          hash_Base - internal data that lbid_hash_value is stored 
   1367  * Returns:
   1368  *      BCM_E_xxxx
   1369  * Note: bcmSwitchLoadBalanceHashSelect must be set to 7 
   1370  *   and bcmSwitchLoadBalanceHashSet0UnicastOffset must be set properly.    
   1371  *       if lbid_hash_sub_sel and hash_Base->hash_x_valid mismatches, 
   1372  *       then lbid_hash_val saved in hash_Base will be 0
   1373  */
   1374 STATIC int
   1375 main_gh2_compute_lbid(int unit, bcm_rtag7_base_hash_t *hash_Base)
   1376 {
   1377     /*regular var declaration*/
   1378     uint32 lbid_hash_sub_sel;
   1379     uint32 lbid_hash_offset;
   1380     uint32 lbid_hash_value = 0;
   1381 
   1382     /*register var declaration*/
   1383     int lbid_rtag = 0;
   1384     uint64 ing_hash_config_reg;
   1385     int    rv = BCM_E_NONE;
   1386     uint32 rtag7_hash_sel;
   1387     uint32 port_based_hash_index;
   1388     int hash_index = 0;
   1389     rtag7_port_based_hash_entry_t port_based_hash_entry;
   1390     rtag7_flow_based_hash_entry_t flow_based_hash_entry;
   1391     uint8   loadbalance_use_flow_hash_uc = 0;
   1392     uint8   loadbalance_use_flow_hash_nonuc = 0;
   1393  
   1394     /* get the lbid rtag value */ 
   1395     if (SOC_REG_FIELD_VALID(unit, ING_CONFIG_64r, LBID_RTAGf)) {
   1396         rv = READ_ING_CONFIG_64r(unit, &ing_hash_config_reg);
   1397         if (BCM_SUCCESS(rv)) {
   1398             lbid_rtag = soc_reg64_field32_get(unit, ING_CONFIG_64r, 
   1399                                ing_hash_config_reg, LBID_RTAGf);
   1400         } else {
   1401             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1402                         (BSL_META_U(unit,
   1403                                     "compute_lbid fail, lbid_rtag=0\n")));
   1404             lbid_rtag =0;
   1405         }
   1406     } else {
   1407         rv = (BCM_E_UNAVAIL);
   1408     }
   1409 
   1410     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1411                 (BSL_META_U(unit,
   1412                             "lbid_rtag = %d\n"), lbid_rtag));
   1413 
   1414     if (lbid_rtag == 7) {
   1415         /* check if flow hash is used for UC*/
   1416         SOC_IF_ERROR_RETURN
   1417             (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel));
   1418         if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_LBID_UCf)) {
   1419              loadbalance_use_flow_hash_uc =
   1420                 soc_reg_field_get(unit, RTAG7_HASH_SELr,
   1421                               rtag7_hash_sel, USE_FLOW_SEL_LBID_UCf);
   1422         } else {
   1423             loadbalance_use_flow_hash_uc = 0; 
   1424         }    
   1425  
   1426         /* check if flow hash is used for NONUC*/
   1427         SOC_IF_ERROR_RETURN
   1428             (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel));
   1429         if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_LBID_NONUCf)) {
   1430             loadbalance_use_flow_hash_nonuc =
   1431                 soc_reg_field_get(unit, RTAG7_HASH_SELr,
   1432                               rtag7_hash_sel, USE_FLOW_SEL_LBID_NONUCf);
   1433         } else {
   1434             loadbalance_use_flow_hash_nonuc = 0; 
   1435         }    
   1436 
   1437         /* RTAG7 hash computation */
   1438         if ((loadbalance_use_flow_hash_nonuc&& (hash_Base->is_nonuc == 0)) || 
   1439             (loadbalance_use_flow_hash_uc && (hash_Base->is_nonuc != 0))) {
   1440             SOC_IF_ERROR_RETURN(
   1441                 READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY,
   1442                         (hash_Base->rtag7_macro_flow_id & 0xff),
   1443                          &flow_based_hash_entry));
   1444 
   1445             /* in RTAG7_FLOW_BASED_HASHm, using same selection for UC and NONUC */
   1446             lbid_hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit,
   1447                                            &flow_based_hash_entry, SUB_SEL_LBIDf);
   1448             lbid_hash_offset  = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit,
   1449                                            &flow_based_hash_entry, OFFSET_LBIDf);
   1450         
   1451         } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) {
   1452             if (hash_Base->dev_src_port < 0) {
   1453                 int field_count = 0;
   1454                 soc_field_t fields[2];
   1455                 uint32 values[2];
   1456                 bcm_gport_t gport;
   1457 
   1458                 BCM_GPORT_PROXY_SET(gport, 
   1459                     hash_Base->src_modid, hash_Base->src_port);
   1460 
   1461                 if (hash_Base->is_nonuc) {
   1462                     fields[0] = SUB_SEL_LBID_NONUCf ;
   1463                     field_count++;
   1464                     fields[1] = OFFSET_LBID_NONUCf;
   1465                     field_count++;
   1466                 } else {
   1467                     fields[0] = SUB_SEL_LBID_UCf ;
   1468                     field_count++;
   1469                     fields[1] = OFFSET_LBID_UCf;
   1470                     field_count++;
   1471                 }
   1472                 BCM_IF_ERROR_RETURN
   1473                     (bcm_esw_port_lport_fields_get(unit, gport, 
   1474                                                    LPORT_PROFILE_RTAG7_TAB,
   1475                                                    field_count, fields, values));
   1476                 lbid_hash_sub_sel = values[0];
   1477                 lbid_hash_offset  = values[1];
   1478             } else {
   1479                 if (soc_feature(unit, soc_feature_rtag7_port_profile)) {
   1480                     BCM_IF_ERROR_RETURN
   1481                         (_bcm_esw_port_tab_get(unit, hash_Base->dev_src_port,
   1482                                                RTAG7_PORT_PROFILE_INDEXf, &hash_index));
   1483                     port_based_hash_index = (uint32) hash_index;
   1484                 } else {
   1485                     port_based_hash_index = hash_Base->dev_src_port +
   1486                                             soc_mem_index_count(unit, LPORT_TABm);
   1487                 }
   1488 
   1489                 SOC_IF_ERROR_RETURN(
   1490                     READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY,
   1491                                 port_based_hash_index, &port_based_hash_entry));
   1492                 if (hash_Base->is_nonuc) {
   1493                     lbid_hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   1494                                         &port_based_hash_entry, SUB_SEL_LBID_NONUCf);
   1495                     lbid_hash_offset  = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   1496                                         &port_based_hash_entry, OFFSET_LBID_NONUCf);
   1497                 } else {
   1498                     lbid_hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   1499                                         &port_based_hash_entry, SUB_SEL_LBID_UCf);
   1500                     lbid_hash_offset  = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   1501                                         &port_based_hash_entry, OFFSET_LBID_UCf);
   1502                 }
   1503             }
   1504         } else {
   1505             lbid_hash_sub_sel = 0;
   1506             lbid_hash_offset  = 0;
   1507         }
   1508 
   1509         switch (lbid_hash_sub_sel) {
   1510         
   1511         case 0: /* use pkt hash A */
   1512             lbid_hash_value = hash_Base->rtag7_hash16_value_a_0;
   1513             if (!hash_Base->hash_a_valid) {
   1514                 /* Missing paramter in input */
   1515                 rv = BCM_E_PARAM;
   1516             }
   1517             break;
   1518         
   1519         case 1: /* use pkt hash B */
   1520             lbid_hash_value = hash_Base->rtag7_hash16_value_b_0;
   1521             if (!hash_Base->hash_b_valid) {
   1522                 /* Missing paramter in input */
   1523                 rv = BCM_E_PARAM;
   1524             }
   1525             break;
   1526         
   1527         case 2: /* Use LBN */
   1528             lbid_hash_value = hash_Base->rtag7_port_lbn;
   1529             break;
   1530         
   1531         case 3: /* Use Destination PORTID or hash A */
   1532             lbid_hash_value = hash_Base->rtag7_hash16_value_a_0;
   1533             if (!hash_Base->hash_a_valid) {
   1534                 /* Missing paramter in input */
   1535                 rv = BCM_E_PARAM;
   1536             }
   1537             break;
   1538         
   1539         case 4: /* Use LBID */
   1540             /* Higig lookup use mh_higig2_lbid */
   1541                 
   1542             lbid_hash_value = 0;
   1543             break;
   1544         
   1545         case 5:
   1546             lbid_hash_value = 0;
   1547             break;
   1548         
   1549         case 6:
   1550             lbid_hash_value = hash_Base->rtag7_hash16_value_a_1;
   1551             if (!hash_Base->hash_a_valid) {
   1552                 /* Missing paramter in input */
   1553                 rv = BCM_E_PARAM;
   1554             }
   1555             break;
   1556         
   1557         case 7:
   1558             lbid_hash_value = hash_Base->rtag7_hash16_value_b_1;
   1559             if (!hash_Base->hash_b_valid) {
   1560                 /* Missing paramter in input */
   1561                 rv = BCM_E_PARAM;
   1562             }
   1563             break;
   1564         }
   1565         
   1566         /*
   1567          * set up the hash value so that the LSB bits are
   1568          * barrel shifted in case offset > 8.
   1569          */
   1570         lbid_hash_value |= ((lbid_hash_value & 0xffff) << 16);
   1571         
   1572         /* Only UC hash offsets apply to ECMP */
   1573         lbid_hash_value = (lbid_hash_value >> lbid_hash_offset);
   1574         
   1575         hash_Base->rtag7_lbid_hash = (lbid_hash_value & 0xff);
   1576         hash_Base->lbid_hash_valid = TRUE;
   1577     } else { /* LBID rtag is 0-6 */        
   1578         /* this function not support the rtag 0-6 */
   1579 
   1580         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1581                     (BSL_META_U(unit,
   1582                                 "Hash calculation: This function doesn't support rtag 0 6"
   1583                                  " pls change register ING_CONFIG.LBID_RTAG to value 7\n")));
   1584         hash_Base->rtag7_lbid_hash = 0;
   1585         hash_Base->lbid_hash_valid = FALSE;
   1586     }
   1587 
   1588     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1589                 (BSL_META_U(unit,
   1590                             "lbid_hash_val=%d, valid=%d\n"),
   1591                  hash_Base->rtag7_lbid_hash, hash_Base->lbid_hash_valid));
   1592 
   1593     return rv;
   1594     /* ******************* END of LBID computation ************************* */
   1595 }
   1596 
   1597 #ifdef INCLUDE_L3
   1598 /*
   1599  * Function:
   1600  *          compute_gh2_ecmp_hash
   1601  * Description:
   1602  *     get ecmp hash value using SUB_SEL_ECMPf and OFFSET_ECMPf
   1603  *     if flow hash is used, get subsel and offset from RTAG7_FLOW_BASED_HASHm 
   1604  *     if flow hash is not used, get subsel and offset from RTAG7_PORT_BASED_HASHm 
   1605  * Parameters:
   1606  *          unit - StrataSwitch PCI device unit number (driver internal).
   1607  *          hash_Base - internal data where ecmp hash value is stored 
   1608  * Returns:
   1609  *      BCM_E_xxxx
   1610  */
   1611 STATIC int
   1612 compute_gh2_ecmp_hash(int unit, bcm_rtag7_base_hash_t *hash_Base,
   1613                   uint32 *hash_value)
   1614 {
   1615     /*regular var declaration*/
   1616     uint32 hash_sub_sel;
   1617     uint32 hash_offset;
   1618     uint64 hash_subfield;
   1619     uint32 hash_subfield_width;
   1620     uint8  rtag7_ecmp_use_macro_flow_hash;
   1621     uint8  ecmp_hash_use_rtag7;
   1622     uint32 rtag7_hash_sel;
   1623     uint32 hash_control;
   1624     uint32 concat;
   1625     uint32 port_based_hash_index;
   1626     int hash_index = 0;
   1627     rtag7_port_based_hash_entry_t port_based_hash_entry;
   1628     rtag7_flow_based_hash_entry_t flow_based_hash_entry;
   1629 
   1630     /* Select between non-RTAG7 hash value and RTAG7 hash value */
   1631     SOC_IF_ERROR_RETURN
   1632         (READ_HASH_CONTROLr(unit, &hash_control));
   1633     ecmp_hash_use_rtag7 =
   1634         soc_reg_field_get(unit, HASH_CONTROLr, hash_control,
   1635                           ECMP_HASH_USE_RTAG7f);
   1636 
   1637     if (ecmp_hash_use_rtag7 == 0) {
   1638         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1639                     (BSL_META_U(unit,
   1640                                 "ECMP Hash calculation:  non rtag7 calc not supported\n")));
   1641         *hash_value =  0;
   1642         return BCM_E_NONE;
   1643     }
   1644 
   1645     /* check if flow hash is used*/
   1646     SOC_IF_ERROR_RETURN
   1647         (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel));
   1648     if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_ECMPf)) {
   1649         rtag7_ecmp_use_macro_flow_hash =
   1650             soc_reg_field_get(unit, RTAG7_HASH_SELr,
   1651                               rtag7_hash_sel, USE_FLOW_SEL_ECMPf);
   1652     } else {
   1653         rtag7_ecmp_use_macro_flow_hash = 0;
   1654     }
   1655 
   1656     /* RTAG7 hash computation */
   1657     if (rtag7_ecmp_use_macro_flow_hash) {
   1658         SOC_IF_ERROR_RETURN(
   1659             READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY,
   1660                     (hash_Base->rtag7_macro_flow_id & 0xff),
   1661                      &flow_based_hash_entry));    
   1662 
   1663         /* Generating RTAG7 Macro Flow Based Hash Subsel and Offset for use in RSEL1 Stage */
   1664         /* For future designs this logic can be placed in RSEL1 */
   1665         hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 
   1666                                            &flow_based_hash_entry, SUB_SEL_ECMPf);
   1667         hash_offset  = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 
   1668                                            &flow_based_hash_entry, OFFSET_ECMPf);
   1669         concat       = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 
   1670                                            &flow_based_hash_entry, CONCATENATE_HASH_FIELDS_ECMPf);
   1671     } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) {     
   1672         if (hash_Base->dev_src_port < 0) {
   1673             int field_count = 0;
   1674             soc_field_t fields[3];
   1675             uint32 values[3];
   1676             bcm_gport_t gport;
   1677         
   1678             BCM_GPORT_PROXY_SET(gport, 
   1679                 hash_Base->src_modid, hash_Base->src_port);
   1680         
   1681             fields[0] = SUB_SEL_ECMPf;
   1682             field_count++;
   1683             fields[1] = OFFSET_ECMPf;
   1684             field_count++;
   1685             fields[2] = CONCATENATE_HASH_FIELDS_ECMPf;
   1686             field_count++;
   1687             BCM_IF_ERROR_RETURN
   1688                 (bcm_esw_port_lport_fields_get(unit, gport, 
   1689                                                LPORT_PROFILE_RTAG7_TAB,
   1690                                                field_count, fields, values));
   1691             hash_sub_sel = values[0];
   1692             hash_offset  = values[1];
   1693             concat       = values[2];
   1694         } else {
   1695             if (soc_feature(unit, soc_feature_rtag7_port_profile)) {
   1696                 BCM_IF_ERROR_RETURN
   1697                     (_bcm_esw_port_tab_get(unit, hash_Base->dev_src_port,
   1698                                            RTAG7_PORT_PROFILE_INDEXf, &hash_index));
   1699                 port_based_hash_index = (uint32) hash_index;
   1700             } else {
   1701                 port_based_hash_index = hash_Base->dev_src_port +
   1702                                         soc_mem_index_count(unit, LPORT_TABm);
   1703             }
   1704 
   1705             SOC_IF_ERROR_RETURN(     
   1706                 READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 
   1707                             port_based_hash_index, &port_based_hash_entry));
   1708 
   1709             hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   1710                                     &port_based_hash_entry, SUB_SEL_ECMPf);
   1711             hash_offset  = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   1712                                     &port_based_hash_entry, OFFSET_ECMPf);
   1713             concat       = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   1714                                     &port_based_hash_entry, CONCATENATE_HASH_FIELDS_ECMPf);
   1715         }
   1716     } else {
   1717         hash_sub_sel = 0;
   1718         hash_offset  = 0;
   1719         concat       = 0;
   1720     }
   1721 
   1722     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1723                 (BSL_META_U(unit,
   1724                             "ecmp hash_seb_sel=%d, hash_offset=%d, concat=%d\n"),
   1725                  hash_sub_sel, hash_offset, concat));
   1726     BCM_IF_ERROR_RETURN
   1727         (select_gh2_hash_subfield(concat, hash_sub_sel, &hash_subfield, hash_Base));
   1728 
   1729     hash_subfield_width = concat ? 64 : 16;
   1730     hash_offset = concat ? hash_offset : (hash_offset & 0xf);
   1731 
   1732     /* Barrel shift the hash subfield, then take the LSB 16 bits */
   1733     HASH_VALUE_64_COMPUTE(hash_subfield, hash_offset, hash_subfield_width);
   1734     HASH_VALUE_32_COMPUTE(*hash_value, hash_subfield);
   1735     *hash_value &= 0xffff;  
   1736 
   1737     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1738                 (BSL_META_U(unit,
   1739                             "ecmp hash val=%d\n"),
   1740                  *hash_value));
   1741 
   1742     return BCM_E_NONE;
   1743     /* ***************** END of ECMP HASH CALCULATIONS.  ************************ */
   1744 }
   1745 #endif /* INCLUDE_L3 */
   1746 
   1747 /*
   1748  * Function:
   1749  *          compute_gh2_rtag7_hash_trunk
   1750  * Description:
   1751  *     get LAG hash value from RTAG7_PORT_BASED_HASHm 
   1752  *     if unicast, SUB_SEL_TRUNK_UCf and OFFSET_TRUNK_UCf are used 
   1753  *     if not unicast, SUB_SEL_TRUNK_NONUCf and OFFSET_TRUNK_NONUCf
   1754  *     if flow hash is used, get subsel and offset from RTAG7_FLOW_BASED_HASH 
   1755  * Parameters:
   1756  *          unit - StrataSwitch PCI device unit number (driver internal).
   1757  *          hash_Base - internal data where trunk hash value is storead
   1758  *          hash_value- result param 
   1759  * Returns:
   1760  *      BCM_E_xxxx
   1761  */
   1762 STATIC int
   1763 compute_gh2_rtag7_hash_trunk(int unit , bcm_rtag7_base_hash_t *hash_Base,
   1764                          uint32 *hash_value)
   1765 {
   1766     uint32 hash_sub_sel;
   1767     uint32 hash_offset;    
   1768     uint32 rtag7_hash_sel;
   1769     uint32 port_based_hash_index;
   1770     int hash_index = 0;
   1771     uint64 hash_subfield; 
   1772     uint32 hash_subfield_width;
   1773     uint32 offset_shift = 0;
   1774     uint32 concat;
   1775     uint8  rtag7_trunk_use_macro_flow_hash_uc    = 0;
   1776     uint8  rtag7_trunk_use_macro_flow_hash_nonuc = 0;
   1777     rtag7_port_based_hash_entry_t port_based_hash_entry;
   1778     rtag7_flow_based_hash_entry_t flow_based_hash_entry;
   1779     uint32 hash_control;
   1780     uint32 nuc_trunk_hash_use_rtag7;
   1781     
   1782     /* check if flow hash is used for UC*/
   1783     SOC_IF_ERROR_RETURN
   1784         (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel));
   1785     if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_TRUNK_UCf)) {
   1786         rtag7_trunk_use_macro_flow_hash_uc =
   1787             soc_reg_field_get(unit, RTAG7_HASH_SELr,
   1788                               rtag7_hash_sel, USE_FLOW_SEL_TRUNK_UCf);
   1789     } else {
   1790         rtag7_trunk_use_macro_flow_hash_uc = 0; 
   1791     }    
   1792  
   1793     /* check if flow hash is used for NONUC*/
   1794     SOC_IF_ERROR_RETURN
   1795         (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel));
   1796     if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_TRUNK_NONUCf)) {
   1797         rtag7_trunk_use_macro_flow_hash_nonuc =
   1798             soc_reg_field_get(unit, RTAG7_HASH_SELr,
   1799                               rtag7_hash_sel, USE_FLOW_SEL_TRUNK_NONUCf);
   1800     } else {
   1801         rtag7_trunk_use_macro_flow_hash_nonuc = 0; 
   1802     }    
   1803        
   1804     /* RTAG7 hash computation */
   1805     if ((rtag7_trunk_use_macro_flow_hash_nonuc && (hash_Base->is_nonuc == 0)) || 
   1806         (rtag7_trunk_use_macro_flow_hash_uc && (hash_Base->is_nonuc != 0))) {
   1807         SOC_IF_ERROR_RETURN(
   1808             READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY,
   1809                     (hash_Base->rtag7_macro_flow_id & 0xff), 
   1810                      &flow_based_hash_entry)); 
   1811  
   1812         /* in RTAG7_FLOW_BASED_HASHm, using same selection for 
   1813            UC and NONUC */
   1814         hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 
   1815                                        &flow_based_hash_entry, SUB_SEL_TRUNKf);
   1816         hash_offset  = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit,
   1817                                        &flow_based_hash_entry, OFFSET_TRUNKf);
   1818         concat       = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit,
   1819                                        &flow_based_hash_entry, CONCATENATE_HASH_FIELDS_TRUNKf);
   1820         offset_shift = 0xffff;
   1821     } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) {
   1822         if (hash_Base->dev_src_port < 0) {
   1823             int field_count = 0;
   1824             soc_field_t fields[3];
   1825             uint32 values[3];
   1826             bcm_gport_t gport;
   1827 
   1828             BCM_GPORT_PROXY_SET(gport, 
   1829                 hash_Base->src_modid, hash_Base->src_port);
   1830 
   1831             if (hash_Base->is_nonuc) {
   1832                 fields[0] = SUB_SEL_TRUNK_NONUCf ;
   1833                 field_count++;
   1834                 fields[1] = OFFSET_TRUNK_NONUCf;
   1835                 field_count++;
   1836                 fields[2] = CONCATENATE_HASH_FIELDS_TRUNK_NONUCf;
   1837                 field_count++;
   1838                 offset_shift = 0xff;
   1839             } else {
   1840                 fields[0] = SUB_SEL_TRUNK_UCf ;
   1841                 field_count++;
   1842                 fields[1] = OFFSET_TRUNK_UCf;
   1843                 field_count++;
   1844                 fields[2] = CONCATENATE_HASH_FIELDS_TRUNK_UCf;
   1845                 field_count++;
   1846                 offset_shift = 0x3ff;
   1847             }
   1848             BCM_IF_ERROR_RETURN
   1849                 (bcm_esw_port_lport_fields_get(unit, gport, 
   1850                                                LPORT_PROFILE_RTAG7_TAB,
   1851                                                field_count, fields, values));
   1852             hash_sub_sel = values[0];
   1853             hash_offset  = values[1];
   1854             concat       = values[2];
   1855         } else {
   1856             if (soc_feature(unit, soc_feature_rtag7_port_profile)) {
   1857                 BCM_IF_ERROR_RETURN
   1858                     (_bcm_esw_port_tab_get(unit, hash_Base->dev_src_port,
   1859                                            RTAG7_PORT_PROFILE_INDEXf, &hash_index));
   1860                 port_based_hash_index = (uint32) hash_index;
   1861             } else {
   1862                 port_based_hash_index = hash_Base->dev_src_port +
   1863                                         soc_mem_index_count(unit, LPORT_TABm);
   1864             }
   1865 
   1866             SOC_IF_ERROR_RETURN( 
   1867                 READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 
   1868                             port_based_hash_index, &port_based_hash_entry));
   1869             if (hash_Base->is_nonuc) {
   1870                 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   1871                                     &port_based_hash_entry, SUB_SEL_TRUNK_NONUCf);
   1872                 hash_offset  = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   1873                                     &port_based_hash_entry, OFFSET_TRUNK_NONUCf); 
   1874                 concat       = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   1875                                     &port_based_hash_entry, CONCATENATE_HASH_FIELDS_TRUNK_NONUCf); 
   1876                 offset_shift = 0xff; 
   1877             } else {
   1878                 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   1879                                     &port_based_hash_entry, SUB_SEL_TRUNK_UCf); 
   1880                 hash_offset  = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   1881                                     &port_based_hash_entry, OFFSET_TRUNK_UCf);
   1882                 concat       = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   1883                                     &port_based_hash_entry, CONCATENATE_HASH_FIELDS_TRUNK_UCf);
   1884                 offset_shift = 0x3ff; 
   1885             }
   1886         }
   1887     } else {
   1888         hash_sub_sel = 0;
   1889         hash_offset  = 0; 
   1890         concat       = 0;
   1891     }
   1892 
   1893     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1894                 (BSL_META_U(unit,
   1895                             "Trunk hash_seb_sel=%d, hash_offset=%d, concat=%d\n"),
   1896                  hash_sub_sel, hash_offset, concat));
   1897 
   1898     BCM_IF_ERROR_RETURN
   1899         (select_gh2_hash_subfield(concat, hash_sub_sel, &hash_subfield, hash_Base));
   1900 
   1901     hash_subfield_width = concat ? 64 : 16;
   1902     hash_offset = concat ? hash_offset : (hash_offset & 0xf);
   1903 
   1904     /* Barrel shift the hash subfield, then take the LSB 10 bits for UC and 8 bits for nonUC */
   1905     HASH_VALUE_64_COMPUTE(hash_subfield, hash_offset, hash_subfield_width);
   1906     HASH_VALUE_32_COMPUTE(*hash_value, hash_subfield);
   1907     *hash_value &= offset_shift;  
   1908     
   1909     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1910                 (BSL_META_U(unit,
   1911                             "Trunk hash_value=%d\n"),
   1912                  *hash_value));
   1913 
   1914     BCM_IF_ERROR_RETURN
   1915         (READ_HASH_CONTROLr(unit, &hash_control));
   1916     nuc_trunk_hash_use_rtag7 =
   1917         soc_reg_field_get(unit, HASH_CONTROLr, hash_control,
   1918                           NON_UC_TRUNK_HASH_USE_RTAG7f);
   1919 
   1920     if (hash_Base->is_nonuc && nuc_trunk_hash_use_rtag7 == 0) {
   1921         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1922                     (BSL_META_U(unit,
   1923                                 "NonUC trunk Hash calculation:  non rtag7 calc not supported\n")));
   1924         *hash_value = 0;
   1925     }
   1926 
   1927     return BCM_E_NONE;
   1928 }
   1929 
   1930 /*
   1931  * Function:
   1932  *          compute_gh2_rtag7_hash_hg_trunk
   1933  * Description:
   1934  *     get HGT hash value from RTAG7_PORT_BASED_HASHm 
   1935  *     if unicast, SUB_SEL_HG_TRUNK_UCf and OFFSET_HG_TRUNK_UCf are used 
   1936  *     if not unicast, SUB_SEL_TRUNK_NONUCf and OFFSET_HG_TRUNK_NONUCf
   1937  *     if flow hash is used, get subsel and offset from RTAG7_FLOW_BASED_HASH 
   1938  * Parameters:
   1939  *          unit - StrataSwitch PCI device unit number (driver internal).
   1940  *          hash_Base - internal data where trunk hash value is storead
   1941  *          hash_value- result param 
   1942  * Returns:
   1943  *      BCM_E_xxxx
   1944  */
   1945 STATIC int
   1946 compute_gh2_rtag7_hash_hg_trunk(int unit , bcm_rtag7_base_hash_t *hash_Base,
   1947                          uint32 *hash_value)
   1948 {
   1949     uint32 hash_sub_sel;
   1950     uint32 hash_offset;     
   1951     uint32 rtag7_hash_sel; 
   1952     uint32 port_based_hash_index; 
   1953     int hash_index = 0;
   1954     uint64 hash_subfield; 
   1955     uint32 hash_subfield_width;
   1956     uint32 offset_shift = 0;
   1957     uint32 concat;
   1958     uint8  rtag7_hgt_use_macro_flow_hash_uc    = 0;
   1959     uint8  rtag7_hgt_use_macro_flow_hash_nonuc = 0; 
   1960     rtag7_port_based_hash_entry_t port_based_hash_entry; 
   1961     rtag7_flow_based_hash_entry_t flow_based_hash_entry; 
   1962 
   1963     /* check if flow hash is used for UC*/
   1964     SOC_IF_ERROR_RETURN 
   1965         (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 
   1966     if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_HG_TRUNK_UCf)) {
   1967         rtag7_hgt_use_macro_flow_hash_uc =
   1968             soc_reg_field_get(unit, RTAG7_HASH_SELr, 
   1969                               rtag7_hash_sel, USE_FLOW_SEL_HG_TRUNK_UCf);
   1970     } else { 
   1971         rtag7_hgt_use_macro_flow_hash_uc = 0;  
   1972     }
   1973   
   1974     /* check if flow hash is used for NONUC*/
   1975     if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_HG_TRUNK_NONUCf)) {
   1976         rtag7_hgt_use_macro_flow_hash_nonuc = 
   1977             soc_reg_field_get(unit, RTAG7_HASH_SELr, 
   1978                               rtag7_hash_sel, USE_FLOW_SEL_HG_TRUNK_NONUCf);
   1979     } else {
   1980         rtag7_hgt_use_macro_flow_hash_nonuc = 0;  
   1981     }     
   1982         
   1983     /* RTAG7 hash computation */
   1984     if ((rtag7_hgt_use_macro_flow_hash_nonuc && (hash_Base->is_nonuc == 0)) ||
   1985         (rtag7_hgt_use_macro_flow_hash_uc && (hash_Base->is_nonuc != 0))) { 
   1986         SOC_IF_ERROR_RETURN(
   1987             READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY,
   1988                     (hash_Base->rtag7_macro_flow_id & 0xff), 
   1989                      &flow_based_hash_entry)); 
   1990  
   1991         /* in RTAG7_FLOW_BASED_HASHm, using same selection for 
   1992            UC and NONUC */
   1993         hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 
   1994                                        &flow_based_hash_entry, SUB_SEL_HG_TRUNKf);
   1995         hash_offset  = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit,
   1996                                        &flow_based_hash_entry, OFFSET_HG_TRUNKf);
   1997         concat       = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit,
   1998                                        &flow_based_hash_entry, CONCATENATE_HASH_FIELDS_HG_TRUNKf);
   1999         offset_shift = 0xffff;
   2000     } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) {
   2001         if (hash_Base->dev_src_port < 0) {
   2002             int field_count = 0;
   2003             soc_field_t fields[3];
   2004             uint32 values[3];
   2005             bcm_gport_t gport;
   2006 
   2007             BCM_GPORT_PROXY_SET(gport, 
   2008                 hash_Base->src_modid, hash_Base->src_port);
   2009 
   2010             if (hash_Base->is_nonuc) {
   2011                 fields[0] = SUB_SEL_HG_TRUNK_NONUCf ;
   2012                 field_count++;
   2013                 fields[1] = OFFSET_HG_TRUNK_NONUCf;
   2014                 field_count++;
   2015                 fields[2] = CONCATENATE_HASH_FIELDS_HG_TRUNK_NONUCf;
   2016                 field_count++;
   2017                 offset_shift = 0xff;
   2018             } else {
   2019                 fields[0] = SUB_SEL_HG_TRUNK_UCf ;
   2020                 field_count++;
   2021                 fields[1] = OFFSET_HG_TRUNK_UCf;
   2022                 field_count++;
   2023                 fields[2] = CONCATENATE_HASH_FIELDS_HG_TRUNK_UCf;
   2024                 field_count++;
   2025                 offset_shift = 0x3ff;
   2026             }
   2027             BCM_IF_ERROR_RETURN
   2028                 (bcm_esw_port_lport_fields_get(unit, gport, 
   2029                                                LPORT_PROFILE_RTAG7_TAB,
   2030                                                field_count, fields, values));
   2031             hash_sub_sel = values[0];
   2032             hash_offset  = values[1];
   2033             concat       = values[2];
   2034         } else {
   2035             if (soc_feature(unit, soc_feature_rtag7_port_profile)) {
   2036                 BCM_IF_ERROR_RETURN
   2037                     (_bcm_esw_port_tab_get(unit, hash_Base->dev_src_port,
   2038                                            RTAG7_PORT_PROFILE_INDEXf, &hash_index));
   2039                 port_based_hash_index = (uint32) hash_index;
   2040             } else {
   2041                 port_based_hash_index = hash_Base->dev_src_port +
   2042                                         soc_mem_index_count(unit, LPORT_TABm);
   2043             }
   2044 
   2045             SOC_IF_ERROR_RETURN( 
   2046                 READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 
   2047                             port_based_hash_index, &port_based_hash_entry));
   2048             if (hash_Base->is_nonuc) {
   2049                 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   2050                                     &port_based_hash_entry, SUB_SEL_HG_TRUNK_NONUCf);
   2051                 hash_offset  = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   2052                                     &port_based_hash_entry, OFFSET_HG_TRUNK_NONUCf); 
   2053                 concat       = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   2054                                     &port_based_hash_entry, CONCATENATE_HASH_FIELDS_HG_TRUNK_NONUCf); 
   2055                 offset_shift = 0xff; 
   2056             } else {
   2057                 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   2058                                     &port_based_hash_entry, SUB_SEL_HG_TRUNK_UCf); 
   2059                 hash_offset  = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   2060                                     &port_based_hash_entry, OFFSET_HG_TRUNK_UCf);
   2061                 concat       = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   2062                                     &port_based_hash_entry, CONCATENATE_HASH_FIELDS_HG_TRUNK_UCf);
   2063                 offset_shift = 0x3ff; 
   2064             }
   2065         }
   2066     } else {
   2067         hash_sub_sel = 0;
   2068         hash_offset  = 0; 
   2069         concat       = 0;
   2070     }
   2071 
   2072     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2073                 (BSL_META_U(unit,
   2074                             "Trunk hash_seb_sel=%d, hash_offset=%d, concat=%d\n"),
   2075                  hash_sub_sel, hash_offset, concat));
   2076 
   2077     BCM_IF_ERROR_RETURN
   2078         (select_gh2_hash_subfield(concat, hash_sub_sel, &hash_subfield, hash_Base)); 
   2079 
   2080     hash_subfield_width = concat ? 64 : 16;
   2081     hash_offset = concat ? hash_offset : (hash_offset & 0xf);
   2082 
   2083     /* Barrel shift the hash subfield, then take the LSB 10 bits for UC and 8 bits for nonUC */
   2084     HASH_VALUE_64_COMPUTE(hash_subfield, hash_offset, hash_subfield_width);
   2085     HASH_VALUE_32_COMPUTE(*hash_value, hash_subfield);
   2086     *hash_value &= offset_shift;  
   2087     
   2088     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2089                 (BSL_META_U(unit,
   2090                             "HG Trunk hash_value=%d\n"),
   2091                  *hash_value));
   2092 
   2093     return BCM_E_NONE;
   2094 }
   2095 
   2096 /*
   2097  * Function:
   2098  *     get_gh2_hash_trunk
   2099  * Description:
   2100  *     Compute unicast destination trunk member port.
   2101  * Parameters:
   2102  *     unit       - (IN) Device unit number.
   2103  *     tgid       - (IN) Trunk port id.
   2104  *     hash_index - (IN) Hash value calculated from
   2105  *                       compute_gh2_rtag7_hash_trunk.
   2106  *     dst_gport  - (OUT) Where egress member port id is stored.
   2107  *
   2108  * Returns:
   2109  *     BCM_E_xxxx
   2110  */
   2111 STATIC int
   2112 get_gh2_hash_trunk(
   2113     int unit,
   2114     int tgid,
   2115     uint32 hash_index,
   2116     bcm_gport_t *dst_gport)
   2117 {
   2118     uint32 trunk_group_size;
   2119     uint32 rtag;
   2120     uint32 trunk_index;
   2121     bcm_module_t mod_id;
   2122     bcm_port_t port_id;
   2123     int mod_is_local;
   2124     trunk_group_entry_t  tg_entry;
   2125     _bcm_gport_dest_t   dest;
   2126 
   2127     BCM_IF_ERROR_RETURN
   2128         (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tgid, &tg_entry));
   2129 
   2130     trunk_group_size = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, TG_SIZEf);
   2131     rtag = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, RTAGf);
   2132 
   2133     if (rtag != 7) {
   2134         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2135                     (BSL_META_U(unit,
   2136                                 "Hash calculation: uport only RTAG7 calc "
   2137                                 "no support for rtag %d\n"),
   2138                      rtag));
   2139     }
   2140 
   2141     trunk_index = ((hash_index & GH2_RTAG7_HASH_TRUNK_UC_MASK) %
   2142                    (trunk_group_size + 1));
   2143 
   2144     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2145                 (BSL_META_U(unit,
   2146                             "\tTrunk HW index 0x%08x\n"),
   2147                  trunk_index));
   2148     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2149                 (BSL_META_U(unit,
   2150                             "\tTrunk group size 0x%08x\n"),
   2151                  trunk_group_size));
   2152 
   2153     mod_id = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry,
   2154                                           _gh2_modulef[trunk_index]);
   2155     port_id = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry,
   2156                                            _gh2_portf[trunk_index]);
   2157 
   2158     BCM_IF_ERROR_RETURN
   2159         (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, mod_id, port_id,
   2160                                  &(dest.modid), &(dest.port)));
   2161     dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   2162 
   2163     BCM_IF_ERROR_RETURN
   2164         (_bcm_esw_modid_is_local(unit, dest.modid,
   2165                                  &mod_is_local));
   2166     if (mod_is_local) {
   2167         if (IS_ST_PORT(unit, dest.port)) {
   2168             dest.gport_type = _SHR_GPORT_TYPE_DEVPORT;
   2169         }
   2170     }
   2171 
   2172     BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, dst_gport));
   2173 
   2174     return BCM_E_NONE;  
   2175 }
   2176 
   2177 /*
   2178  * Function:
   2179  *     get_gh2_hash_trunk_nuc
   2180  * Description:
   2181  *     Compute non-unicast destination trunk member port 
   2182  * Parameters:
   2183  *  unit - StrataSwitch PCI device unit number (driver internal).
   2184  *  tgid - Trunk group id
   2185  *  fwd_reason - Flow foward reason. unicast, ipmc, l2mc, broadcast, dlf.
   2186  *  hash_index - Hash value calculated based on RTAG7
   2187  *  dst_gport  - Where egress member port id is stored
   2188  *
   2189  * Returns:
   2190  *      BCM_E_xxxx
   2191  */
   2192 STATIC int
   2193 get_gh2_hash_trunk_nuc(int unit, int tgid, 
   2194                    bcm_switch_pkt_hash_info_fwd_reason_t fwd_reason, 
   2195                    uint32 hash_index, bcm_gport_t *dst_gport)
   2196 {
   2197     int nuc_type, nuc_tbm_index;
   2198     int modid, port;
   2199     bcm_pbmp_t local_pbmp, block_mask_pbmp;
   2200     trunk_bitmap_entry_t trunk_bitmap_entry;
   2201     nonucast_trunk_block_mask_entry_t mask_entry;
   2202     uint32 disable_flags = BCM_TRUNK_MEMBER_EGRESS_DISABLE;
   2203 
   2204     switch(fwd_reason) {
   2205     case bcmSwitchPktHashInfoFwdReasonIpmc:
   2206         nuc_type = TRUNK_BLOCK_MASK_TYPE_IPMC;
   2207         disable_flags |= BCM_TRUNK_MEMBER_IPMC_EGRESS_DISABLE;
   2208         break;
   2209     case bcmSwitchPktHashInfoFwdReasonL2mc:
   2210         nuc_type = TRUNK_BLOCK_MASK_TYPE_L2MC;
   2211         disable_flags |= BCM_TRUNK_MEMBER_L2MC_EGRESS_DISABLE;
   2212         break;
   2213     case bcmSwitchPktHashInfoFwdReasonBcast:
   2214         nuc_type = TRUNK_BLOCK_MASK_TYPE_BCAST;
   2215         disable_flags |= BCM_TRUNK_MEMBER_BCAST_EGRESS_DISABLE;
   2216         break;
   2217     case bcmSwitchPktHashInfoFwdReasonDlf:
   2218         nuc_type = TRUNK_BLOCK_MASK_TYPE_DLF;
   2219         disable_flags |= BCM_TRUNK_MEMBER_DLF_EGRESS_DISABLE;
   2220         break;
   2221     default:
   2222         return BCM_E_PARAM;
   2223     }
   2224     nuc_tbm_index = (nuc_type << 4) |
   2225                     (hash_index & GH2_RTAG7_HASH_TRUNK_NUC_MASK);
   2226 
   2227     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2228                 (BSL_META_U(unit,
   2229                             "Nonuc-trunk table index = %d\n"), 
   2230                  nuc_tbm_index));
   2231 
   2232     BCM_IF_ERROR_RETURN(
   2233         READ_NONUCAST_TRUNK_BLOCK_MASKm(unit, MEM_BLOCK_ANY,
   2234                                         nuc_tbm_index, &mask_entry));
   2235     soc_mem_pbmp_field_get(unit, NONUCAST_TRUNK_BLOCK_MASKm, &mask_entry, 
   2236                            BLOCK_MASKf, &block_mask_pbmp);
   2237     BCM_IF_ERROR_RETURN(
   2238         READ_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, tgid, &trunk_bitmap_entry));
   2239     soc_mem_pbmp_field_get(unit, TRUNK_BITMAPm, &trunk_bitmap_entry,
   2240                            TRUNK_BITMAPf, &local_pbmp);
   2241 
   2242     BCM_PBMP_REMOVE(local_pbmp, block_mask_pbmp);
   2243 
   2244     if (BCM_PBMP_IS_NULL(local_pbmp)) {
   2245         /* this means that member is not on local device, try SW prediction */
   2246         bcm_trunk_member_t member_array[BCM_TRUNK_MAX_PORTCNT];
   2247         int member_count;
   2248         bcm_gport_t *port_array = NULL;
   2249         int port_count, port_index;
   2250         int region_size, i, all_local;
   2251 
   2252         BCM_IF_ERROR_RETURN
   2253             (bcm_esw_trunk_get(unit, tgid, NULL, BCM_TRUNK_MAX_PORTCNT, 
   2254                                member_array, &member_count));
   2255 
   2256         port_array = sal_alloc(member_count * sizeof(bcm_gport_t),
   2257                                "port_array");
   2258         if (port_array == NULL) {
   2259             return BCM_E_MEMORY;
   2260         }
   2261 
   2262         port_count = 0;
   2263         all_local = TRUE;
   2264         for (i = 0; i < member_count; i++) {
   2265             if (member_array[i].flags & disable_flags) {
   2266                 continue;
   2267             }
   2268             port = member_array[i].gport;
   2269             port_array[port_count++] = port;
   2270             if (all_local) {
   2271                 if (BCM_FAILURE(bcm_esw_port_local_get(unit, port, &port))) {
   2272                     all_local = FALSE;
   2273                 }
   2274             }
   2275         }
   2276         /* All ports are disabled */
   2277         if (port_count == 0) {
   2278             *dst_gport = -1;
   2279             sal_free(port_array);
   2280             return BCM_E_NOT_FOUND;
   2281         }
   2282         region_size = soc_mem_index_count(unit, NONUCAST_TRUNK_BLOCK_MASKm) / 4;
   2283         if (all_local || port_count > BCM_SWITCH_TRUNK_MAX_PORTCNT) {
   2284             port_index = (nuc_tbm_index % region_size) % port_count;
   2285         } else {
   2286             port_index = (nuc_tbm_index % BCM_XGS3_TRUNK_MAX_PORTCNT) % port_count;
   2287         }
   2288         
   2289         *dst_gport = port_array[port_index];
   2290 
   2291         sal_free(port_array);
   2292 
   2293     } else {
   2294         _bcm_gport_dest_t   dest;
   2295 
   2296         /*Each index only has one egress port */
   2297         BCM_PBMP_ITER(local_pbmp, port) {
   2298             break;
   2299         }
   2300         
   2301         if (port == BCM_PBMP_PORT_MAX) {
   2302             /* If not found in iteration, return not found. It never be here */
   2303             *dst_gport = -1;
   2304             return BCM_E_NOT_FOUND;
   2305         }
   2306 
   2307         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid));
   2308 
   2309         BCM_IF_ERROR_RETURN
   2310             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port,
   2311                                             &(dest.modid), &(dest.port)));
   2312         if (IS_ST_PORT(unit, dest.port)) {
   2313             dest.gport_type = _SHR_GPORT_TYPE_DEVPORT;
   2314         } else {
   2315             dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   2316         }
   2317 
   2318         BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, dst_gport));
   2319     } 
   2320  
   2321     return BCM_E_NONE;
   2322 }
   2323 
   2324 
   2325 #ifdef INCLUDE_L3
   2326 /*
   2327  * Function:
   2328  *          get_gh2_hash_ecmp
   2329  * Description:
   2330  *     compute ecmp destination among multipath interfaces 
   2331  * Parameters:
   2332  *  unit - StrataSwitch PCI device unit number (driver internal).
   2333  *  ecmp_group - multipath id
   2334  *  hash_index - hash value calculated from compute_gh2_ecmp_hash
   2335  *  hash_rh_index -  hash value calculated from compute_gh2_ecmp_rh_hash
   2336  *  nh_id - where egress l3 interface id is stored
   2337  *  ecmp_rh_enable - flag indicating if rh is enable for this hashing calculation
   2338  *  ethertype - Ethertype of a packet
   2339  *
   2340  * Returns:
   2341  *      BCM_E_xxxx
   2342  */
   2343 STATIC int
   2344 get_gh2_hash_ecmp(int unit, int ecmp_group, uint32 hash_index, bcm_if_t *nh_id)
   2345 {
   2346     uint32 ecmp_hash_field_upper_bits_count;
   2347                 
   2348     ecmp_count_entry_t ecmpc_entry;
   2349     ecmp_entry_t ecmp_entry;
   2350     uint32 ecmp_ptr = 0;
   2351     uint32 ecmp_count = 0;
   2352     uint32 hash_control;
   2353     uint32 ecmp_mask;
   2354     uint32 ecmp_offset;
   2355     uint32 ecmp_index;
   2356 
   2357 
   2358     if (SOC_REG_FIELD_VALID(unit, HASH_CONTROLr,
   2359                             ECMP_HASH_FIELD_UPPER_BITS_COUNTf)) {
   2360         SOC_IF_ERROR_RETURN
   2361             (READ_HASH_CONTROLr(unit, &hash_control));
   2362         ecmp_hash_field_upper_bits_count =
   2363             soc_reg_field_get(unit, HASH_CONTROLr, hash_control,
   2364                               ECMP_HASH_FIELD_UPPER_BITS_COUNTf);
   2365     } else {
   2366         ecmp_hash_field_upper_bits_count = 0x6; /* A0 bincomp value */
   2367     }
   2368                 
   2369     /* pick up the ecmp count and base_ptr */
   2370     /* Trident+ ECMP Mode where ECMP resolution is done in one step using a 16Mod10 */
   2371     BCM_IF_ERROR_RETURN
   2372         (READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY, ecmp_group, &ecmpc_entry));
   2373 
   2374     ecmp_ptr = soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry,
   2375                                               BASE_PTRf);
   2376     ecmp_count = soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry,
   2377                                               COUNTf);
   2378     switch (ecmp_hash_field_upper_bits_count) {
   2379     case 0:
   2380         ecmp_mask = 0x3ff;
   2381         break;
   2382     case 1:
   2383         ecmp_mask = 0x7ff;
   2384         break;
   2385     case 2:
   2386         ecmp_mask = 0xfff;
   2387         break;
   2388     case 3:
   2389         ecmp_mask = 0x1fff;
   2390         break;
   2391     case 4:
   2392         ecmp_mask = 0x3fff;
   2393         break;
   2394     case 5:
   2395         ecmp_mask = 0x7fff;
   2396         break;
   2397     case 6:
   2398         ecmp_mask = 0xffff;
   2399         break;
   2400     default:
   2401         ecmp_mask = 0xffff;
   2402         break;
   2403     }
   2404 
   2405     ecmp_offset = ((hash_index & ecmp_mask) % (ecmp_count + 1)) & 0x3FF;
   2406     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2407                 (BSL_META_U(unit,
   2408                             "\tECMP offset 0x%08x, ptr 0x%x\n"),
   2409                  ecmp_offset, ecmp_ptr));
   2410     ecmp_index = (ecmp_ptr + ecmp_offset) & 0xfff;
   2411     BCM_IF_ERROR_RETURN
   2412         (READ_L3_ECMPm(unit, MEM_BLOCK_ANY, ecmp_index, &ecmp_entry));
   2413 
   2414     *nh_id =
   2415         soc_L3_ECMPm_field32_get(unit, &ecmp_entry,
   2416                                  NEXT_HOP_INDEXf);
   2417     *nh_id = *nh_id & 0x3fff;
   2418     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2419                 (BSL_META_U(unit,
   2420                             "\tECMP next hop HW index 0x%08x\n"),
   2421                  *nh_id));
   2422 
   2423     return BCM_E_NONE;  
   2424 }
   2425 #endif /* INCLUDE_L3 */
   2426 
   2427 
   2428 STATIC int
   2429 get_gh2_hash_hg_trunk(
   2430     int unit,
   2431     int hgtid,
   2432     uint32 hash_index,
   2433     bcm_gport_t *dst_gport)
   2434 {
   2435     uint64 hg_trunk_group;
   2436     uint32 trunk_group_size;
   2437     uint32 rtag;
   2438     uint32 trunk_index;
   2439     bcm_module_t mod_id;
   2440     bcm_port_t port_id;
   2441     _bcm_gport_dest_t   dest;
   2442 
   2443     COMPILER_64_ZERO(hg_trunk_group);
   2444     BCM_IF_ERROR_RETURN
   2445         (READ_HG_TRUNK_GROUPr(unit, hgtid, &hg_trunk_group));
   2446 
   2447     trunk_group_size = soc_reg64_field32_get(unit, HG_TRUNK_GROUPr,
   2448                                              hg_trunk_group,
   2449                                              HIGIG_TRUNK_SIZEf);
   2450 
   2451     rtag = soc_reg64_field32_get(unit, HG_TRUNK_GROUPr,
   2452                                  hg_trunk_group,
   2453                                  HIGIG_TRUNK_RTAGf);
   2454 
   2455     if (rtag != 7) {
   2456         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2457                     (BSL_META_U(unit,
   2458                                 "Hash calculation: uport only RTAG7 calc "
   2459                                 "no support for rtag %d\n"),
   2460                      rtag));
   2461     }
   2462 
   2463     trunk_index = ((hash_index & GH2_RTAG7_HASH_TRUNK_UC_MASK) %
   2464                    (trunk_group_size + 1));
   2465 
   2466     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2467                 (BSL_META_U(unit,
   2468                             "\tHG Trunk HW index 0x%08x\n"),
   2469                  trunk_index));
   2470     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2471                 (BSL_META_U(unit,
   2472                             "\tHG Trunk group size 0x%08x\n"),
   2473                  trunk_group_size));
   2474 
   2475     port_id = soc_reg64_field32_get(unit, HG_TRUNK_GROUPr,
   2476                                     hg_trunk_group,
   2477                                     _gh2_hg_portf[trunk_index]);
   2478 
   2479     if (BCM_FAILURE(bcm_esw_stk_my_modid_get(unit, &mod_id))) {
   2480         mod_id = 0;
   2481     }
   2482 
   2483     BCM_IF_ERROR_RETURN
   2484         (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, mod_id, port_id,
   2485                                  &(dest.modid), &(dest.port)));
   2486     dest.gport_type = _SHR_GPORT_TYPE_DEVPORT;
   2487 
   2488     BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, dst_gport));
   2489 
   2490     return BCM_E_NONE;
   2491 }
   2492 
   2493 /*
   2494  * Function:
   2495  *    _bcm_gh2_switch_pkt_info_hash_get
   2496  * Description:
   2497  *    Main gh2 hash get function  
   2498  *
   2499  * Parameters     
   2500  *  unit - StrataSwitch PCI device unit number (driver internal).
   2501  *  pkt_info - struct that carries packet's l2, l3, and l4 information
   2502  *  dst_gport - hashing resolved trunk member port as a return val
   2503  *  dst_intf  - hashing resolved ecmp  member port as a retrun val
   2504  *
   2505  * Returns:
   2506  *      BCM_E_xxxx
   2507  */
   2508 int
   2509 _bcm_gh2_switch_pkt_info_hash_get (int unit,
   2510                                    bcm_switch_pkt_info_t *pkt_info,
   2511                                    bcm_gport_t *dst_gport,
   2512                                    bcm_if_t *dst_intf)
   2513 {
   2514     bcm_rtag7_base_hash_t hash_res;
   2515     int pc_out, mod_is_local;
   2516     bcm_gport_t     port;
   2517     bcm_trunk_t     tid;
   2518     int             id;
   2519     uint32          hash_value;
   2520 
   2521     if (pkt_info == NULL) {
   2522         return BCM_E_PARAM;
   2523     }
   2524 
   2525     if (!_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_GPORT)) {
   2526         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2527                     (BSL_META_U(unit,
   2528                                 "Hash calculation: source gport value missing\n")));
   2529         return BCM_E_PARAM;
   2530     }
   2531 
   2532     BCM_IF_ERROR_RETURN
   2533         (_bcm_esw_gport_resolve(unit, pkt_info->src_gport,
   2534                                 &(hash_res.src_modid),
   2535                                 &(hash_res.src_port), 
   2536                                 &tid, &id));
   2537     if ((-1 != id) || (-1 != tid)) {
   2538         /* Must be single system port */
   2539         return BCM_E_PORT;
   2540     }
   2541 
   2542     /* Load balancing retrieval */
   2543     BCM_IF_ERROR_RETURN(
   2544         _bcm_esw_modid_is_local(unit, hash_res.src_modid, &mod_is_local));
   2545     if (mod_is_local) {
   2546         BCM_IF_ERROR_RETURN
   2547             (bcm_esw_port_local_get(unit, pkt_info->src_gport, &port));
   2548         hash_res.dev_src_port = port;
   2549     } else {
   2550         hash_res.dev_src_port = -1;
   2551         if (BCM_GPORT_IS_PROXY(pkt_info->src_gport)) {
   2552             port = pkt_info->src_gport;
   2553         } else {
   2554             BCM_GPORT_PROXY_SET(port,
   2555                 hash_res.src_modid, hash_res.src_port);
   2556         }
   2557     }
   2558     BCM_IF_ERROR_RETURN
   2559         (bcm_esw_port_control_get(unit, port,
   2560                                 bcmPortControlLoadBalancingNumber,
   2561                                 &pc_out)); 
   2562     hash_res.rtag7_port_lbn = pc_out;
   2563 
   2564     /* Check if the foward reason of packet is all non-uc packet or bit 40 in the mac DA is one. */
   2565     hash_res.is_nonuc = pkt_info->fwd_reason || BCM_MAC_IS_MCAST(pkt_info->dst_mac);
   2566     
   2567     BCM_IF_ERROR_RETURN
   2568         (main_gh2_do_rtag7_hashing(unit, pkt_info, &hash_res));
   2569     BCM_IF_ERROR_RETURN
   2570         (main_gh2_compute_lbid(unit, &hash_res));
   2571 
   2572     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2573                 (BSL_META_U(unit,
   2574                             "Hash status: \n")));
   2575     if (hash_res.hash_a_valid) {
   2576         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2577                     (BSL_META_U(unit,
   2578                                 "\tRTAG7 A0 0x%08x\n"),
   2579                      hash_res.rtag7_hash16_value_a_0));
   2580         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2581                     (BSL_META_U(unit,
   2582                                 "\tRTAG7 A1 0x%08x\n"),
   2583                      hash_res.rtag7_hash16_value_a_1));
   2584     } else {
   2585         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2586                     (BSL_META_U(unit,
   2587                                 "\tRTAG7 A hashes invalid due to missing packet info\n")));
   2588     }
   2589     if (hash_res.hash_b_valid) {
   2590         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2591                     (BSL_META_U(unit,
   2592                                 "\tRTAG7 B0 0x%08x\n"),
   2593                      hash_res.rtag7_hash16_value_b_0));
   2594         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2595                     (BSL_META_U(unit,
   2596                                 "\tRTAG7 B1 0x%08x\n"),
   2597                      hash_res.rtag7_hash16_value_b_1));
   2598     } else {
   2599         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2600                     (BSL_META_U(unit,
   2601                                 "\tRTAG7 B hashes invalid due to missing packet info\n")));
   2602     }
   2603     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2604                 (BSL_META_U(unit,
   2605                             "\tRTAG7 LBN 0x%08x\n"),
   2606                  hash_res.rtag7_port_lbn));
   2607     if (hash_res.lbid_hash_valid){
   2608         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2609                     (BSL_META_U(unit,
   2610                                 "\tRTAG7 LBID 0x%08x\n"),
   2611                      hash_res.rtag7_lbid_hash));
   2612     } else {
   2613         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2614                     (BSL_META_U(unit,
   2615                                 "\tRTAG7 LBID not valid due to non-RTAG7 configuration\n")));
   2616     }
   2617 
   2618 #ifdef INCLUDE_L3
   2619     if (0 != (pkt_info->flags & BCM_SWITCH_PKT_INFO_HASH_MULTIPATH)) {
   2620         bcm_if_t        nh_id;
   2621 
   2622         if (dst_intf == NULL) {
   2623             return BCM_E_PARAM;
   2624         }
   2625 
   2626         BCM_IF_ERROR_RETURN
   2627             (compute_gh2_ecmp_hash(unit, &hash_res, &hash_value));
   2628         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2629                     (BSL_META_U(unit,
   2630                                 "\tECMP Hash value 0x%08x\n"),
   2631                      hash_value));
   2632 
   2633         BCM_IF_ERROR_RETURN
   2634             (get_gh2_hash_ecmp(unit,
   2635                 pkt_info->mpintf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit),
   2636                 hash_value, &nh_id));
   2637         /* Convert to egress object format */
   2638         *dst_intf = nh_id + BCM_XGS3_EGRESS_IDX_MIN(unit);
   2639     } else
   2640 #endif /* INCLUDE_L3 */
   2641     if (0 != (pkt_info->flags & BCM_SWITCH_PKT_INFO_HASH_TRUNK)) {
   2642         bcm_trunk_t trunk = BCM_TRUNK_INVALID;
   2643         int member_count;
   2644         bcm_trunk_chip_info_t   ti;
   2645 
   2646         if (dst_gport == NULL) {
   2647             return BCM_E_PARAM;
   2648         }
   2649 
   2650         if (!BCM_GPORT_IS_TRUNK(pkt_info->trunk_gport)) {
   2651             return BCM_E_PORT;
   2652         }
   2653         trunk = BCM_GPORT_TRUNK_GET(pkt_info->trunk_gport);
   2654         BCM_IF_ERROR_RETURN
   2655             (bcm_esw_trunk_get(unit, trunk, NULL, 0, NULL, &member_count));
   2656         if (0 == member_count) {
   2657             /* Return failure for no trunk members */
   2658             return BCM_E_FAIL;
   2659         }
   2660 
   2661         BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &ti));
   2662 
   2663         if (trunk >= ti.trunk_id_min && trunk <= ti.trunk_id_max) {
   2664             BCM_IF_ERROR_RETURN
   2665                 (compute_gh2_rtag7_hash_trunk(unit, &hash_res, &hash_value));
   2666             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2667                         (BSL_META_U(unit,
   2668                                     "\tTrunk Hash value 0x%08x\n"),
   2669                          hash_value));
   2670             if (hash_res.is_nonuc) {
   2671                 BCM_IF_ERROR_RETURN
   2672                     (get_gh2_hash_trunk_nuc(unit, trunk, pkt_info->fwd_reason, 
   2673                                 hash_value, dst_gport));
   2674             } else {
   2675                 BCM_IF_ERROR_RETURN
   2676                     (get_gh2_hash_trunk(unit, trunk,
   2677                                     hash_value, dst_gport));
   2678             }
   2679         } else if (trunk >= ti.trunk_fabric_id_min && trunk <= ti.trunk_fabric_id_max) {
   2680             BCM_IF_ERROR_RETURN
   2681                 (compute_gh2_rtag7_hash_hg_trunk(unit, &hash_res, &hash_value));
   2682             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2683                         (BSL_META_U(unit,
   2684                                     "\tHG-Trunk Hash value 0x%08x\n"),
   2685                          hash_value));
   2686             BCM_IF_ERROR_RETURN
   2687                 (get_gh2_hash_hg_trunk(unit, trunk - ti.trunk_fabric_id_min,
   2688                                 hash_value, dst_gport));
   2689         }
   2690     } else if (pkt_info->flags & BCM_SWITCH_PKT_INFO_HASH_LBID) {
   2691         /* LBID hashing resolution */
   2692         if (dst_intf == NULL || hash_res.lbid_hash_valid == 0) {
   2693             return BCM_E_FAIL;
   2694         } else {
   2695             *dst_intf = hash_res.rtag7_lbid_hash;
   2696         }
   2697     } else {
   2698         return BCM_E_PARAM;
   2699     }
   2700     
   2701     return BCM_E_NONE;
   2702 }