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


      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:     TD2-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_RH_MODE_ECMP    0
     49 #define RTAG7_RH_MODE_LAG     1
     50 #define RTAG7_RH_MODE_HGT     2
     51 
     52 #define RTAG7_L2_ONLY         0x0
     53 #define RTAG7_UNKNOWN_HIGIG   0x1
     54 #define RTAG7_MPLS            0x2
     55 #define RTAG7_MIM             0x3
     56 #define RTAG7_IPV4            0x4
     57 #define RTAG7_IPV6            0x5
     58 #define RTAG7_FCOE            0x6
     59 #define RTAG7_TRILL           0x7
     60 
     61 #define ENHANCED_HASHING_CONTROLRH_FLOWSET_TABLE_CONFIG_ENCODING_HALF_AND_HALF 0
     62 #define ENHANCED_HASHING_CONTROLRH_FLOWSET_TABLE_CONFIG_ENCODING_ALL_ECMP      1
     63 #define ENHANCED_HASHING_CONTROLRH_FLOWSET_TABLE_CONFIG_ENCODING_ALL_LAG       2
     64 
     65 #define RH_LAG_FLOWSET_MOD_ID_SHIFT_VAL 7
     66 
     67 #define HASH_VALUE_64_COMPUTE(subfield,offset,width) do { \
     68         uint64 sf; \
     69         COMPILER_64_ZERO(sf); \
     70         COMPILER_64_ADD_64(sf, subfield); \
     71         COMPILER_64_SHR(subfield, offset); \
     72         COMPILER_64_SHL(sf, (width - offset)); \
     73         COMPILER_64_OR(subfield, sf); \
     74     } while(0)
     75 
     76 #define HASH_VALUE_32_COMPUTE(hash_value_32, hash_value_64) do { \
     77         COMPILER_64_TO_32_LO(hash_value_32, hash_value_64); \
     78     } while(0)
     79 
     80 
     81 /*
     82  * Function:
     83  *          main_td2_do_rtag7_hashing
     84  * Description:
     85  *          read hash control register values and
     86  *          set hash_res' fields
     87  * Parameters:
     88  *          unit - StrataSwitch PCI device unit number (driver internal).
     89  *          pkt_info - ptr to data that has packet information
     90  *          hash_res - internal data where hashing informaiton is stored 
     91  * Returns:
     92  *      BCM_E_xxxx
     93  */
     94 STATIC int
     95 main_td2_do_rtag7_hashing(int unit,
     96                        bcm_switch_pkt_info_t *pkt_info,
     97                        bcm_rtag7_base_hash_t *hash_res)
     98 {
     99     /* regular var declaration */
    100     uint32      hash_src_port;
    101     uint32      hash_src_modid;
    102     uint32      rtag7_a_sel;
    103     bcm_ip_t            sip_a;       /* Source IPv4 address. */
    104     bcm_ip_t            dip_a;       /* Destination IPv4 address. */
    105     uint32      rtag7_b_sel;
    106     bcm_ip_t            sip_b;       /* Source IPv4 address. */
    107     bcm_ip_t            dip_b;       /* Destination IPv4 address. */
    108     uint32      hash_field_bmap_a;   /* block A chosen bitmap*/
    109     uint32      hash_field_bmap_b;   /* block B chosen bitmap*/
    110     
    111     uint32 hash_word[7];
    112     uint32 hash[13];
    113     int    elem, elem_bit;
    114     uint32 hash_element_valid_bits;
    115     int    sip_valid = FALSE, dip_valid = FALSE;
    116     uint32 macro_flow_id;
    117     
    118     uint32 hash_crc16_bisync;
    119     uint32 hash_crc16_ccitt;
    120     uint32 hash_crc32;
    121     uint32 hash_xor16;
    122     uint32 hash_xor8;
    123     uint32 hash_xor4;
    124     uint32 hash_xor2;
    125     uint32 hash_xor1;
    126     uint32 xor32;
    127 
    128     /* register var declaration */
    129     uint8 rtag7_disable_hash_ipv4_a;
    130     uint8 rtag7_disable_hash_ipv6_a;
    131     uint8 rtag7_disable_hash_ipv4_b;
    132     uint8 rtag7_disable_hash_ipv6_b;
    133     uint8 rtag7_ipv6_addr_use_lsb_a;
    134     uint8 rtag7_ipv6_addr_use_lsb_b;
    135     uint8 rtag7_pre_processing_enable_a;
    136     uint8 rtag7_pre_processing_enable_b;
    137     uint8 rtag7_en_flow_label_ipv6_a;
    138     uint8 rtag7_en_flow_label_ipv6_b;
    139     uint8 rtag7_en_bin_12_overlay_a;
    140     uint8 rtag7_en_bin_12_overlay_b;
    141     uint32 rtag7_hash_seed_a;
    142     uint32 rtag7_hash_seed_b;
    143     uint32 rtag7_hash_a0_function_select;
    144     uint32 rtag7_hash_a1_function_select;
    145     uint32 rtag7_hash_b0_function_select;
    146     uint32 rtag7_hash_b1_function_select;
    147     uint32 rtag7_macro_flow_hash_function_select;
    148     uint8 rtag7_macro_flow_hash_byte_sel;
    149 
    150     uint64 rtag7_hash_control, rtag7_hash_control_2_64;
    151     uint32 rtag7_hash_control_2, rtag7_hash_control_3;
    152     uint32 rtag7_hash_seed_a_reg, rtag7_hash_seed_b_reg;
    153     soc_reg_t sc_reg;
    154     soc_field_t sc_field;
    155     uint32 sc_val;
    156     int symmetric_hash_control_mask = 0;
    157     int symmetric_hash_need_swap_ip6 = 0;
    158     int symmetric_hash_need_swap_ip4 = 0;
    159 
    160     /* read RTAG7 hash control register values */
    161     SOC_IF_ERROR_RETURN
    162         (READ_RTAG7_HASH_CONTROLr(unit, &rtag7_hash_control));
    163     if (SOC_REG_IS_VALID(unit, RTAG7_HASH_CONTROL_2_64r)) {
    164         SOC_IF_ERROR_RETURN
    165             (READ_RTAG7_HASH_CONTROL_2_64r(unit, &rtag7_hash_control_2_64));
    166     } else if (SOC_REG_IS_VALID(unit, RTAG7_HASH_CONTROL_2r)) {
    167         SOC_IF_ERROR_RETURN
    168             (READ_RTAG7_HASH_CONTROL_2r(unit, &rtag7_hash_control_2));
    169     }
    170     SOC_IF_ERROR_RETURN
    171         (READ_RTAG7_HASH_CONTROL_3r(unit, &rtag7_hash_control_3));
    172     SOC_IF_ERROR_RETURN
    173         (READ_RTAG7_HASH_SEED_Ar(unit, &rtag7_hash_seed_a_reg));
    174     SOC_IF_ERROR_RETURN
    175         (READ_RTAG7_HASH_SEED_Br(unit, &rtag7_hash_seed_b_reg));
    176 
    177     /* read RTAG7 fields from hash control registers */
    178     rtag7_disable_hash_ipv4_a =
    179         soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control,
    180                           DISABLE_HASH_IPV4_Af);
    181     rtag7_disable_hash_ipv6_a =
    182         soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control,
    183                           DISABLE_HASH_IPV6_Af);
    184     rtag7_disable_hash_ipv4_b =
    185         soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control,
    186                           DISABLE_HASH_IPV4_Bf);
    187     rtag7_disable_hash_ipv6_b =
    188         soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control,
    189                           DISABLE_HASH_IPV6_Bf);
    190     rtag7_ipv6_addr_use_lsb_a =
    191         soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control,
    192                           IPV6_COLLAPSED_ADDR_SELECT_Af);
    193     rtag7_ipv6_addr_use_lsb_b =
    194         soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control,
    195                           IPV6_COLLAPSED_ADDR_SELECT_Bf);
    196 
    197     /* read RTAG7 fields from hash control3 registers */
    198     rtag7_pre_processing_enable_a =
    199         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3,
    200                           HASH_PRE_PROCESSING_ENABLE_Af);
    201     rtag7_pre_processing_enable_b =
    202         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3,
    203                           HASH_PRE_PROCESSING_ENABLE_Bf);
    204     rtag7_hash_a0_function_select =
    205         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3,
    206                           HASH_A0_FUNCTION_SELECTf);
    207     rtag7_hash_a1_function_select =
    208         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3,
    209                           HASH_A1_FUNCTION_SELECTf);
    210     rtag7_hash_b0_function_select =
    211         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3,
    212                           HASH_B0_FUNCTION_SELECTf);
    213     rtag7_hash_b1_function_select =
    214         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3,
    215                           HASH_B1_FUNCTION_SELECTf);
    216 
    217     /* read RTAG7 fields from hash control2 registers */
    218     if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r,
    219                             ENABLE_FLOW_LABEL_IPV6_Af)) {
    220         rtag7_en_flow_label_ipv6_a =
    221             soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r,
    222                               rtag7_hash_control_2,
    223                               ENABLE_FLOW_LABEL_IPV6_Af);
    224     } else if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2_64r,
    225                                    ENABLE_FLOW_LABEL_IPV6_Af)) {
    226         rtag7_en_flow_label_ipv6_a =
    227             soc_reg64_field32_get(unit, RTAG7_HASH_CONTROL_2_64r,
    228                               rtag7_hash_control_2_64,
    229                               ENABLE_FLOW_LABEL_IPV6_Af);
    230     } else {
    231         rtag7_en_flow_label_ipv6_a = 0;
    232     }
    233     if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r,
    234                             ENABLE_FLOW_LABEL_IPV6_Bf)) {
    235         rtag7_en_flow_label_ipv6_b =
    236             soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r,
    237                               rtag7_hash_control_2,
    238                               ENABLE_FLOW_LABEL_IPV6_Bf);
    239     } else if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2_64r,
    240                                    ENABLE_FLOW_LABEL_IPV6_Bf)) {
    241         rtag7_en_flow_label_ipv6_b =
    242             soc_reg64_field32_get(unit, RTAG7_HASH_CONTROL_2_64r,
    243                               rtag7_hash_control_2_64,
    244                               ENABLE_FLOW_LABEL_IPV6_Bf);
    245     } else {
    246         rtag7_en_flow_label_ipv6_b = 0;
    247     }
    248     if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r,
    249                             ENABLE_BIN_12_OVERLAY_Af)) {
    250         rtag7_en_bin_12_overlay_a =
    251             soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r,
    252                               rtag7_hash_control_2,
    253                               ENABLE_BIN_12_OVERLAY_Af);
    254     } else if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2_64r,
    255                                    ENABLE_BIN_12_OVERLAY_Af)) {
    256         rtag7_en_bin_12_overlay_a =
    257             soc_reg64_field32_get(unit, RTAG7_HASH_CONTROL_2_64r,
    258                               rtag7_hash_control_2_64,
    259                               ENABLE_BIN_12_OVERLAY_Af);
    260     } else {
    261         rtag7_en_bin_12_overlay_a = 0;
    262     }
    263     if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r,
    264                             ENABLE_BIN_12_OVERLAY_Bf)) {
    265         rtag7_en_bin_12_overlay_b =
    266             soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r,
    267                               rtag7_hash_control_2,
    268                               ENABLE_BIN_12_OVERLAY_Bf);
    269     } else if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2_64r,
    270                                    ENABLE_BIN_12_OVERLAY_Bf)) {
    271         rtag7_en_bin_12_overlay_b =
    272             soc_reg64_field32_get(unit, RTAG7_HASH_CONTROL_2_64r,
    273                               rtag7_hash_control_2_64,
    274                               ENABLE_BIN_12_OVERLAY_Bf);
    275     } else {
    276         rtag7_en_bin_12_overlay_b = 0;
    277     }
    278     if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r,
    279                             MACRO_FLOW_HASH_FUNC_SELf)) {
    280         rtag7_macro_flow_hash_function_select =
    281             soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r,
    282                               rtag7_hash_control_2,
    283                               MACRO_FLOW_HASH_FUNC_SELf);
    284     } else if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2_64r,
    285                                    MACRO_FLOW_HASH_FUNC_SELf)) {
    286         rtag7_macro_flow_hash_function_select =
    287             soc_reg64_field32_get(unit, RTAG7_HASH_CONTROL_2_64r,
    288                               rtag7_hash_control_2_64,
    289                               MACRO_FLOW_HASH_FUNC_SELf);
    290     } else {
    291         rtag7_macro_flow_hash_function_select = 0;
    292     }
    293     if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r,
    294                             MACRO_FLOW_HASH_BYTE_SELf)) {
    295         rtag7_macro_flow_hash_byte_sel =
    296             soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r,
    297                               rtag7_hash_control_2,
    298                               MACRO_FLOW_HASH_BYTE_SELf);
    299     } else if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2_64r,
    300                                    MACRO_FLOW_HASH_BYTE_SELf)) {
    301         rtag7_macro_flow_hash_byte_sel =
    302             soc_reg64_field32_get(unit, RTAG7_HASH_CONTROL_2_64r,
    303                               rtag7_hash_control_2_64,
    304                               MACRO_FLOW_HASH_BYTE_SELf);
    305     } else {
    306         rtag7_macro_flow_hash_byte_sel = 0;
    307     }
    308 
    309     /* read RTAG7 fields from hash seed registers */
    310     rtag7_hash_seed_a =
    311         soc_reg_field_get(unit, RTAG7_HASH_SEED_Ar, rtag7_hash_seed_a_reg,
    312                           HASH_SEED_Af);
    313     rtag7_hash_seed_b =
    314         soc_reg_field_get(unit, RTAG7_HASH_SEED_Br, rtag7_hash_seed_b_reg,
    315                           HASH_SEED_Bf);
    316 
    317 #if defined(BCM_TRIUMPH3_SUPPORT)
    318     if (BCM_SUCCESS(bcm_esw_switch_control_get(unit,
    319             bcmSwitchSymmetricHashControl, &symmetric_hash_control_mask))) {
    320         if (symmetric_hash_control_mask & 
    321             (BCM_SYMMETRIC_HASH_0_IP6_ENABLE | BCM_SYMMETRIC_HASH_1_IP6_ENABLE)) {
    322             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6) && 
    323                 _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6) &&
    324                 (sal_memcmp(pkt_info->sip6, pkt_info->dip6, BCM_IP6_ADDRLEN) < 0)) {
    325                 symmetric_hash_need_swap_ip6 = 1;
    326             }
    327         }
    328         if (symmetric_hash_control_mask & 
    329             (BCM_SYMMETRIC_HASH_0_IP4_ENABLE | BCM_SYMMETRIC_HASH_1_IP4_ENABLE)) {
    330             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IP) && 
    331                 _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IP) &&
    332                 (pkt_info->sip < pkt_info->dip)) {
    333                 symmetric_hash_need_swap_ip4 = 1;
    334             }
    335         }
    336     }
    337 #endif /* BCM_TRIUMPH3_SUPPORT */
    338 
    339     /* RTAG7 tables */
    340     /* the first step is to choose the paket type and to fold the ipv6
    341      * addresses in case of IPv6 packet*/   
    342 
    343     /* option A ip folding for rtag 7 */
    344     if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) &&
    345          (pkt_info->ethertype == ETHERTYPE_IPV6)) &&
    346                (rtag7_disable_hash_ipv6_a == 0)) {
    347 
    348         rtag7_a_sel = RTAG7_IPV6;
    349         
    350         /* This section will fold the Ipv6 address to single 32 bit address
    351          * by using of of the methose LSB or xor */
    352         if (rtag7_ipv6_addr_use_lsb_a) {
    353             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) {
    354                 sip_a = (pkt_info->sip6[12] << 24) |
    355                     (pkt_info->sip6[13] << 16) |
    356                     (pkt_info->sip6[14] << 8) |
    357                     (pkt_info->sip6[15]);
    358                 sip_valid = TRUE;
    359             } else {
    360                 sip_a = 0;
    361             }
    362             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) {
    363                 dip_a = (pkt_info->dip6[12] << 24) |
    364                     (pkt_info->dip6[13] << 16) |
    365                     (pkt_info->dip6[14] << 8) |
    366                     (pkt_info->dip6[15]);
    367                 dip_valid = TRUE;
    368             } else {
    369                 dip_a = 0;
    370             }
    371         } else {   
    372             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) {
    373                 sip_a =
    374                     ((pkt_info->sip6[12] << 24) |
    375                      (pkt_info->sip6[13] << 16) |
    376                      (pkt_info->sip6[14] << 8) |
    377                      (pkt_info->sip6[15])) ^
    378                     ((pkt_info->sip6[8] << 24) |
    379                      (pkt_info->sip6[9] << 16) |
    380                      (pkt_info->sip6[10] << 8) |
    381                      (pkt_info->sip6[11])) ^
    382                     ((pkt_info->sip6[4] << 24) |
    383                      (pkt_info->sip6[5] << 16) |
    384                      (pkt_info->sip6[6] << 8) |
    385                      (pkt_info->sip6[7])) ^
    386                     ((pkt_info->sip6[0] << 24) |
    387                      (pkt_info->sip6[1] << 16) |
    388                      (pkt_info->sip6[2] << 8) |
    389                      (pkt_info->sip6[3]));
    390                 sip_valid = TRUE;
    391             } else {
    392                 sip_a = 0;
    393             }
    394 
    395             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) {
    396                 dip_a =
    397                     ((pkt_info->dip6[12] << 24) |
    398                      (pkt_info->dip6[13] << 16) |
    399                      (pkt_info->dip6[14] << 8) |
    400                      (pkt_info->dip6[15])) ^
    401                     ((pkt_info->dip6[8] << 24) |
    402                      (pkt_info->dip6[9] << 16) |
    403                      (pkt_info->dip6[10] << 8) |
    404                      (pkt_info->dip6[11])) ^
    405                     ((pkt_info->dip6[4] << 24) |
    406                      (pkt_info->dip6[5] << 16) |
    407                      (pkt_info->dip6[6] << 8) |
    408                      (pkt_info->dip6[7])) ^
    409                     ((pkt_info->dip6[0] << 24) |
    410                      (pkt_info->dip6[1] << 16) |
    411                      (pkt_info->dip6[2] << 8) |
    412                      (pkt_info->dip6[3]));
    413                 dip_valid = TRUE;
    414             } else {
    415                 dip_a = 0;
    416             }
    417         }
    418     } else if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) &&
    419                 (pkt_info->ethertype == ETHERTYPE_IPV4)) && 
    420                (rtag7_disable_hash_ipv4_a == 0)) {
    421 
    422         rtag7_a_sel = RTAG7_IPV4;
    423 
    424         /* only one IPv4 hdr */
    425         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IP)) {
    426             sip_a = pkt_info->sip;
    427             sip_valid = TRUE;
    428         } else {
    429             sip_a = 0;
    430         }
    431         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IP)) {
    432             dip_a = pkt_info->dip;
    433             dip_valid = TRUE;
    434         } else {
    435             dip_a = 0;
    436         }
    437     } else {
    438         rtag7_a_sel = RTAG7_L2_ONLY;
    439         sip_a = dip_a = 0;
    440     }
    441 
    442     /* End of option A ip folding for rtag 7 */
    443 
    444     /* option B ip folding for rtag 7 */
    445     if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) &&
    446          (pkt_info->ethertype == ETHERTYPE_IPV6)) &&
    447                (rtag7_disable_hash_ipv6_b == 0)) {
    448 
    449         rtag7_b_sel = RTAG7_IPV6;
    450         
    451         /* This section will fold the Ipv6 address to single 32 bit address
    452          * by using of of the methose LSB or xor */
    453         if (rtag7_ipv6_addr_use_lsb_b) {
    454             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) {
    455                 sip_b = (pkt_info->sip6[12] << 24) |
    456                     (pkt_info->sip6[13] << 16) |
    457                     (pkt_info->sip6[14] << 8) |
    458                     (pkt_info->sip6[15]);
    459                 sip_valid = TRUE;
    460             } else {
    461                 sip_b = 0;
    462             }
    463             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) {
    464                 dip_b = (pkt_info->dip6[12] << 24) |
    465                     (pkt_info->dip6[13] << 16) |
    466                     (pkt_info->dip6[14] << 8) |
    467                     (pkt_info->dip6[15]);
    468                 dip_valid = TRUE;
    469             } else {
    470                 dip_b = 0;
    471             }
    472         } else {   
    473             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) {
    474                 sip_b =
    475                     ((pkt_info->sip6[12] << 24) |
    476                      (pkt_info->sip6[13] << 16) |
    477                      (pkt_info->sip6[14] << 8) |
    478                      (pkt_info->sip6[15])) ^
    479                     ((pkt_info->sip6[8] << 24) |
    480                      (pkt_info->sip6[9] << 16) |
    481                      (pkt_info->sip6[10] << 8) |
    482                      (pkt_info->sip6[11])) ^
    483                     ((pkt_info->sip6[4] << 24) |
    484                      (pkt_info->sip6[5] << 16) |
    485                      (pkt_info->sip6[6] << 8) |
    486                      (pkt_info->sip6[7])) ^
    487                     ((pkt_info->sip6[0] << 24) |
    488                      (pkt_info->sip6[1] << 16) |
    489                      (pkt_info->sip6[2] << 8) |
    490                      (pkt_info->sip6[3]));
    491                 sip_valid = TRUE;
    492             } else {
    493                 sip_b = 0;
    494             }
    495 
    496             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) {
    497                 dip_b =
    498                     ((pkt_info->dip6[12] << 24) |
    499                      (pkt_info->dip6[13] << 16) |
    500                      (pkt_info->dip6[14] << 8) |
    501                      (pkt_info->dip6[15])) ^
    502                     ((pkt_info->dip6[8] << 24) |
    503                      (pkt_info->dip6[9] << 16) |
    504                      (pkt_info->dip6[10] << 8) |
    505                      (pkt_info->dip6[11])) ^
    506                     ((pkt_info->dip6[4] << 24) |
    507                      (pkt_info->dip6[5] << 16) |
    508                      (pkt_info->dip6[6] << 8) |
    509                      (pkt_info->dip6[7])) ^
    510                     ((pkt_info->dip6[0] << 24) |
    511                      (pkt_info->dip6[1] << 16) |
    512                      (pkt_info->dip6[2] << 8) |
    513                      (pkt_info->dip6[3]));
    514                 dip_valid = TRUE;
    515             } else {
    516                 dip_b = 0;
    517             }
    518         }      
    519     } else if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) &&
    520                 (pkt_info->ethertype == ETHERTYPE_IPV4)) && 
    521                (rtag7_disable_hash_ipv4_b == 0)) {
    522                
    523         rtag7_b_sel = RTAG7_IPV4;
    524 
    525         /* only one IPv4 hdr */
    526         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IP)) {
    527             sip_b = pkt_info->sip;
    528             sip_valid = TRUE;
    529         } else {
    530             sip_b = 0;
    531         }
    532         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IP)) {
    533             dip_b = pkt_info->dip;
    534             dip_valid = TRUE;
    535         } else {
    536             dip_b = 0;
    537         }
    538     } else {    
    539         rtag7_b_sel = RTAG7_L2_ONLY;
    540         sip_b = dip_b = 0;
    541     }
    542     /* End of option B ip folding for rtag 7 */
    543 
    544 
    545 
    546     /*
    547      * =============
    548      * RTAG7 HASHING 
    549      * =============
    550      */
    551 
    552     /* The inputs to the RTAG7 hash function were reduced in the begining
    553      * of this function.  
    554      * This logic takes the hash inputs and computes both A and B RTAG7
    555      * hash values.
    556      */
    557 
    558     /* Change source modid/port to PORT32 space for hashing */
    559     hash_src_port  = hash_res->src_port;
    560     hash_src_modid = hash_res->src_modid;
    561 
    562     /* Only if the packet was sourced by this chip, make sure to use
    563      * PORT32 space modid and port if dual modid is enabled
    564      * Need to do this because of front panel ports.
    565      *
    566      * Already handled by API gport resolve */
    567 
    568     /* initialize the variables */   
    569     sal_memset(hash,0x0,(sizeof(uint32))*13);
    570     sal_memset(hash_word,0x0,(sizeof(uint32))*7);
    571     
    572     hash_crc16_bisync = 0;
    573     hash_crc16_ccitt = 0;
    574     hash_crc32      = 0;
    575     hash_xor16      = 0;
    576     hash_xor8       = 0;
    577     hash_xor4       = 0;
    578     hash_xor2       = 0;
    579     hash_xor1       = 0;
    580     xor32           = 0;
    581 
    582     hash[12] = 0;   
    583     hash[3] = hash_src_port;
    584     hash[2] = hash_src_modid & 0xff;
    585     hash[1] = 0;
    586     hash[0] = 0;
    587 
    588     hash_element_valid_bits = 0x1fff; /* Init to valid fields above */
    589 
    590     /* option A hash calculation for rtag 7 */
    591     
    592     if ((rtag7_a_sel == RTAG7_IPV6) || (rtag7_a_sel == RTAG7_IPV4)) {
    593 
    594         if (sip_valid) {
    595             hash[11] = (sip_a >> 16) & 0xffff;
    596             hash[10] =  sip_a & 0xffff;
    597         } else {
    598             hash_element_valid_bits &= ~0xc00;
    599         }
    600         if (dip_valid) {
    601             hash[9]  = (dip_a >> 16) & 0xffff;
    602             hash[8]  =  dip_a & 0xffff;
    603         } else {
    604             hash_element_valid_bits &= ~0x300;
    605         }
    606 
    607         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) {
    608             hash[7]  = pkt_info->vid & 0xfff;
    609         } else {
    610             hash_element_valid_bits &= ~0x80;
    611         }
    612         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT)) {
    613             hash[6]  = pkt_info->src_l4_port;
    614         } else {
    615             hash_element_valid_bits &= ~0x40;
    616         }
    617         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT)) {
    618             hash[5]  = pkt_info->dst_l4_port;
    619         } else {
    620             hash_element_valid_bits &= ~0x20;
    621         }
    622         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL)) {
    623             hash[4]  = pkt_info->protocol;
    624         } else {
    625             hash_element_valid_bits &= ~0x10;
    626         }
    627 
    628         /* Symmetric hash swap src/dst ipaddr/l4_port for option A */
    629         if (((rtag7_a_sel == RTAG7_IPV6) && 
    630             symmetric_hash_need_swap_ip6 && 
    631             (symmetric_hash_control_mask & BCM_SYMMETRIC_HASH_0_IP6_ENABLE)) 
    632             ||
    633             ((rtag7_a_sel == RTAG7_IPV4) && 
    634             symmetric_hash_need_swap_ip4 && 
    635             (symmetric_hash_control_mask & BCM_SYMMETRIC_HASH_0_IP4_ENABLE))) {
    636 
    637             uint32 temp;
    638             temp = hash[11]; hash[11] = hash[9]; hash[9] = temp;
    639             temp = hash[10]; hash[10] = hash[8]; hash[8] = temp;
    640             temp = hash[6]; hash[6] = hash[5]; hash[5] = temp;
    641             LOG_VERBOSE(BSL_LS_BCM_COMMON,
    642                         (BSL_META_U(unit,
    643                                     "Symmetric hash swap for hash A calculation.\n")));
    644         }
    645 
    646         if ((rtag7_a_sel == RTAG7_IPV6) && rtag7_en_flow_label_ipv6_a) {
    647             LOG_VERBOSE(BSL_LS_BCM_COMMON,
    648                         (BSL_META_U(unit,
    649                                     "Hash calculation: The system is set to use ipv6 flow label" 
    650                                      " and the code can't get this info\n")));
    651         }
    652 
    653         if (rtag7_a_sel == RTAG7_IPV4) {  /* Use IPv4 BITMAPs */
    654             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) &&
    655                 ((pkt_info->protocol == IP_PROT_TCP) ||
    656                 (pkt_info->protocol == IP_PROT_UDP))) { 
    657                 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) &&
    658                     _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) &&
    659                     (pkt_info->src_l4_port == pkt_info->dst_l4_port)) {
    660                     sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_1r;
    661                     sc_field = IPV4_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Af;
    662                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
    663                                 (BSL_META_U(unit,
    664                                             "Hash calculation: Bitmap is block A IPv4 TCP=UDP\n")));
    665                 } else {
    666                     sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_2r;
    667                     sc_field = IPV4_TCP_UDP_FIELD_BITMAP_Af;
    668                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
    669                                 (BSL_META_U(unit,
    670                                             "Hash calculation: Bitmap is block A IPv4 L4 tcp/udp\n")));
    671                 }
    672             } else {
    673                 sc_reg = RTAG7_HASH_FIELD_BMAP_1r;
    674                 sc_field = IPV4_FIELD_BITMAP_Af;
    675                 LOG_VERBOSE(BSL_LS_BCM_COMMON,
    676                             (BSL_META_U(unit,
    677                                         "Hash calculation: Bitmap is block A IPv4 \n")));
    678             }
    679 
    680         } else { /* Use IPv6 BITMAPs */
    681             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) &&
    682                 ((pkt_info->protocol == IP_PROT_TCP) ||
    683                 (pkt_info->protocol == IP_PROT_UDP))) { 
    684                 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) &&
    685                     _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) &&
    686                     (pkt_info->src_l4_port == pkt_info->dst_l4_port)) {
    687                     sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_1r;
    688                     sc_field = IPV6_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Af;
    689                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
    690                                 (BSL_META_U(unit,
    691                                             "Hash calculation: Bitmap is block A IPv6 TCP=UDP\n")));
    692                 } else {
    693                     sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_2r;
    694                     sc_field = IPV6_TCP_UDP_FIELD_BITMAP_Af;
    695                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
    696                                 (BSL_META_U(unit,
    697                                             "Hash calculation: Bitmap is block A IPv6 L4 tcp/udp\n")));
    698                 }
    699             } else {
    700                 sc_reg = RTAG7_HASH_FIELD_BMAP_2r;
    701                 sc_field = IPV6_FIELD_BITMAP_Af;
    702                 LOG_VERBOSE(BSL_LS_BCM_COMMON,
    703                             (BSL_META_U(unit,
    704                                         "Hash calculation: Bitmap is block A IPv6 \n")));
    705             }
    706         }
    707         
    708     } else { /* Catch-all for RTAG7_L2_ONLY */
    709 
    710         /* L2 only hash key */
    711         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_MAC)) {
    712             hash[11] = (pkt_info->src_mac[0] << 8) | pkt_info->src_mac[1];
    713             hash[10] = (pkt_info->src_mac[2] << 8) | pkt_info->src_mac[3];
    714             hash[9] = (pkt_info->src_mac[4] << 8) | pkt_info->src_mac[5];
    715         } else {
    716             hash_element_valid_bits &= ~0xe00;
    717         }
    718         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_MAC)) {
    719             hash[8] = (pkt_info->dst_mac[0] << 8) | pkt_info->dst_mac[1];
    720             hash[7] = (pkt_info->dst_mac[2] << 8) | pkt_info->dst_mac[3];
    721             hash[6] = (pkt_info->dst_mac[4] << 8) | pkt_info->dst_mac[5];
    722         } else {
    723             hash_element_valid_bits &= ~0x1c0;
    724         }
    725 
    726         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE)) {
    727             hash[5] = (pkt_info->ethertype >= ETHERTYPE_MIN) ?
    728                 pkt_info->ethertype : 0;
    729         } else {
    730             hash_element_valid_bits &= ~0x20;
    731         }
    732 
    733         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) {
    734             hash[4] = pkt_info->vid & 0xfff;
    735         } else {
    736             hash_element_valid_bits &= ~0x10;
    737         }
    738 
    739         sc_reg = RTAG7_HASH_FIELD_BMAP_3r;
    740         sc_field = L2_FIELD_BITMAP_Af;
    741         LOG_VERBOSE(BSL_LS_BCM_COMMON,
    742                     (BSL_META_U(unit,
    743                                 "Hash calculation: Bitmap is block A L2\n")));
    744     }
    745 
    746     BCM_IF_ERROR_RETURN
    747         (soc_reg32_get(unit, sc_reg, REG_PORT_ANY, 0, &sc_val));
    748     hash_field_bmap_a = soc_reg_field_get(unit, sc_reg, sc_val, sc_field);
    749 
    750     /* Pre-Processing */
    751 
    752     if (rtag7_pre_processing_enable_a) {
    753 
    754         hash[12] = hash[12] ^ (hash[12] >> 3) ^ (hash[12] << 2);
    755         hash[11] = hash[11] ^ (hash[11] >> 3) ^ (hash[11] << 2);
    756         hash[10] = hash[10] ^ (hash[10] >> 3) ^ (hash[10] << 2);
    757         hash[9] = hash[9] ^ (hash[9] >> 3) ^ (hash[9] << 2);
    758         hash[8] = hash[8] ^ (hash[8] >> 3) ^ (hash[8] << 2);
    759         hash[7] = hash[7] ^ (hash[7] >> 3) ^ (hash[7] << 2);
    760         hash[6] = hash[6] ^ (hash[6] >> 3) ^ (hash[6] << 2);
    761         hash[5] = hash[5] ^ (hash[5] >> 3) ^ (hash[5] << 2);
    762         hash[4] = hash[4] ^ (hash[4] >> 3) ^ (hash[4] << 2);
    763         hash[3] = hash[3] ^ (hash[3] >> 3) ^ (hash[3] << 2);
    764         hash[2] = hash[2] ^ (hash[2] >> 3) ^ (hash[2] << 2);
    765         hash[1] = hash[1] ^ (hash[1] >> 3) ^ (hash[1] << 2);
    766         hash[0] = hash[0] ^ (hash[0] >> 3) ^ (hash[0] << 2);
    767     
    768     }
    769 
    770     if (((hash_field_bmap_a >> 12) & 0x1) == 0) {
    771         hash[12] = 0;
    772     }    
    773 
    774     if (rtag7_en_bin_12_overlay_a) {
    775         hash_word[6] = (rtag7_hash_seed_a & 0xffff0000) | (hash[12] & 0xffff);
    776     } else {
    777         hash_word[6] = rtag7_hash_seed_a;
    778     }    
    779 
    780     hash_res->hash_a_valid = TRUE;
    781     for (elem = 11; elem >= 0; elem--) {
    782         elem_bit = 1 << elem;
    783         if (0 != (hash_field_bmap_a & elem_bit)) {
    784             if (0 != (hash_element_valid_bits & elem_bit)) {
    785                 hash_word[elem/2] |=
    786                     ((hash[elem] & 0xffff) << (16 * (elem % 2)));
    787             } else {
    788                 hash_res->hash_a_valid = FALSE;
    789                 break;
    790             }
    791         }
    792     }
    793 
    794     /*Calculation*/
    795     xor32 = hash_word[6] ^ hash_word[5] ^ hash_word[4] ^ hash_word[3] ^
    796         hash_word[2] ^ hash_word[1] ^ hash_word[0];
    797 
    798     hash_xor16 = (xor32 & 0xffff) ^ ((xor32 >> 16) & 0xffff);  
    799     hash_xor8 = (hash_xor16 & 0xff) ^ ((hash_xor16 >> 8) & 0xff);
    800     hash_xor4 = (hash_xor8 & 0xf) ^ ((hash_xor8 >> 4) & 0xf);
    801     hash_xor2 = (hash_xor4 & 0x3) ^ ((hash_xor4 >> 2) & 0x3);
    802     hash_xor1 = (hash_xor2 & 0x1) ^ ((hash_xor2 >> 1) & 0x1);
    803 
    804     hash_crc16_bisync = _shr_crc16_draco_array(hash_word, 28);
    805     hash_crc16_ccitt =  _shr_crc16_ccitt_array(hash_word, 28);
    806     hash_crc32 =        _shr_crc32_castagnoli_array(hash_word, 28);
    807 
    808     switch (rtag7_hash_a0_function_select) {
    809     case 0: /* reserved */
    810         hash_res->rtag7_hash16_value_a_0 = 0;
    811         break;
    812     case 1: /* reserved */
    813         hash_res->rtag7_hash16_value_a_0 = 0;
    814         break;
    815     case 2: /* reserved */
    816         hash_res->rtag7_hash16_value_a_0 = 0;
    817         break;
    818     case 3: /* CRC16 BISYNC */
    819         hash_res->rtag7_hash16_value_a_0 = hash_crc16_bisync;
    820         break;
    821     case 4: /* CRC16_XOR1 */ 
    822         hash_res->rtag7_hash16_value_a_0 = hash_xor1 & 0x1;
    823         hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    824         break;
    825     case 5: /* CRC16_XOR2 */
    826         hash_res->rtag7_hash16_value_a_0 = hash_xor2 & 0x3;
    827         hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    828         break;
    829     case 6: /* CRC16_XOR4 */ 
    830         hash_res->rtag7_hash16_value_a_0 = hash_xor4 & 0xf;
    831         hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    832         break;
    833     case 7: /* CRC16_XOR8 */
    834         hash_res->rtag7_hash16_value_a_0 = hash_xor8 & 0xff;
    835         hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    836         break;
    837     case 8: /* XOR16 */
    838         hash_res->rtag7_hash16_value_a_0 = hash_xor16;
    839         break;
    840     case 9: /* CRC16_CCITT */
    841         hash_res->rtag7_hash16_value_a_0 = hash_crc16_ccitt;
    842         break;
    843     case 10: /* CRC32_LO */
    844         hash_res->rtag7_hash16_value_a_0 = hash_crc32 & 0xffff;
    845         break;
    846     case 11: /* CRC32_HI */
    847         hash_res->rtag7_hash16_value_a_0 = (hash_crc32 >> 16) & 0xffff;
    848         break;
    849     default: /* reserved */
    850         hash_res->rtag7_hash16_value_a_0 = 0;
    851         break;
    852     }
    853 
    854     switch (rtag7_hash_a1_function_select) {
    855     case 0: /* reserved */
    856         hash_res->rtag7_hash16_value_a_1 = 0;
    857         break;
    858     case 1: /* reserved */
    859         hash_res->rtag7_hash16_value_a_1 = 0;
    860         break;
    861     case 2: /* reserved */
    862         hash_res->rtag7_hash16_value_a_1 = 0;
    863         break;
    864     case 3: /* CRC16 BISYNC */
    865         hash_res->rtag7_hash16_value_a_1 = hash_crc16_bisync;
    866         break;
    867     case 4: /* CRC16_XOR1 */ 
    868         hash_res->rtag7_hash16_value_a_1 = hash_xor1 & 0x1;
    869         hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    870         break;
    871     case 5: /* CRC16_XOR2 */
    872         hash_res->rtag7_hash16_value_a_1 = hash_xor2 & 0x3;
    873         hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    874         break;
    875     case 6: /* CRC16_XOR4 */ 
    876         hash_res->rtag7_hash16_value_a_1 = hash_xor4 & 0xf;
    877         hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    878         break;
    879     case 7: /* CRC16_XOR8 */
    880         hash_res->rtag7_hash16_value_a_1 = hash_xor8 & 0xff;
    881         hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    882         break;
    883     case 8: /* XOR16 */
    884         hash_res->rtag7_hash16_value_a_1 = hash_xor16;
    885         break;
    886     case 9: /* CRC16_CCITT */
    887         hash_res->rtag7_hash16_value_a_1 = hash_crc16_ccitt;
    888         break;
    889     case 10: /* CRC32_LO */
    890         hash_res->rtag7_hash16_value_a_1 = hash_crc32 & 0xffff;
    891         break;
    892     case 11: /* CRC32_HI */
    893         hash_res->rtag7_hash16_value_a_1 = (hash_crc32 >> 16) & 0xffff;
    894         break;
    895     default: /* reserved */
    896         hash_res->rtag7_hash16_value_a_1 = 0;
    897         break;
    898     }
    899 
    900     /* End of option A hash calculation for rtag 7 */
    901 
    902     /* Generation of Macro Flow Based HASH Select */
    903     /* This is used for Macro flow based Hash function selection for all consumers of RTAG7 HASH */
    904     /* Macro flow based hash function selection improves distribution among members */
    905     /* Refer Each application (ECMP, LAG, HG-TRUNK) on how this is being used */
    906     switch (rtag7_macro_flow_hash_function_select) {
    907     case 0: /* reserved */
    908         macro_flow_id = 0;
    909         break;
    910     case 1: /* reserved */
    911         macro_flow_id = 0;
    912         break;
    913     case 2: /* reserved */
    914         macro_flow_id = 0;
    915         break;
    916     case 3: /* CRC16 BISYNC */
    917         macro_flow_id = hash_crc16_bisync;
    918         break;
    919     case 4: /* CRC16_XOR1 */ 
    920         macro_flow_id = hash_xor1 & 0x1;
    921         macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    922         break;
    923     case 5: /* CRC16_XOR2 */
    924         macro_flow_id = hash_xor2 & 0x3;
    925         macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    926         break;
    927     case 6: /* CRC16_XOR4 */ 
    928         macro_flow_id = hash_xor4 & 0xf;
    929         macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    930         break;
    931     case 7: /* CRC16_XOR8 */
    932         macro_flow_id = hash_xor8 & 0xff;
    933         macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    934         break;
    935     case 8: /* XOR16 */
    936         macro_flow_id = hash_xor16;
    937         break;
    938     case 9: /* CRC16_CCITT */
    939         macro_flow_id = hash_crc16_ccitt;
    940         break;
    941     case 10: /* CRC32_LO */
    942         macro_flow_id = hash_crc32 & 0xffff;
    943         break;
    944     case 11: /* CRC32_HI */
    945         macro_flow_id = (hash_crc32 >> 16) & 0xffff;
    946         break;
    947     default: /* reserved */
    948         macro_flow_id = 0;
    949         break;
    950     }
    951     hash_res->rtag7_macro_flow_id = (rtag7_macro_flow_hash_byte_sel) ?  
    952         ((macro_flow_id >> 8) & 0xff) : (macro_flow_id & 0xff);
    953 
    954     /* option B hash calculation for rtag 7 */
    955 
    956     /* initialize the variables */   
    957     
    958     sal_memset(hash,0x0,(sizeof(uint32))*13);
    959     sal_memset(hash_word,0x0,(sizeof(uint32))*7);
    960     
    961     hash_crc16_bisync = 0;
    962     hash_crc16_ccitt = 0;
    963     hash_crc32      = 0;
    964     hash_xor16      = 0;
    965     hash_xor8       = 0;
    966     hash_xor4       = 0;
    967     hash_xor2       = 0;
    968     hash_xor1       = 0;
    969     xor32           = 0;
    970  
    971     hash[12] = 0;   
    972     hash[3] = hash_src_port;
    973     hash[2] = hash_src_modid & 0xff;
    974     hash[1] = 0;
    975     hash[0] = 0; 
    976 
    977     hash_element_valid_bits = 0x1fff; /* Init to valid fields above */
    978 
    979     /* option B hash calculation for rtag 7 */
    980     
    981     if ((rtag7_b_sel == RTAG7_IPV6) || (rtag7_b_sel == RTAG7_IPV4)) {
    982         if (sip_valid) {
    983             hash[11] = (sip_b >> 16) & 0xffff;
    984             hash[10] =  sip_b & 0xffff;
    985         } else {
    986             hash_element_valid_bits &= ~0xc00;
    987         }
    988         if (dip_valid) {
    989             hash[9]  = (dip_b >> 16) & 0xffff;
    990             hash[8]  =  dip_b & 0xffff;
    991         } else {
    992             hash_element_valid_bits &= ~0x300;
    993         }
    994 
    995         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) {
    996             hash[7]  = pkt_info->vid & 0xfff;
    997         } else {
    998             hash_element_valid_bits &= ~0x80;
    999         }
   1000         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT)) {
   1001             hash[6]  = pkt_info->src_l4_port;
   1002         } else {
   1003             hash_element_valid_bits &= ~0x40;
   1004         }
   1005         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT)) {
   1006             hash[5]  = pkt_info->dst_l4_port;
   1007         } else {
   1008             hash_element_valid_bits &= ~0x20;
   1009         }
   1010         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL)) {
   1011             hash[4]  = pkt_info->protocol;
   1012         } else {
   1013             hash_element_valid_bits &= ~0x10;
   1014         }
   1015 
   1016         /* Symmetric hash swap src/dst ipaddr/l4_port for option B */
   1017         if (((rtag7_b_sel == RTAG7_IPV6) && 
   1018             symmetric_hash_need_swap_ip6 && 
   1019             (symmetric_hash_control_mask & BCM_SYMMETRIC_HASH_1_IP6_ENABLE)) 
   1020             ||
   1021             ((rtag7_b_sel == RTAG7_IPV4) && 
   1022             symmetric_hash_need_swap_ip4 && 
   1023             (symmetric_hash_control_mask & BCM_SYMMETRIC_HASH_1_IP4_ENABLE))) {
   1024 
   1025             uint32 temp;
   1026             temp = hash[11]; hash[11] = hash[9]; hash[9] = temp;
   1027             temp = hash[10]; hash[10] = hash[8]; hash[8] = temp;
   1028             temp = hash[6]; hash[6] = hash[5]; hash[5] = temp;
   1029             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1030                         (BSL_META_U(unit,
   1031                                     "Symmetric hash swap for hash B calculation.\n")));
   1032         }
   1033 
   1034         if ((rtag7_b_sel == RTAG7_IPV6) && rtag7_en_flow_label_ipv6_b) {
   1035             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1036                         (BSL_META_U(unit,
   1037                                     "Hash calculation: The system is set to use ipv6 flow label" 
   1038                                      " and the code can't get this info\n")));
   1039         }
   1040 
   1041         if (rtag7_b_sel == RTAG7_IPV4) {  /* Use IPv4 BITMAPs */
   1042             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) &&
   1043                 ((pkt_info->protocol == IP_PROT_TCP) ||
   1044                 (pkt_info->protocol == IP_PROT_UDP))) { 
   1045                 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) &&
   1046                     _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) &&
   1047                     (pkt_info->src_l4_port == pkt_info->dst_l4_port)) {
   1048                     sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_1r;
   1049                     sc_field = IPV4_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Bf;
   1050                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1051                                 (BSL_META_U(unit,
   1052                                             "Hash calculation: Bitmap is block B IPv4 TCP=UDP\n")));
   1053                 } else {
   1054                     sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_2r;
   1055                     sc_field = IPV4_TCP_UDP_FIELD_BITMAP_Bf;
   1056                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1057                                 (BSL_META_U(unit,
   1058                                             "Hash calculation: Bitmap is block B IPv4 L4 tcp/udp\n")));
   1059                 }
   1060             } else {
   1061                 sc_reg = RTAG7_HASH_FIELD_BMAP_1r;
   1062                 sc_field = IPV4_FIELD_BITMAP_Bf;
   1063                 LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1064                             (BSL_META_U(unit,
   1065                                         "Hash calculation: Bitmap is block B IPv4\n")));
   1066             }
   1067 
   1068         } else { /* Use IPv6 BITMAPs */
   1069 
   1070             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) &&
   1071                 ((pkt_info->protocol == IP_PROT_TCP) ||
   1072                 (pkt_info->protocol == IP_PROT_UDP))) { 
   1073                 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) &&
   1074                     _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) &&
   1075                     (pkt_info->src_l4_port == pkt_info->dst_l4_port)) {
   1076                     sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_1r;
   1077                     sc_field = IPV6_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Bf;
   1078                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1079                                 (BSL_META_U(unit,
   1080                                             "Hash calculation: Bitmap is block B IPv6 TCP=UDP\n")));
   1081                 } else {
   1082                     sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_2r;
   1083                     sc_field = IPV6_TCP_UDP_FIELD_BITMAP_Bf;
   1084                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1085                                 (BSL_META_U(unit,
   1086                                             "Hash calculation: Bitmap is block B IPv6 TCP=UDP\n")));
   1087                 }
   1088             } else {
   1089                 sc_reg = RTAG7_HASH_FIELD_BMAP_2r;
   1090                 sc_field = IPV6_FIELD_BITMAP_Bf;
   1091                 LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1092                             (BSL_META_U(unit,
   1093                                         "Hash calculation: Bitmap is block B IPv6\n")));
   1094             }
   1095         }
   1096     } else { /* Catch-all for RTAG7_L2_ONLY */
   1097 
   1098         /* L2 only hash key */
   1099         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_MAC)) {
   1100             hash[11] = (pkt_info->src_mac[0] << 8) | pkt_info->src_mac[1];
   1101             hash[10] = (pkt_info->src_mac[2] << 8) | pkt_info->src_mac[3];
   1102             hash[9] = (pkt_info->src_mac[4] << 8) | pkt_info->src_mac[5];
   1103         } else {
   1104             hash_element_valid_bits &= ~0xe00;
   1105         }
   1106         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_MAC)) {
   1107             hash[8] = (pkt_info->dst_mac[0] << 8) | pkt_info->dst_mac[1];
   1108             hash[7] = (pkt_info->dst_mac[2] << 8) | pkt_info->dst_mac[3];
   1109             hash[6] = (pkt_info->dst_mac[4] << 8) | pkt_info->dst_mac[5];
   1110         } else {
   1111             hash_element_valid_bits &= ~0x1c0;
   1112         }
   1113 
   1114         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE)) {
   1115             hash[5] = (pkt_info->ethertype >= ETHERTYPE_MIN) ?
   1116                 pkt_info->ethertype : 0;
   1117         } else {
   1118             hash_element_valid_bits &= ~0x20;
   1119         }
   1120 
   1121         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) {
   1122             hash[4] = pkt_info->vid & 0xfff;
   1123         } else {
   1124             hash_element_valid_bits &= ~0x10;
   1125         }
   1126 
   1127         sc_reg = RTAG7_HASH_FIELD_BMAP_3r;
   1128         sc_field = L2_FIELD_BITMAP_Bf;
   1129         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1130                     (BSL_META_U(unit,
   1131                                 "Hash calculation: Bitmap is block B L2\n")));
   1132     }
   1133 
   1134     BCM_IF_ERROR_RETURN
   1135         (soc_reg32_get(unit, sc_reg, REG_PORT_ANY, 0, &sc_val));
   1136     hash_field_bmap_b = soc_reg_field_get(unit, sc_reg, sc_val, sc_field);
   1137     /* Pre-Processing */
   1138 
   1139     if (rtag7_pre_processing_enable_b) {
   1140 
   1141         hash[12] = hash[12] ^ (hash[12] >> 3) ^ (hash[12] << 2);
   1142         hash[11] = hash[11] ^ (hash[11] >> 3) ^ (hash[11] << 2);
   1143         hash[10] = hash[10] ^ (hash[10] >> 3) ^ (hash[10] << 2);
   1144         hash[9] = hash[9] ^ (hash[9] >> 3) ^ (hash[9] << 2);
   1145         hash[8] = hash[8] ^ (hash[8] >> 3) ^ (hash[8] << 2);
   1146         hash[7] = hash[7] ^ (hash[7] >> 3) ^ (hash[7] << 2);
   1147         hash[6] = hash[6] ^ (hash[6] >> 3) ^ (hash[6] << 2);
   1148         hash[5] = hash[5] ^ (hash[5] >> 3) ^ (hash[5] << 2);
   1149         hash[4] = hash[4] ^ (hash[4] >> 3) ^ (hash[4] << 2);
   1150         hash[3] = hash[3] ^ (hash[3] >> 3) ^ (hash[3] << 2);
   1151         hash[2] = hash[2] ^ (hash[2] >> 3) ^ (hash[2] << 2);
   1152         hash[1] = hash[1] ^ (hash[1] >> 3) ^ (hash[1] << 2);
   1153         hash[0] = hash[0] ^ (hash[0] >> 3) ^ (hash[0] << 2);
   1154     
   1155     }
   1156 
   1157     if (((hash_field_bmap_b >> 12) & 0x1) == 0) {
   1158         hash[12] = 0;
   1159     }    
   1160 
   1161     if (rtag7_en_bin_12_overlay_b) {
   1162         hash_word[6] = (rtag7_hash_seed_b & 0xffff0000) | (hash[12] & 0xffff);
   1163     } else {
   1164         hash_word[6] = rtag7_hash_seed_b;
   1165     }    
   1166 
   1167     hash_res->hash_b_valid = TRUE;
   1168     for (elem = 11; elem >= 0; elem--) {
   1169         elem_bit = 1 << elem;
   1170         if (0 != (hash_field_bmap_b & elem_bit)) {
   1171             if (0 != (hash_element_valid_bits & elem_bit)) {
   1172                 hash_word[elem/2] |=
   1173                     ((hash[elem] & 0xffff) << (16 * (elem % 2)));
   1174             } else {
   1175                 hash_res->hash_b_valid = FALSE;
   1176                 break;
   1177             }
   1178         }
   1179     }
   1180 
   1181     xor32 = hash_word[6] ^ hash_word[5] ^ hash_word[4] ^ hash_word[3] ^ hash_word[2] ^ hash_word[1] ^ hash_word[0];
   1182     hash_xor16 = (xor32 & 0xffff) ^ ((xor32 >> 16) & 0xffff);  
   1183     hash_xor8 = (hash_xor16 & 0xff) ^ ((hash_xor16 >> 8) & 0xff);
   1184     hash_xor4 = (hash_xor8 & 0xf) ^ ((hash_xor8 >> 4) & 0xf);
   1185     hash_xor2 = (hash_xor4 & 0x3) ^ ((hash_xor4 >> 2) & 0x3);
   1186     hash_xor1 = (hash_xor2 & 0x1) ^ ((hash_xor2 >> 1) & 0x1);
   1187 
   1188     hash_crc16_bisync = _shr_crc16_draco_array(hash_word, 28);
   1189     hash_crc16_ccitt =  _shr_crc16_ccitt_array(hash_word, 28);
   1190     hash_crc32 =        _shr_crc32_castagnoli_array(hash_word, 28);
   1191 
   1192     switch (rtag7_hash_b0_function_select) {
   1193     case 0: /* reserved */
   1194         hash_res->rtag7_hash16_value_b_0 = 0;
   1195         break;
   1196     case 1: /* reserved */
   1197         hash_res->rtag7_hash16_value_b_0 = 0;
   1198         break;
   1199     case 2: /* reserved */
   1200         hash_res->rtag7_hash16_value_b_0 = 0;
   1201         break;
   1202     case 3: /* CRC16 BISYNC */
   1203         hash_res->rtag7_hash16_value_b_0 = hash_crc16_bisync;
   1204         break;
   1205     case 4: /* CRC16_XOR1 */ 
   1206         hash_res->rtag7_hash16_value_b_0 = hash_xor1 & 0x1;
   1207         hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1208         break;
   1209     case 5: /* CRC16_XOR2 */
   1210         hash_res->rtag7_hash16_value_b_0 = hash_xor2 & 0x3;
   1211         hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1212         break;
   1213     case 6: /* CRC16_XOR4 */ 
   1214         hash_res->rtag7_hash16_value_b_0 = hash_xor4 & 0xf;
   1215         hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1216         break;
   1217     case 7: /* CRC16_XOR8 */
   1218         hash_res->rtag7_hash16_value_b_0 = hash_xor8 & 0xff;
   1219         hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1220         break;
   1221     case 8: /* XOR16 */
   1222         hash_res->rtag7_hash16_value_b_0 = hash_xor16;
   1223         break;
   1224     case 9: /* CRC16_CCITT */
   1225         hash_res->rtag7_hash16_value_b_0 = hash_crc16_ccitt;
   1226         break;
   1227     case 10: /* CRC32_LO */
   1228         hash_res->rtag7_hash16_value_b_0 = hash_crc32 & 0xffff;
   1229         break;
   1230     case 11: /* CRC32_HI */
   1231         hash_res->rtag7_hash16_value_b_0 = (hash_crc32 >> 16) & 0xffff;
   1232         break;
   1233     default: /* reserved */
   1234         hash_res->rtag7_hash16_value_b_0 = 0;
   1235         break;
   1236     }
   1237 
   1238     switch (rtag7_hash_b1_function_select) {
   1239     case 0: /* reserved */
   1240         hash_res->rtag7_hash16_value_b_1 = 0;
   1241         break;
   1242     case 1: /* reserved */
   1243         hash_res->rtag7_hash16_value_b_1 = 0;
   1244         break;
   1245     case 2: /* reserved */
   1246         hash_res->rtag7_hash16_value_b_1 = 0;
   1247         break;
   1248     case 3: /* CRC16 BISYNC */
   1249         hash_res->rtag7_hash16_value_b_1 = hash_crc16_bisync;
   1250         break;
   1251     case 4: /* CRC16_XOR1 */ 
   1252         hash_res->rtag7_hash16_value_b_1 = hash_xor1 & 0x1;
   1253         hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1254         break;
   1255     case 5: /* CRC16_XOR2 */
   1256         hash_res->rtag7_hash16_value_b_1 = hash_xor2 & 0x3;
   1257         hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1258         break;
   1259     case 6: /* CRC16_XOR4 */ 
   1260         hash_res->rtag7_hash16_value_b_1 = hash_xor4 & 0xf;
   1261         hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1262         break;
   1263     case 7: /* CRC16_XOR8 */
   1264         hash_res->rtag7_hash16_value_b_1 = hash_xor8 & 0xff;
   1265         hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1266         break;
   1267     case 8: /* XOR16 */
   1268         hash_res->rtag7_hash16_value_b_1 = hash_xor16;
   1269         break;
   1270     case 9: /* CRC16_CCITT */
   1271         hash_res->rtag7_hash16_value_b_1 = hash_crc16_ccitt;
   1272         break;
   1273     case 10: /* CRC32_LO */
   1274         hash_res->rtag7_hash16_value_b_1 = hash_crc32 & 0xffff;
   1275         break;
   1276     case 11: /* CRC32_HI */
   1277         hash_res->rtag7_hash16_value_b_1 = (hash_crc32 >> 16) & 0xffff;
   1278         break;
   1279     default: /* reserved */
   1280         hash_res->rtag7_hash16_value_b_1 = 0;
   1281         break;
   1282     }
   1283 
   1284     /* End of option B hash calculation for rtag 7 */
   1285     return BCM_E_NONE;
   1286 }
   1287 
   1288 /*
   1289  * Function:
   1290  *          select_td2_hash_subfield
   1291  * Description:
   1292  *          read hashing values of hash A0,A1,B0,B1,LBID
   1293  *          from sub_sel_block pointed by hash_sub_sel
   1294  * Parameters:
   1295  *          concat - tell whether is in concatenated mode or not
   1296  *          hash_sub_sel - tell which hash sub to choose
   1297  *          seleted_subfiled - saves subfield value
   1298  *          hash_Base - internal data where hashing informaiton is stored
   1299  * Returns:
   1300  *      BCM_E_xxxx
   1301  * Note: if hash_sub_sel and hash_Base->hash_x_valid mismatches, 
   1302  *       it will return BCM_E_PARAM
   1303  */
   1304 STATIC int
   1305 select_td2_hash_subfield(uint32 concat, int hash_sub_sel, uint64 *selected_subfield,
   1306                      bcm_rtag7_base_hash_t *hash_Base)
   1307 {
   1308     int rv = BCM_E_NONE;
   1309 
   1310     switch (hash_sub_sel) {
   1311         case 0: /* select pkt hash A */
   1312             if (concat) {
   1313                 COMPILER_64_SET(*selected_subfield,
   1314                     (hash_Base->rtag7_hash16_value_b_1 << 16 | hash_Base->rtag7_hash16_value_b_0),
   1315                     (hash_Base->rtag7_hash16_value_a_1 << 16 | hash_Base->rtag7_hash16_value_a_0));
   1316                 if (!hash_Base->hash_a_valid || !hash_Base->hash_b_valid) {
   1317                     /* Missing paramter in input */
   1318                     rv = BCM_E_PARAM;
   1319                 }
   1320             } else {
   1321                 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_hash16_value_a_0);
   1322                 if (!hash_Base->hash_a_valid) {
   1323                     /* Missing paramter in input */
   1324                     rv = BCM_E_PARAM;
   1325                 }
   1326             }
   1327             break;
   1328 
   1329         case 1: /* select pkt hash B */
   1330             if (concat) {
   1331                 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_port_lbn);
   1332             } else {
   1333                 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_hash16_value_b_0);
   1334                 if (!hash_Base->hash_b_valid) {
   1335                     /* Missing paramter in input */
   1336                     rv = BCM_E_PARAM;
   1337                 }
   1338             }
   1339             break;
   1340 
   1341         case 2: /* select port LBN */
   1342             COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_port_lbn);
   1343             break;
   1344 
   1345         case 3: /* select destination port id or hash A */
   1346             if (concat) {
   1347                 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_port_lbn);
   1348             } else {
   1349                 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_hash16_value_a_0);
   1350                 if (!hash_Base->hash_a_valid) {
   1351                     /* Missing paramter in input */
   1352                     rv = BCM_E_PARAM;
   1353                 }
   1354             }
   1355             break;
   1356 
   1357         case 4: /* select LBID from module header or from SW1 stage */ 
   1358             COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_lbid_hash);
   1359             if (!hash_Base->lbid_hash_valid) {
   1360                 /* LBID setting isn't RTAG7 */
   1361                 rv = BCM_E_CONFIG;
   1362             }
   1363             break;
   1364 
   1365         case 5: /* select LBID from SW1 stage */
   1366             COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_lbid_hash);
   1367             if (!hash_Base->lbid_hash_valid) {
   1368                 /* LBID setting isn't RTAG7 */
   1369                 rv = BCM_E_CONFIG;
   1370             }
   1371             break;
   1372 
   1373         case 6:
   1374             if (concat) {
   1375                 COMPILER_64_ZERO(*selected_subfield);
   1376             } else {
   1377                 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_hash16_value_a_1);
   1378                 if (!hash_Base->hash_a_valid) {
   1379                     /* Missing paramter in input */
   1380                     rv = BCM_E_PARAM;
   1381                 }
   1382             }
   1383             break;
   1384 
   1385         case 7: 
   1386             if (concat) {
   1387                 COMPILER_64_ZERO(*selected_subfield);
   1388             } else {
   1389                 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_hash16_value_b_1);
   1390                 if (!hash_Base->hash_b_valid) {
   1391                     /* Missing paramter in input */
   1392                     rv = BCM_E_PARAM;
   1393                 }
   1394             }
   1395             break;
   1396 
   1397         default:
   1398             return BCM_E_PARAM;
   1399     }
   1400 
   1401     return rv;
   1402 }
   1403 
   1404 /*
   1405  * Function:
   1406  *          main_td2_compute_lbid
   1407  * Description:
   1408  *     get lbid value that is used in hashing calculation
   1409  *     if flow hash is used, get SUB_SEL_LBID_OR_ENTROPY_LABELf and 
   1410  *        OFFSET_LBID_OR_ENTROPY_LABELf from RTAG7_FLOW_BASED_HASHm 
   1411  *     if flow hash is not used, get SUB_SEL_LBID_(non)UCf and 
   1412  *        OFFSET_LBID_(non)UCf from RTAG7_PORT_BASED_HASHm 
   1413  * Parameters:
   1414  *          unit - StrataSwitch PCI device unit number (driver internal).
   1415  *          hash_Base - internal data that lbid_hash_value is stored 
   1416  * Returns:
   1417  *      BCM_E_xxxx
   1418  * Note: bcmSwitchLoadBalanceHashSelect must be set to 7 
   1419  *   and bcmSwitchLoadBalanceHashSet0UnicastOffset must be set properly.    
   1420  *       if lbid_hash_sub_sel and hash_Base->hash_x_valid mismatches, 
   1421  *       then lbid_hash_val saved in hash_Base will be 0
   1422  */
   1423 STATIC int
   1424 main_td2_compute_lbid(int unit, bcm_rtag7_base_hash_t *hash_Base)
   1425 {
   1426     /*regular var declaration*/
   1427     uint32 lbid_hash_sub_sel;
   1428     uint32 lbid_hash_offset;
   1429     uint32 lbid_hash_value = 0;
   1430 
   1431     /*register var declaration*/
   1432     int lbid_rtag = 0;
   1433     uint64 ing_hash_config_reg;
   1434     int    rv = BCM_E_NONE;
   1435     uint32 rtag7_hash_sel;
   1436     uint32 port_based_hash_index;
   1437 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1438     int    hash_index = 0;
   1439 #endif
   1440     rtag7_port_based_hash_entry_t
   1441            port_based_hash_entry;
   1442     rtag7_flow_based_hash_entry_t 
   1443             flow_based_hash_entry;
   1444     uint8   loadbalance_use_flow_hash_uc = 0;
   1445     uint8   loadbalance_use_flow_hash_nonuc = 0;
   1446  
   1447     /* get the lbid rtag value */ 
   1448     if (SOC_REG_FIELD_VALID(unit, ING_CONFIG_64r, LBID_RTAGf)) {
   1449         rv = READ_ING_CONFIG_64r(unit, &ing_hash_config_reg);
   1450         if (BCM_SUCCESS(rv)) {
   1451             lbid_rtag = soc_reg64_field32_get(unit, ING_CONFIG_64r, 
   1452                                ing_hash_config_reg, LBID_RTAGf);  
   1453         } else {
   1454             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1455                         (BSL_META_U(unit,
   1456                                     "compute_lbid fail, lbid_rtag=0\n")));
   1457             lbid_rtag =0;
   1458         }
   1459     } else {
   1460         rv = (BCM_E_UNAVAIL);
   1461     }
   1462 
   1463     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1464                 (BSL_META_U(unit,
   1465                             "lbid_rtag = %d\n"),
   1466                  lbid_rtag));
   1467     /* ******************* LBID computation ************************* */
   1468 
   1469     if (lbid_rtag == 7) {
   1470         /* check if flow hash is used for UC*/
   1471         SOC_IF_ERROR_RETURN
   1472             (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel));
   1473         if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_LBID_UCf)) {
   1474              loadbalance_use_flow_hash_uc =
   1475                 soc_reg_field_get(unit, RTAG7_HASH_SELr,
   1476                               rtag7_hash_sel, USE_FLOW_SEL_LBID_UCf);
   1477         } else {
   1478             loadbalance_use_flow_hash_uc = 0; 
   1479         }    
   1480  
   1481         /* check if flow hash is used for NONUC*/
   1482         SOC_IF_ERROR_RETURN
   1483             (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel));
   1484         if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_LBID_NONUCf)) {
   1485             loadbalance_use_flow_hash_nonuc =
   1486                 soc_reg_field_get(unit, RTAG7_HASH_SELr,
   1487                               rtag7_hash_sel, USE_FLOW_SEL_LBID_NONUCf);
   1488         } else {
   1489             loadbalance_use_flow_hash_nonuc = 0; 
   1490         }    
   1491 
   1492         /* RTAG7 hash computation */
   1493         if ((loadbalance_use_flow_hash_nonuc&& (hash_Base->is_nonuc == 0)) || 
   1494             (loadbalance_use_flow_hash_uc && (hash_Base->is_nonuc != 0))) {
   1495             SOC_IF_ERROR_RETURN(
   1496                 READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY,
   1497                         (hash_Base->rtag7_macro_flow_id & 0xff),
   1498                          &flow_based_hash_entry));
   1499 
   1500             /* in RTAG7_FLOW_BASED_HASHm, using same selection for 
   1501                UC and NONUC */
   1502             lbid_hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit,
   1503                                            &flow_based_hash_entry, SUB_SEL_LBID_OR_ENTROPY_LABELf);
   1504             lbid_hash_offset  = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit,
   1505                                            &flow_based_hash_entry, OFFSET_LBID_OR_ENTROPY_LABELf);
   1506          
   1507         } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) {
   1508             if (hash_Base->dev_src_port < 0) {
   1509                 int field_count = 0;
   1510                 soc_field_t fields[2];
   1511                 uint32 values[2];
   1512                 bcm_gport_t gport;
   1513 
   1514                 BCM_GPORT_PROXY_SET(gport, 
   1515                     hash_Base->src_modid, hash_Base->src_port);
   1516 
   1517                 if (hash_Base->is_nonuc) {
   1518                     fields[0] = SUB_SEL_LBID_NONUCf ;
   1519                     field_count++;
   1520                     fields[1] = OFFSET_LBID_NONUCf;
   1521                     field_count++;
   1522                 } else {
   1523                     fields[0] = SUB_SEL_LBID_UCf ;
   1524                     field_count++;
   1525                     fields[1] = OFFSET_LBID_UCf;
   1526                     field_count++;
   1527                 }
   1528                 PORT_LOCK(unit);
   1529                 rv = bcm_esw_port_lport_fields_get(unit, gport,
   1530                                                    LPORT_PROFILE_RTAG7_TAB,
   1531                                                    field_count, fields, values);
   1532                 PORT_UNLOCK(unit);
   1533                 if (BCM_FAILURE(rv)) {
   1534                     return rv;
   1535                 }
   1536                 lbid_hash_sub_sel = values[0];
   1537                 lbid_hash_offset  = values[1];
   1538             } else {
   1539 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1540                 if (soc_feature(unit, soc_feature_rtag7_port_profile)) {
   1541                     BCM_IF_ERROR_RETURN
   1542                         (_bcm_esw_port_tab_get(unit, hash_Base->dev_src_port,
   1543                                                RTAG7_PORT_PROFILE_INDEXf, &hash_index));
   1544                     port_based_hash_index = (uint32) hash_index;
   1545                 } else
   1546 #endif
   1547                 {
   1548                     port_based_hash_index = hash_Base->dev_src_port +
   1549                                             soc_mem_index_count(unit, LPORT_TABm);
   1550                 }
   1551                 SOC_IF_ERROR_RETURN(
   1552                     READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY,
   1553                                 port_based_hash_index, &port_based_hash_entry));
   1554                 if (hash_Base->is_nonuc) {
   1555                     lbid_hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   1556                                         &port_based_hash_entry, SUB_SEL_LBID_NONUCf);
   1557                     lbid_hash_offset  = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   1558                                         &port_based_hash_entry, OFFSET_LBID_NONUCf);
   1559                 } else {
   1560                     lbid_hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   1561                                         &port_based_hash_entry, SUB_SEL_LBID_UCf);
   1562                     lbid_hash_offset  = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   1563                                         &port_based_hash_entry, OFFSET_LBID_UCf);
   1564                 }
   1565             }
   1566         } else {
   1567             lbid_hash_sub_sel = 0;
   1568             lbid_hash_offset  = 0;
   1569         }
   1570 
   1571         switch (lbid_hash_sub_sel) {
   1572         
   1573         case 0: /* use pkt hash A */
   1574             lbid_hash_value = hash_Base->rtag7_hash16_value_a_0;
   1575             if (!hash_Base->hash_a_valid) {
   1576                 /* Missing paramter in input */
   1577                 rv = BCM_E_PARAM;    
   1578             }
   1579             break;
   1580         
   1581         case 1: /* use pkt hash B */
   1582             lbid_hash_value = hash_Base->rtag7_hash16_value_b_0;
   1583             if (!hash_Base->hash_b_valid) {
   1584                 /* Missing paramter in input */
   1585                 rv = BCM_E_PARAM;
   1586             }
   1587             break;
   1588         
   1589         case 2: /* Use LBN */
   1590             lbid_hash_value = hash_Base->rtag7_port_lbn;
   1591             break;
   1592         
   1593         case 3: /* Use Destination PORTID or hash A */
   1594             lbid_hash_value = hash_Base->rtag7_hash16_value_a_0;
   1595             if (!hash_Base->hash_a_valid) {
   1596                 /* Missing paramter in input */
   1597                 rv = BCM_E_PARAM;                
   1598             }
   1599             break;
   1600         
   1601         case 4: /* Use LBID */
   1602             /* Higig lookup use mh_higig2_lbid */
   1603                 
   1604             lbid_hash_value = 0;
   1605             break;
   1606         
   1607         case 5:
   1608             lbid_hash_value = 0;
   1609             break;
   1610         
   1611         case 6:
   1612             lbid_hash_value = hash_Base->rtag7_hash16_value_a_1;
   1613             if (!hash_Base->hash_a_valid) {
   1614                 /* Missing paramter in input */
   1615                 rv = BCM_E_PARAM;
   1616             }
   1617             break;
   1618         
   1619         case 7:
   1620             lbid_hash_value = hash_Base->rtag7_hash16_value_b_1;
   1621             if (!hash_Base->hash_b_valid) {
   1622                 /* Missing paramter in input */
   1623                 rv = BCM_E_PARAM;
   1624             }
   1625             break;
   1626         }
   1627         
   1628         /*
   1629          * set up the hash value so that the LSB bits are
   1630          * barrel shifted in case offset > 8.
   1631          */
   1632         lbid_hash_value |= ((lbid_hash_value & 0xffff) << 16);
   1633        
   1634         /* Only UC hash offsets apply to ECMP */
   1635         lbid_hash_value = (lbid_hash_value >> lbid_hash_offset);
   1636         
   1637         hash_Base->rtag7_lbid_hash = (lbid_hash_value & 0xff);
   1638         hash_Base->lbid_hash_valid = TRUE;
   1639     } else { /* LBID rtag is 0-6 */        
   1640         /* this function not support the rtag 0-6 */
   1641         
   1642         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1643                     (BSL_META_U(unit,
   1644                                 "Hash calculation: This function doesn't support rtag 0 6" 
   1645                                  " pls change register ING_CONFIG.LBID_RTAG to value 7\n")));
   1646         hash_Base->rtag7_lbid_hash = 0;
   1647         hash_Base->lbid_hash_valid = FALSE;
   1648     }
   1649 
   1650     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1651                 (BSL_META_U(unit,
   1652                             "lbid_hash_val=%d, valid=%d\n"),
   1653                  hash_Base->rtag7_lbid_hash, hash_Base->lbid_hash_valid));
   1654 
   1655     return rv;
   1656     /* ******************* END of LBID computation ************************* */
   1657 }
   1658 
   1659 #ifdef INCLUDE_L3
   1660 /*
   1661  * Function:
   1662  *          compute_td2_ecmp_hash
   1663  * Description:
   1664  *     get ecmp hash value using SUB_SEL_ECMPf and OFFSET_ECMPf
   1665  *     if flow hash is used, get subsel and offset from RTAG7_FLOW_BASED_HASHm 
   1666  *     if flow hash is not used, get subsel and offset from RTAG7_PORT_BASED_HASHm 
   1667  * Parameters:
   1668  *          unit - StrataSwitch PCI device unit number (driver internal).
   1669  *          hash_Base - internal data where ecmp hash value is stored 
   1670  * Returns:
   1671  *      BCM_E_xxxx
   1672  */
   1673 STATIC int
   1674 compute_td2_ecmp_hash(int unit, uint32 flags, bcm_rtag7_base_hash_t *hash_Base,
   1675                   uint32 *hash_value)
   1676 {
   1677     /*regular var declaration*/
   1678     uint32 hash_sub_sel;
   1679     uint32 hash_offset;
   1680     uint64 hash_subfield;
   1681     uint32 hash_subfield_width;
   1682     uint8  rtag7_ecmp_use_macro_flow_hash;
   1683     uint8  ecmp_hash_use_rtag7;
   1684     uint32 rtag7_hash_sel;
   1685     uint32 hash_control;
   1686     uint32 concat;
   1687     uint32 port_based_hash_index;
   1688 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1689     int hash_index            = 0;
   1690 #endif
   1691     int sub_sel_f             = SUB_SEL_ECMPf;
   1692     int ecmp_offset_f         = OFFSET_ECMPf ;
   1693     int concat_f              = CONCATENATE_HASH_FIELDS_ECMPf ;
   1694     int ecmp_hash_control_f   = ECMP_HASH_USE_RTAG7f;
   1695     int rtag7_ecmp_hash_sel_f = USE_FLOW_SEL_ECMPf;
   1696     rtag7_port_based_hash_entry_t
   1697            port_based_hash_entry;
   1698     rtag7_flow_based_hash_entry_t 
   1699            flow_based_hash_entry;
   1700     int rv = BCM_E_NONE;
   1701 
   1702 #if defined(BCM_RIOT_SUPPORT) || defined (BCM_MULTI_LEVEL_ECMP_SUPPORT)
   1703     if (((soc_feature(unit, soc_feature_riot) ||
   1704           soc_feature(unit, soc_feature_multi_level_ecmp)) &&
   1705         flags & BCM_SWITCH_PKT_INFO_HASH_OVERLAY)) {
   1706 
   1707         sub_sel_f             = SUB_SEL_ECMP_LEVEL1f;
   1708         ecmp_offset_f         = OFFSET_ECMP_LEVEL1f ;
   1709         concat_f              = CONCATENATE_HASH_FIELDS_ECMP_LEVEL1f ;
   1710         ecmp_hash_control_f   = ECMP1_HASH_USE_RTAG7f;
   1711         rtag7_ecmp_hash_sel_f = USE_FLOW_SEL_ECMP1f;
   1712     }
   1713 #endif
   1714     /* Select between non-RTAG7 hash value and RTAG7 hash value */
   1715     SOC_IF_ERROR_RETURN
   1716         (READ_HASH_CONTROLr(unit, &hash_control));
   1717     ecmp_hash_use_rtag7 =
   1718         soc_reg_field_get(unit, HASH_CONTROLr, hash_control,
   1719                           ecmp_hash_control_f);
   1720 
   1721     if (ecmp_hash_use_rtag7 == 0) {
   1722         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1723                     (BSL_META_U(unit,
   1724                                 "ECMP Hash calculation:  non rtag7 calc not supported\n")));
   1725         *hash_value =  0;
   1726         return BCM_E_NONE;
   1727     }
   1728 
   1729     /* check if flow hash is used*/
   1730     SOC_IF_ERROR_RETURN
   1731         (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel));
   1732     if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, rtag7_ecmp_hash_sel_f)) {
   1733         rtag7_ecmp_use_macro_flow_hash =
   1734             soc_reg_field_get(unit, RTAG7_HASH_SELr,
   1735                               rtag7_hash_sel, rtag7_ecmp_hash_sel_f);
   1736     } else {
   1737         rtag7_ecmp_use_macro_flow_hash = 0;
   1738     }
   1739 
   1740     /* RTAG7 hash computation */
   1741     if (rtag7_ecmp_use_macro_flow_hash) {
   1742         SOC_IF_ERROR_RETURN(
   1743             READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY,
   1744                     (hash_Base->rtag7_macro_flow_id & 0xff),
   1745                      &flow_based_hash_entry));    
   1746 
   1747         /* Generating RTAG7 Macro Flow Based Hash Subsel and Offset for use in RSEL1 Stage */
   1748         /* For future designs this logic can be placed in RSEL1 */
   1749         hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 
   1750                                            &flow_based_hash_entry, sub_sel_f);
   1751         hash_offset  = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 
   1752                                            &flow_based_hash_entry, ecmp_offset_f);
   1753         concat       = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 
   1754                                            &flow_based_hash_entry, concat_f);
   1755     } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) {     
   1756         if (hash_Base->dev_src_port < 0) {
   1757             int field_count = 0;
   1758             soc_field_t fields[3];
   1759             uint32 values[3];
   1760             bcm_gport_t gport;
   1761         
   1762             BCM_GPORT_PROXY_SET(gport, 
   1763                 hash_Base->src_modid, hash_Base->src_port);
   1764         
   1765             fields[0] = sub_sel_f;
   1766             field_count++;
   1767             fields[1] = ecmp_offset_f;
   1768             field_count++;
   1769             fields[2] = concat_f;
   1770             field_count++;
   1771             PORT_LOCK(unit);
   1772             rv = bcm_esw_port_lport_fields_get(unit, gport,
   1773                                                LPORT_PROFILE_RTAG7_TAB,
   1774                                                field_count, fields, values);
   1775             PORT_UNLOCK(unit);
   1776             if (BCM_FAILURE(rv)) {
   1777                 return rv;
   1778             }
   1779             hash_sub_sel = values[0];
   1780             hash_offset  = values[1];
   1781             concat       = values[2];
   1782         } else {
   1783 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1784             if (soc_feature(unit, soc_feature_rtag7_port_profile)) {
   1785                 BCM_IF_ERROR_RETURN
   1786                     (_bcm_esw_port_tab_get(unit, hash_Base->dev_src_port,
   1787                                            RTAG7_PORT_PROFILE_INDEXf, &hash_index));
   1788                 port_based_hash_index = (uint32) hash_index;
   1789             } else
   1790 #endif
   1791             {
   1792                 port_based_hash_index = hash_Base->dev_src_port +
   1793                                         soc_mem_index_count(unit, LPORT_TABm);
   1794             }
   1795             SOC_IF_ERROR_RETURN(     
   1796                 READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 
   1797                             port_based_hash_index, &port_based_hash_entry));
   1798 
   1799             hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   1800                                     &port_based_hash_entry, sub_sel_f);
   1801             hash_offset  = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   1802                                     &port_based_hash_entry, ecmp_offset_f);
   1803             concat       = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   1804                                     &port_based_hash_entry, concat_f);
   1805         }
   1806     } else {
   1807         hash_sub_sel = 0;
   1808         hash_offset  = 0;
   1809         concat       = 0;
   1810     }
   1811 
   1812     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1813                 (BSL_META_U(unit,
   1814                             "ecmp hash_seb_sel=%d, hash_offset=%d, concat=%d\n"),
   1815                  hash_sub_sel, hash_offset, concat));
   1816     BCM_IF_ERROR_RETURN
   1817         (select_td2_hash_subfield(concat, hash_sub_sel, &hash_subfield, hash_Base));
   1818 
   1819     hash_subfield_width = concat ? 64 : 16;
   1820     hash_offset = concat ? hash_offset : (hash_offset & 0xf);
   1821 
   1822     /* Barrel shift the hash subfield, then take the LSB 16 bits */
   1823     HASH_VALUE_64_COMPUTE(hash_subfield, hash_offset, hash_subfield_width);
   1824     HASH_VALUE_32_COMPUTE(*hash_value, hash_subfield);
   1825     *hash_value &= 0xffff;  
   1826 
   1827     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1828                 (BSL_META_U(unit,
   1829                             "ecmp hash val=%d\n"),
   1830                  *hash_value));
   1831 
   1832     return BCM_E_NONE;
   1833     /* ***************** END of ECMP HASH CALCULATIONS.  ************************ */
   1834 }
   1835 
   1836 /*
   1837  * Function:
   1838  *          compute_td2_ecmp_rh_hash
   1839  * Description:
   1840  *     get ecmp rh hash value using SUB_SEL_RH_ECMPf and OFFSET_RH_ECMPf 
   1841  *     if flow hash is used, get subsel and offset from RTAG7_FLOW_BASED_HASHm 
   1842  *     if flow hash is not used, get subsel and offset from RTAG7_PORT_BASED_HASHm 
   1843  * Parameters:
   1844  *          unit - StrataSwitch PCI device unit number (driver internal).
   1845  *          hash_Base - internal data where rh ecmp hash value is stored 
   1846  * Returns:
   1847  *      BCM_E_xxxx
   1848  */
   1849 STATIC int
   1850 compute_td2_ecmp_rh_hash(int unit, bcm_rtag7_base_hash_t *hash_Base,
   1851                   uint32 *hash_value)
   1852 {
   1853     /*regular var declaration*/
   1854     uint32 hash_sub_sel;
   1855     uint32 hash_offset;
   1856     uint64 hash_subfield;
   1857     uint32 hash_subfield_width;
   1858     uint8  rtag7_ecmp_use_macro_flow_hash;
   1859     uint8  ecmp_hash_use_rtag7;
   1860     uint32 rtag7_hash_sel;
   1861     uint32 hash_control;
   1862     uint32 concat;
   1863     rtag7_flow_based_hash_entry_t 
   1864            flow_based_hash_entry;
   1865     rtag7_port_based_hash_entry_t
   1866             port_based_hash_entry;
   1867     uint32 port_based_hash_index;
   1868 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1869     int    hash_index = 0;
   1870 #endif
   1871     int rv = BCM_E_NONE;
   1872 
   1873     /* Select between non-RTAG7 hash value and RTAG7 hash value */
   1874     SOC_IF_ERROR_RETURN
   1875         (READ_HASH_CONTROLr(unit, &hash_control));
   1876     ecmp_hash_use_rtag7 =
   1877         soc_reg_field_get(unit, HASH_CONTROLr, hash_control,
   1878                           ECMP_HASH_USE_RTAG7f);
   1879 
   1880     if (ecmp_hash_use_rtag7 == 0) {
   1881         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1882                     (BSL_META_U(unit,
   1883                                 "ECMP RH Hash calculation:  non rtag7 calc not supported\n")));
   1884         *hash_value =  0;
   1885         return BCM_E_NONE;
   1886     }
   1887 
   1888     /* check if is uses flow hash */
   1889     SOC_IF_ERROR_RETURN
   1890         (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel));
   1891     if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_RH_ECMPf)) {
   1892         rtag7_ecmp_use_macro_flow_hash =
   1893             soc_reg_field_get(unit, RTAG7_HASH_SELr,
   1894                               rtag7_hash_sel, USE_FLOW_SEL_RH_ECMPf);
   1895     } else {
   1896         /* A0 bincomp value */
   1897         rtag7_ecmp_use_macro_flow_hash = 0;
   1898     }
   1899 
   1900 
   1901     /* RTAG7 hash computation */
   1902     if (rtag7_ecmp_use_macro_flow_hash) {
   1903         SOC_IF_ERROR_RETURN(
   1904             READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY,
   1905                     (hash_Base->rtag7_macro_flow_id & 0xff),
   1906                      &flow_based_hash_entry));    
   1907 
   1908         /* Generating RTAG7 Macro Flow Based Hash Subsel and Offset for use in RSEL1 Stage */
   1909         /* For future designs this logic can be placed in RSEL1 */
   1910         hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 
   1911                                            &flow_based_hash_entry, SUB_SEL_ECMPf);
   1912         hash_offset  = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 
   1913                                            &flow_based_hash_entry, OFFSET_ECMPf);
   1914         concat       = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 
   1915                                            &flow_based_hash_entry, CONCATENATE_HASH_FIELDS_ECMPf);
   1916     } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) {     
   1917         if (hash_Base->dev_src_port < 0) {
   1918             int field_count = 0;
   1919             soc_field_t fields[3];
   1920             uint32 values[3];
   1921             bcm_gport_t gport;
   1922         
   1923             BCM_GPORT_PROXY_SET(gport, 
   1924                 hash_Base->src_modid, hash_Base->src_port);
   1925         
   1926             fields[0] = SUB_SEL_RH_ECMPf;
   1927             field_count++;
   1928             fields[1] = OFFSET_RH_ECMPf;
   1929             field_count++;
   1930             fields[2] = CONCATENATE_HASH_FIELDS_RH_ECMPf;
   1931             field_count++;
   1932             PORT_LOCK(unit);
   1933             rv = bcm_esw_port_lport_fields_get(unit, gport,
   1934                                                LPORT_PROFILE_RTAG7_TAB,
   1935                                                field_count, fields, values);
   1936             PORT_UNLOCK(unit);
   1937             if (BCM_FAILURE(rv)) {
   1938                 return rv;
   1939             }
   1940             hash_sub_sel = values[0];
   1941             hash_offset  = values[1];
   1942             concat       = values[2];
   1943         } else {
   1944 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1945             if (soc_feature(unit, soc_feature_rtag7_port_profile)) {
   1946                 BCM_IF_ERROR_RETURN
   1947                     (_bcm_esw_port_tab_get(unit, hash_Base->dev_src_port,
   1948                                            RTAG7_PORT_PROFILE_INDEXf, &hash_index));
   1949                 port_based_hash_index = (uint32) hash_index;
   1950             } else
   1951 #endif
   1952             {
   1953                 port_based_hash_index = hash_Base->dev_src_port +
   1954                                         soc_mem_index_count(unit, LPORT_TABm);
   1955             }
   1956             SOC_IF_ERROR_RETURN(     
   1957                 READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 
   1958                             port_based_hash_index, &port_based_hash_entry));
   1959 
   1960             hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   1961                                     &port_based_hash_entry, SUB_SEL_RH_ECMPf);
   1962             hash_offset  = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   1963                                     &port_based_hash_entry, OFFSET_RH_ECMPf);
   1964             concat       = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   1965                                     &port_based_hash_entry, CONCATENATE_HASH_FIELDS_RH_ECMPf);
   1966         }
   1967     } else {
   1968         hash_sub_sel = 0;
   1969         hash_offset  = 0;
   1970         concat       = 0;
   1971     }
   1972 
   1973     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1974                 (BSL_META_U(unit,
   1975                             "ecmp rh hash_seb_sel=%d, hash_offset=%d, concat=%d\n"),
   1976                  hash_sub_sel, hash_offset, concat));
   1977 
   1978     BCM_IF_ERROR_RETURN
   1979         (select_td2_hash_subfield(concat, hash_sub_sel, &hash_subfield, hash_Base));
   1980 
   1981     hash_subfield_width = concat ? 64 : 16;
   1982     hash_offset = concat ? hash_offset : (hash_offset & 0xf);
   1983 
   1984     /* Barrel shift the hash subfield, then take the LSB 16 bits */
   1985     HASH_VALUE_64_COMPUTE(hash_subfield, hash_offset, hash_subfield_width);
   1986     HASH_VALUE_32_COMPUTE(*hash_value, hash_subfield);
   1987     *hash_value &= 0xffff;  
   1988     
   1989     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1990                 (BSL_META_U(unit,
   1991                             "ecmp rh hash val=%d\n"),
   1992                  *hash_value));
   1993 
   1994     return BCM_E_NONE;
   1995     /* ***************** END of ECMP RH HASH CALCULATIONS.  ************************ */
   1996 }
   1997 #endif /* INCLUDE_L3 */
   1998 
   1999 /*
   2000  * Function:
   2001  *          compute_td2_rtag7_hash_trunk
   2002  * Description:
   2003  *     get LAG hash value from RTAG7_PORT_BASED_HASHm 
   2004  *     if unicast, SUB_SEL_TRUNK_UCf and OFFSET_TRUNK_UCf are used 
   2005  *     if not unicast, SUB_SEL_TRUNK_NONUCf and OFFSET_TRUNK_NONUCf
   2006  *     if flow hash is used, get subsel and offset from RTAG7_FLOW_BASED_HASH 
   2007  * Parameters:
   2008  *          unit - StrataSwitch PCI device unit number (driver internal).
   2009  *          hash_Base - internal data where trunk hash value is storead
   2010  *          hash_value- result param 
   2011  * Returns:
   2012  *      BCM_E_xxxx
   2013  */
   2014 STATIC int
   2015 compute_td2_rtag7_hash_trunk(int unit , bcm_rtag7_base_hash_t *hash_Base,
   2016                          uint32 *hash_value)
   2017 {
   2018     uint32 hash_sub_sel;
   2019     uint32 hash_offset;     
   2020     uint32 rtag7_hash_sel; 
   2021     uint32 port_based_hash_index; 
   2022 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2023     int    hash_index = 0;
   2024 #endif
   2025     uint64 hash_subfield; 
   2026     uint32 hash_subfield_width;
   2027     uint32 offset_shift = 0;
   2028     uint32 concat;
   2029     uint8  rtag7_trunk_use_macro_flow_hash_uc    = 0;
   2030     uint8  rtag7_trunk_use_macro_flow_hash_nonuc = 0; 
   2031     rtag7_port_based_hash_entry_t 
   2032            port_based_hash_entry; 
   2033     rtag7_flow_based_hash_entry_t
   2034             flow_based_hash_entry; 
   2035     uint32 hash_control;
   2036     uint32 nuc_trunk_hash_use_rtag7;
   2037     int rv = BCM_E_NONE;
   2038 
   2039     /* check if flow hash is used for UC*/
   2040     SOC_IF_ERROR_RETURN 
   2041         (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 
   2042     if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_TRUNK_UCf)) {
   2043         rtag7_trunk_use_macro_flow_hash_uc =
   2044             soc_reg_field_get(unit, RTAG7_HASH_SELr, 
   2045                               rtag7_hash_sel, USE_FLOW_SEL_TRUNK_UCf);
   2046     } else { 
   2047         rtag7_trunk_use_macro_flow_hash_uc = 0;  
   2048     }
   2049   
   2050     /* check if flow hash is used for NONUC*/
   2051     SOC_IF_ERROR_RETURN 
   2052         (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 
   2053     if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_TRUNK_NONUCf)) {
   2054         rtag7_trunk_use_macro_flow_hash_nonuc = 
   2055             soc_reg_field_get(unit, RTAG7_HASH_SELr, 
   2056                               rtag7_hash_sel, USE_FLOW_SEL_TRUNK_NONUCf);
   2057     } else {
   2058         rtag7_trunk_use_macro_flow_hash_nonuc = 0;  
   2059     }     
   2060         
   2061     /* RTAG7 hash computation */
   2062     if ((rtag7_trunk_use_macro_flow_hash_nonuc && (hash_Base->is_nonuc == 0)) ||
   2063         (rtag7_trunk_use_macro_flow_hash_uc && (hash_Base->is_nonuc != 0))) { 
   2064         SOC_IF_ERROR_RETURN(
   2065             READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY,
   2066                     (hash_Base->rtag7_macro_flow_id & 0xff), 
   2067                      &flow_based_hash_entry)); 
   2068  
   2069         /* in RTAG7_FLOW_BASED_HASHm, using same selection for 
   2070            UC and NONUC */
   2071         hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 
   2072                                        &flow_based_hash_entry, SUB_SEL_TRUNKf);
   2073         hash_offset  = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit,
   2074                                        &flow_based_hash_entry, OFFSET_TRUNKf);
   2075         concat       = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit,
   2076                                        &flow_based_hash_entry, CONCATENATE_HASH_FIELDS_TRUNKf);
   2077         offset_shift = 0xffff;
   2078     } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) {
   2079         if (hash_Base->dev_src_port < 0) {
   2080             int field_count = 0;
   2081             soc_field_t fields[3];
   2082             uint32 values[3];
   2083             bcm_gport_t gport;
   2084 
   2085             BCM_GPORT_PROXY_SET(gport, 
   2086                 hash_Base->src_modid, hash_Base->src_port);
   2087 
   2088             if (hash_Base->is_nonuc) {
   2089                 fields[0] = SUB_SEL_TRUNK_NONUCf ;
   2090                 field_count++;
   2091                 fields[1] = OFFSET_TRUNK_NONUCf;
   2092                 field_count++;
   2093                 fields[2] = CONCATENATE_HASH_FIELDS_TRUNK_NONUCf;
   2094                 field_count++;
   2095                 offset_shift = 0xff;
   2096             } else {
   2097                 fields[0] = SUB_SEL_TRUNK_UCf ;
   2098                 field_count++;
   2099                 fields[1] = OFFSET_TRUNK_UCf;
   2100                 field_count++;
   2101                 fields[2] = CONCATENATE_HASH_FIELDS_TRUNK_UCf;
   2102                 field_count++;
   2103                 offset_shift = 0x3ff;
   2104             }
   2105             PORT_LOCK(unit);
   2106             rv = bcm_esw_port_lport_fields_get(unit, gport,
   2107                                                LPORT_PROFILE_RTAG7_TAB,
   2108                                                field_count, fields, values);
   2109             PORT_UNLOCK(unit);
   2110             if (BCM_FAILURE(rv)) {
   2111                 return rv;
   2112             }
   2113             hash_sub_sel = values[0];
   2114             hash_offset  = values[1];
   2115             concat       = values[2];
   2116         } else {
   2117 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2118             if (soc_feature(unit, soc_feature_rtag7_port_profile)) {
   2119                 BCM_IF_ERROR_RETURN
   2120                     (_bcm_esw_port_tab_get(unit, hash_Base->dev_src_port,
   2121                                            RTAG7_PORT_PROFILE_INDEXf, &hash_index));
   2122                 port_based_hash_index = (uint32) hash_index;
   2123             } else
   2124 #endif
   2125             {
   2126                 port_based_hash_index = hash_Base->dev_src_port +
   2127                                         soc_mem_index_count(unit, LPORT_TABm);
   2128             }
   2129             SOC_IF_ERROR_RETURN( 
   2130                 READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 
   2131                             port_based_hash_index, &port_based_hash_entry));
   2132             if (hash_Base->is_nonuc) {
   2133                 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   2134                                     &port_based_hash_entry, SUB_SEL_TRUNK_NONUCf);
   2135                 hash_offset  = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   2136                                     &port_based_hash_entry, OFFSET_TRUNK_NONUCf); 
   2137                 concat       = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   2138                                     &port_based_hash_entry, CONCATENATE_HASH_FIELDS_TRUNK_NONUCf); 
   2139                 offset_shift = 0xff; 
   2140             } else {
   2141                 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   2142                                     &port_based_hash_entry, SUB_SEL_TRUNK_UCf); 
   2143                 hash_offset  = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   2144                                     &port_based_hash_entry, OFFSET_TRUNK_UCf);
   2145                 concat       = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   2146                                     &port_based_hash_entry, CONCATENATE_HASH_FIELDS_TRUNK_UCf);
   2147                 offset_shift = 0x3ff; 
   2148             }
   2149         }
   2150     } else {
   2151         hash_sub_sel = 0;
   2152         hash_offset  = 0; 
   2153         concat       = 0;
   2154     }
   2155 
   2156     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2157                 (BSL_META_U(unit,
   2158                             "Trunk hash_seb_sel=%d, hash_offset=%d, concat=%d\n"),
   2159                  hash_sub_sel, hash_offset, concat));
   2160 
   2161     BCM_IF_ERROR_RETURN
   2162         (select_td2_hash_subfield(concat, hash_sub_sel, &hash_subfield, hash_Base)); 
   2163 
   2164     hash_subfield_width = concat ? 64 : 16;
   2165     hash_offset = concat ? hash_offset : (hash_offset & 0xf);
   2166 
   2167     /* Barrel shift the hash subfield, then take the LSB 10 bits for UC and 8 bits for nonUC */
   2168     HASH_VALUE_64_COMPUTE(hash_subfield, hash_offset, hash_subfield_width);
   2169     HASH_VALUE_32_COMPUTE(*hash_value, hash_subfield);
   2170     *hash_value &= offset_shift;  
   2171     
   2172     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2173                 (BSL_META_U(unit,
   2174                             "Trunk hash_value=%d\n"),
   2175                  *hash_value));
   2176 
   2177     BCM_IF_ERROR_RETURN
   2178         (READ_HASH_CONTROLr(unit, &hash_control));
   2179     nuc_trunk_hash_use_rtag7 =
   2180         soc_reg_field_get(unit, HASH_CONTROLr, hash_control,
   2181                           NON_UC_TRUNK_HASH_USE_RTAG7f);
   2182 
   2183     if (hash_Base->is_nonuc && nuc_trunk_hash_use_rtag7 == 0) {
   2184         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2185                     (BSL_META_U(unit,
   2186                                 "NonUC trunk Hash calculation:  non rtag7 calc not supported\n")));
   2187         *hash_value = 0;
   2188     }
   2189 
   2190     return BCM_E_NONE;
   2191 }
   2192 
   2193 /*
   2194  * Function:
   2195  *          compute_td2_rtag7_hash_hg_trunk
   2196  * Description:
   2197  *     get HGT hash value from RTAG7_PORT_BASED_HASHm 
   2198  *     if unicast, SUB_SEL_TRUNK_UCf and OFFSET_TRUNK_UCf are used 
   2199  *     if not unicast, SUB_SEL_TRUNK_NONUCf and OFFSET_TRUNK_NONUCf
   2200  *     if flow hash is used, get subsel and offset from RTAG7_FLOW_BASED_HASH 
   2201  * Parameters:
   2202  *          unit - StrataSwitch PCI device unit number (driver internal).
   2203  *          hash_Base - internal data where trunk hash value is storead
   2204  *          hash_value- result param 
   2205  * Returns:
   2206  *      BCM_E_xxxx
   2207  */
   2208 STATIC int
   2209 compute_td2_rtag7_hash_hg_trunk(int unit , bcm_rtag7_base_hash_t *hash_Base,
   2210                          uint32 *hash_value)
   2211 {
   2212     uint32 hash_sub_sel;
   2213     uint32 hash_offset;     
   2214     uint32 rtag7_hash_sel; 
   2215     uint32 port_based_hash_index; 
   2216 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2217     int    hash_index = 0;
   2218 #endif
   2219     uint64 hash_subfield; 
   2220     uint32 hash_subfield_width;
   2221     uint32 offset_shift = 0;
   2222     uint32 concat;
   2223     uint8  rtag7_hgt_use_macro_flow_hash_uc    = 0;
   2224     uint8  rtag7_hgt_use_macro_flow_hash_nonuc = 0; 
   2225     rtag7_port_based_hash_entry_t 
   2226            port_based_hash_entry; 
   2227     rtag7_flow_based_hash_entry_t
   2228             flow_based_hash_entry; 
   2229     int rv = BCM_E_NONE;
   2230 
   2231     /* check if flow hash is used for UC*/
   2232     SOC_IF_ERROR_RETURN 
   2233         (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 
   2234     if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_HG_TRUNK_UCf)) {
   2235         rtag7_hgt_use_macro_flow_hash_uc =
   2236             soc_reg_field_get(unit, RTAG7_HASH_SELr, 
   2237                               rtag7_hash_sel, USE_FLOW_SEL_HG_TRUNK_UCf);
   2238     } else { 
   2239         rtag7_hgt_use_macro_flow_hash_uc = 0;  
   2240     }
   2241   
   2242     /* check if flow hash is used for NONUC*/
   2243     if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_HG_TRUNK_NONUCf)) {
   2244         rtag7_hgt_use_macro_flow_hash_nonuc = 
   2245             soc_reg_field_get(unit, RTAG7_HASH_SELr, 
   2246                               rtag7_hash_sel, USE_FLOW_SEL_HG_TRUNK_NONUCf);
   2247     } else {
   2248         rtag7_hgt_use_macro_flow_hash_nonuc = 0;  
   2249     }     
   2250         
   2251     /* RTAG7 hash computation */
   2252     if ((rtag7_hgt_use_macro_flow_hash_nonuc && (hash_Base->is_nonuc == 0)) ||
   2253         (rtag7_hgt_use_macro_flow_hash_uc && (hash_Base->is_nonuc != 0))) { 
   2254         SOC_IF_ERROR_RETURN(
   2255             READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY,
   2256                     (hash_Base->rtag7_macro_flow_id & 0xff), 
   2257                      &flow_based_hash_entry)); 
   2258  
   2259         /* in RTAG7_FLOW_BASED_HASHm, using same selection for 
   2260            UC and NONUC */
   2261         hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 
   2262                                        &flow_based_hash_entry, SUB_SEL_HG_TRUNKf);
   2263         hash_offset  = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit,
   2264                                        &flow_based_hash_entry, OFFSET_HG_TRUNKf);
   2265         concat       = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit,
   2266                                        &flow_based_hash_entry, CONCATENATE_HASH_FIELDS_HG_TRUNKf);
   2267         offset_shift = 0xffff;
   2268     } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) {
   2269         if (hash_Base->dev_src_port < 0) {
   2270             int field_count = 0;
   2271             soc_field_t fields[3];
   2272             uint32 values[3];
   2273             bcm_gport_t gport;
   2274 
   2275             BCM_GPORT_PROXY_SET(gport, 
   2276                 hash_Base->src_modid, hash_Base->src_port);
   2277 
   2278             if (hash_Base->is_nonuc) {
   2279                 fields[0] = SUB_SEL_HG_TRUNK_NONUCf ;
   2280                 field_count++;
   2281                 fields[1] = OFFSET_HG_TRUNK_NONUCf;
   2282                 field_count++;
   2283                 fields[2] = CONCATENATE_HASH_FIELDS_HG_TRUNK_NONUCf;
   2284                 field_count++;
   2285                 offset_shift = 0xff;
   2286             } else {
   2287                 fields[0] = SUB_SEL_HG_TRUNK_UCf ;
   2288                 field_count++;
   2289                 fields[1] = OFFSET_HG_TRUNK_UCf;
   2290                 field_count++;
   2291                 fields[2] = CONCATENATE_HASH_FIELDS_HG_TRUNK_UCf;
   2292                 field_count++;
   2293                 offset_shift = 0x3ff;
   2294             }
   2295             PORT_LOCK(unit);
   2296             rv = bcm_esw_port_lport_fields_get(unit, gport,
   2297                                                LPORT_PROFILE_RTAG7_TAB,
   2298                                                field_count, fields, values);
   2299             PORT_UNLOCK(unit);
   2300             if (BCM_FAILURE(rv)) {
   2301                 return rv;
   2302             }
   2303             hash_sub_sel = values[0];
   2304             hash_offset  = values[1];
   2305             concat       = values[2];
   2306         } else {
   2307 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2308             if (soc_feature(unit, soc_feature_rtag7_port_profile)) {
   2309                 BCM_IF_ERROR_RETURN
   2310                     (_bcm_esw_port_tab_get(unit, hash_Base->dev_src_port,
   2311                                            RTAG7_PORT_PROFILE_INDEXf, &hash_index));
   2312                 port_based_hash_index = (uint32) hash_index;
   2313             } else
   2314 #endif
   2315             {
   2316                 port_based_hash_index = hash_Base->dev_src_port +
   2317                                         soc_mem_index_count(unit, LPORT_TABm);
   2318             }
   2319             SOC_IF_ERROR_RETURN( 
   2320                 READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 
   2321                             port_based_hash_index, &port_based_hash_entry));
   2322             if (hash_Base->is_nonuc) {
   2323                 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   2324                                     &port_based_hash_entry, SUB_SEL_HG_TRUNK_NONUCf);
   2325                 hash_offset  = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   2326                                     &port_based_hash_entry, OFFSET_HG_TRUNK_NONUCf); 
   2327                 concat       = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   2328                                     &port_based_hash_entry, CONCATENATE_HASH_FIELDS_HG_TRUNK_NONUCf); 
   2329                 offset_shift = 0xff; 
   2330             } else {
   2331                 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   2332                                     &port_based_hash_entry, SUB_SEL_HG_TRUNK_UCf); 
   2333                 hash_offset  = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   2334                                     &port_based_hash_entry, OFFSET_HG_TRUNK_UCf);
   2335                 concat       = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   2336                                     &port_based_hash_entry, CONCATENATE_HASH_FIELDS_HG_TRUNK_UCf);
   2337                 offset_shift = 0x3ff; 
   2338             }
   2339         }
   2340     } else {
   2341         hash_sub_sel = 0;
   2342         hash_offset  = 0; 
   2343         concat       = 0;
   2344     }
   2345 
   2346     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2347                 (BSL_META_U(unit,
   2348                             "Trunk hash_seb_sel=%d, hash_offset=%d, concat=%d\n"),
   2349                  hash_sub_sel, hash_offset, concat));
   2350 
   2351     BCM_IF_ERROR_RETURN
   2352         (select_td2_hash_subfield(concat, hash_sub_sel, &hash_subfield, hash_Base)); 
   2353 
   2354     hash_subfield_width = concat ? 64 : 16;
   2355     hash_offset = concat ? hash_offset : (hash_offset & 0xf);
   2356 
   2357     /* Barrel shift the hash subfield, then take the LSB 10 bits for UC and 8 bits for nonUC */
   2358     HASH_VALUE_64_COMPUTE(hash_subfield, hash_offset, hash_subfield_width);
   2359     HASH_VALUE_32_COMPUTE(*hash_value, hash_subfield);
   2360     *hash_value &= offset_shift;  
   2361     
   2362     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2363                 (BSL_META_U(unit,
   2364                             "HG Trunk hash_value=%d\n"),
   2365                  *hash_value));
   2366 
   2367     return BCM_E_NONE;
   2368 }
   2369 
   2370 /*
   2371  * Function:
   2372  *          compute_td2_rtag7_hash_rh_trunk
   2373  * Description:
   2374  *     get LAG RH hash value using SUB_SEL_RH_LAGf and OFFSET_RH_LAGf 
   2375  *     from RTAG7_PORT_BASED_HASHm 
   2376  * Parameters:
   2377  *          unit - StrataSwitch PCI device unit number (driver internal).
   2378  *          hash_Base - internal data where rh hash value is stored
   2379  *          hash_value- result param 
   2380  * Returns:
   2381  *      BCM_E_xxxx
   2382  */
   2383 STATIC int
   2384 compute_td2_rtag7_hash_rh_trunk(int unit , bcm_rtag7_base_hash_t *hash_Base,
   2385                          uint32 *hash_value)
   2386 {
   2387     uint32 hash_sub_sel;
   2388     uint32 hash_offset;    
   2389     uint32 rtag7_hash_sel; 
   2390     uint32 port_based_hash_index;
   2391 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2392     int    hash_index = 0;
   2393 #endif
   2394     uint64 hash_subfield;
   2395     uint32 hash_subfield_width;
   2396     uint32 concat;
   2397     uint32 offset_shift = 0;
   2398     rtag7_port_based_hash_entry_t 
   2399            port_based_hash_entry;
   2400     rtag7_flow_based_hash_entry_t
   2401             flow_based_hash_entry; 
   2402     uint32 hash_control;
   2403     uint32 nuc_trunk_hash_use_rtag7;
   2404     int rv = BCM_E_NONE;
   2405 
   2406 
   2407     /* check if flow hash is used for UC*/
   2408     SOC_IF_ERROR_RETURN 
   2409         (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 
   2410     /* RTAG7 hash computation */
   2411     if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_RH_LAGf) && 
   2412         soc_reg_field_get(unit, RTAG7_HASH_SELr, 
   2413                               rtag7_hash_sel, USE_FLOW_SEL_RH_LAGf)) { 
   2414         SOC_IF_ERROR_RETURN(
   2415             READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY,
   2416                     (hash_Base->rtag7_macro_flow_id & 0xff), 
   2417                      &flow_based_hash_entry)); 
   2418  
   2419         /* in RTAG7_FLOW_BASED_HASHm, using same selection for 
   2420            UC and NONUC */
   2421         hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 
   2422                                        &flow_based_hash_entry, SUB_SEL_TRUNKf);
   2423         hash_offset  = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit,
   2424                                        &flow_based_hash_entry, OFFSET_TRUNKf);
   2425         concat       = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit,
   2426                                        &flow_based_hash_entry, CONCATENATE_HASH_FIELDS_TRUNKf);
   2427         offset_shift = 0xffff;
   2428     } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) {
   2429         if (hash_Base->dev_src_port < 0) {
   2430             int field_count = 0;
   2431             soc_field_t fields[3];
   2432             uint32 values[3];
   2433             bcm_gport_t gport;
   2434 
   2435             BCM_GPORT_PROXY_SET(gport, 
   2436                 hash_Base->src_modid, hash_Base->src_port);
   2437 
   2438             fields[0] = SUB_SEL_RH_LAGf ;
   2439             field_count++;
   2440             fields[1] = OFFSET_RH_LAGf;
   2441             field_count++;
   2442             fields[2] = CONCATENATE_HASH_FIELDS_RH_LAGf;
   2443             field_count++;
   2444 
   2445             PORT_LOCK(unit);
   2446             rv = bcm_esw_port_lport_fields_get(unit, gport,
   2447                                                LPORT_PROFILE_RTAG7_TAB,
   2448                                                field_count, fields, values);
   2449             PORT_UNLOCK(unit);
   2450             if (BCM_FAILURE(rv)) {
   2451                 return rv;
   2452             }
   2453             hash_sub_sel = values[0];
   2454             hash_offset  = values[1];
   2455             concat       = values[2];
   2456             offset_shift = 0x3ff;
   2457         } else {
   2458 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2459             if (soc_feature(unit, soc_feature_rtag7_port_profile)) {
   2460                 BCM_IF_ERROR_RETURN
   2461                     (_bcm_esw_port_tab_get(unit, hash_Base->dev_src_port,
   2462                                            RTAG7_PORT_PROFILE_INDEXf, &hash_index));
   2463                 port_based_hash_index = (uint32) hash_index;
   2464             } else
   2465 #endif
   2466             {
   2467                 port_based_hash_index = hash_Base->dev_src_port +
   2468                                         soc_mem_index_count(unit, LPORT_TABm);
   2469             }
   2470             BCM_IF_ERROR_RETURN (  
   2471                 READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 
   2472                                 port_based_hash_index, &port_based_hash_entry));
   2473             hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   2474                                         &port_based_hash_entry, SUB_SEL_RH_LAGf);
   2475             hash_offset  = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   2476                                         &port_based_hash_entry, OFFSET_RH_LAGf);
   2477             concat       = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   2478                                         &port_based_hash_entry, CONCATENATE_HASH_FIELDS_RH_LAGf);
   2479             offset_shift = 0x3ff;
   2480         }
   2481     } else {
   2482         hash_sub_sel = 0;
   2483         hash_offset  = 0; 
   2484         concat       = 0;
   2485     }
   2486 
   2487     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2488                 (BSL_META_U(unit,
   2489                             "Trunk RH hash_sub_sel=%d, hash_offset=%d, concat=%d\n"),
   2490                  hash_sub_sel, hash_offset, concat));
   2491 
   2492     BCM_IF_ERROR_RETURN
   2493         (select_td2_hash_subfield(concat, hash_sub_sel, &hash_subfield, hash_Base));
   2494 
   2495     hash_subfield_width = concat ? 64 : 16;
   2496     hash_offset = concat ? hash_offset : (hash_offset & 0xf);
   2497 
   2498     /* Barrel shift the hash subfield, then take the LSB 10 bits for UC and 8 bits for nonUC */
   2499     HASH_VALUE_64_COMPUTE(hash_subfield, hash_offset, hash_subfield_width);
   2500     HASH_VALUE_32_COMPUTE(*hash_value, hash_subfield);
   2501     *hash_value &= offset_shift;  
   2502 
   2503     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2504                 (BSL_META_U(unit,
   2505                             "Trunk RH hash_value=%d\n"),
   2506                  *hash_value));
   2507 
   2508     BCM_IF_ERROR_RETURN
   2509         (READ_HASH_CONTROLr(unit, &hash_control));
   2510     nuc_trunk_hash_use_rtag7 =
   2511         soc_reg_field_get(unit, HASH_CONTROLr, hash_control,
   2512                           NON_UC_TRUNK_HASH_USE_RTAG7f);
   2513 
   2514     if (hash_Base->is_nonuc && nuc_trunk_hash_use_rtag7 == 0) {
   2515         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2516                     (BSL_META_U(unit,
   2517                                 "NonUC trunk Hash calculation:  non rtag7 calc not supported\n")));
   2518         *hash_value = 0;
   2519     }
   2520 
   2521     return BCM_E_NONE;
   2522 }
   2523 
   2524 /*
   2525  * Function:
   2526  *          compute_td2_rtag7_hash_rh_hg_trunk
   2527  * Description:
   2528  *     get HGT RH hash value using SUB_SEL_RH_LAGf and OFFSET_RH_LAGf 
   2529  *     from RTAG7_PORT_BASED_HASHm 
   2530  * Parameters:
   2531  *          unit - StrataSwitch PCI device unit number (driver internal).
   2532  *          hash_Base - internal data where rh hash value is stored
   2533  *          hash_value- result param 
   2534  * Returns:
   2535  *      BCM_E_xxxx
   2536  */
   2537 STATIC int
   2538 compute_td2_rtag7_hash_rh_hg_trunk(int unit , bcm_rtag7_base_hash_t *hash_Base,
   2539                          uint32 *hash_value)
   2540 {
   2541     uint32 hash_sub_sel;
   2542     uint32 hash_offset;     
   2543     uint32 rtag7_hash_sel; 
   2544     uint32 port_based_hash_index; 
   2545 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2546     int    hash_index = 0;
   2547 #endif
   2548     uint64 hash_subfield; 
   2549     uint32 hash_subfield_width;
   2550     uint32 offset_shift = 0;
   2551     uint32 concat;
   2552     rtag7_port_based_hash_entry_t 
   2553            port_based_hash_entry; 
   2554     rtag7_flow_based_hash_entry_t
   2555             flow_based_hash_entry; 
   2556     int rv = BCM_E_NONE;
   2557 
   2558     /* check if flow hash is used for UC*/
   2559     SOC_IF_ERROR_RETURN 
   2560         (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 
   2561     /* RTAG7 hash computation */
   2562     if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_RH_HGTf) && 
   2563         soc_reg_field_get(unit, RTAG7_HASH_SELr, 
   2564                               rtag7_hash_sel, USE_FLOW_SEL_RH_HGTf)) { 
   2565         SOC_IF_ERROR_RETURN(
   2566             READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY,
   2567                     (hash_Base->rtag7_macro_flow_id & 0xff), 
   2568                      &flow_based_hash_entry)); 
   2569  
   2570         /* in RTAG7_FLOW_BASED_HASHm, using same selection for 
   2571            UC and NONUC */
   2572         hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 
   2573                                        &flow_based_hash_entry, SUB_SEL_HG_TRUNKf);
   2574         hash_offset  = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit,
   2575                                        &flow_based_hash_entry, OFFSET_HG_TRUNKf);
   2576         concat       = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit,
   2577                                        &flow_based_hash_entry, CONCATENATE_HASH_FIELDS_HG_TRUNKf);
   2578         offset_shift = 0xffff;
   2579     } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) {
   2580         if (hash_Base->dev_src_port < 0) {
   2581             int field_count = 0;
   2582             soc_field_t fields[3];
   2583             uint32 values[3];
   2584             bcm_gport_t gport;
   2585 
   2586             BCM_GPORT_PROXY_SET(gport, 
   2587                 hash_Base->src_modid, hash_Base->src_port);
   2588 
   2589             fields[0] = SUB_SEL_RH_HGTf ;
   2590             field_count++;
   2591             fields[1] = OFFSET_RH_HGTf;
   2592             field_count++;
   2593             fields[2] = CONCATENATE_HASH_FIELDS_RH_HGTf;
   2594             field_count++;
   2595 
   2596             PORT_LOCK(unit);
   2597             rv = bcm_esw_port_lport_fields_get(unit, gport,
   2598                                                LPORT_PROFILE_RTAG7_TAB,
   2599                                                field_count, fields, values);
   2600             PORT_UNLOCK(unit);
   2601             if (BCM_FAILURE(rv)) {
   2602                 return rv;
   2603             }
   2604             hash_sub_sel = values[0];
   2605             hash_offset  = values[1];
   2606             concat       = values[2];
   2607             offset_shift = 0x3ff;
   2608         } else {
   2609 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2610             if (soc_feature(unit, soc_feature_rtag7_port_profile)) {
   2611                 BCM_IF_ERROR_RETURN
   2612                     (_bcm_esw_port_tab_get(unit, hash_Base->dev_src_port,
   2613                                            RTAG7_PORT_PROFILE_INDEXf, &hash_index));
   2614                 port_based_hash_index = (uint32) hash_index;
   2615             } else
   2616 #endif
   2617             {
   2618                 port_based_hash_index = hash_Base->dev_src_port +
   2619                                         soc_mem_index_count(unit, LPORT_TABm);
   2620             }
   2621             SOC_IF_ERROR_RETURN( 
   2622                 READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 
   2623                             port_based_hash_index, &port_based_hash_entry));
   2624             hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   2625                                         &port_based_hash_entry, SUB_SEL_RH_HGTf);
   2626             hash_offset  = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   2627                                         &port_based_hash_entry, OFFSET_RH_HGTf);
   2628             concat       = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   2629                                         &port_based_hash_entry, CONCATENATE_HASH_FIELDS_RH_HGTf);
   2630             offset_shift = 0x3ff;
   2631         }
   2632     } else {
   2633         hash_sub_sel = 0;
   2634         hash_offset  = 0; 
   2635         concat       = 0;
   2636     }
   2637 
   2638     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2639                 (BSL_META_U(unit,
   2640                             "HGT RH hash_sub_sel=%d, hash_offset=%d, concat=%d\n"),
   2641                  hash_sub_sel, hash_offset, concat));
   2642 
   2643     BCM_IF_ERROR_RETURN
   2644         (select_td2_hash_subfield(concat, hash_sub_sel, &hash_subfield, hash_Base)); 
   2645 
   2646     hash_subfield_width = concat ? 64 : 16;
   2647     hash_offset = concat ? hash_offset : (hash_offset & 0xf);
   2648 
   2649     /* Barrel shift the hash subfield, then take the LSB 10 bits for UC and 8 bits for nonUC */
   2650     HASH_VALUE_64_COMPUTE(hash_subfield, hash_offset, hash_subfield_width);
   2651     HASH_VALUE_32_COMPUTE(*hash_value, hash_subfield);
   2652     *hash_value &= offset_shift;  
   2653     
   2654     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2655                 (BSL_META_U(unit,
   2656                             "HGT RH hash_value=%d\n"),
   2657                  *hash_value));
   2658 
   2659     return BCM_E_NONE;
   2660 }
   2661 
   2662 /*
   2663  * Function:
   2664  *          compute_td2_rtag7_vxlan
   2665  * Description: compute entropy value of vxlan packet
   2666  * Parameters:
   2667  *          unit - StrataSwitch PCI device unit number (driver internal).
   2668  *          hash_Base - internal data where trunk hash value is storead
   2669  *          hash_value- result param 
   2670  * Returns:
   2671  *      BCM_E_xxxx
   2672  */
   2673 STATIC int
   2674 compute_td2_rtag7_vxlan(int unit , bcm_rtag7_base_hash_t *hash_Base,
   2675                                    uint32 *hash_value)
   2676 {
   2677     uint32 hash_sub_sel;
   2678     uint32 hash_offset;     
   2679     uint32 rtag7_hash_sel; 
   2680     uint32 port_based_hash_index; 
   2681 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2682     int    hash_index = 0;
   2683 #endif
   2684     uint64 hash_subfield; 
   2685     uint32 hash_subfield_width;
   2686     uint32 offset_shift = 0xffff;
   2687     uint32 concat;
   2688     uint8  rtag7_vxlan_use_flow_sel_entropy_label = 0;
   2689     rtag7_port_based_hash_entry_t 
   2690            port_based_hash_entry; 
   2691     rtag7_flow_based_hash_entry_t
   2692             flow_based_hash_entry; 
   2693 
   2694     /* check if vxlan use RTAG7_FLOW_BASED_HASH 
   2695        else use RTAG7_PORT_BASED_HASH selection for ENTROPY_LABEL*/
   2696     SOC_IF_ERROR_RETURN 
   2697         (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 
   2698     if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_ENTROPY_LABELf)) {
   2699         rtag7_vxlan_use_flow_sel_entropy_label =
   2700             soc_reg_field_get(unit, RTAG7_HASH_SELr, 
   2701                               rtag7_hash_sel, USE_FLOW_SEL_ENTROPY_LABELf);
   2702     } else { 
   2703         rtag7_vxlan_use_flow_sel_entropy_label = 0;  
   2704     }
   2705        
   2706     /* RTAG7 hash computation */
   2707     if (rtag7_vxlan_use_flow_sel_entropy_label) {
   2708         /* read flow_based_hash table and set hash_sub_sel, offset, and concat value */
   2709         SOC_IF_ERROR_RETURN(
   2710             READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY,
   2711                     (hash_Base->rtag7_macro_flow_id & 0xff), 
   2712                      &flow_based_hash_entry)); 
   2713  
   2714        
   2715         hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 
   2716                                        &flow_based_hash_entry, SUB_SEL_LBID_OR_ENTROPY_LABELf);
   2717         hash_offset  = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit,
   2718                                        &flow_based_hash_entry, OFFSET_LBID_OR_ENTROPY_LABELf);
   2719         concat       = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit,
   2720                                        &flow_based_hash_entry, CONCATENATE_HASH_FIELDS_LBID_OR_ENTROPY_LABELf);
   2721     } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) {  
   2722         /* read port_based_hash table and set hash_sub_sel, offset, and concat value */    
   2723 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2724         if (soc_feature(unit, soc_feature_rtag7_port_profile)) {
   2725             BCM_IF_ERROR_RETURN
   2726                 (_bcm_esw_port_tab_get(unit, hash_Base->dev_src_port,
   2727                                        RTAG7_PORT_PROFILE_INDEXf, &hash_index));
   2728             port_based_hash_index = (uint32) hash_index;
   2729         } else
   2730 #endif
   2731         {
   2732             port_based_hash_index = hash_Base->dev_src_port +
   2733                                     soc_mem_index_count(unit, LPORT_TABm);
   2734         }
   2735         SOC_IF_ERROR_RETURN( 
   2736             READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 
   2737                         port_based_hash_index, &port_based_hash_entry));
   2738             hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit,
   2739                                 &port_based_hash_entry, SUB_SEL_ENTROPY_LABELf);
   2740             hash_offset  = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   2741                                 &port_based_hash_entry, OFFSET_ENTROPY_LABELf); 
   2742             concat       = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 
   2743                                 &port_based_hash_entry, CONCATENATE_HASH_FIELDS_ENTROPY_LABELf); 
   2744     } else {
   2745         hash_sub_sel = 0;
   2746         hash_offset  = 0; 
   2747         concat       = 0;
   2748     }
   2749 
   2750     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2751                 (BSL_META_U(unit,
   2752                             "vxlan hash_seb_sel=%d, hash_offset=%d, concat=%d\n"),
   2753                  hash_sub_sel, hash_offset, concat));
   2754     BCM_IF_ERROR_RETURN
   2755         (select_td2_hash_subfield(concat, hash_sub_sel, &hash_subfield, hash_Base)); 
   2756 
   2757     hash_subfield_width = concat ? 64 : 16;
   2758     hash_offset = concat ? hash_offset : (hash_offset & 0xf);
   2759 
   2760     /* Barrel shift the hash subfield, then take the LSB 10 bits for UC and 8 bits for nonUC */
   2761     HASH_VALUE_64_COMPUTE(hash_subfield, hash_offset, hash_subfield_width);
   2762     HASH_VALUE_32_COMPUTE(*hash_value, hash_subfield);
   2763     *hash_value &= offset_shift;  
   2764     
   2765     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2766                 (BSL_META_U(unit,
   2767                             "vxlan hash_value=%d\n"),
   2768                  *hash_value));
   2769 
   2770     return BCM_E_NONE;
   2771 }
   2772 
   2773 
   2774 /* check ethertype eligibility for resilient hashing */ 
   2775 uint8 check_td2_ether_type_eligibility_for_rh(int unit, uint8 rh_mode, uint32 rh_ethertype) 
   2776 {
   2777     uint8  ethertype_enable = 0;
   2778     uint8  ethertype_eligibility_config = 0;
   2779     uint32 ethertype_control;
   2780     uint32 ethercount;
   2781     int    ethertype;  
   2782     rh_ecmp_ethertype_eligibility_map_entry_t ethertype_entry;
   2783     
   2784     if (rh_mode == RTAG7_RH_MODE_ECMP) {
   2785         SOC_IF_ERROR_RETURN
   2786           (READ_RH_ECMP_ETHERTYPE_ELIGIBILITY_CONTROLr(unit, &ethertype_control));
   2787 
   2788         ethertype_eligibility_config = soc_reg_field_get(unit, 
   2789                                                 RH_ECMP_ETHERTYPE_ELIGIBILITY_CONTROLr, 
   2790                                                 ethertype_control,
   2791                                                 ETHERTYPE_ELIGIBILITY_CONFIGf);
   2792     } else if (rh_mode == RTAG7_RH_MODE_LAG) {
   2793         SOC_IF_ERROR_RETURN
   2794             (READ_RH_LAG_ETHERTYPE_ELIGIBILITY_CONTROLr(unit, &ethertype_control));
   2795 
   2796         ethertype_eligibility_config = soc_reg_field_get(unit, 
   2797                                                 RH_LAG_ETHERTYPE_ELIGIBILITY_CONTROLr, 
   2798                                                 ethertype_control,
   2799                                                 ETHERTYPE_ELIGIBILITY_CONFIGf);
   2800     } else if (rh_mode == RTAG7_RH_MODE_HGT) {
   2801         SOC_IF_ERROR_RETURN
   2802             (READ_RH_HGT_ETHERTYPE_ELIGIBILITY_CONTROLr(unit, &ethertype_control));
   2803 
   2804         ethertype_eligibility_config = soc_reg_field_get(unit, 
   2805                                                 RH_HGT_ETHERTYPE_ELIGIBILITY_CONTROLr, 
   2806                                                 ethertype_control,
   2807                                                 ETHERTYPE_ELIGIBILITY_CONFIGf);
   2808     }
   2809 
   2810     /* Check for 16 Ethertypes supported based on operating in the "exclude mode" or "include mode"*/
   2811     if (ethertype_eligibility_config) {
   2812         ethertype_enable = 0;
   2813         for (ethercount = 0; 
   2814             ethercount <  soc_mem_index_count(unit,RH_ECMP_ETHERTYPE_ELIGIBILITY_MAPm); 
   2815             ethercount++) {
   2816 
   2817             if (rh_mode == RTAG7_RH_MODE_ECMP) {
   2818                 SOC_IF_ERROR_RETURN(READ_RH_ECMP_ETHERTYPE_ELIGIBILITY_MAPm(unit,
   2819                                 MEM_BLOCK_ANY, ethercount, &ethertype_entry));
   2820                 if (soc_RH_ECMP_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit,
   2821                                                 &ethertype_entry, VALIDf)) {
   2822                     ethertype = soc_RH_ECMP_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit,
   2823                                                 &ethertype_entry, ETHERTYPEf);
   2824                     ethertype_enable |= (rh_ethertype == ethertype);
   2825                 }
   2826             } else if (rh_mode == RTAG7_RH_MODE_LAG) {
   2827                 SOC_IF_ERROR_RETURN(READ_RH_LAG_ETHERTYPE_ELIGIBILITY_MAPm(unit,
   2828                                 MEM_BLOCK_ANY, ethercount, &ethertype_entry));
   2829                 if (soc_RH_LAG_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit,
   2830                                                 &ethertype_entry, VALIDf)) {
   2831                     ethertype = soc_RH_LAG_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit,
   2832                                                 &ethertype_entry, ETHERTYPEf);
   2833                     ethertype_enable |= (rh_ethertype == ethertype);
   2834                 }
   2835             } else if (rh_mode == RTAG7_RH_MODE_HGT) {
   2836                 SOC_IF_ERROR_RETURN(READ_RH_HGT_ETHERTYPE_ELIGIBILITY_MAPm(unit,
   2837                                 MEM_BLOCK_ANY, ethercount, &ethertype_entry));
   2838                 if (soc_RH_HGT_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit,
   2839                                                 &ethertype_entry, VALIDf)) {
   2840                     ethertype = soc_RH_HGT_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit,
   2841                                                 &ethertype_entry, ETHERTYPEf);
   2842                     ethertype_enable |= (rh_ethertype == ethertype);
   2843                 }
   2844             }
   2845         } /* end of forloop */
   2846     } else {
   2847         ethertype_enable = 1;
   2848          for (ethercount = 0; 
   2849             ethercount <  soc_mem_index_count(unit,RH_ECMP_ETHERTYPE_ELIGIBILITY_MAPm); 
   2850             ethercount++) {
   2851 
   2852             if (rh_mode == RTAG7_RH_MODE_ECMP) {
   2853                 SOC_IF_ERROR_RETURN(READ_RH_ECMP_ETHERTYPE_ELIGIBILITY_MAPm(unit,
   2854                                 MEM_BLOCK_ANY, ethercount, &ethertype_entry));
   2855                 if (soc_RH_ECMP_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit,
   2856                                                 &ethertype_entry, VALIDf)) {
   2857                     ethertype = soc_RH_ECMP_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit,
   2858                                                 &ethertype_entry, ETHERTYPEf);
   2859                     ethertype_enable &= !(rh_ethertype == ethertype);
   2860                 }
   2861             } else if (rh_mode == RTAG7_RH_MODE_LAG) {
   2862                 SOC_IF_ERROR_RETURN(READ_RH_LAG_ETHERTYPE_ELIGIBILITY_MAPm(unit,
   2863                                 MEM_BLOCK_ANY, ethercount, &ethertype_entry));
   2864                 if (soc_RH_LAG_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit,
   2865                                                 &ethertype_entry, VALIDf)) {
   2866                     ethertype = soc_RH_LAG_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit,
   2867                                                 &ethertype_entry, ETHERTYPEf);
   2868                     ethertype_enable &= !(rh_ethertype == ethertype);
   2869                 }
   2870             } else if (rh_mode == RTAG7_RH_MODE_HGT) {
   2871                 SOC_IF_ERROR_RETURN(READ_RH_HGT_ETHERTYPE_ELIGIBILITY_MAPm(unit,
   2872                                 MEM_BLOCK_ANY, ethercount, &ethertype_entry));
   2873                 if (soc_RH_HGT_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit,
   2874                                                 &ethertype_entry, VALIDf)) {
   2875                     ethertype = soc_RH_HGT_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit,
   2876                                                 &ethertype_entry, ETHERTYPEf);
   2877                     ethertype_enable &= !(rh_ethertype == ethertype);
   2878                 }
   2879             }
   2880         } /* end of forloop */
   2881     }
   2882 
   2883     return ethertype_enable;
   2884 }
   2885 
   2886 /* calcualte resilient hashing value */
   2887 int perform_td2_rh(int unit,uint32 flow_set_base, uint8 flow_set_size, uint8 rh_mode, 
   2888                 uint32  ecmp_hash,uint32 trunk_hash, 
   2889                 uint32* resolved_member, uint8* resolved_member_is_valid) 
   2890 {
   2891     uint32 rtag7_hash = 0;
   2892     uint32 flow_set_index = 0;
   2893     uint32 rh_flowset_table_config;
   2894     uint32 port_id;
   2895     uint32 mod_id;
   2896     rh_ecmp_flowset_entry_t ecmp_flow_entry;
   2897     rh_lag_flowset_entry_t  lag_flow_entry;
   2898     rh_hgt_flowset_entry_t  hgt_flow_entry;
   2899     soc_field_t port_fld = EGRESS_PORTf;
   2900 
   2901     if (!soc_mem_field_valid(unit, RH_HGT_FLOWSETm, port_fld)) {
   2902         port_fld = PORT_NUMf;
   2903     }
   2904 
   2905    
   2906     if (rh_mode == RTAG7_RH_MODE_ECMP) {
   2907         rtag7_hash = ecmp_hash; 
   2908     } else if (rh_mode == RTAG7_RH_MODE_LAG) {
   2909         rtag7_hash = trunk_hash;
   2910     } else if (rh_mode == RTAG7_RH_MODE_HGT) {
   2911         rtag7_hash = trunk_hash;
   2912     }
   2913 
   2914     /* Compute flow set index */
   2915 
   2916     switch (flow_set_size) {
   2917         case 0: /* 0 - Flow Index is  0 */
   2918             flow_set_index = 0;
   2919             break;
   2920         case 1: /* 64 - take 6 hash bits*/
   2921             flow_set_index = flow_set_base + (rtag7_hash & 0x3f);
   2922             break;
   2923         case 2: /* 128 - take 7 hash bits*/
   2924             flow_set_index = flow_set_base + (rtag7_hash & 0x7f);
   2925             break;
   2926         case 3: /* 256 - take 8 hash bits*/
   2927             flow_set_index = flow_set_base + (rtag7_hash & 0xff);
   2928             break;
   2929         case 4: /* 512 - take 9 hash bits*/
   2930             flow_set_index = flow_set_base + (rtag7_hash & 0x1ff);
   2931             break;
   2932         case 5: /* 1024 - take 10 hash bits*/
   2933             flow_set_index = flow_set_base + (rtag7_hash & 0x3ff);
   2934             break;
   2935         case 6: /* 2048 - take 11 hash bits*/
   2936             flow_set_index = flow_set_base + (rtag7_hash & 0x7ff);
   2937             break;
   2938         case 7: /* 4096 - take 12 hash bits*/
   2939             flow_set_index = flow_set_base + (rtag7_hash & 0xfff);
   2940             break;
   2941         case 8: /* 8192 - take 13 hash bits*/
   2942             flow_set_index = flow_set_base + (rtag7_hash & 0x1fff);
   2943             break;
   2944         case 9: /* 16384 - take 14 hash bits*/
   2945             flow_set_index = flow_set_base + (rtag7_hash & 0x3fff);
   2946             break;
   2947         case 10: /* 32768 - take 15 hash bits*/
   2948             flow_set_index = flow_set_base + (rtag7_hash & 0x7fff);
   2949             break;
   2950         case 11: /* 65536 - take 16 hash bits*/
   2951             flow_set_index = flow_set_base + (rtag7_hash & 0xffff);
   2952             break;
   2953     }
   2954 
   2955     if (rh_mode == RTAG7_RH_MODE_ECMP || rh_mode == RTAG7_RH_MODE_LAG) {
   2956         uint32 enhanced_hash_control;
   2957         SOC_IF_ERROR_RETURN(
   2958             READ_ENHANCED_HASHING_CONTROLr(unit, &enhanced_hash_control)); 
   2959         if (soc_feature(unit, soc_feature_td3_style_dlb_rh)){
   2960             rh_flowset_table_config = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROLr,
   2961                        enhanced_hash_control, ECMP_FLOWSET_TABLE_CONFIGf);
   2962         } else {
   2963             rh_flowset_table_config = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROLr,
   2964                     enhanced_hash_control, RH_FLOWSET_TABLE_CONFIG_ENCODINGf);
   2965         }
   2966         if (rh_flowset_table_config == 
   2967             ENHANCED_HASHING_CONTROLRH_FLOWSET_TABLE_CONFIG_ENCODING_HALF_AND_HALF) {
   2968         
   2969             /* 32K flow sets are allocated to each ECMP and LAG */
   2970             flow_set_index = flow_set_index & 0x7fff;
   2971         
   2972         } else if (rh_flowset_table_config == 
   2973             ENHANCED_HASHING_CONTROLRH_FLOWSET_TABLE_CONFIG_ENCODING_ALL_ECMP) {
   2974         
   2975             flow_set_index = flow_set_index & 0xffff;
   2976         
   2977         } else if (rh_flowset_table_config == 
   2978             ENHANCED_HASHING_CONTROLRH_FLOWSET_TABLE_CONFIG_ENCODING_ALL_LAG) {
   2979         
   2980             flow_set_index = flow_set_index & 0xffff;
   2981         }
   2982     } else if (rh_mode == RTAG7_RH_MODE_HGT) {
   2983         flow_set_index = flow_set_index & 0xffff;
   2984     }
   2985 
   2986     if (rh_mode == RTAG7_RH_MODE_ECMP) {
   2987         /* Read RH_ECMP_FLOWSET TABLE */
   2988         SOC_IF_ERROR_RETURN(READ_RH_ECMP_FLOWSETm(unit,
   2989                             MEM_BLOCK_ANY, flow_set_index, &ecmp_flow_entry));
   2990         *resolved_member_is_valid = soc_RH_ECMP_FLOWSETm_field32_get(
   2991                             unit, &ecmp_flow_entry, VALIDf);
   2992         *resolved_member = soc_RH_ECMP_FLOWSETm_field32_get(unit,
   2993                             &ecmp_flow_entry, NEXT_HOP_INDEXf);
   2994     } else if (rh_mode == RTAG7_RH_MODE_LAG) {
   2995         /* Read RH_LAG_FLOWSET TABLE */
   2996         SOC_IF_ERROR_RETURN(READ_RH_LAG_FLOWSETm(unit,
   2997                             MEM_BLOCK_ANY, flow_set_index, &lag_flow_entry));
   2998         *resolved_member_is_valid = soc_RH_LAG_FLOWSETm_field32_get(
   2999                             unit, &lag_flow_entry, VALIDf);
   3000         port_id = soc_RH_LAG_FLOWSETm_field32_get(unit,
   3001                             &lag_flow_entry, PORT_NUMf);
   3002 
   3003         mod_id =  soc_RH_LAG_FLOWSETm_field32_get(unit,
   3004                             &lag_flow_entry, MODULE_IDf);
   3005         
   3006         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3007                     (BSL_META_U(unit,
   3008                                 "RH_LAG_FLOWSET.PORT_NUMf=%d\n"),
   3009                      port_id));
   3010         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3011                     (BSL_META_U(unit,
   3012                                 "RH_LAG_FLOWSET.MODULE_IDF=%d\n"),
   3013                      mod_id));
   3014 
   3015         *resolved_member = port_id | (mod_id << RH_LAG_FLOWSET_MOD_ID_SHIFT_VAL); 
   3016     } else if (rh_mode == RTAG7_RH_MODE_HGT) {
   3017         /* Read RH_HGT_FLOWSET TABLE */
   3018         SOC_IF_ERROR_RETURN(READ_RH_HGT_FLOWSETm(unit,
   3019                             MEM_BLOCK_ANY, flow_set_index, &hgt_flow_entry));
   3020         *resolved_member_is_valid = soc_RH_HGT_FLOWSETm_field32_get(
   3021                             unit, &hgt_flow_entry, VALIDf);
   3022         port_id = soc_RH_HGT_FLOWSETm_field32_get(unit,
   3023                             &hgt_flow_entry, port_fld);
   3024 
   3025         *resolved_member = port_id; 
   3026     }
   3027 
   3028     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3029                 (BSL_META_U(unit,
   3030                             "rh flowset *resolved_member=%d\n"),
   3031                  *resolved_member));
   3032 
   3033     return BCM_E_NONE;
   3034 }
   3035 
   3036 #ifdef INCLUDE_L3
   3037 /* helper function check if resilient hashing is enabled on an ecmp group */
   3038 STATIC uint8 
   3039 check_td2_ecmp_rh_enable (int unit, int ecmp_group, uint32 ethertype) 
   3040 {
   3041     ecmp_count_entry_t ecmpc_entry;
   3042     uint8  rh_ecmp_ethertype_enable, rh_ecmp_enable=0;
   3043     uint32 rh_flowset_table_config, enhanced_hash_control;
   3044 
   3045     SOC_IF_ERROR_RETURN(READ_ENHANCED_HASHING_CONTROLr(unit, &enhanced_hash_control));    
   3046     if (soc_feature(unit, soc_feature_td3_style_dlb_rh)){
   3047         rh_flowset_table_config = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROLr, enhanced_hash_control,
   3048                                                 ECMP_FLOWSET_TABLE_CONFIGf);
   3049     } else {
   3050         rh_flowset_table_config = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROLr, enhanced_hash_control,
   3051                                                 RH_FLOWSET_TABLE_CONFIG_ENCODINGf);
   3052     }
   3053 
   3054     BCM_IF_ERROR_RETURN
   3055         (READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY, ecmp_group, &ecmpc_entry));
   3056     if (soc_feature(unit, soc_feature_td3_style_dlb_rh)){
   3057         rh_ecmp_enable  = soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry, LB_MODEf);
   3058     } else {
   3059         rh_ecmp_enable  = soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry, ENHANCED_HASHING_ENABLEf);
   3060     }
   3061     rh_ecmp_ethertype_enable = check_td2_ether_type_eligibility_for_rh(unit, RTAG7_RH_MODE_ECMP, ethertype);
   3062     
   3063     if ((rh_flowset_table_config == ENHANCED_HASHING_CONTROLRH_FLOWSET_TABLE_CONFIG_ENCODING_HALF_AND_HALF) ||
   3064         (rh_flowset_table_config == ENHANCED_HASHING_CONTROLRH_FLOWSET_TABLE_CONFIG_ENCODING_ALL_ECMP)) {
   3065         rh_ecmp_enable = (rh_ecmp_enable && rh_ecmp_ethertype_enable);
   3066     }
   3067     return rh_ecmp_enable;
   3068 }
   3069 
   3070 
   3071 /*
   3072  * Function:
   3073  *          get_td2_hash_ecmp
   3074  * Description:
   3075  *     compute ecmp destination among multipath interfaces 
   3076  * Parameters:
   3077  *  unit - StrataSwitch PCI device unit number (driver internal).
   3078  *  ecmp_group - multipath id
   3079  *  hash_index - hash value calculated from compute_td2_ecmp_hash
   3080  *  hash_rh_index -  hash value calculated from compute_td2_ecmp_rh_hash
   3081  *  nh_id - where egress l3 interface id is stored
   3082  *  ecmp_rh_enable - flag indicating if rh is enable for this hashing calculation
   3083  *  ethertype - Ethertype of a packet
   3084  *
   3085  * Returns:
   3086  *      BCM_E_xxxx
   3087  */
   3088 STATIC int
   3089 get_td2_hash_ecmp(int unit, int ecmp_group, uint32 hash_index,uint32 hash_rh_index, bcm_if_t *nh_id,
   3090                   uint8 ecmp_rh_enable, uint32 ethertype)
   3091 {
   3092     uint32 ecmp_hash_field_upper_bits_count;
   3093                 
   3094     ecmp_count_entry_t ecmpc_entry;
   3095     ecmp_entry_t ecmp_entry;
   3096     initial_l3_ecmp_group_entry_t
   3097                  ecmp_group_entry;
   3098  
   3099     uint32 ecmp_ptr = 0;
   3100     uint32 ecmp_count = 0;
   3101     uint32 hash_control;
   3102                 
   3103     uint32 ecmp_mask;
   3104     uint32 ecmp_offset;
   3105     uint32 ecmp_index;
   3106     
   3107     uint32 ecmp_rh_flow_set_base;
   3108     uint8  ecmp_rh_flow_set_size;
   3109     uint32 resolved_member;
   3110     uint8  resolved_member_valid;
   3111 
   3112       /*register read*/
   3113     if (SOC_REG_FIELD_VALID(unit, HASH_CONTROLr,
   3114                             ECMP_HASH_FIELD_UPPER_BITS_COUNTf)) {
   3115         SOC_IF_ERROR_RETURN
   3116             (READ_HASH_CONTROLr(unit, &hash_control));
   3117         ecmp_hash_field_upper_bits_count =
   3118             soc_reg_field_get(unit, HASH_CONTROLr, hash_control,
   3119                               ECMP_HASH_FIELD_UPPER_BITS_COUNTf);
   3120     } else {
   3121         ecmp_hash_field_upper_bits_count = 0x6; /* A0 bincomp value */
   3122     }
   3123                 
   3124     if (ecmp_rh_enable) {
   3125         SOC_IF_ERROR_RETURN
   3126             (READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY, ecmp_group, &ecmp_group_entry));    
   3127         ecmp_rh_flow_set_base = soc_L3_ECMP_COUNTm_field32_get(unit, &ecmp_group_entry, RH_FLOW_SET_BASEf);    
   3128         ecmp_rh_flow_set_size = soc_L3_ECMP_COUNTm_field32_get(unit, &ecmp_group_entry, RH_FLOW_SET_SIZEf);    
   3129 
   3130         perform_td2_rh(unit, ecmp_rh_flow_set_base, ecmp_rh_flow_set_size, RTAG7_RH_MODE_ECMP, hash_rh_index, 0,
   3131                   &resolved_member, &resolved_member_valid);
   3132 
   3133         if (resolved_member_valid) {
   3134             *nh_id = resolved_member & 0xffff; 
   3135         } else {
   3136             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3137                         (BSL_META_U(unit,
   3138                                     "Hash calculation: Such Configuration is not supported: resolved_lag_member_valid==FALSE\n")));
   3139             return BCM_E_PARAM;
   3140         }
   3141     } else {
   3142         /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   3143          * A ECMP_COUNT value of 0 implies 1 entry 
   3144          * a value of 1 implies 2 entries etc...
   3145          * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   3146          */
   3147         SOC_IF_ERROR_RETURN
   3148             (READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY, ecmp_group, &ecmpc_entry));
   3149  
   3150         ecmp_ptr = soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry,
   3151                                                   BASE_PTRf);
   3152         ecmp_count = soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry,
   3153                                                   COUNTf);
   3154         switch (ecmp_hash_field_upper_bits_count) {
   3155         case 0:
   3156             ecmp_mask = 0x3ff;
   3157             break;
   3158         case 1:
   3159             ecmp_mask = 0x7ff;
   3160             break;
   3161         case 2:
   3162             ecmp_mask = 0xfff;
   3163             break;
   3164         case 3:
   3165             ecmp_mask = 0x1fff;
   3166             break;
   3167         case 4:
   3168             ecmp_mask = 0x3fff;
   3169             break;
   3170         case 5:
   3171             ecmp_mask = 0x7fff;
   3172             break;
   3173         case 6:
   3174             ecmp_mask = 0xffff;
   3175             break;
   3176         default:
   3177             ecmp_mask = 0xffff;
   3178             break;
   3179         }
   3180         
   3181         ecmp_offset = ((hash_index & ecmp_mask) % (ecmp_count + 1)) & 0x3FF;
   3182         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3183                     (BSL_META_U(unit,
   3184                                 "\tECMP offset 0x%08x, ptr 0x%x\n"),
   3185                      ecmp_offset, ecmp_ptr));
   3186         ecmp_index = (ecmp_ptr + ecmp_offset) & 0x3fff;
   3187         SOC_IF_ERROR_RETURN
   3188             (READ_L3_ECMPm(unit, MEM_BLOCK_ANY, ecmp_index, &ecmp_entry));
   3189 
   3190         *nh_id = 
   3191               soc_L3_ECMPm_field32_get(unit, &ecmp_entry,
   3192                                      NEXT_HOP_INDEXf); 
   3193         *nh_id = *nh_id & 0xffff;
   3194         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3195                     (BSL_META_U(unit,
   3196                                 "\tECMP next hop HW index 0x%08x\n"),
   3197                      *nh_id));
   3198     }
   3199 
   3200     return BCM_E_NONE;  
   3201 }
   3202 #endif /* INCLUDE_L3 */
   3203 
   3204 /* helper function check if resilient hashing is enabled on a lag */
   3205 uint8 
   3206 check_td2_lag_rh_enable (int unit, int tgid, uint32 ethertype) 
   3207 {
   3208     trunk_group_entry_t dst_tg_entry;
   3209     uint8  rh_lag_group_enable = 0, rh_lag_ethertype_enable, lag_rh_enable=0;
   3210     uint32 rh_flowset_table_config, enhanced_hash_control;
   3211 
   3212     if(!soc_feature(unit, soc_feature_lag_resilient_hash)){
   3213        return lag_rh_enable;
   3214     }
   3215 
   3216     BCM_IF_ERROR_RETURN
   3217         (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tgid, &dst_tg_entry));
   3218 
   3219     SOC_IF_ERROR_RETURN(READ_ENHANCED_HASHING_CONTROLr(unit, &enhanced_hash_control));
   3220     if (soc_feature(unit, soc_feature_td3_style_dlb_rh)){
   3221         rh_flowset_table_config = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROL_2r, enhanced_hash_control,
   3222                                                 HGT_LAG_FLOWSET_TABLE_CONFIGf);
   3223         rh_lag_group_enable = (soc_TRUNK_GROUPm_field32_get(unit, &dst_tg_entry,
   3224                                              TRUNK_MODEf)) ==  3 ? 1 : 0;
   3225     } else {
   3226         rh_flowset_table_config = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROLr, enhanced_hash_control,
   3227                                                 RH_FLOWSET_TABLE_CONFIG_ENCODINGf);
   3228         rh_lag_group_enable  = soc_TRUNK_GROUPm_field32_get(unit, &dst_tg_entry, ENHANCED_HASHING_ENABLEf);
   3229     }
   3230 
   3231     
   3232     rh_lag_ethertype_enable = check_td2_ether_type_eligibility_for_rh(unit, RTAG7_RH_MODE_LAG, ethertype);
   3233     
   3234     if ((rh_flowset_table_config == ENHANCED_HASHING_CONTROLRH_FLOWSET_TABLE_CONFIG_ENCODING_HALF_AND_HALF) ||
   3235         (rh_flowset_table_config == ENHANCED_HASHING_CONTROLRH_FLOWSET_TABLE_CONFIG_ENCODING_ALL_LAG)) {
   3236         lag_rh_enable = (rh_lag_group_enable && rh_lag_ethertype_enable);
   3237     }
   3238     return lag_rh_enable;
   3239 }
   3240 
   3241 /* helper function check if resilient hashing is enabled on a lag */
   3242 uint8 
   3243 check_td2_hgt_rh_enable (int unit, int hgtid, uint32 ethertype) 
   3244 {
   3245     hg_trunk_group_entry_t hg_tg_entry;
   3246     uint8  rh_hgt_group_enable = 0, rh_hgt_ethertype_enable, hgt_rh_enable = 0;
   3247     uint32 rh_hgt_enable = 0, enhanced_hash_control;
   3248     hg_trunk_mode_entry_t hg_trunk_mode_entry;
   3249 
   3250     if(!soc_feature(unit, soc_feature_hg_resilient_hash)){
   3251        return hgt_rh_enable;
   3252     }
   3253 
   3254     SOC_IF_ERROR_RETURN(READ_ENHANCED_HASHING_CONTROLr(unit, &enhanced_hash_control));
   3255     if (soc_feature(unit, soc_feature_td3_style_dlb_rh)){
   3256         SOC_IF_ERROR_RETURN(READ_HG_TRUNK_MODEm(unit, MEM_BLOCK_ANY, hgtid,
   3257                     &hg_trunk_mode_entry));
   3258         rh_hgt_group_enable  = soc_HG_TRUNK_MODEm_field32_get(unit, &hg_trunk_mode_entry,
   3259                                                          HG_TRUNK_LB_MODEf);
   3260         SOC_IF_ERROR_RETURN(READ_ENHANCED_HASHING_CONTROL_2r(unit, &enhanced_hash_control));
   3261         rh_hgt_enable = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROL_2r, enhanced_hash_control,
   3262                                                 RH_DLB_SELECTIONf);
   3263 
   3264     } else {
   3265         BCM_IF_ERROR_RETURN
   3266         (READ_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, hgtid, &hg_tg_entry));
   3267         rh_hgt_group_enable  = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_tg_entry, ENHANCED_HASHING_ENABLEf);
   3268         SOC_IF_ERROR_RETURN(READ_ENHANCED_HASHING_CONTROLr(unit, &enhanced_hash_control));
   3269         rh_hgt_enable = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROLr, enhanced_hash_control,
   3270                                                 RH_HGT_ENABLEf);
   3271     }
   3272     
   3273     rh_hgt_ethertype_enable = check_td2_ether_type_eligibility_for_rh(unit, RTAG7_RH_MODE_HGT, ethertype);
   3274     
   3275     hgt_rh_enable = (rh_hgt_enable && rh_hgt_group_enable && rh_hgt_ethertype_enable);
   3276 
   3277     return hgt_rh_enable;
   3278 }
   3279 
   3280 /*
   3281  * Function:
   3282  *          get_td2_hash_trunk
   3283  * Description:
   3284  *     compute destination trunk member port 
   3285  * Parameters:
   3286  *  unit - StrataSwitch PCI device unit number (driver internal).
   3287  *  ecmp_group - multipath id
   3288  *  tgid - trunk port id
   3289  *  hash_index - hash value calculated from compute_td2_rtag7_hash_trunk
   3290  *  hash_rh_index -  hash value calculated from compute_td2_rtag7_hash_rh_trunk
   3291  *  dst_tgid - where egress member port id is stored
   3292  *  hash_rh_value - flag indicating if rh is enable for this hashing calculation
   3293  *  ethertype - Ethertype of a packet
   3294  *
   3295  * Returns:
   3296  *      BCM_E_xxxx
   3297  */
   3298 STATIC int
   3299 get_td2_hash_trunk(int unit, int tgid, uint32 hash_index, 
   3300                 bcm_gport_t *dst_tgid, uint32 hash_rh_value, 
   3301                   uint8 lag_rh_enable, uint32 ethertype)
   3302 {
   3303     uint32 trunk_base;
   3304     uint32 trunk_group_size;    
   3305     uint32 rtag;
   3306     uint32 trunk_index;
   3307     uint32 trunk_member_table_index;
   3308     bcm_module_t mod_id;
   3309     bcm_port_t port_id;
   3310     int mod_is_local;
   3311     trunk_member_entry_t trunk_member_entry;
   3312     trunk_group_entry_t  tg_entry, dst_tg_entry;
   3313     _bcm_gport_dest_t   dest;
   3314    
   3315     uint32 lag_rh_flow_set_base;
   3316     uint32 lag_rh_flow_set_size;
   3317     
   3318     uint32 resolved_member;
   3319     uint8  resolved_member_valid;
   3320     
   3321     BCM_IF_ERROR_RETURN
   3322         (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tgid, &tg_entry));
   3323 
   3324     trunk_base           = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, BASE_PTRf);
   3325     trunk_group_size     = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, TG_SIZEf);
   3326     rtag                 = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, RTAGf);
   3327                  
   3328     if (rtag != 7){
   3329          LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3330                      (BSL_META_U(unit,
   3331                                  "Hash calculation: uport only RTAG7 calc no support for rtag %d\n"),
   3332                       rtag));
   3333     }
   3334 
   3335     trunk_index = hash_index % (trunk_group_size + 1);
   3336     trunk_member_table_index = (trunk_base + trunk_index) & 0x7ff;
   3337     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3338                 (BSL_META_U(unit,
   3339                             "\tTrunk HW index 0x%08x\n"),
   3340                  trunk_index));
   3341     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3342                 (BSL_META_U(unit,
   3343                             "\tTrunk group size 0x%08x\n"),
   3344                  trunk_group_size));
   3345 
   3346     if (lag_rh_enable) {
   3347         BCM_IF_ERROR_RETURN
   3348             (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tgid, &dst_tg_entry));
   3349         lag_rh_flow_set_base = soc_TRUNK_GROUPm_field32_get(unit, &dst_tg_entry, RH_FLOW_SET_BASEf);    
   3350         lag_rh_flow_set_size = soc_TRUNK_GROUPm_field32_get(unit, &dst_tg_entry, RH_FLOW_SET_SIZEf);    
   3351    
   3352         perform_td2_rh(unit, lag_rh_flow_set_base, lag_rh_flow_set_size, RTAG7_RH_MODE_LAG, 0, hash_rh_value,
   3353                    &resolved_member, &resolved_member_valid);
   3354 
   3355         if (resolved_member_valid) { 
   3356             port_id = resolved_member & 0x7f;
   3357             mod_id  = (resolved_member >> RH_LAG_FLOWSET_MOD_ID_SHIFT_VAL) & 0xff;
   3358         } else {
   3359             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3360                         (BSL_META_U(unit,
   3361                                     "Hash calculation: Such Configuration is not supported: \n")));
   3362             return BCM_E_PARAM;
   3363         }
   3364     } else {
   3365         BCM_IF_ERROR_RETURN
   3366             (READ_TRUNK_MEMBERm(unit, MEM_BLOCK_ANY, trunk_member_table_index,
   3367                                         &trunk_member_entry));
   3368         mod_id  = soc_TRUNK_MEMBERm_field32_get(unit, &trunk_member_entry,
   3369                                         MODULE_IDf);
   3370         port_id = soc_TRUNK_MEMBERm_field32_get(unit, &trunk_member_entry,
   3371                                         PORT_NUMf);
   3372     }
   3373 
   3374     BCM_IF_ERROR_RETURN
   3375         (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, mod_id, port_id,
   3376                                         &(dest.modid), &(dest.port)));
   3377     dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   3378 
   3379     BCM_IF_ERROR_RETURN
   3380         (_bcm_esw_modid_is_local(unit, dest.modid,
   3381                                  &mod_is_local));
   3382     if (mod_is_local) {
   3383         if (IS_ST_PORT(unit, port_id)) {
   3384             dest.modid = mod_id;
   3385             dest.port = port_id;
   3386             dest.gport_type = _SHR_GPORT_TYPE_DEVPORT;
   3387         }
   3388     }
   3389 
   3390     BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, dst_tgid));
   3391 
   3392     return BCM_E_NONE;  
   3393 }
   3394 
   3395 /*
   3396  * Function:
   3397  *     get_td2_hash_trunk_nuc
   3398  * Description:
   3399  *     Compute non-unicast destination trunk member port 
   3400  * Parameters:
   3401  *  unit - StrataSwitch PCI device unit number (driver internal).
   3402  *  tgid - Trunk group id
   3403  *  fwd_reason - Flow foward reason. unicast, ipmc, l2mc, broadcast, dlf.
   3404  *  hash_index - Hash value calculated based on RTAG7
   3405  *  dst_gport  - Where egress member port id is stored
   3406  *
   3407  * Returns:
   3408  *      BCM_E_xxxx
   3409  */
   3410 STATIC int
   3411 get_td2_hash_trunk_nuc(int unit, int tgid, 
   3412                    bcm_switch_pkt_hash_info_fwd_reason_t fwd_reason, 
   3413                    uint32 hash_index, bcm_gport_t *dst_gport)
   3414 {
   3415     int nuc_type, nuc_tbm_index;
   3416     int modid, port;
   3417     bcm_pbmp_t local_pbmp, block_mask_pbmp;
   3418     trunk_bitmap_entry_t trunk_bitmap_entry;
   3419     nonucast_trunk_block_mask_entry_t mask_entry;
   3420     uint32 disable_flags = BCM_TRUNK_MEMBER_EGRESS_DISABLE;
   3421 
   3422     switch(fwd_reason) {
   3423     case bcmSwitchPktHashInfoFwdReasonIpmc:
   3424         nuc_type = TRUNK_BLOCK_MASK_TYPE_IPMC;
   3425         disable_flags |= BCM_TRUNK_MEMBER_IPMC_EGRESS_DISABLE;
   3426         break;
   3427     case bcmSwitchPktHashInfoFwdReasonL2mc:
   3428         nuc_type = TRUNK_BLOCK_MASK_TYPE_L2MC;
   3429         disable_flags |= BCM_TRUNK_MEMBER_L2MC_EGRESS_DISABLE;
   3430         break;
   3431     case bcmSwitchPktHashInfoFwdReasonBcast:
   3432         nuc_type = TRUNK_BLOCK_MASK_TYPE_BCAST;
   3433         disable_flags |= BCM_TRUNK_MEMBER_BCAST_EGRESS_DISABLE;
   3434         break;
   3435     case bcmSwitchPktHashInfoFwdReasonDlf:
   3436         nuc_type = TRUNK_BLOCK_MASK_TYPE_DLF;
   3437         disable_flags |= BCM_TRUNK_MEMBER_DLF_EGRESS_DISABLE;
   3438         break;
   3439     default:
   3440         return BCM_E_PARAM;
   3441     }
   3442     nuc_tbm_index = (nuc_type << 8) | (hash_index & 0xff);
   3443 
   3444     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3445                 (BSL_META_U(unit,
   3446                             "Nonuc-trunk table index = %d\n"), 
   3447                  nuc_tbm_index));
   3448 
   3449     BCM_IF_ERROR_RETURN(
   3450         READ_NONUCAST_TRUNK_BLOCK_MASKm(unit, MEM_BLOCK_ANY,
   3451                                         nuc_tbm_index, &mask_entry));
   3452     soc_mem_pbmp_field_get(unit, NONUCAST_TRUNK_BLOCK_MASKm, &mask_entry, 
   3453                            BLOCK_MASKf, &block_mask_pbmp);
   3454     BCM_IF_ERROR_RETURN(
   3455         READ_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, tgid, &trunk_bitmap_entry));
   3456     soc_mem_pbmp_field_get(unit, TRUNK_BITMAPm, &trunk_bitmap_entry,
   3457                            TRUNK_BITMAPf, &local_pbmp);
   3458 
   3459     BCM_PBMP_REMOVE(local_pbmp, block_mask_pbmp);
   3460 
   3461     if (BCM_PBMP_IS_NULL(local_pbmp)) {
   3462         /* this means that member is not on local device, try SW prediction */
   3463         bcm_trunk_member_t member_array[BCM_TRUNK_MAX_PORTCNT];
   3464         int member_count;
   3465         bcm_gport_t *port_array = NULL;
   3466         int port_count, port_index = BCM_TRUNK_UNSPEC_INDEX;
   3467         int region_size, i, all_local;
   3468         bcm_trunk_info_t trunk_info;
   3469 
   3470         bcm_trunk_info_t_init(&trunk_info);
   3471 
   3472         BCM_IF_ERROR_RETURN
   3473             (bcm_esw_trunk_get(unit, tgid, &trunk_info, BCM_TRUNK_MAX_PORTCNT,
   3474                                member_array, &member_count));
   3475 
   3476         /* coverity[dead_error_condition] */
   3477         switch(fwd_reason) {
   3478         case bcmSwitchPktHashInfoFwdReasonIpmc:
   3479             port_index = trunk_info.ipmc_index;
   3480             break;
   3481         case bcmSwitchPktHashInfoFwdReasonL2mc:
   3482             port_index = trunk_info.mc_index;
   3483             break;
   3484         case bcmSwitchPktHashInfoFwdReasonBcast:
   3485         case bcmSwitchPktHashInfoFwdReasonDlf:
   3486             port_index = trunk_info.dlf_index;
   3487             break;
   3488         default:
   3489             return BCM_E_PARAM;
   3490         }
   3491 
   3492         if (port_index != BCM_TRUNK_UNSPEC_INDEX) {
   3493             if (port_index >= member_count) {
   3494                 *dst_gport = -1;
   3495                 return BCM_E_NOT_FOUND;
   3496             }
   3497 
   3498             *dst_gport = member_array[port_index].gport;
   3499 
   3500         } else {
   3501             port_array = sal_alloc(member_count * sizeof(bcm_gport_t),
   3502                                    "port_array");
   3503             if (port_array == NULL) {
   3504                 return BCM_E_MEMORY;
   3505             }
   3506 
   3507             port_count = 0;
   3508             all_local = TRUE;
   3509             for (i = 0; i < member_count; i++) {
   3510                 if (member_array[i].flags & disable_flags) {
   3511                     continue;
   3512                 }
   3513                 port = member_array[i].gport;
   3514                 port_array[port_count++] = port;
   3515                 if (all_local) {
   3516                     if (BCM_FAILURE(bcm_esw_port_local_get(unit, port,
   3517                                                             &port))) {
   3518                         all_local = FALSE;
   3519                     }
   3520                 }
   3521             }
   3522             /* All ports are disabled */
   3523             if (port_count == 0) {
   3524                 *dst_gport = -1;
   3525                 sal_free(port_array);
   3526                 return BCM_E_NOT_FOUND;
   3527             }
   3528             if (all_local || port_count > BCM_SWITCH_TRUNK_MAX_PORTCNT) {
   3529                 region_size = soc_mem_index_count(unit, NONUCAST_TRUNK_BLOCK_MASKm) / 4;
   3530             } else {
   3531                 region_size = BCM_XGS3_TRUNK_MAX_PORTCNT;
   3532             }
   3533             port_index = (nuc_tbm_index % region_size) % port_count;
   3534 
   3535             *dst_gport = port_array[port_index];
   3536 
   3537             sal_free(port_array);
   3538 
   3539         }
   3540     } else {
   3541         _bcm_gport_dest_t   dest;
   3542 
   3543         /*Each index only has one egress port */
   3544         BCM_PBMP_ITER(local_pbmp, port) {
   3545             break;
   3546         }
   3547         
   3548         if (port == BCM_PBMP_PORT_MAX) {
   3549             /* If not found in iteration, return not found. It never be here */
   3550             *dst_gport = -1;
   3551             return BCM_E_NOT_FOUND;
   3552         }
   3553 
   3554         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid));
   3555 
   3556         BCM_IF_ERROR_RETURN
   3557             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port,
   3558                                             &(dest.modid), &(dest.port)));
   3559         if (IS_ST_PORT(unit, port)) {
   3560             dest.modid = modid;
   3561             dest.port = port;
   3562             dest.gport_type = _SHR_GPORT_TYPE_DEVPORT;
   3563         } else {
   3564             dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   3565         }
   3566 
   3567         BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, dst_gport));
   3568     } 
   3569  
   3570     return BCM_E_NONE;
   3571 }
   3572 
   3573 STATIC int
   3574 get_td2_hash_hg_trunk(int unit, int hgtid, uint32 hash_index, 
   3575                 bcm_gport_t *dst_tgid, uint32 hash_rh_value, 
   3576                 uint8 lag_rh_enable, uint32 ethertype)
   3577 {
   3578     uint32 trunk_base;
   3579     uint32 trunk_group_size;    
   3580     uint32 rtag;
   3581     uint32 trunk_index;
   3582     uint32 trunk_member_table_index;
   3583     bcm_module_t mod_id;
   3584     bcm_port_t port_id;
   3585     hg_trunk_member_entry_t hg_trunk_member_entry;
   3586     hg_trunk_group_entry_t  hg_tg_entry;
   3587     rh_hgt_group_control_entry_t rh_hgt_group_control_entry;
   3588     _bcm_gport_dest_t   dest;
   3589    
   3590     uint32 hgt_rh_flow_set_base;
   3591     uint32 hgt_rh_flow_set_size;
   3592 
   3593     uint32 resolved_member;
   3594     uint8  resolved_member_valid;
   3595     
   3596     BCM_IF_ERROR_RETURN
   3597         (READ_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, hgtid, &hg_tg_entry));
   3598 
   3599     trunk_base           = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_tg_entry, BASE_PTRf);
   3600     trunk_group_size     = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_tg_entry, TG_SIZEf);
   3601     rtag                 = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_tg_entry, RTAGf);
   3602                  
   3603     if (rtag != 7) {
   3604          LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3605                      (BSL_META_U(unit,
   3606                                  "Hash calculation: uport only RTAG7 calc no support for rtag %d\n"),
   3607                       rtag));
   3608     }
   3609 
   3610     trunk_index = hash_index % (trunk_group_size + 1);
   3611     trunk_member_table_index = (trunk_base + trunk_index) & 0xff;
   3612     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3613                 (BSL_META_U(unit,
   3614                             "\tHG Trunk HW index 0x%08x\n"),
   3615                  trunk_index));
   3616     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3617                 (BSL_META_U(unit,
   3618                             "\tHG Trunk group size 0x%08x\n"),
   3619                  trunk_group_size));
   3620 
   3621     if (lag_rh_enable) {
   3622 #ifdef BCM_TRIDENT3_SUPPORT
   3623         if (soc_feature(unit, soc_feature_td3_style_dlb_rh)){
   3624             hgt_rh_flow_set_base = soc_HG_TRUNK_GROUPm_field32_get(unit,
   3625                                            &hg_tg_entry, RH_FLOW_SET_BASEf);
   3626             hgt_rh_flow_set_size = soc_HG_TRUNK_GROUPm_field32_get(unit,
   3627                                            &hg_tg_entry, RH_FLOW_SET_SIZEf);
   3628         } else
   3629 #endif
   3630         {
   3631             BCM_IF_ERROR_RETURN
   3632                 (READ_RH_HGT_GROUP_CONTROLm(unit, MEM_BLOCK_ANY, hgtid,
   3633                                             &rh_hgt_group_control_entry));
   3634             hgt_rh_flow_set_base = soc_RH_HGT_GROUP_CONTROLm_field32_get(unit,
   3635                                             &rh_hgt_group_control_entry, FLOW_SET_BASEf);
   3636             hgt_rh_flow_set_size = soc_RH_HGT_GROUP_CONTROLm_field32_get(unit,
   3637                                             &rh_hgt_group_control_entry, FLOW_SET_SIZEf);
   3638         }
   3639    
   3640         perform_td2_rh(unit, hgt_rh_flow_set_base, hgt_rh_flow_set_size, RTAG7_RH_MODE_HGT, 0, hash_rh_value,
   3641                    &resolved_member, &resolved_member_valid);
   3642 
   3643         if (resolved_member_valid) { 
   3644             port_id = resolved_member & 0x7f;
   3645         } else {
   3646             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3647                         (BSL_META_U(unit,
   3648                                     "Hash calculation: Such Configuration is not supported: \n")));
   3649             return BCM_E_PARAM;
   3650         }
   3651     } else {
   3652         BCM_IF_ERROR_RETURN
   3653             (READ_HG_TRUNK_MEMBERm(unit, MEM_BLOCK_ANY, trunk_member_table_index,
   3654                                         &hg_trunk_member_entry));
   3655         port_id = soc_HG_TRUNK_MEMBERm_field32_get(unit, &hg_trunk_member_entry,
   3656                                         PORT_NUMf);
   3657     }
   3658 
   3659     if (BCM_FAILURE(bcm_esw_stk_my_modid_get(unit, &mod_id))) {
   3660         mod_id = 0;
   3661     }
   3662     
   3663     BCM_IF_ERROR_RETURN
   3664         (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, mod_id, port_id,
   3665                                         &(dest.modid), &(dest.port)));
   3666     dest.gport_type = _SHR_GPORT_TYPE_DEVPORT;
   3667     BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, dst_tgid));
   3668 
   3669     return BCM_E_NONE;  
   3670 }
   3671 
   3672 /*
   3673  * Function:
   3674  *          _bcm_td2_switch_pkt_info_hash_get
   3675  * Description:
   3676  *    main td2 hash get function  
   3677  *
   3678  * Parameters     
   3679  *  unit - StrataSwitch PCI device unit number (driver internal).
   3680  *  pkt_info - struct that carries packet's l2, l3, and l4 information
   3681  *  dst_gport - hashing resolved trunk member port as a return val
   3682  *  dst_intf  - hashing resolved ecmp  member port as a return val
   3683  *              or entropy label of vxlan as a return val
   3684  * Returns:
   3685  *      BCM_E_xxxx
   3686  */
   3687 int
   3688 _bcm_td2_switch_pkt_info_hash_get(int unit,
   3689                                    bcm_switch_pkt_info_t *pkt_info,
   3690                                    bcm_gport_t *dst_gport,
   3691                                    bcm_if_t *dst_intf)
   3692 {
   3693     bcm_rtag7_base_hash_t hash_res;
   3694     int pc_out, mod_is_local;
   3695     bcm_gport_t     port;
   3696     bcm_trunk_t     tid;
   3697     int             id;
   3698     uint32          hash_value;
   3699     uint32          hash_rh_value;
   3700     bcm_ethertype_t ethertype;
   3701     int             rc;
   3702 
   3703     if (pkt_info == NULL) {
   3704         return BCM_E_PARAM;
   3705     }
   3706 
   3707     if (!_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_GPORT)) {
   3708         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3709                     (BSL_META_U(unit,
   3710                                 "Hash calculation: source gport value missing\n")));
   3711         return BCM_E_PARAM;
   3712     }
   3713 
   3714     rc = _bcm_esw_gport_resolve(unit, pkt_info->src_gport,
   3715                                 &(hash_res.src_modid),
   3716                                 &(hash_res.src_port), 
   3717                                 &tid, &id);
   3718     if (rc != BCM_E_NONE) {
   3719         return rc;
   3720     }
   3721 
   3722     if ((-1 != id) || (-1 != tid)) {
   3723         /* Must be single system port */
   3724         return BCM_E_PORT;
   3725     }
   3726 
   3727     /* Load balancing retrieval */
   3728     BCM_IF_ERROR_RETURN(
   3729         _bcm_esw_modid_is_local(unit, hash_res.src_modid, &mod_is_local));
   3730     if (mod_is_local) {
   3731         BCM_IF_ERROR_RETURN
   3732             (bcm_esw_port_local_get(unit, pkt_info->src_gport, &port));
   3733         hash_res.dev_src_port = port;
   3734     } else {
   3735         hash_res.dev_src_port = -1;
   3736         if (BCM_GPORT_IS_PROXY(pkt_info->src_gport)) {
   3737             port = pkt_info->src_gport;
   3738         } else {
   3739             BCM_GPORT_PROXY_SET(port,
   3740                 hash_res.src_modid, hash_res.src_port);
   3741         }
   3742     }
   3743     BCM_IF_ERROR_RETURN
   3744         (bcm_esw_port_control_get(unit, port,
   3745                                 bcmPortControlLoadBalancingNumber,
   3746                                 &pc_out)); 
   3747     hash_res.rtag7_port_lbn = pc_out;
   3748 
   3749     /* check if the foward reason of packet is all non-uc packet or bit 40 in the mac DA is one. */
   3750     hash_res.is_nonuc = pkt_info->fwd_reason || BCM_MAC_IS_MCAST(pkt_info->dst_mac);
   3751     
   3752     BCM_IF_ERROR_RETURN
   3753         (main_td2_do_rtag7_hashing(unit, pkt_info, &hash_res));
   3754     BCM_IF_ERROR_RETURN
   3755         (main_td2_compute_lbid(unit, &hash_res));
   3756 
   3757     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3758                 (BSL_META_U(unit,
   3759                             "Hash status: \n")));
   3760     if (hash_res.hash_a_valid) {
   3761         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3762                     (BSL_META_U(unit,
   3763                                 "\tRTAG7 A0 0x%08x\n"),
   3764                      hash_res.rtag7_hash16_value_a_0));
   3765         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3766                     (BSL_META_U(unit,
   3767                                 "\tRTAG7 A1 0x%08x\n"),
   3768                      hash_res.rtag7_hash16_value_a_1));
   3769     } else {
   3770         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3771                     (BSL_META_U(unit,
   3772                                 "\tRTAG7 A hashes invalid due to missing packet info\n")));
   3773     }
   3774     if (hash_res.hash_b_valid) {
   3775         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3776                     (BSL_META_U(unit,
   3777                                 "\tRTAG7 B0 0x%08x\n"),
   3778                      hash_res.rtag7_hash16_value_b_0));
   3779         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3780                     (BSL_META_U(unit,
   3781                                 "\tRTAG7 B1 0x%08x\n"),
   3782                      hash_res.rtag7_hash16_value_b_1));
   3783     } else {
   3784         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3785                     (BSL_META_U(unit,
   3786                                 "\tRTAG7 B hashes invalid due to missing packet info\n")));
   3787     }
   3788     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3789                 (BSL_META_U(unit,
   3790                             "\tRTAG7 LBN 0x%08x\n"),
   3791                  hash_res.rtag7_port_lbn));
   3792     if (hash_res.lbid_hash_valid){
   3793         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3794                     (BSL_META_U(unit,
   3795                                 "\tRTAG7 LBID 0x%08x\n"),
   3796                      hash_res.rtag7_lbid_hash));
   3797     } else {
   3798         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3799                     (BSL_META_U(unit,
   3800                                 "\tRTAG7 LBID not valid due to non-RTAG7 configuration\n")));
   3801     }
   3802 
   3803     ethertype = pkt_info->ethertype;
   3804 
   3805 #ifdef INCLUDE_L3
   3806     if (0 != (pkt_info->flags & BCM_SWITCH_PKT_INFO_HASH_MULTIPATH)) {
   3807         bcm_if_t        nh_id;
   3808         uint8           ecmp_rh_enable;
   3809         nh_id = 0;
   3810 
   3811         if (dst_intf == NULL) {
   3812             return BCM_E_PARAM;
   3813         }
   3814 
   3815         if (0 != (check_td2_ecmp_rh_enable(unit, 
   3816                     pkt_info->mpintf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit), ethertype ))) { 
   3817             ecmp_rh_enable = TRUE;
   3818             hash_value = 0;
   3819             rc = compute_td2_ecmp_rh_hash(unit, &hash_res, &hash_rh_value);
   3820             if (rc != BCM_E_NONE) {
   3821                 return rc;
   3822             }
   3823             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3824                         (BSL_META_U(unit,
   3825                                     "\tECMP Hash rh value 0x%08x\n"),
   3826                          hash_rh_value));
   3827         } else {
   3828             ecmp_rh_enable = FALSE;
   3829             hash_rh_value = 0;
   3830             rc = compute_td2_ecmp_hash(unit, pkt_info->flags, &hash_res, &hash_value);
   3831             if (rc != BCM_E_NONE) {
   3832                 return rc;
   3833             }
   3834             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3835                         (BSL_META_U(unit,
   3836                                     "\tECMP Hash value 0x%08x\n"),
   3837                          hash_value));
   3838         }
   3839 
   3840         rc = get_td2_hash_ecmp(unit,
   3841                            pkt_info->mpintf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit),
   3842                            hash_value, hash_rh_value,&nh_id,
   3843                            ecmp_rh_enable, ethertype); 
   3844         /* Convert to egress object format */
   3845         *dst_intf = nh_id + BCM_XGS3_EGRESS_IDX_MIN(unit);
   3846     } else
   3847 #endif /* INCLUDE_L3 */
   3848     if (0 != (pkt_info->flags & BCM_SWITCH_PKT_INFO_HASH_TRUNK)) {
   3849         int member_count;
   3850         bcm_trunk_t trunk;
   3851         uint8 lag_rh_enable = FALSE;
   3852         uint8 hgt_rh_enable = FALSE;
   3853         bcm_trunk_chip_info_t   ti;
   3854 
   3855         if (dst_gport == NULL) {
   3856             return BCM_E_PARAM;
   3857         }
   3858 
   3859         trunk = BCM_TRUNK_INVALID;
   3860         if (!BCM_GPORT_IS_TRUNK(pkt_info->trunk_gport)) {
   3861             return BCM_E_PORT;
   3862         }
   3863         trunk = BCM_GPORT_TRUNK_GET(pkt_info->trunk_gport);
   3864         BCM_IF_ERROR_RETURN
   3865             (bcm_esw_trunk_get(unit, trunk, NULL, 0, NULL, &member_count));
   3866         if (0 == member_count) {
   3867             /* Return failure for no trunk members */
   3868             return BCM_E_FAIL;
   3869         }
   3870 
   3871         BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &ti));
   3872 
   3873         if (trunk >= ti.trunk_id_min && trunk <= ti.trunk_id_max) {
   3874             rc = compute_td2_rtag7_hash_trunk(unit, &hash_res, &hash_value);
   3875             
   3876             if (rc != BCM_E_NONE) {
   3877                 return rc;
   3878             }
   3879             
   3880             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3881                         (BSL_META_U(unit,
   3882                                     "\tTrunk Hash value 0x%08x\n"),
   3883                          hash_value));
   3884             
   3885             if (0 != (check_td2_lag_rh_enable(unit, trunk, 
   3886                       ethertype))) { 
   3887                  lag_rh_enable = TRUE;
   3888                  rc = 
   3889                     compute_td2_rtag7_hash_rh_trunk(unit, &hash_res, &hash_rh_value);
   3890             
   3891                     if (rc != BCM_E_NONE) {
   3892                         return rc;
   3893                     }
   3894             } else {
   3895                 lag_rh_enable = FALSE;    
   3896                 hash_rh_value = 0;
   3897             }
   3898             
   3899             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3900                         (BSL_META_U(unit,
   3901                                     "\tTrunk RH Hash value 0x%08x\n"),
   3902                          hash_rh_value));
   3903 
   3904             if (hash_res.is_nonuc) {
   3905                 BCM_IF_ERROR_RETURN
   3906                     (get_td2_hash_trunk_nuc(unit, trunk, pkt_info->fwd_reason, 
   3907                                 hash_value, dst_gport));
   3908             } else {
   3909                 BCM_IF_ERROR_RETURN
   3910                     (get_td2_hash_trunk(unit, trunk,
   3911                                         hash_value, dst_gport, hash_rh_value,
   3912                                         lag_rh_enable, ethertype));
   3913             }
   3914         } else if (trunk >= ti.trunk_fabric_id_min && trunk <= ti.trunk_fabric_id_max) {
   3915 
   3916             rc = compute_td2_rtag7_hash_hg_trunk(unit, &hash_res, &hash_value);
   3917             if (rc != BCM_E_NONE) {
   3918                 return rc;
   3919             }
   3920             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3921                         (BSL_META_U(unit,
   3922                                     "\tHG-Trunk Hash value 0x%08x\n"),
   3923                          hash_value));
   3924 
   3925             if (0 != (check_td2_hgt_rh_enable(unit, trunk - ti.trunk_fabric_id_min, 
   3926                       ethertype))) { 
   3927                 hgt_rh_enable = TRUE;
   3928                 rc = compute_td2_rtag7_hash_rh_hg_trunk(unit, &hash_res, &hash_rh_value);
   3929 
   3930                 if (rc != BCM_E_NONE) {
   3931                     return rc;
   3932                 }
   3933             } else {
   3934                 hgt_rh_enable = FALSE;    
   3935                 hash_rh_value = 0;
   3936             }
   3937 
   3938             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3939                         (BSL_META_U(unit,
   3940                                     "\tHG-Trunk RH Hash value 0x%08x\n"),
   3941                          hash_rh_value));
   3942             BCM_IF_ERROR_RETURN
   3943                 (get_td2_hash_hg_trunk(unit, trunk - ti.trunk_fabric_id_min,
   3944                                     hash_value, dst_gport, hash_rh_value,
   3945                                     hgt_rh_enable, ethertype));
   3946 
   3947         }
   3948     } 
   3949     /* vxlan hashing resolution */
   3950     else if (pkt_info->flags & BCM_SWITCH_PKT_INFO_HASH_UDP_SOURCE_PORT) {
   3951         /* coverity[negative_returns : FALSE] */
   3952         rc = compute_td2_rtag7_vxlan(unit, &hash_res, &hash_value);
   3953         if (rc != BCM_E_NONE) {
   3954             return rc;
   3955         }
   3956         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   3957                     (BSL_META_U(unit,
   3958                                 "\tVXlan Hash value 0x%08x\n"),
   3959                      hash_value));
   3960         *dst_intf = hash_value;
   3961     } else if (pkt_info->flags & BCM_SWITCH_PKT_INFO_HASH_LBID) {
   3962         /* LBID hashing resolution */
   3963         if (dst_intf == NULL || hash_res.lbid_hash_valid == 0) {
   3964             return BCM_E_FAIL;
   3965         } else {
   3966             *dst_intf = hash_res.rtag7_lbid_hash;
   3967         }
   3968     } else {
   3969         return BCM_E_PARAM;
   3970     }
   3971     
   3972     return BCM_E_NONE;
   3973 }
   3974