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 (103608B)


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