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


      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:     Hash calcualtions for trunk and ECMP packets.
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <soc/drv.h>
     14 #include <soc/hash.h>
     15 #include <bcm/switch.h>
     16 #include <bcm/error.h>
     17 
     18 #include <bcm_int/esw_dispatch.h>
     19 #include <bcm_int/esw/firebolt.h>
     20 #include <bcm_int/esw/port.h>
     21 #include <bcm_int/esw/stack.h>
     22 #include <bcm_int/esw/switch.h>
     23 
     24 typedef struct bcm_rtag7_base_hash_s {
     25     uint32 rtag7_hash16_value_a_0;      /* hash a0 result */
     26     uint32 rtag7_hash16_value_a_1;      /* hash a1 result */
     27     uint32 rtag7_hash16_value_b_0;      /* hash b0 result */
     28     uint32 rtag7_hash16_value_b_1;      /* hash b1 result */
     29     uint32 rtag7_macro_flow_id;         /* hash micro flow result */
     30     uint32 rtag7_port_lbn;     	        /* port LBN value from the port table*/
     31     uint32 rtag7_lbid_hash;             /* LBID hash calculation*/
     32     bcm_port_t dev_src_port;            /* Local source port */
     33     bcm_port_t src_port;                /* System source port */
     34     bcm_module_t src_modid;             /* System source modid */
     35     uint8 is_nonuc;                     /* Non-unicast */
     36     uint8 hash_a_valid;                 /* Hash A result use valid input */
     37     uint8 hash_b_valid;                 /* Hash B result use valid input */
     38     uint8 lbid_hash_valid;              /* LBID Hash value is valid */
     39 } bcm_rtag7_base_hash_t;
     40 
     41 #define   ETHERTYPE_IPV6 0x86dd /* ipv6 ethertype */
     42 #define   ETHERTYPE_IPV4 0x0800 /* ipv4 ethertype */
     43 #define   ETHERTYPE_MIN  0x0600 /* minimum ethertype for hashing */
     44 
     45 #define   IP_PROT_TCP 0x6  /* TCP protocol number */
     46 #define   IP_PROT_UDP 0x11 /* TCP protocol number */
     47 
     48 #define RTAG7_L2_ONLY         0x0
     49 #define RTAG7_UNKNOWN_HIGIG   0x1
     50 #define RTAG7_MPLS            0x2
     51 #define RTAG7_MIM             0x3
     52 #define RTAG7_IPV4            0x4
     53 #define RTAG7_IPV6            0x5
     54 #define RTAG7_FCOE            0x6
     55 #define RTAG7_TRILL           0x7
     56 
     57 
     58 
     59 STATIC int
     60 main__do_rtag7_hashing(int unit,
     61                        bcm_switch_pkt_info_t *pkt_info,
     62                        bcm_rtag7_base_hash_t *hash_res)
     63 {
     64     /* regular var declaration */
     65     uint32		hash_src_port;
     66     uint32		hash_src_modid;
     67     uint32		rtag7_a_sel;
     68     bcm_ip_t	        sip_a;               /* Source IPv4 address. */
     69     bcm_ip_t	        dip_a;               /* Destination IPv4 address. */
     70     uint32		rtag7_b_sel;
     71     bcm_ip_t	        sip_b;               /* Source IPv4 address. */
     72     bcm_ip_t	        dip_b;               /* Destination IPv4 address. */
     73     uint32		hash_field_bmap_a;   /* block A chosen bitmap*/
     74     uint32		hash_field_bmap_b;   /* block B chosen bitmap*/
     75 	
     76     uint32 hash_word[7];
     77     uint32 hash[13];
     78     int    elem, elem_bit;
     79     uint32 hash_element_valid_bits;
     80     /* int    ip6_addrs = FALSE, ip4_addrs = FALSE; */
     81     int    sip_valid = FALSE, dip_valid = FALSE;
     82     uint32 macro_flow_id;
     83 	
     84     uint32 hash_crc16_bisync;
     85     uint32 hash_crc16_ccitt;
     86     uint32 hash_crc32;
     87     uint32 hash_xor16;
     88     uint32 hash_xor8;
     89     uint32 hash_xor4;
     90     uint32 hash_xor2;
     91     uint32 hash_xor1;
     92     uint32 xor32;
     93 
     94     /* register var declaration */
     95     uint8 rtag7_disable_hash_ipv4_a;
     96     uint8 rtag7_disable_hash_ipv6_a; 
     97    
     98     uint8 rtag7_disable_hash_ipv4_b;
     99     uint8 rtag7_disable_hash_ipv6_b;
    100     uint8 rtag7_ipv6_addr_use_lsb_a;
    101     uint8 rtag7_ipv6_addr_use_lsb_b;	
    102     uint8 rtag7_pre_processing_enable_a;
    103     uint8 rtag7_pre_processing_enable_b;	
    104     uint8 rtag7_en_flow_label_ipv6_a;
    105     uint8 rtag7_en_flow_label_ipv6_b;	
    106     uint8 rtag7_en_bin_12_overlay_a;
    107     uint8 rtag7_en_bin_12_overlay_b;	
    108     uint32 rtag7_hash_seed_a;
    109     uint32 rtag7_hash_seed_b;	
    110     uint32 rtag7_hash_a0_function_select;
    111     uint32 rtag7_hash_a1_function_select;	
    112     uint32 rtag7_hash_b0_function_select;
    113     uint32 rtag7_hash_b1_function_select;	
    114     uint32 rtag7_macro_flow_hash_function_select;
    115     uint8 rtag7_macro_flow_hash_byte_sel;
    116 	
    117     uint64 rtag7_hash_control;
    118     uint32 rtag7_hash_control_2, rtag7_hash_control_3;
    119     uint32 rtag7_hash_seed_a_reg, rtag7_hash_seed_b_reg;
    120     soc_reg_t sc_reg;
    121     soc_field_t sc_field;
    122     uint32 sc_val;
    123 
    124     SOC_IF_ERROR_RETURN
    125         (READ_RTAG7_HASH_CONTROLr(unit, &rtag7_hash_control));
    126     SOC_IF_ERROR_RETURN
    127         (READ_RTAG7_HASH_CONTROL_2r(unit, &rtag7_hash_control_2));
    128 
    129     SOC_IF_ERROR_RETURN
    130         (READ_RTAG7_HASH_CONTROL_3r(unit, &rtag7_hash_control_3));
    131     SOC_IF_ERROR_RETURN
    132         (READ_RTAG7_HASH_SEED_Ar(unit, &rtag7_hash_seed_a_reg));
    133     SOC_IF_ERROR_RETURN
    134         (READ_RTAG7_HASH_SEED_Br(unit, &rtag7_hash_seed_b_reg));
    135 
    136     /* RTAG7 hash registers */
    137     rtag7_disable_hash_ipv4_a =
    138         soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control,
    139                           DISABLE_HASH_IPV4_Af);
    140     rtag7_disable_hash_ipv6_a =
    141         soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control,
    142                           DISABLE_HASH_IPV6_Af);
    143     rtag7_disable_hash_ipv4_b =
    144         soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control,
    145                           DISABLE_HASH_IPV4_Bf);
    146     rtag7_disable_hash_ipv6_b =
    147         soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control,
    148                           DISABLE_HASH_IPV6_Bf);
    149     rtag7_ipv6_addr_use_lsb_a =
    150         soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control,
    151                           IPV6_COLLAPSED_ADDR_SELECT_Af);
    152     rtag7_ipv6_addr_use_lsb_b =
    153         soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control,
    154                           IPV6_COLLAPSED_ADDR_SELECT_Bf);
    155 	
    156     rtag7_pre_processing_enable_a =
    157         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3,
    158                           HASH_PRE_PROCESSING_ENABLE_Af);
    159     rtag7_pre_processing_enable_b =
    160         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3,
    161                           HASH_PRE_PROCESSING_ENABLE_Bf);
    162     rtag7_hash_a0_function_select =
    163         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3,
    164                           HASH_A0_FUNCTION_SELECTf);
    165     rtag7_hash_a1_function_select =
    166         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3,
    167                           HASH_A1_FUNCTION_SELECTf);
    168     rtag7_hash_b0_function_select =
    169         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3,
    170                           HASH_B0_FUNCTION_SELECTf);
    171     rtag7_hash_b1_function_select =
    172         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3,
    173                           HASH_B1_FUNCTION_SELECTf);
    174 	
    175     if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r,
    176                             ENABLE_FLOW_LABEL_IPV6_Af)) {
    177         rtag7_en_flow_label_ipv6_a =
    178             soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r,
    179                               rtag7_hash_control_2,
    180                               ENABLE_FLOW_LABEL_IPV6_Af);
    181     } else {
    182         rtag7_en_flow_label_ipv6_a = 0; /* A0 bincomp value */
    183     }
    184     if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r,
    185                             ENABLE_FLOW_LABEL_IPV6_Bf)) {
    186         rtag7_en_flow_label_ipv6_b =
    187             soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r,
    188                               rtag7_hash_control_2,
    189                               ENABLE_FLOW_LABEL_IPV6_Bf);
    190     } else {
    191         rtag7_en_flow_label_ipv6_b = 0; /* A0 bincomp value */
    192     }
    193     rtag7_en_bin_12_overlay_a =
    194         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, rtag7_hash_control_2,
    195                           ENABLE_BIN_12_OVERLAY_Af);
    196     rtag7_en_bin_12_overlay_b =
    197         soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, rtag7_hash_control_2,
    198                           ENABLE_BIN_12_OVERLAY_Bf);
    199     if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r,
    200                             MACRO_FLOW_HASH_FUNC_SELf)) {
    201         rtag7_macro_flow_hash_function_select =
    202             soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r,
    203                               rtag7_hash_control_2,
    204                               MACRO_FLOW_HASH_FUNC_SELf);
    205     } else {
    206         rtag7_macro_flow_hash_function_select = 0; /* A0 bincomp value */
    207     }
    208     if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r,
    209                             MACRO_FLOW_HASH_BYTE_SELf)) {
    210         rtag7_macro_flow_hash_byte_sel =
    211             soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r,
    212                               rtag7_hash_control_2,
    213                               MACRO_FLOW_HASH_BYTE_SELf);
    214     } else {
    215         rtag7_macro_flow_hash_byte_sel = 0; /* A0 bincomp value */
    216     }
    217 
    218     rtag7_hash_seed_a =
    219         soc_reg_field_get(unit, RTAG7_HASH_SEED_Ar, rtag7_hash_seed_a_reg,
    220                           HASH_SEED_Af);
    221     rtag7_hash_seed_b =
    222         soc_reg_field_get(unit, RTAG7_HASH_SEED_Br, rtag7_hash_seed_b_reg,
    223                           HASH_SEED_Bf);
    224 
    225     /* RTAG7 tables */
    226     /* the first step is to choose the paket type and to fold the ipv6
    227      * addresses in case of IPv6 packet*/	
    228 
    229     /* option A ip folding for rtag 7 */
    230     if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) &&
    231          (pkt_info->ethertype == ETHERTYPE_IPV6)) &&
    232                (rtag7_disable_hash_ipv6_a == 0)) {
    233 
    234       /* ip6_addrs = TRUE; */
    235         rtag7_a_sel = RTAG7_IPV6;
    236         
    237         /* This section will fold the Ipv6 address to single 32 bit address
    238          * by using of of the methose LSB or xor */
    239         if (rtag7_ipv6_addr_use_lsb_a) {
    240             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) {
    241                 sip_a = (pkt_info->sip6[12] << 24) |
    242                     (pkt_info->sip6[13] << 16) |
    243                     (pkt_info->sip6[14] << 8) |
    244                     (pkt_info->sip6[15]);
    245                 sip_valid = TRUE;
    246             } else {
    247                 sip_a = 0;
    248             }
    249             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) {
    250                 dip_a = (pkt_info->dip6[12] << 24) |
    251                     (pkt_info->dip6[13] << 16) |
    252                     (pkt_info->dip6[14] << 8) |
    253                     (pkt_info->dip6[15]);
    254                 dip_valid = TRUE;
    255             } else {
    256                 dip_a = 0;
    257             }
    258         } else {   
    259             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) {
    260                 sip_a =
    261                     ((pkt_info->sip6[12] << 24) |
    262                      (pkt_info->sip6[13] << 16) |
    263                      (pkt_info->sip6[14] << 8) |
    264                      (pkt_info->sip6[15])) ^
    265                     ((pkt_info->sip6[8] << 24) |
    266                      (pkt_info->sip6[9] << 16) |
    267                      (pkt_info->sip6[10] << 8) |
    268                      (pkt_info->sip6[11])) ^
    269                     ((pkt_info->sip6[4] << 24) |
    270                      (pkt_info->sip6[5] << 16) |
    271                      (pkt_info->sip6[6] << 8) |
    272                      (pkt_info->sip6[7])) ^
    273                     ((pkt_info->sip6[0] << 24) |
    274                      (pkt_info->sip6[1] << 16) |
    275                      (pkt_info->sip6[2] << 8) |
    276                      (pkt_info->sip6[3]));
    277                 sip_valid = TRUE;
    278             } else {
    279                 sip_a = 0;
    280             }
    281 
    282             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) {
    283                 dip_a =
    284                     ((pkt_info->dip6[12] << 24) |
    285                      (pkt_info->dip6[13] << 16) |
    286                      (pkt_info->dip6[14] << 8) |
    287                      (pkt_info->dip6[15])) ^
    288                     ((pkt_info->dip6[8] << 24) |
    289                      (pkt_info->dip6[9] << 16) |
    290                      (pkt_info->dip6[10] << 8) |
    291                      (pkt_info->dip6[11])) ^
    292                     ((pkt_info->dip6[4] << 24) |
    293                      (pkt_info->dip6[5] << 16) |
    294                      (pkt_info->dip6[6] << 8) |
    295                      (pkt_info->dip6[7])) ^
    296                     ((pkt_info->dip6[0] << 24) |
    297                      (pkt_info->dip6[1] << 16) |
    298                      (pkt_info->dip6[2] << 8) |
    299                      (pkt_info->dip6[3]));
    300                 dip_valid = TRUE;
    301             } else {
    302                 dip_a = 0;
    303             }
    304         }
    305     } else if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) &&
    306                 (pkt_info->ethertype == ETHERTYPE_IPV4)) && 
    307                (rtag7_disable_hash_ipv4_a == 0)) {
    308 
    309       /*        ip4_addrs = TRUE; */
    310         rtag7_a_sel = RTAG7_IPV4;
    311 
    312         /* only one IPv4 hdr */
    313         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IP)) {
    314             sip_a = pkt_info->sip;
    315             sip_valid = TRUE;
    316         } else {
    317             sip_a = 0;
    318         }
    319         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IP)) {
    320             dip_a = pkt_info->dip;
    321             dip_valid = TRUE;
    322         } else {
    323             dip_a = 0;
    324         }
    325     } else {
    326         rtag7_a_sel = RTAG7_L2_ONLY;
    327         sip_a = dip_a = 0;
    328     }
    329 
    330     /* End of option A ip folding for rtag 7 */
    331 
    332     /* option B ip folding for rtag 7 */
    333     if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) &&
    334          (pkt_info->ethertype == ETHERTYPE_IPV6)) &&
    335                (rtag7_disable_hash_ipv6_b == 0)) {
    336 
    337       /*         ip6_addrs = TRUE; */
    338         rtag7_b_sel = RTAG7_IPV6;
    339         
    340         /* This section will fold the Ipv6 address to single 32 bit address
    341          * by using of of the methose LSB or xor */
    342         if (rtag7_ipv6_addr_use_lsb_b) {
    343             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) {
    344                 sip_b = (pkt_info->sip6[12] << 24) |
    345                     (pkt_info->sip6[13] << 16) |
    346                     (pkt_info->sip6[14] << 8) |
    347                     (pkt_info->sip6[15]);
    348                 sip_valid = TRUE;
    349             } else {
    350                 sip_b = 0;
    351             }
    352             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) {
    353                 dip_b = (pkt_info->dip6[12] << 24) |
    354                     (pkt_info->dip6[13] << 16) |
    355                     (pkt_info->dip6[14] << 8) |
    356                     (pkt_info->dip6[15]);
    357                 dip_valid = TRUE;
    358             } else {
    359                 dip_b = 0;
    360             }
    361         } else {   
    362             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) {
    363                 sip_b =
    364                     ((pkt_info->sip6[12] << 24) |
    365                      (pkt_info->sip6[13] << 16) |
    366                      (pkt_info->sip6[14] << 8) |
    367                      (pkt_info->sip6[15])) ^
    368                     ((pkt_info->sip6[8] << 24) |
    369                      (pkt_info->sip6[9] << 16) |
    370                      (pkt_info->sip6[10] << 8) |
    371                      (pkt_info->sip6[11])) ^
    372                     ((pkt_info->sip6[4] << 24) |
    373                      (pkt_info->sip6[5] << 16) |
    374                      (pkt_info->sip6[6] << 8) |
    375                      (pkt_info->sip6[7])) ^
    376                     ((pkt_info->sip6[0] << 24) |
    377                      (pkt_info->sip6[1] << 16) |
    378                      (pkt_info->sip6[2] << 8) |
    379                      (pkt_info->sip6[3]));
    380                 sip_valid = TRUE;
    381             } else {
    382                 sip_b = 0;
    383             }
    384 
    385             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) {
    386                 dip_b =
    387                     ((pkt_info->dip6[12] << 24) |
    388                      (pkt_info->dip6[13] << 16) |
    389                      (pkt_info->dip6[14] << 8) |
    390                      (pkt_info->dip6[15])) ^
    391                     ((pkt_info->dip6[8] << 24) |
    392                      (pkt_info->dip6[9] << 16) |
    393                      (pkt_info->dip6[10] << 8) |
    394                      (pkt_info->dip6[11])) ^
    395                     ((pkt_info->dip6[4] << 24) |
    396                      (pkt_info->dip6[5] << 16) |
    397                      (pkt_info->dip6[6] << 8) |
    398                      (pkt_info->dip6[7])) ^
    399                     ((pkt_info->dip6[0] << 24) |
    400                      (pkt_info->dip6[1] << 16) |
    401                      (pkt_info->dip6[2] << 8) |
    402                      (pkt_info->dip6[3]));
    403                 dip_valid = TRUE;
    404             } else {
    405                 dip_b = 0;
    406             }
    407         }      
    408     } else if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) &&
    409                 (pkt_info->ethertype == ETHERTYPE_IPV4)) && 
    410                (rtag7_disable_hash_ipv4_b == 0)) {
    411 			   
    412       /*         ip4_addrs = TRUE; */
    413         rtag7_b_sel = RTAG7_IPV4;
    414 
    415         /* only one IPv4 hdr */
    416         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IP)) {
    417             sip_b = pkt_info->sip;
    418             sip_valid = TRUE;
    419         } else {
    420             sip_b = 0;
    421         }
    422         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IP)) {
    423             dip_b = pkt_info->dip;
    424             dip_valid = TRUE;
    425         } else {
    426             dip_b = 0;
    427         }
    428     } else {	
    429         rtag7_b_sel = RTAG7_L2_ONLY;
    430         sip_b = dip_b = 0;
    431     }
    432     /* End of option B ip folding for rtag 7 */
    433 
    434 
    435 
    436     /*
    437      * =============
    438      * RTAG7 HASHING 
    439      * =============
    440      */
    441 
    442     /* The inputs to the RTAG7 hash function were reduced in the begining
    443      * of this function.  
    444      * This logic takes the hash inputs and computes both A and B RTAG7
    445      * hash values.
    446      */
    447 
    448     /* Change source modid/port to PORT32 space for hashing */
    449     hash_src_port  = hash_res->src_port;
    450     hash_src_modid = hash_res->src_modid;
    451 
    452     /* Only if the packet was sourced by this chip, make sure to use
    453      * PORT32 space modid and port if dual modid is enabled
    454      * Need to do this because of front panel ports.
    455      *
    456      * Already handled by API gport resolve */
    457 
    458     /* initialize the variables */   
    459     sal_memset(hash,0x0,(sizeof(uint32))*13);
    460     sal_memset(hash_word,0x0,(sizeof(uint32))*7);
    461 	
    462     hash_crc16_bisync = 0;
    463     hash_crc16_ccitt = 0;
    464     hash_crc32      = 0;
    465     hash_xor16      = 0;
    466     hash_xor8       = 0;
    467     hash_xor4       = 0;
    468     hash_xor2       = 0;
    469     hash_xor1       = 0;
    470     xor32           = 0;
    471 
    472     hash[12] = 0;	
    473     hash[3] = hash_src_port;
    474     hash[2] = hash_src_modid & 0xff;
    475     hash[1] = 0;
    476     hash[0] = 0;
    477 
    478     hash_element_valid_bits = 0x1fff; /* Init to valid fields above */
    479 
    480     /* option A hash calculation for rtag 7 */
    481     
    482     if ((rtag7_a_sel == RTAG7_IPV6) || (rtag7_a_sel == RTAG7_IPV4)) {
    483 
    484         if (sip_valid) {
    485             hash[11] = (sip_a >> 16) & 0xffff;
    486             hash[10] =  sip_a & 0xffff;
    487         } else {
    488             hash_element_valid_bits &= ~0xc00;
    489         }
    490         if (dip_valid) {
    491             hash[9]  = (dip_a >> 16) & 0xffff;
    492             hash[8]  =  dip_a & 0xffff;
    493         } else {
    494             hash_element_valid_bits &= ~0x300;
    495         }
    496 
    497         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) {
    498             hash[7]  = pkt_info->vid & 0xfff;
    499         } else {
    500             hash_element_valid_bits &= ~0x80;
    501         }
    502         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT)) {
    503             hash[6]  = pkt_info->src_l4_port;
    504         } else {
    505             hash_element_valid_bits &= ~0x40;
    506         }
    507         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT)) {
    508             hash[5]  = pkt_info->dst_l4_port;
    509         } else {
    510             hash_element_valid_bits &= ~0x20;
    511         }
    512         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL)) {
    513             hash[4]  = pkt_info->protocol;
    514         } else {
    515             hash_element_valid_bits &= ~0x10;
    516         }
    517 
    518         if ((rtag7_a_sel == RTAG7_IPV6) && rtag7_en_flow_label_ipv6_a) {
    519             LOG_VERBOSE(BSL_LS_BCM_COMMON,
    520                         (BSL_META_U(unit,
    521                                     "Hash calculation: The system is set to use ipv6 flow label and the code can't get this info\n")));
    522         }
    523 
    524         if (rtag7_a_sel == RTAG7_IPV4) {  /* Use IPv4 BITMAPs */
    525             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) &&
    526                 ((pkt_info->protocol == IP_PROT_TCP) ||
    527                 (pkt_info->protocol == IP_PROT_UDP))) { 
    528                 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) &&
    529                     _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) &&
    530                     (pkt_info->src_l4_port == pkt_info->dst_l4_port)) {
    531                     sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_1r;
    532                     sc_field = IPV4_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Af;
    533                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
    534                                 (BSL_META_U(unit,
    535                                             "Hash calculation: Bitmap is block A IPv4 TCP=UDP\n")));
    536                 } else {
    537                     sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_2r;
    538                     sc_field = IPV4_TCP_UDP_FIELD_BITMAP_Af;
    539                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
    540                                 (BSL_META_U(unit,
    541                                             "Hash calculation: Bitmap is block A IPv4 L4 tcp/udp\n")));
    542                 }
    543             } else {
    544                 sc_reg = RTAG7_HASH_FIELD_BMAP_1r;
    545                 sc_field = IPV4_FIELD_BITMAP_Af;
    546                 LOG_VERBOSE(BSL_LS_BCM_COMMON,
    547                             (BSL_META_U(unit,
    548                                         "Hash calculation: Bitmap is block A IPv4 \n")));
    549             }
    550 
    551         } else { /* Use IPv6 BITMAPs */
    552             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) &&
    553                 ((pkt_info->protocol == IP_PROT_TCP) ||
    554                 (pkt_info->protocol == IP_PROT_UDP))) { 
    555                 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) &&
    556                     _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) &&
    557                     (pkt_info->src_l4_port == pkt_info->dst_l4_port)) {
    558                     sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_1r;
    559                     sc_field = IPV6_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Af;
    560                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
    561                                 (BSL_META_U(unit,
    562                                             "Hash calculation: Bitmap is block A IPv6 TCP=UDP\n")));
    563                 } else {
    564                     sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_2r;
    565                     sc_field = IPV6_TCP_UDP_FIELD_BITMAP_Af;
    566                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
    567                                 (BSL_META_U(unit,
    568                                             "Hash calculation: Bitmap is block A IPv6 L4 tcp/udp\n")));
    569                 }
    570             } else {
    571                 sc_reg = RTAG7_HASH_FIELD_BMAP_2r;
    572                 sc_field = IPV6_FIELD_BITMAP_Af;
    573                 LOG_VERBOSE(BSL_LS_BCM_COMMON,
    574                             (BSL_META_U(unit,
    575                                         "Hash calculation: Bitmap is block A IPv6 \n")));
    576             }
    577         }
    578         
    579     } else { /* Catch-all for RTAG7_L2_ONLY */
    580 
    581         /* L2 only hash key */
    582         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_MAC)) {
    583             hash[11] = (pkt_info->src_mac[0] << 8) | pkt_info->src_mac[1];
    584             hash[10] = (pkt_info->src_mac[2] << 8) | pkt_info->src_mac[3];
    585             hash[9] = (pkt_info->src_mac[4] << 8) | pkt_info->src_mac[5];
    586         } else {
    587             hash_element_valid_bits &= ~0xe00;
    588         }
    589         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_MAC)) {
    590             hash[8] = (pkt_info->dst_mac[0] << 8) | pkt_info->dst_mac[1];
    591             hash[7] = (pkt_info->dst_mac[2] << 8) | pkt_info->dst_mac[3];
    592             hash[6] = (pkt_info->dst_mac[4] << 8) | pkt_info->dst_mac[5];
    593         } else {
    594             hash_element_valid_bits &= ~0x1c0;
    595         }
    596 
    597         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE)) {
    598             hash[5] = (pkt_info->ethertype >= ETHERTYPE_MIN) ?
    599                 pkt_info->ethertype : 0;
    600         } else {
    601             hash_element_valid_bits &= ~0x20;
    602         }
    603 
    604         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) {
    605             hash[4] = pkt_info->vid & 0xfff;
    606         } else {
    607             hash_element_valid_bits &= ~0x10;
    608         }
    609 
    610         sc_reg = RTAG7_HASH_FIELD_BMAP_3r;
    611         sc_field = L2_FIELD_BITMAP_Af;
    612         LOG_VERBOSE(BSL_LS_BCM_COMMON,
    613                     (BSL_META_U(unit,
    614                                 "Hash calculation: Bitmap is block A L2\n")));
    615     }
    616 
    617     BCM_IF_ERROR_RETURN
    618         (soc_reg32_get(unit, sc_reg, REG_PORT_ANY, 0, &sc_val));
    619     hash_field_bmap_a = soc_reg_field_get(unit, sc_reg, sc_val, sc_field);
    620 
    621     /* Pre-Processing */
    622 
    623     if (rtag7_pre_processing_enable_a) {
    624 
    625         hash[12] = hash[12] ^ (hash[12] >> 3) ^ (hash[12] << 2);
    626         hash[11] = hash[11] ^ (hash[11] >> 3) ^ (hash[11] << 2);
    627         hash[10] = hash[10] ^ (hash[10] >> 3) ^ (hash[10] << 2);
    628         hash[9] = hash[9] ^ (hash[9] >> 3) ^ (hash[9] << 2);
    629         hash[8] = hash[8] ^ (hash[8] >> 3) ^ (hash[8] << 2);
    630         hash[7] = hash[7] ^ (hash[7] >> 3) ^ (hash[7] << 2);
    631         hash[6] = hash[6] ^ (hash[6] >> 3) ^ (hash[6] << 2);
    632         hash[5] = hash[5] ^ (hash[5] >> 3) ^ (hash[5] << 2);
    633         hash[4] = hash[4] ^ (hash[4] >> 3) ^ (hash[4] << 2);
    634         hash[3] = hash[3] ^ (hash[3] >> 3) ^ (hash[3] << 2);
    635         hash[2] = hash[2] ^ (hash[2] >> 3) ^ (hash[2] << 2);
    636         hash[1] = hash[1] ^ (hash[1] >> 3) ^ (hash[1] << 2);
    637         hash[0] = hash[0] ^ (hash[0] >> 3) ^ (hash[0] << 2);
    638     
    639     }
    640 
    641     if (((hash_field_bmap_a >> 12) & 0x1) == 0) {
    642         hash[12] = 0;
    643     }    
    644 
    645     if (rtag7_en_bin_12_overlay_a) {
    646         hash_word[6] = (rtag7_hash_seed_a & 0xffff0000) | (hash[12] & 0xffff);
    647     } else {
    648         hash_word[6] = rtag7_hash_seed_a;
    649     }    
    650 
    651     hash_res->hash_a_valid = TRUE;
    652     for (elem = 11; elem >= 0; elem--) {
    653         elem_bit = 1 << elem;
    654         if (0 != (hash_field_bmap_a & elem_bit)) {
    655             if (0 != (hash_element_valid_bits & elem_bit)) {
    656                 hash_word[elem/2] |=
    657                     ((hash[elem] & 0xffff) << (16 * (elem % 2)));
    658             } else {
    659                 hash_res->hash_a_valid = FALSE;
    660                 break;
    661             }
    662         }
    663     }
    664 
    665     /*Calculation*/
    666     xor32 = hash_word[6] ^ hash_word[5] ^ hash_word[4] ^ hash_word[3] ^
    667         hash_word[2] ^ hash_word[1] ^ hash_word[0];
    668 
    669     hash_xor16 = (xor32 & 0xffff) ^ ((xor32 >> 16) & 0xffff);  
    670     hash_xor8 = (hash_xor16 & 0xff) ^ ((hash_xor16 >> 8) & 0xff);
    671     hash_xor4 = (hash_xor8 & 0xf) ^ ((hash_xor8 >> 4) & 0xf);
    672     hash_xor2 = (hash_xor4 & 0x3) ^ ((hash_xor4 >> 2) & 0x3);
    673     hash_xor1 = (hash_xor2 & 0x1) ^ ((hash_xor2 >> 1) & 0x1);
    674 
    675     hash_crc16_bisync = _shr_crc16_draco_array(hash_word, 28);
    676     hash_crc16_ccitt =  _shr_crc16_ccitt_array(hash_word, 28);
    677     hash_crc32 =        _shr_crc32_castagnoli_array(hash_word, 28);
    678 
    679     switch (rtag7_hash_a0_function_select) {
    680     case 0: /* reserved */
    681         hash_res->rtag7_hash16_value_a_0 = 0;
    682         break;
    683     case 1: /* reserved */
    684         hash_res->rtag7_hash16_value_a_0 = 0;
    685         break;
    686     case 2: /* reserved */
    687         hash_res->rtag7_hash16_value_a_0 = 0;
    688         break;
    689     case 3: /* CRC16 BISYNC */
    690         hash_res->rtag7_hash16_value_a_0 = hash_crc16_bisync;
    691         break;
    692     case 4: /* CRC16_XOR1 */ 
    693         hash_res->rtag7_hash16_value_a_0 = hash_xor1 & 0x1;
    694         hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    695         break;
    696     case 5: /* CRC16_XOR2 */
    697         hash_res->rtag7_hash16_value_a_0 = hash_xor2 & 0x3;
    698         hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    699         break;
    700     case 6: /* CRC16_XOR4 */ 
    701         hash_res->rtag7_hash16_value_a_0 = hash_xor4 & 0xf;
    702         hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    703         break;
    704     case 7: /* CRC16_XOR8 */
    705         hash_res->rtag7_hash16_value_a_0 = hash_xor8 & 0xff;
    706         hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    707         break;
    708     case 8: /* XOR16 */
    709         hash_res->rtag7_hash16_value_a_0 = hash_xor16;
    710         break;
    711     case 9: /* CRC16_CCITT */
    712         hash_res->rtag7_hash16_value_a_0 = hash_crc16_ccitt;
    713         break;
    714     case 10: /* CRC32_LO */
    715         hash_res->rtag7_hash16_value_a_0 = hash_crc32 & 0xffff;
    716         break;
    717     case 11: /* CRC32_HI */
    718         hash_res->rtag7_hash16_value_a_0 = (hash_crc32 >> 16) & 0xffff;
    719         break;
    720     default: /* reserved */
    721         hash_res->rtag7_hash16_value_a_0 = 0;
    722         break;
    723     }
    724 
    725     switch (rtag7_hash_a1_function_select) {
    726     case 0: /* reserved */
    727         hash_res->rtag7_hash16_value_a_1 = 0;
    728         break;
    729     case 1: /* reserved */
    730         hash_res->rtag7_hash16_value_a_1 = 0;
    731         break;
    732     case 2: /* reserved */
    733         hash_res->rtag7_hash16_value_a_1 = 0;
    734         break;
    735     case 3: /* CRC16 BISYNC */
    736         hash_res->rtag7_hash16_value_a_1 = hash_crc16_bisync;
    737         break;
    738     case 4: /* CRC16_XOR1 */ 
    739         hash_res->rtag7_hash16_value_a_1 = hash_xor1 & 0x1;
    740         hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    741         break;
    742     case 5: /* CRC16_XOR2 */
    743         hash_res->rtag7_hash16_value_a_1 = hash_xor2 & 0x3;
    744         hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    745         break;
    746     case 6: /* CRC16_XOR4 */ 
    747         hash_res->rtag7_hash16_value_a_1 = hash_xor4 & 0xf;
    748         hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    749         break;
    750     case 7: /* CRC16_XOR8 */
    751         hash_res->rtag7_hash16_value_a_1 = hash_xor8 & 0xff;
    752         hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    753         break;
    754     case 8: /* XOR16 */
    755         hash_res->rtag7_hash16_value_a_1 = hash_xor16;
    756         break;
    757     case 9: /* CRC16_CCITT */
    758         hash_res->rtag7_hash16_value_a_1 = hash_crc16_ccitt;
    759         break;
    760     case 10: /* CRC32_LO */
    761         hash_res->rtag7_hash16_value_a_1 = hash_crc32 & 0xffff;
    762         break;
    763     case 11: /* CRC32_HI */
    764         hash_res->rtag7_hash16_value_a_1 = (hash_crc32 >> 16) & 0xffff;
    765         break;
    766     default: /* reserved */
    767         hash_res->rtag7_hash16_value_a_1 = 0;
    768         break;
    769     }
    770 
    771     /* End of option A hash calculation for rtag 7 */
    772 
    773     /* Generation of Macro Flow Based HASH Select */
    774     /* This is used for Macro flow based Hash function selection for all consumers of RTAG7 HASH */
    775     /* Macro flow based hash function selection improves distribution among members */
    776     /* Refer Each application (ECMP, LAG, HG-TRUNK) on how this is being used */
    777     switch (rtag7_macro_flow_hash_function_select) {
    778     case 0: /* reserved */
    779         macro_flow_id = 0;
    780         break;
    781     case 1: /* reserved */
    782         macro_flow_id = 0;
    783         break;
    784     case 2: /* reserved */
    785         macro_flow_id = 0;
    786         break;
    787     case 3: /* CRC16 BISYNC */
    788         macro_flow_id = hash_crc16_bisync;
    789         break;
    790     case 4: /* CRC16_XOR1 */ 
    791         macro_flow_id = hash_xor1 & 0x1;
    792         macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    793         break;
    794     case 5: /* CRC16_XOR2 */
    795         macro_flow_id = hash_xor2 & 0x3;
    796         macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    797         break;
    798     case 6: /* CRC16_XOR4 */ 
    799         macro_flow_id = hash_xor4 & 0xf;
    800         macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    801         break;
    802     case 7: /* CRC16_XOR8 */
    803         macro_flow_id = hash_xor8 & 0xff;
    804         macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
    805         break;
    806     case 8: /* XOR16 */
    807         macro_flow_id = hash_xor16;
    808         break;
    809     case 9: /* CRC16_CCITT */
    810         macro_flow_id = hash_crc16_ccitt;
    811         break;
    812     case 10: /* CRC32_LO */
    813         macro_flow_id = hash_crc32 & 0xffff;
    814         break;
    815     case 11: /* CRC32_HI */
    816         macro_flow_id = (hash_crc32 >> 16) & 0xffff;
    817         break;
    818     default: /* reserved */
    819         macro_flow_id = 0;
    820         break;
    821     }
    822     hash_res->rtag7_macro_flow_id = (rtag7_macro_flow_hash_byte_sel) ?  
    823         ((macro_flow_id >> 8) & 0xff) : (macro_flow_id & 0xff);
    824 
    825     /* option B hash calculation for rtag 7 */
    826 
    827     /* initialize the variables */   
    828 	
    829     sal_memset(hash,0x0,(sizeof(uint32))*13);
    830     sal_memset(hash_word,0x0,(sizeof(uint32))*7);
    831 	
    832     hash_crc16_bisync = 0;
    833     hash_crc16_ccitt = 0;
    834     hash_crc32      = 0;
    835     hash_xor16      = 0;
    836     hash_xor8       = 0;
    837     hash_xor4       = 0;
    838     hash_xor2       = 0;
    839     hash_xor1       = 0;
    840     xor32           = 0;
    841  
    842     hash[12] = 0;	
    843     hash[3] = hash_src_port;
    844     hash[2] = hash_src_modid & 0xff;
    845     hash[1] = 0;
    846     hash[0] = 0; 
    847 
    848     hash_element_valid_bits = 0x1fff; /* Init to valid fields above */
    849 
    850     /* option B hash calculation for rtag 7 */
    851     
    852     if ((rtag7_b_sel == RTAG7_IPV6) || (rtag7_b_sel == RTAG7_IPV4)) {
    853         if (sip_valid) {
    854             hash[11] = (sip_b >> 16) & 0xffff;
    855             hash[10] =  sip_b & 0xffff;
    856         } else {
    857             hash_element_valid_bits &= ~0xc00;
    858         }
    859         if (dip_valid) {
    860             hash[9]  = (dip_b >> 16) & 0xffff;
    861             hash[8]  =  dip_b & 0xffff;
    862         } else {
    863             hash_element_valid_bits &= ~0x300;
    864         }
    865 
    866         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) {
    867             hash[7]  = pkt_info->vid & 0xfff;
    868         } else {
    869             hash_element_valid_bits &= ~0x80;
    870         }
    871         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT)) {
    872             hash[6]  = pkt_info->src_l4_port;
    873         } else {
    874             hash_element_valid_bits &= ~0x40;
    875         }
    876         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT)) {
    877             hash[5]  = pkt_info->dst_l4_port;
    878         } else {
    879             hash_element_valid_bits &= ~0x20;
    880         }
    881         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL)) {
    882             hash[4]  = pkt_info->protocol;
    883         } else {
    884             hash_element_valid_bits &= ~0x10;
    885         }
    886 
    887         if ((rtag7_b_sel == RTAG7_IPV6) && rtag7_en_flow_label_ipv6_b) {
    888             LOG_VERBOSE(BSL_LS_BCM_COMMON,
    889                         (BSL_META_U(unit,
    890                                     "Hash calculation: The system is set to use ipv6 flow label and the code can't get this info\n")));
    891         }
    892 
    893         if (rtag7_b_sel == RTAG7_IPV4) {  /* Use IPv4 BITMAPs */
    894             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) &&
    895                 ((pkt_info->protocol == IP_PROT_TCP) ||
    896                 (pkt_info->protocol == IP_PROT_UDP))) { 
    897                 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) &&
    898                     _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) &&
    899                     (pkt_info->src_l4_port == pkt_info->dst_l4_port)) {
    900                     sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_1r;
    901                     sc_field = IPV4_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Bf;
    902                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
    903                                 (BSL_META_U(unit,
    904                                             "Hash calculation: Bitmap is block B IPv4 TCP=UDP\n")));
    905                 } else {
    906                     sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_2r;
    907                     sc_field = IPV4_TCP_UDP_FIELD_BITMAP_Bf;
    908                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
    909                                 (BSL_META_U(unit,
    910                                             "Hash calculation: Bitmap is block B IPv4 L4 tcp/udp\n")));
    911                 }
    912             } else {
    913                 sc_reg = RTAG7_HASH_FIELD_BMAP_1r;
    914                 sc_field = IPV4_FIELD_BITMAP_Bf;
    915                 LOG_VERBOSE(BSL_LS_BCM_COMMON,
    916                             (BSL_META_U(unit,
    917                                         "Hash calculation: Bitmap is block B IPv4\n")));
    918             }
    919 
    920         } else { /* Use IPv6 BITMAPs */
    921 
    922             if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) &&
    923                 ((pkt_info->protocol == IP_PROT_TCP) ||
    924                 (pkt_info->protocol == IP_PROT_UDP))) { 
    925                 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) &&
    926                     _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) &&
    927                     (pkt_info->src_l4_port == pkt_info->dst_l4_port)) {
    928                     sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_1r;
    929                     sc_field = IPV6_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Bf;
    930                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
    931                                 (BSL_META_U(unit,
    932                                             "Hash calculation: Bitmap is block B IPv6 TCP=UDP\n")));
    933                 } else {
    934                     sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_2r;
    935                     sc_field = IPV6_TCP_UDP_FIELD_BITMAP_Bf;
    936                     LOG_VERBOSE(BSL_LS_BCM_COMMON,
    937                                 (BSL_META_U(unit,
    938                                             "Hash calculation: Bitmap is block B IPv6 TCP=UDP\n")));
    939                 }
    940             } else {
    941                 sc_reg = RTAG7_HASH_FIELD_BMAP_2r;
    942                 sc_field = IPV6_FIELD_BITMAP_Bf;
    943                 LOG_VERBOSE(BSL_LS_BCM_COMMON,
    944                             (BSL_META_U(unit,
    945                                         "Hash calculation: Bitmap is block B IPv6\n")));
    946             }
    947         }
    948     } else { /* Catch-all for RTAG7_L2_ONLY */
    949 
    950         /* L2 only hash key */
    951         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_MAC)) {
    952             hash[11] = (pkt_info->src_mac[0] << 8) | pkt_info->src_mac[1];
    953             hash[10] = (pkt_info->src_mac[2] << 8) | pkt_info->src_mac[3];
    954             hash[9] = (pkt_info->src_mac[4] << 8) | pkt_info->src_mac[5];
    955         } else {
    956             hash_element_valid_bits &= ~0xe00;
    957         }
    958         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_MAC)) {
    959             hash[8] = (pkt_info->dst_mac[0] << 8) | pkt_info->dst_mac[1];
    960             hash[7] = (pkt_info->dst_mac[2] << 8) | pkt_info->dst_mac[3];
    961             hash[6] = (pkt_info->dst_mac[4] << 8) | pkt_info->dst_mac[5];
    962         } else {
    963             hash_element_valid_bits &= ~0x1c0;
    964         }
    965 
    966         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE)) {
    967             hash[5] = (pkt_info->ethertype >= ETHERTYPE_MIN) ?
    968                 pkt_info->ethertype : 0;
    969         } else {
    970             hash_element_valid_bits &= ~0x20;
    971         }
    972 
    973         if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) {
    974             hash[4] = pkt_info->vid & 0xfff;
    975         } else {
    976             hash_element_valid_bits &= ~0x10;
    977         }
    978 
    979         sc_reg = RTAG7_HASH_FIELD_BMAP_3r;
    980         sc_field = L2_FIELD_BITMAP_Bf;
    981         LOG_VERBOSE(BSL_LS_BCM_COMMON,
    982                     (BSL_META_U(unit,
    983                                 "Hash calculation: Bitmap is block B L2\n")));
    984     }
    985 
    986     BCM_IF_ERROR_RETURN
    987         (soc_reg32_get(unit, sc_reg, REG_PORT_ANY, 0, &sc_val));
    988     hash_field_bmap_b = soc_reg_field_get(unit, sc_reg, sc_val, sc_field);
    989 
    990     /* Pre-Processing */
    991 
    992     if (rtag7_pre_processing_enable_b) {
    993 
    994         hash[12] = hash[12] ^ (hash[12] >> 3) ^ (hash[12] << 2);
    995         hash[11] = hash[11] ^ (hash[11] >> 3) ^ (hash[11] << 2);
    996         hash[10] = hash[10] ^ (hash[10] >> 3) ^ (hash[10] << 2);
    997         hash[9] = hash[9] ^ (hash[9] >> 3) ^ (hash[9] << 2);
    998         hash[8] = hash[8] ^ (hash[8] >> 3) ^ (hash[8] << 2);
    999         hash[7] = hash[7] ^ (hash[7] >> 3) ^ (hash[7] << 2);
   1000         hash[6] = hash[6] ^ (hash[6] >> 3) ^ (hash[6] << 2);
   1001         hash[5] = hash[5] ^ (hash[5] >> 3) ^ (hash[5] << 2);
   1002         hash[4] = hash[4] ^ (hash[4] >> 3) ^ (hash[4] << 2);
   1003         hash[3] = hash[3] ^ (hash[3] >> 3) ^ (hash[3] << 2);
   1004         hash[2] = hash[2] ^ (hash[2] >> 3) ^ (hash[2] << 2);
   1005         hash[1] = hash[1] ^ (hash[1] >> 3) ^ (hash[1] << 2);
   1006         hash[0] = hash[0] ^ (hash[0] >> 3) ^ (hash[0] << 2);
   1007     
   1008     }
   1009 
   1010     if (((hash_field_bmap_b >> 12) & 0x1) == 0) {
   1011         hash[12] = 0;
   1012     }    
   1013 
   1014     if (rtag7_en_bin_12_overlay_b) {
   1015         hash_word[6] = (rtag7_hash_seed_b & 0xffff0000) | (hash[12] & 0xffff);
   1016     } else {
   1017         hash_word[6] = rtag7_hash_seed_b;
   1018     }    
   1019 
   1020     hash_res->hash_b_valid = TRUE;
   1021     for (elem = 11; elem >= 0; elem--) {
   1022         elem_bit = 1 << elem;
   1023         if (0 != (hash_field_bmap_b & elem_bit)) {
   1024             if (0 != (hash_element_valid_bits & elem_bit)) {
   1025                 hash_word[elem/2] |=
   1026                     ((hash[elem] & 0xffff) << (16 * (elem % 2)));
   1027             } else {
   1028                 hash_res->hash_b_valid = FALSE;
   1029                 break;
   1030             }
   1031         }
   1032     }
   1033 
   1034     xor32 = hash_word[6] ^ hash_word[5] ^ hash_word[4] ^ hash_word[3] ^ hash_word[2] ^ hash_word[1] ^ hash_word[0];
   1035     hash_xor16 = (xor32 & 0xffff) ^ ((xor32 >> 16) & 0xffff);  
   1036     hash_xor8 = (hash_xor16 & 0xff) ^ ((hash_xor16 >> 8) & 0xff);
   1037     hash_xor4 = (hash_xor8 & 0xf) ^ ((hash_xor8 >> 4) & 0xf);
   1038     hash_xor2 = (hash_xor4 & 0x3) ^ ((hash_xor4 >> 2) & 0x3);
   1039     hash_xor1 = (hash_xor2 & 0x1) ^ ((hash_xor2 >> 1) & 0x1);
   1040 
   1041     hash_crc16_bisync = _shr_crc16_draco_array(hash_word, 28);
   1042     hash_crc16_ccitt =  _shr_crc16_ccitt_array(hash_word, 28);
   1043     hash_crc32 =        _shr_crc32_castagnoli_array(hash_word, 28);
   1044 
   1045     switch (rtag7_hash_b0_function_select) {
   1046     case 0: /* reserved */
   1047         hash_res->rtag7_hash16_value_b_0 = 0;
   1048         break;
   1049     case 1: /* reserved */
   1050         hash_res->rtag7_hash16_value_b_0 = 0;
   1051         break;
   1052     case 2: /* reserved */
   1053         hash_res->rtag7_hash16_value_b_0 = 0;
   1054         break;
   1055     case 3: /* CRC16 BISYNC */
   1056         hash_res->rtag7_hash16_value_b_0 = hash_crc16_bisync;
   1057         break;
   1058     case 4: /* CRC16_XOR1 */ 
   1059         hash_res->rtag7_hash16_value_b_0 = hash_xor1 & 0x1;
   1060         hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1061         break;
   1062     case 5: /* CRC16_XOR2 */
   1063         hash_res->rtag7_hash16_value_b_0 = hash_xor2 & 0x3;
   1064         hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1065         break;
   1066     case 6: /* CRC16_XOR4 */ 
   1067         hash_res->rtag7_hash16_value_b_0 = hash_xor4 & 0xf;
   1068         hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1069         break;
   1070     case 7: /* CRC16_XOR8 */
   1071         hash_res->rtag7_hash16_value_b_0 = hash_xor8 & 0xff;
   1072         hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1073         break;
   1074     case 8: /* XOR16 */
   1075         hash_res->rtag7_hash16_value_b_0 = hash_xor16;
   1076         break;
   1077     case 9: /* CRC16_CCITT */
   1078         hash_res->rtag7_hash16_value_b_0 = hash_crc16_ccitt;
   1079         break;
   1080     case 10: /* CRC32_LO */
   1081         hash_res->rtag7_hash16_value_b_0 = hash_crc32 & 0xffff;
   1082         break;
   1083     case 11: /* CRC32_HI */
   1084         hash_res->rtag7_hash16_value_b_0 = (hash_crc32 >> 16) & 0xffff;
   1085         break;
   1086     default: /* reserved */
   1087         hash_res->rtag7_hash16_value_b_0 = 0;
   1088         break;
   1089     }
   1090 
   1091     switch (rtag7_hash_b1_function_select) {
   1092     case 0: /* reserved */
   1093         hash_res->rtag7_hash16_value_b_1 = 0;
   1094         break;
   1095     case 1: /* reserved */
   1096         hash_res->rtag7_hash16_value_b_1 = 0;
   1097         break;
   1098     case 2: /* reserved */
   1099         hash_res->rtag7_hash16_value_b_1 = 0;
   1100         break;
   1101     case 3: /* CRC16 BISYNC */
   1102         hash_res->rtag7_hash16_value_b_1 = hash_crc16_bisync;
   1103         break;
   1104     case 4: /* CRC16_XOR1 */ 
   1105         hash_res->rtag7_hash16_value_b_1 = hash_xor1 & 0x1;
   1106         hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1107         break;
   1108     case 5: /* CRC16_XOR2 */
   1109         hash_res->rtag7_hash16_value_b_1 = hash_xor2 & 0x3;
   1110         hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1111         break;
   1112     case 6: /* CRC16_XOR4 */ 
   1113         hash_res->rtag7_hash16_value_b_1 = hash_xor4 & 0xf;
   1114         hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1115         break;
   1116     case 7: /* CRC16_XOR8 */
   1117         hash_res->rtag7_hash16_value_b_1 = hash_xor8 & 0xff;
   1118         hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8);
   1119         break;
   1120     case 8: /* XOR16 */
   1121         hash_res->rtag7_hash16_value_b_1 = hash_xor16;
   1122         break;
   1123     case 9: /* CRC16_CCITT */
   1124         hash_res->rtag7_hash16_value_b_1 = hash_crc16_ccitt;
   1125         break;
   1126     case 10: /* CRC32_LO */
   1127         hash_res->rtag7_hash16_value_b_1 = hash_crc32 & 0xffff;
   1128         break;
   1129     case 11: /* CRC32_HI */
   1130         hash_res->rtag7_hash16_value_b_1 = (hash_crc32 >> 16) & 0xffff;
   1131         break;
   1132     default: /* reserved */
   1133         hash_res->rtag7_hash16_value_b_1 = 0;
   1134         break;
   1135     }
   1136 
   1137     /* End of option B hash calculation for rtag 7 */
   1138     return BCM_E_NONE;
   1139 }
   1140 
   1141 /*----------------------------------------------------------------*/
   1142 
   1143 
   1144 
   1145 STATIC int
   1146 select_hash_subfield(int hash_sub_sel, uint32 *selected_subfield,
   1147                      bcm_rtag7_base_hash_t *hash_Base)
   1148 {
   1149     int rv = BCM_E_NONE;
   1150     *selected_subfield = 0;
   1151 
   1152     switch (hash_sub_sel) {
   1153         case 0: /* select pkt hash A */
   1154             *selected_subfield = hash_Base->rtag7_hash16_value_a_0;
   1155             if (!hash_Base->hash_a_valid) {
   1156                 /* Missing paramter in input */
   1157                 rv = BCM_E_PARAM;
   1158             }
   1159             break;
   1160 
   1161         case 1: /* select pkt hash B */
   1162             *selected_subfield = hash_Base->rtag7_hash16_value_b_0;
   1163             if (!hash_Base->hash_b_valid) {
   1164                 /* Missing paramter in input */
   1165                 rv = BCM_E_PARAM;
   1166             }
   1167             break;
   1168 
   1169         case 2: /* select port LBN */
   1170             *selected_subfield = hash_Base->rtag7_port_lbn;
   1171             break;
   1172 
   1173         case 3: /* select destination port id or hash A */
   1174             
   1175             *selected_subfield = hash_Base->rtag7_hash16_value_a_0;
   1176             if (!hash_Base->hash_a_valid) {
   1177                 /* Missing paramter in input */
   1178                 rv = BCM_E_PARAM;
   1179             }
   1180             break;
   1181 
   1182         case 4: /* select LBID from module header or from SW1 stage */ 
   1183             *selected_subfield = hash_Base->rtag7_lbid_hash; 
   1184             if (!hash_Base->lbid_hash_valid) {
   1185                 /* LBID setting isn't RTAG7 */
   1186                 rv = BCM_E_CONFIG;
   1187             }
   1188             break;
   1189 
   1190         case 5: /* select LBID from SW1 stage */
   1191             *selected_subfield = hash_Base->rtag7_lbid_hash;
   1192             if (!hash_Base->lbid_hash_valid) {
   1193                 /* LBID setting isn't RTAG7 */
   1194                 rv = BCM_E_CONFIG;
   1195             }
   1196             break;
   1197 
   1198         case 6:
   1199             *selected_subfield = hash_Base->rtag7_hash16_value_a_1;
   1200             if (!hash_Base->hash_a_valid) {
   1201                 /* Missing paramter in input */
   1202                 rv = BCM_E_PARAM;
   1203             }
   1204             break;
   1205 
   1206         case 7: 
   1207             *selected_subfield = hash_Base->rtag7_hash16_value_b_1;
   1208             if (!hash_Base->hash_b_valid) {
   1209                 /* Missing paramter in input */
   1210                 rv = BCM_E_PARAM;
   1211             }
   1212             break;
   1213     }
   1214 
   1215     return rv;
   1216 }
   1217 
   1218 
   1219 STATIC int
   1220 main__compute_lbid(int unit, bcm_rtag7_base_hash_t *hash_Base)
   1221 {
   1222     /*regular var declaration*/
   1223     uint32 lbid_hash_sub_sel;
   1224     uint32 lbid_hash_offset;
   1225     uint32 lbid_hash_value = 0;
   1226 
   1227     /*register var declaration*/
   1228     int lbid_rtag;
   1229     uint8 rtag7_hash_cfg_sel_lbid;
   1230     uint32 rtag7_hash_lbid_reg;
   1231     int pc_out, sc_val, lbid_idx, rv = BCM_E_NONE;
   1232 	
   1233     /*register read*/
   1234     BCM_IF_ERROR_RETURN
   1235         (bcm_esw_port_control_get(unit, hash_Base->dev_src_port,
   1236                                   bcmPortControlLoadBalancingNumber,
   1237                                   &pc_out)); 
   1238     rtag7_hash_cfg_sel_lbid = pc_out;
   1239     BCM_IF_ERROR_RETURN
   1240         (bcm_esw_switch_control_get(unit, bcmSwitchLoadBalanceHashSelect,
   1241                                     &sc_val));
   1242     lbid_rtag = sc_val;
   1243 	
   1244     /* ******************* LBID computation ************************* */
   1245 
   1246     if (lbid_rtag == 7) {
   1247         lbid_idx = (0 != rtag7_hash_cfg_sel_lbid) ? 1 : 0;
   1248         SOC_IF_ERROR_RETURN
   1249             (READ_RTAG7_HASH_LBIDr(unit, lbid_idx, &rtag7_hash_lbid_reg));
   1250         if (hash_Base->is_nonuc) {
   1251             lbid_hash_sub_sel =
   1252                 soc_reg_field_get(unit, RTAG7_HASH_LBIDr,
   1253                                   rtag7_hash_lbid_reg, SUB_SEL_NONUCf);
   1254             lbid_hash_offset =
   1255                 soc_reg_field_get(unit, RTAG7_HASH_LBIDr,
   1256                                   rtag7_hash_lbid_reg, OFFSET_NONUCf);
   1257         } else {
   1258             lbid_hash_sub_sel =
   1259                 soc_reg_field_get(unit, RTAG7_HASH_LBIDr,
   1260                                   rtag7_hash_lbid_reg, SUB_SEL_UCf);
   1261             lbid_hash_offset =
   1262                 soc_reg_field_get(unit, RTAG7_HASH_LBIDr,
   1263                                   rtag7_hash_lbid_reg, OFFSET_UCf);
   1264         }		
   1265         /* Only UC hash selects apply to ECMP */
   1266         switch (lbid_hash_sub_sel) {
   1267 		
   1268         case 0: /* use pkt hash A */
   1269             lbid_hash_value = hash_Base->rtag7_hash16_value_a_0;
   1270             if (!hash_Base->hash_a_valid) {
   1271                 /* Missing paramter in input */
   1272                 rv = BCM_E_PARAM;
   1273             }
   1274             break;
   1275 		
   1276         case 1: /* use pkt hash B */
   1277             lbid_hash_value = hash_Base->rtag7_hash16_value_b_0;
   1278             if (!hash_Base->hash_b_valid) {
   1279                 /* Missing paramter in input */
   1280                 rv = BCM_E_PARAM;
   1281             }
   1282             break;
   1283 		
   1284         case 2: /* Use LBN */
   1285             lbid_hash_value = hash_Base->rtag7_port_lbn;
   1286             break;
   1287 		
   1288         case 3: /* Use Destination PORTID or hash A */
   1289             lbid_hash_value = hash_Base->rtag7_hash16_value_a_0;
   1290             if (!hash_Base->hash_a_valid) {
   1291                 /* Missing paramter in input */
   1292                 rv = BCM_E_PARAM;
   1293             }
   1294             break;
   1295 		
   1296         case 4: /* Use LBID */
   1297             /* Higig lookup use mh_higig2_lbid */
   1298 				
   1299             lbid_hash_value = 0;
   1300             break;
   1301 		
   1302         case 5:
   1303             lbid_hash_value = 0;
   1304             break;
   1305 		
   1306         case 6:
   1307             lbid_hash_value = hash_Base->rtag7_hash16_value_a_1;
   1308             if (!hash_Base->hash_a_valid) {
   1309                 /* Missing paramter in input */
   1310                 rv = BCM_E_PARAM;
   1311             }
   1312             break;
   1313 		
   1314         case 7:
   1315             lbid_hash_value = hash_Base->rtag7_hash16_value_b_1;
   1316             if (!hash_Base->hash_b_valid) {
   1317                 /* Missing paramter in input */
   1318                 rv = BCM_E_PARAM;
   1319             }
   1320             break;
   1321         }
   1322 		
   1323         /*
   1324          * set up the hash value so that the LSB bits are
   1325          * barrel shifted in case offset > 8.
   1326          */
   1327         lbid_hash_value |= ((lbid_hash_value & 0xffff) << 16);
   1328 		
   1329         /* Only UC hash offsets apply to ECMP */
   1330         lbid_hash_value = (lbid_hash_value >> lbid_hash_offset);
   1331 		
   1332         hash_Base->rtag7_lbid_hash = (lbid_hash_value & 0xff);
   1333         hash_Base->lbid_hash_valid = TRUE;
   1334 
   1335     } else { /* LBID rtag is 0-6 */        
   1336         /* this function not support the rtag 0-6 */
   1337 		
   1338         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1339                     (BSL_META_U(unit,
   1340                                 "Hash calculation: This function doesn't support rtag 0 6 pls change register ING_CONFIG.LBID_RTAG to value 7\n")));
   1341         hash_Base->rtag7_lbid_hash = 0;
   1342         hash_Base->lbid_hash_valid = FALSE;
   1343     }
   1344     return rv;
   1345     /* ******************* END of LBID computation ************************* */
   1346 }
   1347 
   1348 #ifdef INCLUDE_L3
   1349 STATIC int
   1350 compute_ecmp_hash(int unit, bcm_rtag7_base_hash_t *hash_Base,
   1351                   uint32 *hash_val)
   1352 {
   1353     /*regular var declaration*/
   1354     uint32 hash_sub_sel;
   1355     uint32 hash_offset;
   1356     uint32 hash_subfield;
   1357     uint32 rtag7_ecmp_hash_value;
   1358     uint8 rtag7_ecmp_use_macro_flow_hash;
   1359     uint8 ecmp_hash_16bits;
   1360     uint8 ecmp_hash_use_rtag7;
   1361     uint32 rtag7_hash_ecmp;
   1362     uint32 ing_config_2, hash_control;
   1363     int pc_out, ecmp_idx;
   1364     rtag7_flow_based_hash_entry_t rt7_fbh_entry;
   1365 
   1366     /*register read*/
   1367     BCM_IF_ERROR_RETURN
   1368         (bcm_esw_port_control_get(unit, hash_Base->dev_src_port,
   1369                                   bcmPortControlECMPHashSet,
   1370                                   &pc_out));
   1371     ecmp_idx = (0 != pc_out) ? 1 : 0;
   1372 
   1373     SOC_IF_ERROR_RETURN
   1374         (READ_RTAG7_HASH_ECMPr(unit, ecmp_idx, &rtag7_hash_ecmp));
   1375     if (soc_reg_field_valid(unit, RTAG7_HASH_ECMPr, USE_FLOW_HASHf)) {
   1376         rtag7_ecmp_use_macro_flow_hash =
   1377             soc_reg_field_get(unit, RTAG7_HASH_ECMPr,
   1378                               rtag7_hash_ecmp, USE_FLOW_HASHf);
   1379     } else {
   1380         /* A0 bincomp value */
   1381         rtag7_ecmp_use_macro_flow_hash = 0;
   1382     }
   1383 
   1384     if (SOC_REG_IS_VALID(unit, ING_CONFIG_2r)) {
   1385         SOC_IF_ERROR_RETURN
   1386             (READ_ING_CONFIG_2r(unit, &ing_config_2));
   1387         ecmp_hash_16bits =
   1388             soc_reg_field_get(unit, ING_CONFIG_2r, ing_config_2,
   1389                               ECMP_HASH_16BITSf);
   1390     } else {
   1391         ecmp_hash_16bits = 0;
   1392     }
   1393 
   1394     SOC_IF_ERROR_RETURN
   1395         (READ_HASH_CONTROLr(unit, &hash_control));
   1396     ecmp_hash_use_rtag7 =
   1397         soc_reg_field_get(unit, HASH_CONTROLr, hash_control,
   1398                           ECMP_HASH_USE_RTAG7f);
   1399 
   1400     /* RTAG7 hash computation */
   1401 
   1402     if (rtag7_ecmp_use_macro_flow_hash) {
   1403         SOC_IF_ERROR_RETURN
   1404             (soc_mem_read(unit, RTAG7_FLOW_BASED_HASHm, MEM_BLOCK_ANY,
   1405                           (hash_Base->rtag7_macro_flow_id & 0xff),
   1406                           &rt7_fbh_entry));
   1407 
   1408         /* Generating RTAG7 Macro Flow Based Hash Subsel and Offset for use in RSEL1 Stage */
   1409         /* For future designs this logic can be placed in RSEL1 */
   1410 
   1411         hash_sub_sel = soc_mem_field32_get(unit, RTAG7_FLOW_BASED_HASHm,
   1412                                            &rt7_fbh_entry, SUB_SEL_ECMPf);
   1413         hash_offset  = soc_mem_field32_get(unit, RTAG7_FLOW_BASED_HASHm,
   1414                                            &rt7_fbh_entry, OFFSET_ECMPf);
   1415 
   1416     } else if (SOC_REG_IS_VALID(unit, RTAG7_HASH_ECMPr)) {
   1417         hash_sub_sel =
   1418             soc_reg_field_get(unit, RTAG7_HASH_ECMPr,
   1419                               rtag7_hash_ecmp, SUB_SELf);
   1420         hash_offset =
   1421             soc_reg_field_get(unit, RTAG7_HASH_ECMPr,
   1422                               rtag7_hash_ecmp, OFFSETf);
   1423     } else {
   1424         /* A0 bincomp values */
   1425         hash_sub_sel = 0;
   1426         hash_offset  = 0;
   1427     }
   1428 
   1429     BCM_IF_ERROR_RETURN
   1430         (select_hash_subfield(hash_sub_sel, &hash_subfield, hash_Base));
   1431 
   1432     if (ecmp_hash_16bits) {
   1433         /* Barrel shift the hash subfield, then take the LSB 16 bits */
   1434         rtag7_ecmp_hash_value = ((hash_subfield >> hash_offset) | (hash_subfield << (16 - hash_offset))) & 0xffff; 
   1435     } else {
   1436         /* Trident-A0/A1 ECMP mode - SDK restricts to 256 members or less */
   1437         /* Barrel shift the hash subfield, then take the LSB 10 bits */
   1438         rtag7_ecmp_hash_value = ((hash_subfield >> hash_offset) | (hash_subfield << (16 - hash_offset))) & 0x3ff; 
   1439     }
   1440 	
   1441     /* Select between non-RTAG7 hash value and RTAG7 hash value */
   1442 
   1443     if (ecmp_hash_use_rtag7 == 0) {
   1444         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1445                     (BSL_META_U(unit,
   1446                                 "Hash calculation:  non rtag7 calc not supported\n")));
   1447         *hash_val =  0;
   1448     } else {
   1449         *hash_val =  rtag7_ecmp_hash_value;
   1450     }
   1451 
   1452     return BCM_E_NONE;
   1453     /* ***************** END of ECMP HASH CALCULATIONS.  ************************ */
   1454 }
   1455 #endif /* INCLUDE_L3 */
   1456 
   1457 STATIC int
   1458 compute_rtag7_hash_trunk(int unit , bcm_rtag7_base_hash_t *hash_Base,
   1459                          uint32 *hash_value)
   1460 {
   1461     uint32 hash_sub_sel;
   1462     uint32 hash_offset;    
   1463     uint32 hash_subfield;
   1464     uint32 rtag7_hash_trunk;
   1465     uint32 rtag7_hash_trunk_value;
   1466     int offset_shift;
   1467     int pc_out, trunk_idx;
   1468     uint32 hash_control;
   1469     uint32 nuc_trunk_hash_use_rtag7;
   1470 
   1471     BCM_IF_ERROR_RETURN
   1472         (bcm_esw_port_control_get(unit, hash_Base->dev_src_port,
   1473                                   bcmPortControlTrunkHashSet,
   1474                                   &pc_out));
   1475     trunk_idx = (0 != pc_out) ? 1 : 0;
   1476     SOC_IF_ERROR_RETURN
   1477         (READ_RTAG7_HASH_TRUNKr(unit, trunk_idx, &rtag7_hash_trunk));
   1478 
   1479     /* Compute RTAG7 hash for trunking */
   1480     if(hash_Base->is_nonuc) {
   1481         hash_sub_sel =
   1482             soc_reg_field_get(unit, RTAG7_HASH_TRUNKr,
   1483                               rtag7_hash_trunk, SUB_SEL_NONUCf);
   1484         hash_offset =
   1485             soc_reg_field_get(unit, RTAG7_HASH_TRUNKr,
   1486                               rtag7_hash_trunk, OFFSET_NONUCf);
   1487         offset_shift = 0xff;
   1488     } else {
   1489         hash_sub_sel =
   1490             soc_reg_field_get(unit, RTAG7_HASH_TRUNKr,
   1491                               rtag7_hash_trunk, SUB_SEL_UCf);
   1492         hash_offset =
   1493             soc_reg_field_get(unit, RTAG7_HASH_TRUNKr,
   1494                               rtag7_hash_trunk, OFFSET_UCf);
   1495         offset_shift = 0x3ff;
   1496     }        
   1497 
   1498     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1499                 (BSL_META_U(unit,
   1500                             "Trunk hash_seb_sel=%d, hash_offset=%d\n"),
   1501                 hash_sub_sel, hash_offset));
   1502     BCM_IF_ERROR_RETURN
   1503         (select_hash_subfield(hash_sub_sel, &hash_subfield, hash_Base));
   1504 
   1505     /* Barrel shift the hash subfield, then take the LSB 10 bits for UC and 8 bits for nonUC */
   1506     rtag7_hash_trunk_value = ((hash_subfield >> hash_offset) | (hash_subfield << (16 - hash_offset))) & offset_shift; 
   1507 	
   1508     /* Compute the trunk_member_table index
   1509      *  trunk_index = trunk_hash % (trunk_group_size + 1);
   1510      *   Irsel2_rsel2__trunk_member_table_index =
   1511      *        (trunk_base_ptr + trunk_index) & 0x7ff;
   1512      */
   1513 
   1514     *hash_value = rtag7_hash_trunk_value;
   1515 
   1516     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1517                 (BSL_META_U(unit,
   1518                             "Trunk hash_value=%d\n"),
   1519                  *hash_value));
   1520 
   1521     BCM_IF_ERROR_RETURN
   1522         (READ_HASH_CONTROLr(unit, &hash_control));
   1523     nuc_trunk_hash_use_rtag7 =
   1524         soc_reg_field_get(unit, HASH_CONTROLr, hash_control,
   1525                           NON_UC_TRUNK_HASH_USE_RTAG7f);
   1526 
   1527     if (hash_Base->is_nonuc && nuc_trunk_hash_use_rtag7 == 0) {
   1528         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1529                     (BSL_META_U(unit,
   1530                                 "NonUC trunk Hash calculation:  non rtag7 calc not supported\n")));
   1531         *hash_value = 0;
   1532     }
   1533 
   1534     return BCM_E_NONE;
   1535 }
   1536  
   1537 STATIC int
   1538 get_hash_trunk(int unit, int tgid, uint32 hash_index, bcm_gport_t *dst_gport)
   1539 {
   1540     uint32 trunk_base;
   1541     uint32 trunk_group_size;    
   1542     uint32 rtag;
   1543     uint32 trunk_index;
   1544     uint32 trunk_member_table_index;
   1545     bcm_module_t mod_id;
   1546     bcm_port_t port_id;
   1547     int mod_is_local;
   1548     trunk_member_entry_t trunk_member_entry;
   1549     trunk_group_entry_t  tg_entry;
   1550     _bcm_gport_dest_t   dest;
   1551     
   1552     BCM_IF_ERROR_RETURN
   1553         (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tgid, &tg_entry));
   1554 
   1555     trunk_base = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, BASE_PTRf);
   1556     trunk_group_size = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry,
   1557                                                     TG_SIZEf);
   1558     rtag = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, RTAGf);
   1559                 
   1560     if (rtag != 7){
   1561          LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1562                      (BSL_META_U(unit,
   1563                                  "Hash calculation: uport only RTAG7 calc no support for rtag %d\n"),
   1564                       rtag));
   1565     }
   1566 
   1567     trunk_index = hash_index % (trunk_group_size + 1);
   1568     trunk_member_table_index = (trunk_base + trunk_index) & 0x7ff;
   1569     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1570                 (BSL_META_U(unit,
   1571                             "\tTrunk HW index 0x%08x\n"),
   1572                  trunk_index));
   1573     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1574                 (BSL_META_U(unit,
   1575                             "\tTrunk group size 0x%08x\n"),
   1576                  trunk_group_size));
   1577 
   1578 
   1579     BCM_IF_ERROR_RETURN
   1580         (READ_TRUNK_MEMBERm(unit, MEM_BLOCK_ANY, trunk_member_table_index,
   1581                             &trunk_member_entry));
   1582 
   1583     mod_id = soc_TRUNK_MEMBERm_field32_get(unit, &trunk_member_entry,
   1584                                            MODULE_IDf);
   1585     port_id = soc_TRUNK_MEMBERm_field32_get(unit, &trunk_member_entry,
   1586                                             PORT_NUMf);
   1587 
   1588     BCM_IF_ERROR_RETURN
   1589         (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, mod_id, port_id,
   1590                                         &(dest.modid), &(dest.port)));
   1591     dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   1592 
   1593     BCM_IF_ERROR_RETURN
   1594         (_bcm_esw_modid_is_local(unit, dest.modid,
   1595                                  &mod_is_local));
   1596     if (mod_is_local) {
   1597         if (IS_ST_PORT(unit, port_id)) {
   1598             dest.modid = mod_id;
   1599             dest.port = port_id;
   1600             dest.gport_type = _SHR_GPORT_TYPE_DEVPORT;
   1601         }
   1602     }
   1603 
   1604     BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, dst_gport));
   1605 
   1606     return BCM_E_NONE;  
   1607 }
   1608 
   1609 /*
   1610  * Function:
   1611  *     get_hash_trunk_nuc
   1612  * Description:
   1613  *     Compute non-unicast destination trunk member port 
   1614  * Parameters:
   1615  *  unit - StrataSwitch PCI device unit number (driver internal).
   1616  *  tgid - Trunk group id
   1617  *  fwd_reason - Flow foward reason. unicast, ipmc, l2mc, broadcast, dlf.
   1618  *  hash_index - Hash value calculated based on RTAG7
   1619  *  dst_gport  - Where egress member port id is stored
   1620  *
   1621  * Returns:
   1622  *      BCM_E_xxxx
   1623  */
   1624 STATIC int
   1625 get_hash_trunk_nuc(int unit, int tgid, 
   1626                    bcm_switch_pkt_hash_info_fwd_reason_t fwd_reason, 
   1627                    uint32 hash_index, bcm_gport_t *dst_gport)
   1628 {
   1629     int nuc_type, nuc_tbm_index;
   1630     int modid, port;
   1631     bcm_pbmp_t local_pbmp, block_mask_pbmp;
   1632     trunk_bitmap_entry_t trunk_bitmap_entry;
   1633     nonucast_trunk_block_mask_entry_t mask_entry;
   1634     uint32 disable_flags = BCM_TRUNK_MEMBER_EGRESS_DISABLE;
   1635 
   1636     switch(fwd_reason) {
   1637     case bcmSwitchPktHashInfoFwdReasonIpmc:
   1638         nuc_type = TRUNK_BLOCK_MASK_TYPE_IPMC;
   1639         disable_flags |= BCM_TRUNK_MEMBER_IPMC_EGRESS_DISABLE;
   1640         break;
   1641     case bcmSwitchPktHashInfoFwdReasonL2mc:
   1642         nuc_type = TRUNK_BLOCK_MASK_TYPE_L2MC;
   1643         disable_flags |= BCM_TRUNK_MEMBER_L2MC_EGRESS_DISABLE;
   1644         break;
   1645     case bcmSwitchPktHashInfoFwdReasonBcast:
   1646         nuc_type = TRUNK_BLOCK_MASK_TYPE_BCAST;
   1647         disable_flags |= BCM_TRUNK_MEMBER_BCAST_EGRESS_DISABLE;
   1648         break;
   1649     case bcmSwitchPktHashInfoFwdReasonDlf:
   1650         nuc_type = TRUNK_BLOCK_MASK_TYPE_DLF;
   1651         disable_flags |= BCM_TRUNK_MEMBER_DLF_EGRESS_DISABLE;
   1652         break;
   1653     default:
   1654         return BCM_E_PARAM;
   1655     }
   1656     nuc_tbm_index = (nuc_type << 8) | (hash_index & 0xff);
   1657 
   1658     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1659                 (BSL_META_U(unit,
   1660                             "Nonuc-trunk table index = %d\n"), 
   1661                  nuc_tbm_index));
   1662 
   1663     BCM_IF_ERROR_RETURN(
   1664         READ_NONUCAST_TRUNK_BLOCK_MASKm(unit, MEM_BLOCK_ANY,
   1665                                         nuc_tbm_index, &mask_entry));
   1666     soc_mem_pbmp_field_get(unit, NONUCAST_TRUNK_BLOCK_MASKm, &mask_entry, 
   1667                            BLOCK_MASKf, &block_mask_pbmp);
   1668     BCM_IF_ERROR_RETURN(
   1669         READ_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, tgid, &trunk_bitmap_entry));
   1670     soc_mem_pbmp_field_get(unit, TRUNK_BITMAPm, &trunk_bitmap_entry,
   1671                            TRUNK_BITMAPf, &local_pbmp);
   1672 
   1673     BCM_PBMP_REMOVE(local_pbmp, block_mask_pbmp);
   1674 
   1675     if (BCM_PBMP_IS_NULL(local_pbmp)) {
   1676         /* this means that member is not on local device, try SW prediction */
   1677         bcm_trunk_member_t member_array[BCM_TRUNK_MAX_PORTCNT];
   1678         int member_count;
   1679         bcm_gport_t *port_array = NULL;
   1680         int port_count, port_index;
   1681         int region_size, i, all_local;
   1682 
   1683         BCM_IF_ERROR_RETURN
   1684             (bcm_esw_trunk_get(unit, tgid, NULL, BCM_TRUNK_MAX_PORTCNT, 
   1685                                member_array, &member_count));
   1686 
   1687         port_array = sal_alloc(member_count * sizeof(bcm_gport_t),
   1688                                "port_array");
   1689         if (port_array == NULL) {
   1690             return BCM_E_MEMORY;
   1691         }
   1692 
   1693         port_count = 0;
   1694         all_local = TRUE;
   1695         for (i = 0; i < member_count; i++) {
   1696             if (member_array[i].flags & disable_flags) {
   1697                 continue;
   1698             }
   1699             port = member_array[i].gport;
   1700             port_array[port_count++] = port;
   1701             if (all_local) {
   1702                 if (BCM_FAILURE(bcm_esw_port_local_get(unit, port, &port))) {
   1703                     all_local = FALSE;
   1704                 }
   1705             }
   1706         }
   1707         /* All ports are disabled */
   1708         if (port_count == 0) {
   1709             *dst_gport = -1;
   1710             sal_free(port_array);
   1711             return BCM_E_NOT_FOUND;
   1712         }
   1713         region_size = soc_mem_index_count(unit, NONUCAST_TRUNK_BLOCK_MASKm) / 4;
   1714         if (all_local || port_count > BCM_SWITCH_TRUNK_MAX_PORTCNT) {
   1715             port_index = (nuc_tbm_index % region_size) % port_count;
   1716         } else {
   1717             port_index = (nuc_tbm_index % BCM_XGS3_TRUNK_MAX_PORTCNT) % port_count;
   1718         }
   1719         
   1720         *dst_gport = port_array[port_index];
   1721 
   1722         sal_free(port_array);
   1723 
   1724     } else {
   1725         _bcm_gport_dest_t   dest;
   1726 
   1727         /*Each index only has one egress port */
   1728         BCM_PBMP_ITER(local_pbmp, port) {
   1729             break;
   1730         }
   1731         
   1732         if (port == BCM_PBMP_PORT_MAX) {
   1733             /* If not found in iteration, return not found. It never be here */
   1734             *dst_gport = -1;
   1735             return BCM_E_NOT_FOUND;
   1736         }
   1737 
   1738         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid));
   1739 
   1740         BCM_IF_ERROR_RETURN
   1741             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port,
   1742                                             &(dest.modid), &(dest.port)));
   1743         if (IS_ST_PORT(unit, port)) {
   1744             dest.modid = modid;
   1745             dest.port = port;
   1746             dest.gport_type = _SHR_GPORT_TYPE_DEVPORT;
   1747         } else {
   1748             dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   1749         }
   1750 
   1751         BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, dst_gport));
   1752     } 
   1753  
   1754     return BCM_E_NONE;
   1755 }
   1756 
   1757 #ifdef INCLUDE_L3
   1758 STATIC int
   1759 get_hash_ecmp(int unit, int ecmp_group, uint32 hash_index, bcm_if_t *nh_id)
   1760 {
   1761     uint8 ecmp_hash_16bits;
   1762     uint32 ecmp_hash_field_upper_bits_count;
   1763                 
   1764     ecmp_count_entry_t ecmpc_entry;
   1765     ecmp_entry_t ecmp_entry;
   1766     uint32 ecmp_ptr = 0;
   1767     uint32 ecmp_count = 0;
   1768     uint32 ing_config_2, hash_control;
   1769                 
   1770     uint32 ecmp_mask;
   1771     uint32 ecmp_offset;
   1772     uint32 ecmp_index;
   1773 
   1774     /*register read*/
   1775     if (SOC_REG_IS_VALID(unit, ING_CONFIG_2r)) {
   1776         SOC_IF_ERROR_RETURN
   1777             (READ_ING_CONFIG_2r(unit, &ing_config_2));
   1778         ecmp_hash_16bits =
   1779             soc_reg_field_get(unit, ING_CONFIG_2r, ing_config_2,
   1780                               ECMP_HASH_16BITSf);
   1781     } else {
   1782         ecmp_hash_16bits = 0;
   1783     }
   1784 
   1785     if (SOC_REG_FIELD_VALID(unit, HASH_CONTROLr,
   1786                             ECMP_HASH_FIELD_UPPER_BITS_COUNTf)) {
   1787         SOC_IF_ERROR_RETURN
   1788             (READ_HASH_CONTROLr(unit, &hash_control));
   1789         ecmp_hash_field_upper_bits_count =
   1790             soc_reg_field_get(unit, HASH_CONTROLr, hash_control,
   1791                               ECMP_HASH_FIELD_UPPER_BITS_COUNTf);
   1792     } else {
   1793         ecmp_hash_field_upper_bits_count = 0x6; /* A0 bincomp value */
   1794     }
   1795                 
   1796     /* pick up the ecmp count and base_ptr */
   1797     /* Trident+ ECMP Mode where ECMP resolution is done in one step using a 16Mod10 */
   1798     BCM_IF_ERROR_RETURN
   1799         (READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY, ecmp_group, &ecmpc_entry));
   1800 
   1801     /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   1802      * A ECMP_COUNT value of 0 implies 1 entry 
   1803      * a value of 1 implies 2 entries etc...
   1804      * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   1805      */
   1806      /* ECMP Mask is expected to be set to 0x3ff for TridentA0/A1 mode */
   1807     if (ecmp_hash_16bits == 0) {
   1808         /* Trident-A0/A1 ECMP mode - SDK restricts to 256 members or less */
   1809         ecmp_mask = 0x3ff;
   1810         ecmp_count =
   1811             soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry,
   1812                                            COUNT_0f);
   1813         ecmp_ptr =
   1814             soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry,
   1815                                            BASE_PTR_0f);
   1816    } else {
   1817         ecmp_ptr = soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry,
   1818                                                   BASE_PTRf);
   1819         ecmp_count = soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry,
   1820                                                   COUNTf);
   1821         switch (ecmp_hash_field_upper_bits_count) {
   1822         case 0:
   1823             ecmp_mask = 0x3ff;
   1824             break;
   1825         case 1:
   1826             ecmp_mask = 0x7ff;
   1827             break;
   1828         case 2:
   1829             ecmp_mask = 0xfff;
   1830             break;
   1831         case 3:
   1832             ecmp_mask = 0x1fff;
   1833             break;
   1834         case 4:
   1835             ecmp_mask = 0x3fff;
   1836             break;
   1837         case 5:
   1838             ecmp_mask = 0x7fff;
   1839             break;
   1840         case 6:
   1841             ecmp_mask = 0xffff;
   1842             break;
   1843         default:
   1844             ecmp_mask = 0xffff;
   1845             break;
   1846         }
   1847     }
   1848 
   1849     ecmp_offset = ((hash_index & ecmp_mask) % (ecmp_count + 1)) & 0x3FF;
   1850     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1851                 (BSL_META_U(unit,
   1852                             "\tECMP offset 0x%08x\n"),
   1853                  ecmp_offset));
   1854     ecmp_index = (ecmp_ptr + ecmp_offset) & 0xfff;
   1855     BCM_IF_ERROR_RETURN
   1856         (READ_L3_ECMPm(unit, MEM_BLOCK_ANY, ecmp_index, &ecmp_entry));
   1857 
   1858     *nh_id =
   1859         soc_L3_ECMPm_field32_get(unit, &ecmp_entry,
   1860                                  NEXT_HOP_INDEXf) & 0x3fff;
   1861     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1862                 (BSL_META_U(unit,
   1863                             "\tECMP next hop HW index 0x%08x\n"),
   1864                  *nh_id));
   1865 
   1866     return BCM_E_NONE;  
   1867 }
   1868 #endif /* INCLUDE_L3 */
   1869 
   1870 int
   1871 _bcm_switch_pkt_info_ecmp_hash_get(int unit,
   1872                                    bcm_switch_pkt_info_t *pkt_info,
   1873                                    bcm_gport_t *dst_gport,
   1874                                    bcm_if_t *dst_intf)
   1875 {
   1876     bcm_rtag7_base_hash_t hash_res;
   1877     int pc_out;
   1878     bcm_gport_t     port;
   1879     bcm_trunk_t     tid;
   1880     int             id;
   1881     uint32          hash_value;
   1882 
   1883     if (pkt_info == NULL) {
   1884         return BCM_E_PARAM;
   1885     }
   1886 
   1887     if (!_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_GPORT)) {
   1888         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1889                     (BSL_META_U(unit,
   1890                                 "Hash calculation: source gport value missing\n")));
   1891         return BCM_E_PARAM;
   1892     }
   1893 
   1894     BCM_IF_ERROR_RETURN
   1895         (_bcm_esw_gport_resolve(unit, pkt_info->src_gport,
   1896                                 &(hash_res.src_modid),
   1897                                 &(hash_res.src_port), 
   1898                                 &tid, &id));
   1899     if ((-1 != id) || (-1 != tid)) {
   1900         /* Must be single system port */
   1901         return BCM_E_PORT;
   1902     }
   1903 
   1904     /* If dual module mode enable, mod/port should be in PORT32 format */
   1905     BCM_IF_ERROR_RETURN
   1906         (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   1907                                  hash_res.src_modid, hash_res.src_port,
   1908                                  &hash_res.src_modid, &hash_res.src_port));
   1909     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1910                 (BSL_META_U(unit,
   1911                             "src_gport=0x%x, src_modid = %d, src_port=%d\n"),
   1912                 pkt_info->src_gport, hash_res.src_modid, hash_res.src_port));
   1913 
   1914     /* Load balancing retrieval */
   1915     BCM_IF_ERROR_RETURN
   1916         (bcm_esw_port_local_get(unit, pkt_info->src_gport, &port));
   1917     hash_res.dev_src_port = port;
   1918     BCM_IF_ERROR_RETURN
   1919         (bcm_esw_port_control_get(unit, port,
   1920                                   bcmPortControlLoadBalancingNumber,
   1921                                   &pc_out)); 
   1922     hash_res.rtag7_port_lbn = pc_out;
   1923 
   1924     /* check if the foward reason of packet is all non-uc packet or bit 40 in the mac DA is one. */
   1925     hash_res.is_nonuc = pkt_info->fwd_reason || BCM_MAC_IS_MCAST(pkt_info->dst_mac);
   1926 
   1927     BCM_IF_ERROR_RETURN
   1928         (main__do_rtag7_hashing(unit, pkt_info, &hash_res));
   1929     BCM_IF_ERROR_RETURN
   1930         (main__compute_lbid(unit, &hash_res));
   1931 
   1932     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1933                 (BSL_META_U(unit,
   1934                             "Hash status: \n")));
   1935     if (hash_res.hash_a_valid) {
   1936         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1937                     (BSL_META_U(unit,
   1938                                 "\tRTAG7 A0 0x%08x\n"),
   1939                      hash_res.rtag7_hash16_value_a_0));
   1940         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1941                     (BSL_META_U(unit,
   1942                                 "\tRTAG7 A1 0x%08x\n"),
   1943                      hash_res.rtag7_hash16_value_a_1));
   1944     } else {
   1945         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1946                     (BSL_META_U(unit,
   1947                                 "\tRTAG7 A hashes invalid due to missing packet info\n")));
   1948     }
   1949     if (hash_res.hash_b_valid) {
   1950         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1951                     (BSL_META_U(unit,
   1952                                 "\tRTAG7 B0 0x%08x\n"),
   1953                      hash_res.rtag7_hash16_value_b_0));
   1954         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1955                     (BSL_META_U(unit,
   1956                                 "\tRTAG7 B1 0x%08x\n"),
   1957                      hash_res.rtag7_hash16_value_b_1));
   1958     } else {
   1959         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1960                     (BSL_META_U(unit,
   1961                                 "\tRTAG7 B hashes invalid due to missing packet info\n")));
   1962     }
   1963     LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1964                 (BSL_META_U(unit,
   1965                             "\tRTAG7 LBN 0x%08x\n"),
   1966                  hash_res.rtag7_port_lbn));
   1967     if (hash_res.lbid_hash_valid){
   1968         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1969                     (BSL_META_U(unit,
   1970                                 "\tRTAG7 LBID 0x%08x\n"),
   1971                      hash_res.rtag7_lbid_hash));
   1972     } else {
   1973         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1974                     (BSL_META_U(unit,
   1975                                 "\tRTAG7 LBID not valid due to non-RTAG7 configuration\n")));
   1976     }
   1977 
   1978 #ifdef INCLUDE_L3
   1979     if (0 != (pkt_info->flags & BCM_SWITCH_PKT_INFO_HASH_MULTIPATH)) {
   1980         bcm_if_t        nh_id;
   1981 
   1982         if (dst_intf == NULL) {
   1983             return BCM_E_PARAM;
   1984         }
   1985         
   1986         BCM_IF_ERROR_RETURN
   1987             (compute_ecmp_hash(unit, &hash_res, &hash_value));
   1988         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1989                     (BSL_META_U(unit,
   1990                                 "\tECMP Hash value 0x%08x\n"),
   1991                      hash_value));
   1992 
   1993         BCM_IF_ERROR_RETURN
   1994             (get_hash_ecmp(unit,
   1995                            pkt_info->mpintf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit),
   1996                            hash_value, &nh_id));
   1997         /* Convert to egress object format */
   1998         *dst_intf = nh_id + BCM_XGS3_EGRESS_IDX_MIN(unit);
   1999     } else
   2000 #endif /* INCLUDE_L3 */
   2001     if (0 != (pkt_info->flags & BCM_SWITCH_PKT_INFO_HASH_TRUNK)) {
   2002         bcm_trunk_t trunk = BCM_TRUNK_INVALID;
   2003         int member_count;
   2004         bcm_trunk_chip_info_t   ti;
   2005 
   2006         if (dst_gport == NULL) {
   2007             return BCM_E_PARAM;
   2008         }
   2009         
   2010         if (!BCM_GPORT_IS_TRUNK(pkt_info->trunk_gport)) {
   2011             return BCM_E_PORT;
   2012         }
   2013         trunk = BCM_GPORT_TRUNK_GET(pkt_info->trunk_gport);
   2014         BCM_IF_ERROR_RETURN
   2015             (bcm_esw_trunk_get(unit, trunk, NULL, 0, NULL, &member_count));
   2016         if (0 == member_count) {
   2017             /* Return failure for no trunk members */
   2018             return BCM_E_FAIL;
   2019         }
   2020 
   2021         BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &ti));
   2022 
   2023         if (trunk >= ti.trunk_id_min && trunk <= ti.trunk_id_max) {
   2024             BCM_IF_ERROR_RETURN
   2025                 (compute_rtag7_hash_trunk(unit, &hash_res, &hash_value));
   2026             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2027                         (BSL_META_U(unit,
   2028                                     "\tTrunk Hash value 0x%08x\n"),
   2029                          hash_value));
   2030 
   2031             if (hash_res.is_nonuc) {
   2032                 BCM_IF_ERROR_RETURN
   2033                     (get_hash_trunk_nuc(unit, trunk, pkt_info->fwd_reason, 
   2034                                 hash_value, dst_gport));
   2035             } else {
   2036                 BCM_IF_ERROR_RETURN
   2037                     (get_hash_trunk(unit, trunk,
   2038                                 hash_value, dst_gport));
   2039             }
   2040         } else {
   2041             return BCM_E_UNAVAIL;
   2042         }
   2043     } else if (pkt_info->flags & BCM_SWITCH_PKT_INFO_HASH_LBID) {
   2044         /* LBID hashing resolution */
   2045         if (dst_intf == NULL || hash_res.lbid_hash_valid == 0) {
   2046             return BCM_E_FAIL;
   2047         } else {
   2048             *dst_intf = hash_res.rtag7_lbid_hash;
   2049         }
   2050     } else {
   2051         return BCM_E_PARAM;
   2052     }
   2053 	
   2054     return BCM_E_NONE;
   2055 }