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


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