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


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