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

lpm.c (59136B)


      1 /*
      2  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      3  * 
      4  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      5  *
      6  * File:    lpm.c
      7  * Purpose: Trident3 L3 LPM specific functions
      8  */
      9 
     10 #include <shared/bsl.h>
     11 
     12 #include <bcm/error.h>
     13 #include <soc/defs.h>
     14 #include <soc/drv.h>
     15 
     16 #if defined(INCLUDE_L3) && defined(BCM_TRIDENT3_SUPPORT) 
     17 
     18 #include <bcm/l3.h>
     19 #include <soc/lpm.h>
     20 #include <soc/format.h>
     21 #include <soc/esw/flow_db.h>
     22 #include <bcm_int/esw/lpmv6.h>
     23 #include <bcm_int/esw/trident3.h>
     24 #include <bcm_int/esw/flow.h>
     25 
     26 /*
     27  * Function:    
     28  *     _bcm_defip_pair128_flex_ip6_addr_set
     29  * Purpose:  
     30  *     Set IP6 address field in memory from ip6 addr type. 
     31  * Parameters: 
     32  *     unit  - (IN) BCM device number. 
     33  *     mem   - (IN) view id.
     34  *     entry - (IN) HW entry buffer.
     35  *     ip6   - (IN) SW ip6 address buffer.
     36  * Returns:      void
     37  */
     38 STATIC void
     39 _bcm_defip_pair128_flex_ip6_addr_set(int unit, soc_mem_t view_id, uint32 *entry, 
     40                                 const ip6_addr_t ip6)
     41 {
     42     uint32              ip6_field[4];
     43 
     44     if (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__DIPf)) {
     45         soc_mem_ip6_addr_set(unit, view_id, entry,IPV6__DIPf, ip6, 0);
     46     } else if (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__SIPf)) {
     47         soc_mem_ip6_addr_set(unit, view_id, entry,IPV6__SIPf, ip6, 0);
     48     } else {
     49         ip6_field[3] = ((ip6[12] << 24)| (ip6[13] << 16) |
     50                     (ip6[14] << 8) | (ip6[15] << 0));
     51         soc_mem_field32_set(unit, view_id, entry, IP_ADDR0_LWRf, ip6_field[3]);
     52         ip6_field[2] = ((ip6[8] << 24) | (ip6[9] << 16) |
     53                     (ip6[10] << 8) | (ip6[11] << 0));
     54         soc_mem_field32_set(unit, view_id, entry, IP_ADDR1_LWRf, ip6_field[2]);
     55         ip6_field[1] = ((ip6[4] << 24) | (ip6[5] << 16) |
     56                     (ip6[6] << 8)  | (ip6[7] << 0));
     57         soc_mem_field32_set(unit, view_id, entry, IP_ADDR0_UPRf, ip6_field[1]);
     58         ip6_field[0] = ((ip6[0] << 24) | (ip6[1] << 16) |
     59                     (ip6[2] << 8)  | (ip6[3] << 0));
     60         soc_mem_field32_set(unit, view_id, entry, IP_ADDR1_UPRf, ip6_field[0]);
     61     }
     62 }
     63 
     64 /*
     65  * Function:    
     66  *     _bcm_defip_pair128_flex_ip6_mask_set
     67  * Purpose:  
     68  *     Set IP6 mask field in memory from ip6 addr type. 
     69  * Parameters: 
     70  *     unit  - (IN) BCM device number. 
     71  *     mem   - (IN) View id.
     72  *     entry - (IN) HW entry buffer.
     73  *     ip6   - (IN) SW ip6 address buffer.
     74  * Returns:      void
     75  */
     76 STATIC void
     77 _bcm_defip_pair128_flex_ip6_mask_set(int unit, soc_mem_t view_id, uint32 *entry, 
     78                                 const ip6_addr_t ip6)
     79 {
     80     uint32              ip6_field[4];
     81 
     82     if (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__MASKf)) {
     83         soc_mem_ip6_addr_set(unit, view_id, entry,IPV6__MASKf, ip6, 0);
     84     } else {
     85         ip6_field[3] = ((ip6[12] << 24)| (ip6[13] << 16) |
     86                         (ip6[14] << 8) | (ip6[15] << 0));
     87         soc_mem_field32_set(unit, view_id, entry, IP_ADDR_MASK0_LWRf, ip6_field[3]);
     88         ip6_field[2] = ((ip6[8] << 24) | (ip6[9] << 16) |
     89                         (ip6[10] << 8) | (ip6[11] << 0));
     90         soc_mem_field32_set(unit, view_id, entry, IP_ADDR_MASK1_LWRf, ip6_field[2]);
     91         ip6_field[1] = ((ip6[4] << 24) | (ip6[5] << 16) |
     92                         (ip6[6] << 8)  | (ip6[7] << 0));
     93         soc_mem_field32_set(unit, view_id, entry, IP_ADDR_MASK0_UPRf, ip6_field[1]);
     94         ip6_field[0] = ((ip6[0] << 24) | (ip6[1] << 16) |
     95                         (ip6[2] << 8)  | (ip6[3] << 0));
     96         soc_mem_field32_set(unit, view_id, entry, IP_ADDR_MASK1_UPRf, ip6_field[0]);
     97     }
     98 }
     99 /*
    100  * Function:
    101  *      _bcm_defip_pair128_flex_entry_clear
    102  * Purpose:
    103  *      Clear/Reset a single flex route entry. 
    104  * Parameters:
    105  *      unit      - (IN)SOC unit number.
    106  *      view_id   - (IN)View ID number.
    107  *      hw_index  - (IN)Entry index in the tcam. 
    108  * Returns:
    109  *      BCM_E_XXX
    110  */
    111 STATIC int 
    112 _bcm_defip_pair128_flex_entry_clear(int unit, soc_mem_t view_id, int hw_index)  
    113 {
    114     uint32 hw_entry[SOC_MAX_MEM_FIELD_WORDS];
    115     soc_field_t key_field[4], mask_field[4];
    116     int field_count, i;
    117     uint64 val64;
    118     key_field[0] = KEY0_UPRf;
    119     key_field[1] = KEY1_UPRf;
    120     key_field[2] = KEY0_LWRf;
    121     key_field[3] = KEY1_LWRf;
    122     mask_field[0] = MASK0_UPRf;
    123     mask_field[1] = MASK1_UPRf;
    124     mask_field[2] = MASK0_LWRf;
    125     mask_field[3] = MASK1_LWRf;
    126     field_count = 4;
    127     sal_memset(hw_entry, 0, WORDS2BYTES(SOC_MAX_MEM_FIELD_WORDS));
    128     COMPILER_64_ZERO(val64);
    129     for (i = 0; i < field_count; i++) {
    130         if (SOC_MEM_FIELD_VALID(unit, view_id, key_field[i])) { 
    131             soc_mem_field64_set(unit, view_id, hw_entry, key_field[i], val64);
    132         }
    133         if (SOC_MEM_FIELD_VALID(unit, view_id, mask_field[i])) { 
    134             soc_mem_field64_set(unit, view_id, hw_entry, mask_field[i], val64);
    135         }
    136     }
    137 
    138     /* Reset hw entry. */
    139     BCM_IF_ERROR_RETURN
    140         (BCM_XGS3_MEM_WRITE(unit, view_id, hw_index,
    141                             &soc_mem_entry_null(unit, view_id)));
    142     BCM_IF_ERROR_RETURN
    143         (BCM_XGS3_MEM_WRITE(unit, view_id, hw_index, hw_entry));
    144 
    145     /* Reset sw entry. */
    146     BCM_DEFIP_PAIR128_ENTRY_SET(unit, hw_index, 0, 0);
    147 
    148     /* Reset urpf source lookup entry. */
    149     /* If soc_feature_l3_defip_advanced_lookup is TRUE then 
    150      * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
    151      * L3_DEFIP table is not divided into 2 to support URPF (Ex: KT2).
    152      */
    153     if (SOC_URPF_STATUS_GET(unit) &&
    154         !soc_feature(unit, soc_feature_l3_defip_advanced_lookup)) {
    155         BCM_IF_ERROR_RETURN
    156             (BCM_XGS3_MEM_WRITE(unit, view_id, 
    157                             (hw_index + BCM_DEFIP_PAIR128_URPF_OFFSET(unit)),
    158                             &soc_mem_entry_null(unit, view_id)));
    159         BCM_IF_ERROR_RETURN
    160             (BCM_XGS3_MEM_WRITE(unit, view_id, 
    161                  (hw_index+ BCM_DEFIP_PAIR128_URPF_OFFSET(unit)), hw_entry));
    162     }
    163     return (BCM_E_NONE);
    164 }
    165 /*
    166  * Function:
    167  *      _bcm_l3_defip_pair128_flex_add
    168  * Purpose:
    169  *      Add an flex entry to internal L3_DEFIP_PAIR_128 table.
    170  * Parameters:
    171  *      unit        - (IN)SOC unit number.
    172  *      lpm_cfg     - (IN)defip information. 
    173  *      view_id     - (IN)View ID number.
    174  *      hw_entry    - (IN)Buffer to fill defip information. 
    175  *      nh_ecmp_idx - (IN)Next hop or ecmp group index.
    176  * Returns:
    177  *      BCM_E_XXX
    178  */
    179 int
    180 _bcm_l3_defip_pair128_flex_add(int unit, _bcm_defip_cfg_t *lpm_cfg,
    181                               int nh_ecmp_idx, uint32 *hw_entry) 
    182 {
    183     bcm_ip6_t mask;                             /* Subnet mask.              */
    184     int hw_index = 0;                           /* Entry offset in the TCAM. */ 
    185     int rv = BCM_E_NONE;                        /* Operation return status.  */
    186 
    187     soc_mem_t view_id;
    188     int     i;
    189     uint32  field_array[128];
    190     uint32  field_count;
    191     uint32  opaque_array[16];
    192     uint32  opaque_count;
    193     bcm_flow_logical_field_t* user_fields;
    194 
    195     uint32 action_set = 0;
    196 
    197     uint8 process_destination = 0;
    198     uint8 process_class_id = 0;
    199     uint8 process_qos = 0;
    200     uint8 process_pim_sm = 0;
    201     uint8 process_fwd_attributes = 0;
    202     uint8 process_fwd_3_attributes = 0;
    203     soc_mem_t phy_mem;
    204 
    205     /* Input parameters check. */
    206     if (lpm_cfg == NULL) {
    207         return (BCM_E_PARAM);
    208     }
    209 
    210     /* Create mask from prefix length. */
    211     bcm_ip6_mask_create(mask, lpm_cfg->defip_sub_len);
    212 
    213     /* Apply mask on address. */
    214     bcm_xgs3_l3_mask6_apply(mask, lpm_cfg->defip_ip6_addr);
    215 
    216     /* Allocate a new index for inserted entry. */
    217     if (BCM_XGS3_L3_INVALID_INDEX == lpm_cfg->defip_index) {
    218         rv = _bcm_defip_pair128_idx_alloc(unit, lpm_cfg, &hw_index, nh_ecmp_idx);
    219         BCM_IF_ERROR_RETURN(rv);
    220     } else {
    221         hw_index = lpm_cfg->defip_index;
    222     }
    223 
    224     BCM_IF_ERROR_RETURN(
    225         soc_flow_db_ffo_to_mem_view_id_get(unit,
    226                           lpm_cfg->defip_flow_handle,
    227                           lpm_cfg->defip_flow_option_handle,
    228                           SOC_FLOW_DB_FUNC_L3_ROUTE_ID,
    229                           (uint32 *)&view_id));
    230 
    231     /* Initialize control field list for this view id. */
    232     rv = soc_flow_db_mem_view_entry_init(unit, view_id, hw_entry);
    233 
    234     BCM_IF_ERROR_RETURN(rv);
    235 
    236     /* Get logical KEY field list for this view id. */
    237     rv = soc_flow_db_mem_view_field_list_get(unit,
    238                             view_id,
    239                             SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY,
    240                             16,
    241                             opaque_array,
    242                             &opaque_count);
    243     BCM_IF_ERROR_RETURN(rv);
    244 
    245     user_fields = lpm_cfg->defip_logical_fields;
    246 
    247     for (i=0; i<opaque_count; i++) {
    248         if (user_fields[i].id == opaque_array[i]) {
    249             soc_mem_field32_set(unit, view_id, hw_entry, user_fields[i].id,
    250                                 user_fields[i].value);
    251         }
    252     }
    253 
    254     /* Get logical PDD field list for this view id. */
    255     rv = soc_flow_db_mem_view_field_list_get(unit,
    256                             view_id,
    257                             SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
    258                             16,
    259                             opaque_array,
    260                             &opaque_count);
    261 
    262     BCM_IF_ERROR_RETURN(rv);
    263 
    264     user_fields = lpm_cfg->defip_logical_fields;
    265 
    266     for (i=0; i<opaque_count; i++) {
    267         if (user_fields[i].id == opaque_array[i]) {
    268             soc_mem_field32_set(unit, view_id, hw_entry, user_fields[i].id,
    269                                 user_fields[i].value);
    270         }
    271     }
    272 
    273     /* Get PDD field list corresponding to the view id. */
    274     rv = soc_flow_db_mem_view_field_list_get(unit,
    275                             view_id,
    276                             SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA,
    277                             128,
    278                             field_array,
    279                             &field_count);
    280     BCM_IF_ERROR_RETURN(rv);
    281 
    282     for (i=0; i<field_count; i++) {
    283         switch (field_array[i]) {
    284             case DESTINATION_ACTION_SETf:
    285                 process_destination = 1;
    286                 break;
    287             case CLASS_ID_ACTION_SETf:
    288                 process_class_id = 1;
    289                 break;
    290             case QOS_ACTION_SETf:
    291                 process_qos = 1;
    292                 break;
    293             case FWD_ATTRIBUTES_ACTION_SETf:
    294                 process_fwd_attributes = 1;
    295                 break;
    296             case FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf:
    297                 process_fwd_3_attributes = 1;
    298                 break;
    299             case PIM_SM_ACTION_SETf:
    300                 process_pim_sm = 1;
    301                 break;
    302             default:
    303                 return BCM_E_INTERNAL;
    304         }       
    305     }
    306 
    307     /* Set hit bit. */
    308     if (lpm_cfg->defip_flags & BCM_L3_HIT) {
    309         if (SOC_MEM_FIELD_VALID(unit, view_id, HITf)) {
    310             soc_mem_field32_set(unit, view_id, hw_entry, HITf, 1);
    311         }
    312         if (SOC_MEM_FIELD_VALID(unit, view_id, HIT0f)) {
    313             soc_mem_field32_set(unit, view_id, hw_entry, HIT0f, 1);
    314         }
    315         if (SOC_MEM_FIELD_VALID(unit, view_id, HIT1f)) {
    316             soc_mem_field32_set(unit, view_id, hw_entry, HIT1f, 1);
    317         }
    318     }
    319 
    320     /* Set priority override bit. */
    321     action_set = 0;
    322 
    323     if (lpm_cfg->defip_flags & BCM_L3_RPE) {
    324         if (!process_qos) {
    325             return BCM_E_UNAVAIL;
    326         }
    327         soc_format_field32_set(unit, QOS_ACTION_SETfmt,
    328                                &action_set, RPEf, 1);
    329     }
    330     if (process_qos) {
    331         /* Write priority field. */
    332         soc_format_field32_set(unit, QOS_ACTION_SETfmt,
    333                            &action_set, PRIf, lpm_cfg->defip_prio);
    334 
    335         soc_mem_field32_set(unit, view_id, hw_entry,
    336                         QOS_ACTION_SETf, action_set);
    337     }
    338 
    339     /* Set classification group id. */
    340     if (process_class_id) {
    341         /* CLASS_IDf */
    342         soc_mem_field32_set(unit, view_id, hw_entry, CLASS_ID_ACTION_SETf,
    343                             lpm_cfg->defip_lookup_class);
    344     }
    345 
    346     /* Fill next hop information. */
    347     if (!process_destination) {
    348         return BCM_E_INTERNAL;
    349     }
    350 
    351     action_set = 0;
    352     if (lpm_cfg->defip_flags & BCM_L3_MULTIPATH) {
    353         soc_format_field32_set(unit, DESTINATION_FORMATfmt,
    354                            &action_set, DEST_TYPE1f, BCMI_TD3_DEST_TYPE1_ECMP);
    355         soc_format_field32_set(unit, DESTINATION_FORMATfmt,
    356                            &action_set, ECMP_GROUPf, nh_ecmp_idx);
    357     } else {
    358         soc_format_field32_set(unit, DESTINATION_FORMATfmt,
    359                            &action_set, DEST_TYPE0f, BCMI_TD3_DEST_TYPE0_NH);
    360         soc_format_field32_set(unit, DESTINATION_FORMATfmt,
    361                            &action_set, NEXT_HOP_INDEXf, nh_ecmp_idx);
    362     }
    363     soc_mem_field32_set(unit, view_id, hw_entry,
    364                         DESTINATION_ACTION_SETf, action_set);
    365 
    366     /* Set destination discard flag. */
    367     action_set = 0;
    368     if (lpm_cfg->defip_flags & BCM_L3_DST_DISCARD) {
    369         if (!process_fwd_attributes) {
    370             return BCM_E_UNAVAIL;
    371         }
    372         soc_format_field32_set(unit, FWD_ATTRIBUTES_ACTION_SETfmt,
    373                                &action_set, DST_DISCARDf, 1);
    374         soc_mem_field32_set(unit, view_id, hw_entry,
    375                              FWD_ATTRIBUTES_ACTION_SETf, action_set);
    376     }
    377 
    378     if (soc_feature(unit, soc_feature_ipmc_defip) &&
    379             (lpm_cfg->defip_flags & BCM_L3_IPMC)) {
    380 
    381         /* L3MC_INDEXf */
    382         action_set = 0;
    383         if (!process_pim_sm) {
    384             return BCM_E_UNAVAIL;
    385         }
    386 
    387         soc_format_field32_set(unit, DESTINATION_FORMATfmt,
    388                            &action_set, DEST_TYPE1f, BCMI_TD3_DEST_TYPE1_IPMC);
    389         soc_format_field32_set(unit, DESTINATION_FORMATfmt,
    390                            &action_set, IPMC_GROUPf, lpm_cfg->defip_mc_group);
    391         soc_mem_field32_set(unit, view_id, hw_entry,
    392                           DESTINATION_ACTION_SETf, action_set);
    393 
    394         /*
    395          * RP ID has be encoded to 14 bit value, Now it will fit in EXPECTED_L3_IIFf
    396          */
    397         action_set = 0;
    398         if (lpm_cfg->defip_l3a_rp != BCM_IPMC_RP_ID_INVALID) {
    399             soc_format_field32_set(unit, PIM_SM_ACTION_SETfmt,
    400                            &action_set, EXPECTED_L3_IIFf,
    401                            _BCM_DEFIP_IPMC_RP_SET(lpm_cfg->defip_l3a_rp));
    402 
    403         } else if ((lpm_cfg->defip_ipmc_flags & BCM_IPMC_POST_LOOKUP_RPF_CHECK) &&
    404                 (lpm_cfg->defip_expected_intf != 0))  {
    405 
    406             soc_format_field32_set(unit, PIM_SM_ACTION_SETfmt,
    407                            &action_set, EXPECTED_L3_IIFf,
    408                            lpm_cfg->defip_expected_intf);
    409 
    410             if (lpm_cfg->defip_ipmc_flags & BCM_IPMC_RPF_FAIL_DROP) {
    411                 soc_format_field32_set(unit, PIM_SM_ACTION_SETfmt,
    412                            &action_set, IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf, 1);
    413             }
    414             if (lpm_cfg->defip_ipmc_flags & BCM_IPMC_RPF_FAIL_TOCPU) {
    415                 soc_format_field32_set(unit, PIM_SM_ACTION_SETfmt,
    416                            &action_set, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf, 1);
    417             }
    418         }
    419         soc_mem_field32_set(unit, view_id, hw_entry,
    420                           PIM_SM_ACTION_SETf, action_set);
    421     }
    422 
    423     if ((!SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_MASK0_LWRf) ||
    424         !SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_MASK1_LWRf) ||
    425         !SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_MASK0_UPRf) ||
    426         !SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_MASK1_UPRf)) &&
    427         (!SOC_MEM_FIELD_VALID(unit, view_id, IPV6__MASKf))) {
    428         return BCM_E_INTERNAL;
    429     }
    430 
    431     /* Set destination/source ip address. */
    432     _bcm_defip_pair128_flex_ip6_addr_set(unit, view_id, hw_entry,
    433                                  lpm_cfg->defip_ip6_addr);
    434 
    435     /* Set ip mask. */
    436     _bcm_defip_pair128_flex_ip6_mask_set(unit, view_id, hw_entry, mask);
    437 
    438     /* Set vrf id & vrf mask. */
    439     action_set = 0;
    440     if (BCM_L3_VRF_OVERRIDE != lpm_cfg->defip_vrf) {
    441         if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_0f) ||
    442             SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_1f)) {
    443             if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_0f)) {
    444                 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_0f, lpm_cfg->defip_vrf);
    445                 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK0f,
    446                                 (1 << soc_mem_field_length(unit, view_id,
    447                                                      VRF_ID_MASK0f)) - 1);
    448             }
    449             if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_1f)) {
    450                 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_1f, lpm_cfg->defip_vrf);
    451                 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK1f,
    452                                 (1 << soc_mem_field_length(unit, view_id,
    453                                                      VRF_ID_MASK1f)) - 1);
    454             }
    455         } else {
    456             soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_0_LWRf, lpm_cfg->defip_vrf);
    457             soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_1_LWRf, lpm_cfg->defip_vrf);
    458             soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_0_UPRf, lpm_cfg->defip_vrf);
    459             soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_1_UPRf, lpm_cfg->defip_vrf);
    460             soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK0_LWRf,
    461                                 (1 << soc_mem_field_length(unit, view_id,
    462                                                      VRF_ID_MASK0_LWRf)) - 1);
    463             soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK1_LWRf,
    464                                 (1 << soc_mem_field_length(unit, view_id,
    465                                                      VRF_ID_MASK1_LWRf)) - 1);
    466             soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK0_UPRf,
    467                                 (1 << soc_mem_field_length(unit, view_id,
    468                                                          VRF_ID_MASK0_UPRf)) - 1);
    469             soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK1_LWRf,
    470                                 (1 << soc_mem_field_length(unit, view_id,
    471                                                          VRF_ID_MASK1_UPRf)) - 1);
    472         }
    473         if (process_fwd_3_attributes) {
    474             soc_format_field32_set(unit, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETfmt,
    475                                &action_set, GLOBAL_ROUTEf, 0);
    476             soc_mem_field32_set(unit, view_id, hw_entry,
    477                              FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf, action_set);
    478         }
    479     } else {
    480         if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_0f) ||
    481             SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_1f)) {
    482             if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_0f)) {
    483                 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_0f, 0);
    484                 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK0f, 0);
    485             }
    486             if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_1f)) {
    487                 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_1f, 0);
    488                 soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK1f, 0);
    489             }
    490         } else {
    491             soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_0_LWRf, 0);
    492             soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_1_LWRf, 0);
    493             soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_0_UPRf, 0);
    494             soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_1_UPRf, 0);
    495             soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK0_LWRf, 0);
    496             soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK1_LWRf, 0);
    497             soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK0_UPRf, 0);
    498             soc_mem_field32_set(unit, view_id, hw_entry, VRF_ID_MASK1_UPRf, 0);
    499         }
    500     }
    501 
    502     /* Configure entry for SIP lookup if URPF is enabled. This => SIP is default route.*/
    503     /* If soc_feature_l3_defip_advanced_lookup is TRUE then 
    504      * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
    505      * L3_DEFIP table is not divided into 2 to support URPF (Ex: KT2).
    506      */
    507     action_set = 0;
    508     if (soc_feature(unit, soc_feature_l3_defip_advanced_lookup) &&
    509         process_fwd_3_attributes) {
    510         soc_format_field32_set(unit, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETfmt,
    511                            &action_set, DEFAULT_ROUTEf,
    512                            (SOC_URPF_STATUS_GET(unit) ? 1 : 0));
    513         soc_mem_field32_set(unit, view_id, hw_entry,
    514                          FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf, action_set);
    515     }
    516 
    517     SOC_IF_ERROR_RETURN(soc_mem_view_phy_mem_get(unit, view_id, &phy_mem));
    518 
    519     /* Write buffer to hw. */
    520     rv = BCM_XGS3_MEM_WRITE(unit, phy_mem, hw_index, hw_entry);
    521     if (BCM_FAILURE(rv)) {
    522         BCM_DEFIP_PAIR128_ENTRY_SET(unit, hw_index, 0, 0);
    523         return (rv);
    524     }
    525 
    526     /* Write source lookup portion of the entry. */
    527     /* If soc_feature_l3_defip_advanced_lookup is TRUE then 
    528      * both DIP and SIP lookup is done using 1 L3_DEFIP entry.
    529      * L3_DEFIP table is not divided into 2 to support URPF (Ex: KT2).
    530      */
    531     action_set = 0;
    532     if (SOC_URPF_STATUS_GET(unit) &&
    533         !soc_feature(unit, soc_feature_l3_defip_advanced_lookup)) {
    534         if (!process_fwd_attributes) {
    535             return BCM_E_PARAM;
    536         }
    537         soc_format_field32_set(unit, FWD_ATTRIBUTES_ACTION_SETfmt,
    538                                &action_set, SRC_DISCARDf, 0);
    539         soc_mem_field32_set(unit, view_id, hw_entry,
    540                              FWD_ATTRIBUTES_ACTION_SETf, action_set);
    541         rv = BCM_XGS3_MEM_WRITE(unit, L3_DEFIP_PAIR_128m, 
    542                                 (hw_index + BCM_DEFIP_PAIR128_URPF_OFFSET(unit)),
    543                                 hw_entry);
    544         if (BCM_FAILURE(rv)) {
    545             _bcm_defip_pair128_flex_entry_clear(unit, view_id, hw_index);
    546             return (rv);
    547         }
    548     }
    549 
    550     /* If new route added increment total number of routes.  */
    551     /* Lack of index indicates a new route. */
    552     if (BCM_XGS3_L3_INVALID_INDEX == lpm_cfg->defip_index) {
    553         BCM_XGS3_L3_DEFIP_CNT_INC(unit, TRUE);
    554         BCM_DEFIP_PAIR128_USED_COUNT(unit)++;
    555         soc_lpm_stat_128b_count_update(unit, 1);
    556     }
    557 
    558     return rv;
    559 
    560 }
    561 /*
    562  * Function:
    563  *     _bcm_td3_flex_ip6_defip_lwr_set
    564  * Purpose:
    565  *    Set an IP6 address field in L3_DEFIPm at index n
    566  * Parameters:
    567  *    unit    - (IN) SOC unit number;
    568  *    lpm_key - (OUT) Buffer to fill.
    569  *    lpm_cfg - (IN) Route information.
    570  *    view_id - (IN) Memory view id 
    571  * Note:
    572  *    See soc_mem_ip6_addr_set()
    573  */
    574 STATIC void
    575 _bcm_td3_flex_ip6_defip_lwr_set(int unit, void *lpm_key, _bcm_defip_cfg_t *lpm_cfg, soc_mem_t view_id)
    576 {
    577     uint8 *ip6;                 /* Ip6 address.       */
    578     uint8 mask[BCM_IP6_ADDRLEN];        /* Subnet mask.       */
    579     uint32 ip6_word;            /* Temp storage.      */
    580     int idx;
    581 
    582     /* Just to keep variable name short. */
    583     ip6 = lpm_cfg->defip_ip6_addr;
    584 
    585     /* Create mask from prefix length. */
    586     bcm_ip6_mask_create(mask, lpm_cfg->defip_sub_len);
    587 
    588    /* Apply subnet mask */
    589     idx = lpm_cfg->defip_sub_len / 8;   /* Unchanged byte count.    */
    590     if (idx < BCM_IP6_ADDRLEN) {
    591         ip6[idx] &= mask[idx];      /* Apply mask on next byte. */
    592     }
    593     for (idx++; idx < BCM_IP6_ADDRLEN; idx++) {
    594         ip6[idx] = 0;           /* Reset rest of bytes.     */
    595     }
    596 
    597     ip6_word = ((ip6[8] << 24) | (ip6[9] << 16) | (ip6[10] << 8) | (ip6[11]));
    598     soc_mem_field32_set(unit, view_id, lpm_key, IP_ADDR1f, ip6_word);
    599 
    600     ip6_word = ((ip6[12] << 24) | (ip6[13] << 16) | (ip6[14] << 8) | (ip6[15]));
    601     soc_mem_field32_set(unit, view_id, lpm_key, IP_ADDR0f, ip6_word);
    602 
    603     ip6_word = ((mask[8] << 24) | (mask[9] << 16) | (mask[10] << 8) |
    604                (mask[11]));
    605     soc_mem_field32_set(unit, view_id, lpm_key, IP_ADDR_MASK1f, ip6_word);
    606 
    607     ip6_word = ((mask[12] << 24) | (mask[13] << 16) | (mask[14] << 8) |
    608                (mask[15]));
    609     soc_mem_field32_set(unit, view_id, lpm_key, IP_ADDR_MASK0f, ip6_word);
    610 }
    611 /*
    612  * Function:
    613  *     _bcm_td3_flex_ip6_defip_set
    614  * Purpose:
    615  *    Set an IP6 address field in L3_DEFIPm
    616  * Parameters:
    617  *    unit    - (IN) SOC unit number;
    618  *    lpm_key - (OUT) Buffer to fill.
    619  *    lpm_cfg - (IN) Route information.
    620  *    view_id - (IN) Memory view id 
    621  * Note:
    622  *    See soc_mem_ip6_addr_set()
    623  */
    624 STATIC void
    625 _bcm_td3_flex_ip6_defip_set(int unit, void *lpm_key, _bcm_defip_cfg_t *lpm_cfg, soc_mem_t view_id)
    626 {
    627     uint8 *ip6;                 /* Ip6 address.       */
    628     uint8 mask[BCM_IP6_ADDRLEN];        /* Subnet mask.       */
    629     uint32 ip6_word;            /* Temp storage.      */
    630     int idx;                    /* Iteration index .  */
    631 
    632     /* Just to keep variable name short. */
    633     ip6 = lpm_cfg->defip_ip6_addr;
    634 
    635     /* Create mask from prefix length. */
    636     bcm_ip6_mask_create(mask, lpm_cfg->defip_sub_len);
    637 
    638     /* Apply subnet mask */
    639     idx = lpm_cfg->defip_sub_len / 8;   /* Unchanged byte count.    */
    640     ip6[idx] &= mask[idx];      /* Apply mask on next byte. */
    641     for (idx++; idx < BCM_IP6_ADDRLEN; idx++) {
    642         ip6[idx] = 0;           /* Reset rest of bytes.     */
    643     }
    644 
    645 
    646     ip6_word = ((ip6[0] << 24) | (ip6[1] << 16) | (ip6[2] << 8) | (ip6[3]));
    647     soc_mem_field32_set(unit, view_id, lpm_key, IP_ADDR1f, ip6_word);
    648 
    649     ip6_word = ((ip6[4] << 24) | (ip6[5] << 16) | (ip6[6] << 8) | (ip6[7]));
    650     soc_mem_field32_set(unit, view_id, lpm_key, IP_ADDR0f, ip6_word);
    651 
    652     ip6_word = ((mask[0] << 24) | (mask[1] << 16) | (mask[2] << 8) | (mask[3]));
    653     soc_mem_field32_set(unit, view_id, lpm_key, IP_ADDR_MASK1f, ip6_word);
    654 
    655     ip6_word = ((mask[4] << 24) | (mask[5] << 16) | (mask[6] << 8) | (mask[7]));
    656     soc_mem_field32_set(unit, view_id, lpm_key, IP_ADDR_MASK0f, ip6_word);
    657 }
    658 /*
    659  * Function:
    660  *      _bcm_td3_lpm_flex_ent_init
    661  * Purpose:
    662  *      Service routine used to initialize lkup key for flex lpm entry.
    663  * Parameters:
    664  *      unit      - (IN)SOC unit number.
    665  *      lpm_cfg   - (IN)Prefix info.
    666  *      lpm_entry - (OUT)Hw buffer to fill.
    667  * Returns:
    668  *      BCM_E_XXX
    669  */
    670 int
    671 _bcm_td3_lpm_flex_ent_init(int unit, _bcm_defip_cfg_t *lpm_cfg,
    672                      uint32  *lpm_entry)
    673 {
    674     bcm_ip_t ip4_mask;
    675     int vrf_id;
    676     int vrf_mask;
    677     int ipv6 = lpm_cfg->defip_flags & BCM_L3_IP6;
    678     int mode = 1;
    679     soc_mem_t view_id;
    680     uint32 action_set;
    681 
    682     /* Extract entry  vrf id  & vrf mask. */
    683     BCM_IF_ERROR_RETURN
    684         (bcm_xgs3_internal_lpm_vrf_calc(unit, lpm_cfg, &vrf_id, &vrf_mask));
    685 
    686     BCM_IF_ERROR_RETURN(
    687         soc_flow_db_ffo_to_mem_view_id_get(unit,
    688                           lpm_cfg->defip_flow_handle,
    689                           lpm_cfg->defip_flow_option_handle,
    690                           SOC_FLOW_DB_FUNC_L3_ROUTE_ID,
    691                           (uint32 *)&view_id));
    692 
    693     if (!(SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_MASK0f) ||
    694         SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_MASK1f))) {
    695         return BCM_E_INTERNAL;
    696     }
    697 
    698     BCM_IF_ERROR_RETURN(soc_flow_db_mem_view_entry_init(unit, view_id, lpm_entry));
    699 
    700     if (SOC_MEM_FIELD_VALID(unit, view_id, KEY_MODE0_UPRf)) {
    701         mode = soc_mem_field32_get(unit, view_id, lpm_entry, KEY_MODE0_UPRf);
    702     } else if (SOC_MEM_FIELD_VALID(unit, view_id, KEY_MODE0f)) {
    703         mode = soc_mem_field32_get(unit, view_id, lpm_entry, KEY_MODE0f);
    704     }
    705     /* Set prefix ip address & mask. */
    706     if (ipv6) {
    707          if (mode == 3) {
    708             _bcm_td3_flex_ip6_defip_lwr_set(unit, lpm_entry, lpm_cfg, view_id);
    709          } else {
    710             _bcm_td3_flex_ip6_defip_set(unit, lpm_entry, lpm_cfg, view_id);
    711          }
    712     } else {
    713         ip4_mask = BCM_IP4_MASKLEN_TO_ADDR(lpm_cfg->defip_sub_len);
    714         /* Apply subnet mask. */
    715         lpm_cfg->defip_ip_addr &= ip4_mask;
    716 
    717         /* Set address to the buffer. */
    718         soc_mem_field32_set(unit, view_id, lpm_entry, IP_ADDR0f,
    719                                   lpm_cfg->defip_ip_addr);
    720         soc_mem_field32_set(unit, view_id, lpm_entry, IP_ADDR_MASK0f, ip4_mask);
    721     }
    722 
    723     /* Set Virtual Router id if supported. */
    724     if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_0f)) {
    725         soc_mem_field32_set(unit, view_id, lpm_entry, VRF_ID_0f, vrf_id);
    726         soc_mem_field32_set(unit, view_id, lpm_entry, VRF_ID_MASK0f, vrf_mask);
    727     }
    728 
    729     if (ipv6) {
    730         /* Set Virtual Router id if supported. */
    731         if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_1f)) {
    732             soc_mem_field32_set(unit, view_id, lpm_entry, VRF_ID_1f, vrf_id);
    733             soc_mem_field32_set(unit, view_id, lpm_entry, VRF_ID_MASK1f, vrf_mask);
    734         }
    735     }
    736 
    737     action_set = 0;
    738     if (SOC_MEM_FIELD_VALID(unit, view_id, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf)) {
    739         if (BCM_L3_VRF_GLOBAL == lpm_cfg->defip_vrf) {
    740             soc_format_field32_set(unit, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETfmt,
    741                                &action_set, GLOBAL_ROUTEf, 1);
    742         }
    743         if (BCM_L3_VRF_OVERRIDE == lpm_cfg->defip_vrf) {
    744             soc_format_field32_set(unit, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETfmt,
    745                                &action_set, GLOBAL_ROUTEf, 1);
    746         }
    747         soc_mem_field32_set(unit, view_id, lpm_entry,
    748                      FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf, action_set);
    749     }
    750     return (BCM_E_NONE);
    751 }
    752 int
    753 _bcm_td3_lpm_prepare_flex_defip_entry(int unit, _bcm_defip_cfg_t *lpm_cfg,
    754                                 int nh_ecmp_idx, uint32  *lpm_entry)
    755 {
    756     int     i,j;
    757     int     rv;
    758     soc_mem_t view_id;
    759     uint32  field_array[128];
    760     uint32  field_count;
    761     uint32  opaque_array[16];
    762     uint32  opaque_count;
    763     bcm_flow_logical_field_t* user_fields;
    764 
    765     uint32 action_set = 0;
    766 
    767     uint8 process_destination = 0;
    768     uint8 process_class_id = 0;
    769     uint8 process_qos = 0;
    770     uint8 process_pim_sm = 0;
    771     uint8 process_fwd_attributes = 0;
    772     uint8 process_fwd_3_attributes = 0;
    773     uint8 process_vrf = 0;
    774     uint8 process_vrf_mask = 0;
    775 
    776     if (NULL == lpm_cfg || NULL == lpm_entry) {
    777         return BCM_E_PARAM;
    778     }
    779 
    780     /* This routine handles only IP4 entries in L3_DEFIP */
    781     if (lpm_cfg->defip_flags & BCM_L3_IP6) {
    782         return BCM_E_PARAM;
    783     }
    784 
    785     /* Set hit bit. */
    786     if (lpm_cfg->defip_flags & BCM_L3_HIT) {
    787         soc_L3_DEFIPm_field32_set(unit, lpm_entry, HIT0f, 1);
    788     }
    789 
    790     BCM_IF_ERROR_RETURN(
    791         soc_flow_db_ffo_to_mem_view_id_get(unit,
    792                           lpm_cfg->defip_flow_handle,
    793                           lpm_cfg->defip_flow_option_handle,
    794                           SOC_FLOW_DB_FUNC_L3_ROUTE_ID,
    795                           (uint32 *)&view_id));
    796 
    797     /* Initialize control field list for this view id. */
    798     rv = soc_flow_db_mem_view_entry_init(unit, view_id, (uint32 *) lpm_entry);
    799 
    800     BCM_IF_ERROR_RETURN(rv);
    801 
    802     /* Get logical KEY field list for this view id. */
    803     rv = soc_flow_db_mem_view_field_list_get(unit,
    804                             view_id,
    805                             SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY,
    806                             16,
    807                             opaque_array,
    808                             &opaque_count);
    809     BCM_IF_ERROR_RETURN(rv);
    810 
    811     user_fields = lpm_cfg->defip_logical_fields;
    812 
    813     for (j = 0; j < lpm_cfg->defip_num_of_fields; j++) {
    814         for (i=0; i<opaque_count; i++) {
    815             if (user_fields[j].id == opaque_array[i]) {
    816                 soc_mem_field32_set(unit, view_id, lpm_entry, user_fields[j].id,
    817                                 user_fields[j].value);
    818                 break;
    819             }
    820         }
    821     }
    822 
    823     /* Get logical PDD field list for this view id. */
    824     rv = soc_flow_db_mem_view_field_list_get(unit,
    825                             view_id,
    826                             SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
    827                             16,
    828                             opaque_array,
    829                             &opaque_count);
    830     BCM_IF_ERROR_RETURN(rv);
    831 
    832     user_fields = lpm_cfg->defip_logical_fields;
    833 
    834     for (j = 0; j < lpm_cfg->defip_num_of_fields; j++) {
    835         for (i=0; i<opaque_count; i++) {
    836             if (user_fields[j].id == opaque_array[i]) {
    837                 soc_mem_field32_set(unit, view_id, lpm_entry, user_fields[j].id,
    838                                 user_fields[j].value);
    839                 break;
    840             }
    841         }
    842     }
    843 
    844     /* Get PDD field list corresponding to the view id. */
    845     rv = soc_flow_db_mem_view_field_list_get(unit,
    846                             view_id,
    847                             SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA,
    848                             128,
    849                             field_array,
    850                             &field_count);
    851     BCM_IF_ERROR_RETURN(rv);
    852 
    853     for (i=0; i<field_count; i++) {
    854         switch (field_array[i]) {
    855             case DESTINATION_ACTION_SETf:
    856                 process_destination = 1;
    857                 break;
    858             case CLASS_ID_ACTION_SETf:
    859                 process_class_id = 1;
    860                 break;
    861             case QOS_ACTION_SETf:
    862                 process_qos = 1;
    863                 break;
    864             case FWD_ATTRIBUTES_ACTION_SETf:
    865                 process_fwd_attributes = 1;
    866                 break;
    867             case FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf:
    868                 process_fwd_3_attributes = 1;
    869                 break;
    870             case PIM_SM_ACTION_SETf:
    871                 process_pim_sm = 1;
    872                 break;
    873             case VRF_ID_0f:
    874                 process_vrf = 1;
    875                 break;
    876             case VRF_ID_MASK0f:
    877                 process_vrf_mask = 1;
    878                 break;
    879             default:
    880                 break;
    881         }       
    882     }
    883 
    884     action_set = 0;
    885     if (process_vrf) { 
    886         soc_mem_field32_set(unit, view_id, lpm_entry,
    887                          VRF_ID_0f, lpm_cfg->defip_vrf);
    888     }
    889 
    890     if (process_vrf_mask) { 
    891         soc_mem_field32_set(unit, view_id, lpm_entry,
    892                          VRF_ID_MASK0f, 0xfff);
    893     }
    894 
    895     /* Configure entry for SIP lookup if URPF is enabled.
    896      * For devices like KT2 both DIP and SIP lookup is done
    897      * using only 1 L3_DEFIP entry, unlike other devices where
    898      * L3_DEFIP table is divided in 2 parts to support URPF.
    899      * RPExf and DEFAULTROUTExf are not overlayed in KT2 like previous devices.
    900      */
    901     action_set = 0;
    902     if (soc_feature(unit, soc_feature_l3_defip_advanced_lookup) &&
    903         process_fwd_3_attributes) {
    904         /* DEFAULTROUTE0f */
    905         soc_format_field32_set(unit, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETfmt,
    906                            &action_set, DEFAULT_ROUTEf,
    907                            (SOC_URPF_STATUS_GET(unit) ? 1 : 0));
    908         soc_mem_field32_set(unit, view_id, lpm_entry,
    909                          FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf, action_set);
    910  
    911     }
    912 
    913     /* Set priority override bit. */
    914     action_set = 0;
    915 
    916     if (lpm_cfg->defip_flags & BCM_L3_RPE) {
    917         if (!process_qos) {
    918             return BCM_E_UNAVAIL;
    919         }
    920         soc_format_field32_set(unit, QOS_ACTION_SETfmt,
    921                                &action_set, RPEf, 1);
    922     }
    923 
    924     /* Write priority field. */
    925     soc_format_field32_set(unit, QOS_ACTION_SETfmt,
    926                            &action_set, PRIf, lpm_cfg->defip_prio);
    927 
    928     if (process_qos) {
    929         soc_mem_field32_set(unit, view_id, lpm_entry,
    930                         QOS_ACTION_SETf, action_set);
    931     }
    932 
    933     /* Fill next hop information. */
    934     if (!process_destination) {
    935         return BCM_E_INTERNAL;
    936     }
    937 
    938     action_set = 0;
    939 
    940     if (lpm_cfg->defip_flags & BCM_L3_MULTIPATH) {
    941         soc_format_field32_set(unit, DESTINATION_FORMATfmt,
    942                            &action_set, DEST_TYPE1f, BCMI_TD3_DEST_TYPE1_ECMP);
    943         soc_format_field32_set(unit, DESTINATION_FORMATfmt,
    944                            &action_set, ECMP_GROUPf, nh_ecmp_idx);
    945  
    946     } else if (nh_ecmp_idx != BCM_XGS3_L3_INVALID_INDEX) {
    947         soc_format_field32_set(unit, DESTINATION_FORMATfmt,
    948                            &action_set, DEST_TYPE0f, BCMI_TD3_DEST_TYPE0_NH);
    949         soc_format_field32_set(unit, DESTINATION_FORMATfmt,
    950                            &action_set, NEXT_HOP_INDEXf, nh_ecmp_idx);
    951     }
    952     soc_mem_field32_set(unit, view_id, lpm_entry,
    953                         DESTINATION_ACTION_SETf, action_set);
    954 
    955     /* Set destination discard flag. */
    956     action_set = 0;
    957     if (lpm_cfg->defip_flags & BCM_L3_DST_DISCARD) {
    958         if (!process_fwd_attributes) {
    959             return BCM_E_UNAVAIL;
    960         }
    961         soc_format_field32_set(unit, FWD_ATTRIBUTES_ACTION_SETfmt,
    962                                &action_set, DST_DISCARDf, 1);
    963         soc_mem_field32_set(unit, view_id, lpm_entry,
    964                              FWD_ATTRIBUTES_ACTION_SETf, action_set);
    965     }
    966 
    967     /* Set classification group id. */
    968     if (process_class_id) {
    969         /* CLASS_ID0f */
    970         soc_mem_field32_set(unit, view_id, lpm_entry, CLASS_ID_ACTION_SETf,
    971                             lpm_cfg->defip_lookup_class);
    972     }
    973 
    974     /* Set Global route flag. */
    975     if (process_fwd_3_attributes) {
    976         if (BCM_L3_VRF_GLOBAL == lpm_cfg->defip_vrf) {
    977             /* GLOBAL_ROUTE0f */
    978             soc_format_field32_set(unit, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETfmt,
    979                                &action_set, GLOBAL_ROUTEf, 1);
    980      
    981         }
    982         if (BCM_L3_VRF_OVERRIDE == lpm_cfg->defip_vrf) {
    983             soc_format_field32_set(unit, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETfmt,
    984                                &action_set, GLOBAL_ROUTEf, 1);
    985         }
    986         soc_mem_field32_set(unit, view_id, lpm_entry,
    987                          FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf, action_set);
    988     }
    989 
    990     if (soc_feature(unit, soc_feature_ipmc_defip) &&  
    991             (lpm_cfg->defip_flags & BCM_L3_IPMC)) {
    992 
    993         /* L3MC_INDEXf */
    994         action_set = 0;
    995         if (!process_pim_sm) {
    996             return BCM_E_UNAVAIL;
    997         }
    998 
    999         soc_format_field32_set(unit, DESTINATION_FORMATfmt,
   1000                            &action_set, DEST_TYPE1f, BCMI_TD3_DEST_TYPE1_IPMC);
   1001         soc_format_field32_set(unit, DESTINATION_FORMATfmt,
   1002                            &action_set, IPMC_GROUPf, lpm_cfg->defip_mc_group);
   1003         soc_mem_field32_set(unit, view_id, lpm_entry,
   1004                           DESTINATION_ACTION_SETf, action_set);
   1005 
   1006         /*
   1007          * RP ID needs uplift by _BCM_L3_DEFIP_RP_ID_BASE value, Now it wil fit in EXPECTED_L3_IIFf
   1008          */
   1009         action_set = 0;
   1010         if (lpm_cfg->defip_l3a_rp != BCM_IPMC_RP_ID_INVALID) {
   1011             soc_format_field32_set(unit, PIM_SM_ACTION_SETfmt,
   1012                            &action_set, EXPECTED_L3_IIFf,
   1013                            _BCM_DEFIP_IPMC_RP_SET(lpm_cfg->defip_l3a_rp));
   1014 
   1015         } else if ((lpm_cfg->defip_ipmc_flags & BCM_IPMC_POST_LOOKUP_RPF_CHECK) && 
   1016                 (lpm_cfg->defip_expected_intf != 0))  {
   1017 
   1018             soc_format_field32_set(unit, PIM_SM_ACTION_SETfmt,
   1019                            &action_set, EXPECTED_L3_IIFf,
   1020                            lpm_cfg->defip_expected_intf);
   1021 
   1022             if (lpm_cfg->defip_ipmc_flags & BCM_IPMC_RPF_FAIL_DROP) {
   1023                 soc_format_field32_set(unit, PIM_SM_ACTION_SETfmt,
   1024                            &action_set, IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf, 1);
   1025             }
   1026             if (lpm_cfg->defip_ipmc_flags & BCM_IPMC_RPF_FAIL_TOCPU) {
   1027                 soc_format_field32_set(unit, PIM_SM_ACTION_SETfmt,
   1028                            &action_set, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf, 1);
   1029             }
   1030         }
   1031         soc_mem_field32_set(unit, view_id, lpm_entry,
   1032                           PIM_SM_ACTION_SETf, action_set);
   1033     }
   1034 
   1035     /*    
   1036      * Note ipv4 entries are expected to reside in part 0 of the entry.
   1037      *      ipv6 entries both parts should be filled.
   1038      *      Hence if entry is ipv6 copy part 0 to part 1
   1039      */
   1040     if (lpm_cfg->defip_flags & BCM_L3_IP6) {
   1041         soc_fb_lpm_ip4entry0_to_1(unit, lpm_entry, lpm_entry, TRUE);
   1042     }
   1043 
   1044     /*
   1045      * Initialize hw buffer from lpm configuration.
   1046      * NOTE: DON'T MOVE _bcm_fb_defip_ent_init CALL UP,
   1047      * We want to copy flags & nh info, avoid  ipv6 mask & address corruption.
   1048      */
   1049     BCM_IF_ERROR_RETURN(_bcm_td3_lpm_flex_ent_init(unit, lpm_cfg, lpm_entry));
   1050 
   1051     return BCM_E_NONE;
   1052 }
   1053 /*
   1054  * Function:    
   1055  *     _bcm_defip_pair128_ip6_addr_get
   1056  * Purpose:  
   1057  *     Read IP6 address field from memory field to ip6_addr_t buffer. 
   1058  * Parameters: 
   1059  *     unit  - (IN) BCM device number. 
   1060  *     mem   - (IN) Memory id.
   1061  *     entry - (IN) HW entry buffer.
   1062  *     ip6   - (OUT) SW ip6 address buffer.
   1063  * Returns:      void
   1064  */
   1065 STATIC void
   1066 _bcm_defip_pair128_flex_ip6_addr_get(int unit, soc_mem_t view_id, const void *entry, ip6_addr_t ip6)
   1067 {
   1068     uint32              ip6_field[4];
   1069     if (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__DIPf)) {
   1070         soc_mem_ip6_addr_get(unit, view_id, entry,IPV6__DIPf, ip6, 0);
   1071     } else if (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__SIPf)) {
   1072         soc_mem_ip6_addr_get(unit, view_id, entry,IPV6__SIPf, ip6, 0);
   1073     } else {
   1074         ip6_field[3] = soc_mem_field32_get(unit, view_id, entry, IP_ADDR0_LWRf);
   1075         ip6[12] = (uint8) (ip6_field[3] >> 24);
   1076         ip6[13] = (uint8) (ip6_field[3] >> 16 & 0xff);
   1077         ip6[14] = (uint8) (ip6_field[3] >> 8 & 0xff);
   1078         ip6[15] = (uint8) (ip6_field[3] & 0xff);
   1079         ip6_field[2] = soc_mem_field32_get(unit, view_id, entry, IP_ADDR1_LWRf);
   1080         ip6[8] = (uint8) (ip6_field[2] >> 24);
   1081         ip6[9] = (uint8) (ip6_field[2] >> 16 & 0xff);
   1082         ip6[10] = (uint8) (ip6_field[2] >> 8 & 0xff);
   1083         ip6[11] = (uint8) (ip6_field[2] & 0xff);
   1084         ip6_field[1] = soc_mem_field32_get(unit, view_id, entry, IP_ADDR0_UPRf);
   1085         ip6[4] = (uint8) (ip6_field[1] >> 24);
   1086         ip6[5] = (uint8) (ip6_field[1] >> 16 & 0xff);
   1087         ip6[6] =(uint8) (ip6_field[1] >> 8 & 0xff);
   1088         ip6[7] =(uint8) (ip6_field[1] & 0xff);
   1089         ip6_field[0] = soc_mem_field32_get(unit, view_id, entry, IP_ADDR1_UPRf);
   1090         ip6[0] =(uint8) (ip6_field[0] >> 24);
   1091         ip6[1] =(uint8) (ip6_field[0] >> 16 & 0xff);
   1092         ip6[2] =(uint8) (ip6_field[0] >> 8 & 0xff);
   1093         ip6[3] =(uint8) (ip6_field[0] & 0xff);
   1094     } 
   1095 }
   1096 /*
   1097  * Function:    
   1098  *     _bcm_defip_pair128_flex_ip6_mask_get
   1099  * Purpose:  
   1100  *     Read IP6 mask field from memory field to ip6_addr_t buffer. 
   1101  * Parameters: 
   1102  *     unit  - (IN) BCM device number. 
   1103  *     mem   - (IN) Memory id.
   1104  *     entry - (IN) HW entry buffer.
   1105  *     ip6   - (OUT) SW ip6 address buffer.
   1106  * Returns:      void
   1107  */
   1108 STATIC void
   1109 _bcm_defip_pair128_flex_ip6_mask_get(int unit, soc_mem_t view_id, const void *entry, 
   1110                                 ip6_addr_t ip6)
   1111 {
   1112     uint32              ip6_field[4];
   1113 
   1114     if (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__MASKf)) {
   1115         soc_mem_ip6_addr_get(unit, view_id, entry,IPV6__MASKf, ip6, 0);
   1116     } else {
   1117         ip6_field[3] = soc_mem_field32_get(unit, view_id, entry, IP_ADDR_MASK0_LWRf);
   1118         ip6[12] = (uint8) (ip6_field[3] >> 24);
   1119         ip6[13] = (uint8) (ip6_field[3] >> 16 & 0xff);
   1120         ip6[14] = (uint8) (ip6_field[3] >> 8 & 0xff);
   1121         ip6[15] = (uint8) (ip6_field[3] & 0xff);
   1122         ip6_field[2] = soc_mem_field32_get(unit, view_id, entry, IP_ADDR_MASK1_LWRf);
   1123         ip6[8] = (uint8) (ip6_field[2] >> 24);
   1124         ip6[9] = (uint8) (ip6_field[2] >> 16 & 0xff);
   1125         ip6[10] = (uint8) (ip6_field[2] >> 8 & 0xff);
   1126         ip6[11] = (uint8) (ip6_field[2] & 0xff);
   1127         ip6_field[1] = soc_mem_field32_get(unit, view_id, entry, IP_ADDR_MASK0_UPRf);
   1128         ip6[4] = (uint8) (ip6_field[1] >> 24);
   1129         ip6[5] = (uint8) (ip6_field[1] >> 16 & 0xff);
   1130         ip6[6] =(uint8) (ip6_field[1] >> 8 & 0xff);
   1131         ip6[7] =(uint8) (ip6_field[1] & 0xff);
   1132         ip6_field[0] = soc_mem_field32_get(unit, view_id, entry, IP_ADDR_MASK1_UPRf);
   1133         ip6[0] =(uint8) (ip6_field[0] >> 24);
   1134         ip6[1] =(uint8) (ip6_field[0] >> 16 & 0xff);
   1135         ip6[2] =(uint8) (ip6_field[0] >> 8 & 0xff);
   1136         ip6[3] =(uint8) (ip6_field[0] & 0xff);
   1137     }
   1138 }
   1139 /*
   1140  * Function:
   1141  *      _bcm_defip_pair128_get_key
   1142  * Purpose:
   1143  *      Parse route entry key from L3_DEFIP_PAIR_128 table.
   1144  * Parameters:
   1145  *      unit        - (IN)SOC unit number.
   1146  *      entry       - (IN)Hw entry buffer. 
   1147  *      lpm_cfg     - (IN/OUT)Buffer to fill defip information. 
   1148  * Returns:
   1149  *      BCM_E_XXX
   1150  */
   1151 int  
   1152 _bcm_defip_pair128_flex_get_key(int unit, uint32 *hw_entry,
   1153                            _bcm_defip_cfg_t *lpm_cfg, uint32 key_type)
   1154 {
   1155     bcm_ip6_t mask;                      /* Subnet mask.        */
   1156     soc_mem_t view_id;
   1157 
   1158     BCM_IF_ERROR_RETURN (
   1159         soc_flow_db_mem_to_view_id_get(unit,
   1160                     L3_DEFIP_PAIR_128m,
   1161                     key_type,
   1162                     SOC_FLOW_DB_DATA_TYPE_INVALID,
   1163                     0,
   1164                     NULL,
   1165                     (uint32 *)&view_id));
   1166 
   1167     if ((!SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_MASK0_LWRf) ||
   1168         !SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_MASK1_LWRf) ||
   1169         !SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_MASK0_UPRf) ||
   1170         !SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_MASK1_UPRf)) &&
   1171         (!SOC_MEM_FIELD_VALID(unit, view_id, IPV6__MASKf))) {
   1172         return BCM_E_INTERNAL;
   1173     }
   1174 
   1175     /* Extract ip6 address. */
   1176     _bcm_defip_pair128_flex_ip6_addr_get(unit, view_id, hw_entry, lpm_cfg->defip_ip6_addr);
   1177 
   1178     /* Extract subnet mask. */
   1179     _bcm_defip_pair128_flex_ip6_mask_get(unit, view_id, hw_entry, mask);
   1180 
   1181     lpm_cfg->defip_sub_len = bcm_ip6_mask_length(mask);
   1182 
   1183     /* Extract vrf id & vrf mask. */
   1184     if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_MASK0_LWRf)) {
   1185         if (!soc_mem_field32_get(unit, view_id, hw_entry, VRF_ID_MASK0_LWRf)) {
   1186             lpm_cfg->defip_vrf = BCM_L3_VRF_OVERRIDE;
   1187         } else {
   1188             lpm_cfg->defip_vrf = soc_mem_field32_get(unit, view_id, hw_entry, VRF_ID_0_LWRf);
   1189         }
   1190     } else if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_MASK0f)) {
   1191         if (!soc_mem_field32_get(unit, view_id, hw_entry, VRF_ID_MASK0f)) {
   1192             lpm_cfg->defip_vrf = BCM_L3_VRF_OVERRIDE;
   1193         } else {
   1194             lpm_cfg->defip_vrf = soc_mem_field32_get(unit, view_id, hw_entry, VRF_ID_0f);
   1195         }
   1196     }
   1197     return (BCM_E_NONE);
   1198 }
   1199 /*
   1200  * Function:
   1201  *      _bcm_td3_lpm_flex_ent_parse
   1202  * Purpose:
   1203  *      Parse flex route entry to sw structure.
   1204  * Parameters:
   1205  *      unit        - (IN)SOC unit number.
   1206  *      hw_entry    - (IN)Hw entry buffer. 
   1207  *      lpm_cfg     - (IN/OUT)Buffer to fill defip information. 
   1208  *      nh_ecmp_idx - (OUT)Next hop ecmp table index. 
   1209  * Returns:
   1210  *      BCM_E_XXX
   1211  */
   1212 int 
   1213 _bcm_td3_lpm_flex_ent_parse(int unit, uint32 *lpm_entry, uint32 key_type, soc_mem_t mem, _bcm_defip_cfg_t *lpm_cfg, int *nh_ecmp_idx)
   1214 {
   1215     uint32 action_set;
   1216     uint32 dest_action_set;
   1217     uint32 dest_type1;
   1218     soc_mem_t view_id;
   1219     uint32 data_ids[BCM_FLOW_MAX_NOF_LOGICAL_FIELDS];
   1220     uint32 key_ids[BCM_FLOW_MAX_NOF_LOGICAL_FIELDS];
   1221     uint32 key_cnt = 0;
   1222     uint32 data_cnt = 0;
   1223     uint32 i = 0;
   1224 
   1225     BCM_IF_ERROR_RETURN(
   1226         soc_flow_db_mem_to_view_id_get(unit,
   1227                      mem,
   1228                      key_type,
   1229                      SOC_FLOW_DB_DATA_TYPE_INVALID,
   1230                      0,
   1231                      NULL,
   1232                      (uint32 *)&view_id));
   1233 
   1234     if (mem == L3_DEFIP_PAIR_128m ||
   1235        (SOC_MEM_FIELD_VALID(unit, view_id, IPV6f)) ||
   1236        (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__SIPf)) ||
   1237        (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__DIPf))) {
   1238         lpm_cfg->defip_flags |= BCM_L3_IP6;
   1239     }
   1240 
   1241     dest_action_set = soc_mem_field32_get(unit, view_id, lpm_entry,
   1242                       DESTINATION_ACTION_SETf);
   1243 
   1244     dest_type1 =  soc_format_field32_get(unit, DESTINATION_FORMATfmt,
   1245                       &dest_action_set, DEST_TYPE1f);
   1246 
   1247     if (soc_feature(unit, soc_feature_ipmc_defip) &&
   1248         dest_type1 == BCMI_TD3_DEST_TYPE1_IPMC) {
   1249 
   1250         int val;
   1251         lpm_cfg->defip_flags |= BCM_L3_IPMC;
   1252 
   1253         action_set = soc_mem_field32_get(unit, view_id, lpm_entry,
   1254                           PIM_SM_ACTION_SETf);
   1255 
   1256         if (soc_format_field32_get(unit, PIM_SM_ACTION_SETfmt, &action_set, IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf)) {
   1257             lpm_cfg->defip_ipmc_flags |= BCM_IPMC_RPF_FAIL_DROP;
   1258         }
   1259         if (soc_format_field32_get(unit, PIM_SM_ACTION_SETfmt, &action_set, IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf)) {
   1260             lpm_cfg->defip_ipmc_flags |= BCM_IPMC_RPF_FAIL_TOCPU;
   1261         }
   1262         val = soc_format_field32_get(unit, PIM_SM_ACTION_SETfmt,
   1263                        &action_set, EXPECTED_L3_IIFf);
   1264         /*
   1265          * RP ID and ExpectedIIF are overlaid.
   1266          */
   1267         if (soc_feature(unit, soc_feature_l3defip_rp_l3iif_resolve)) {
   1268             int rpa_id_mask;
   1269             if (SOC_MEM_FIELD_VALID(unit, mem, RPA_ID0f)) {
   1270                 rpa_id_mask = (1 << soc_mem_field_length(unit, mem, RPA_ID0f)) - 1;
   1271             } else {
   1272                 rpa_id_mask = (1 << soc_mem_field_length(unit, mem, RPA_IDf)) - 1;
   1273             }
   1274             /*
   1275              * 1) If value is more than RPA_ID field then its l3_iif.
   1276              *    N/A for TD3/MV2/HX5 to support warmboot.
   1277              * 2) When RPF FAIL DROP/TOCPU flags are set then its l3iif valid
   1278              */
   1279             if ((lpm_cfg->defip_ipmc_flags &
   1280                  (BCM_IPMC_RPF_FAIL_DROP | BCM_IPMC_RPF_FAIL_TOCPU)) ||
   1281                 (!(SOC_IS_TRIDENT3(unit) || SOC_IS_MAVERICK2(unit) ||
   1282                    SOC_IS_HELIX5(unit)) && (val > rpa_id_mask))) {
   1283                 lpm_cfg->defip_expected_intf = val;
   1284                 if (0 != lpm_cfg->defip_expected_intf) {
   1285                     lpm_cfg->defip_ipmc_flags |= BCM_IPMC_POST_LOOKUP_RPF_CHECK;
   1286                 }
   1287                 lpm_cfg->defip_l3a_rp = BCM_IPMC_RP_ID_INVALID;
   1288             } else {
   1289                 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_RP_ID_EXPECTED_INTF_RESOLVE;
   1290                 lpm_cfg->defip_l3a_rp = val & rpa_id_mask;
   1291                 lpm_cfg->defip_expected_intf = val;
   1292             }
   1293         } else if (_BCM_DEFIP_IPMC_RP_IS_SET(val)) {
   1294             lpm_cfg->defip_l3a_rp = _BCM_DEFIP_IPMC_RP_GET(val);
   1295         } else {
   1296             lpm_cfg->defip_expected_intf = val;
   1297 
   1298             if (0 != lpm_cfg->defip_expected_intf) {
   1299                 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_POST_LOOKUP_RPF_CHECK;
   1300             }
   1301             lpm_cfg->defip_l3a_rp = BCM_IPMC_RP_ID_INVALID;
   1302         }
   1303         lpm_cfg->defip_mc_group = soc_format_field32_get(unit, DESTINATION_FORMATfmt,
   1304                           &dest_action_set, L3MC_INDEXf);
   1305     }
   1306 
   1307     if (dest_type1 == BCMI_TD3_DEST_TYPE1_ECMP) {
   1308         lpm_cfg->defip_ecmp = TRUE;
   1309         lpm_cfg->defip_flags |= BCM_L3_MULTIPATH;
   1310     } else {
   1311         lpm_cfg->defip_ecmp = 0;
   1312         lpm_cfg->defip_ecmp_count = 0;
   1313     }
   1314     if (nh_ecmp_idx != NULL) {
   1315         *nh_ecmp_idx = soc_format_field32_get(unit, DESTINATION_FORMATfmt,
   1316                        &dest_action_set, NEXT_HOP_INDEXf);
   1317     }
   1318 
   1319     if (SOC_MEM_FIELD_VALID(unit, view_id, QOS_ACTION_SETf)) {
   1320         action_set = soc_mem_field32_get(unit, view_id, lpm_entry,
   1321                         QOS_ACTION_SETf);
   1322 
   1323         /* Get entry priority. */
   1324         lpm_cfg->defip_prio = soc_format_field32_get(unit, QOS_ACTION_SETfmt,
   1325                            &action_set, PRIf);
   1326 
   1327         /* Get priority override bit. */
   1328         if (soc_format_field32_get(unit, QOS_ACTION_SETfmt, &action_set, RPEf)) {
   1329             lpm_cfg->defip_flags |= BCM_L3_RPE;
   1330         }
   1331     }
   1332 
   1333     /* Get classification group id. */
   1334     if (SOC_MEM_FIELD_VALID(unit, view_id, CLASS_ID_ACTION_SETf)) {
   1335         lpm_cfg->defip_lookup_class = 
   1336             soc_mem_field32_get(unit, view_id, lpm_entry, CLASS_ID_ACTION_SETf);
   1337     }
   1338 
   1339     /* Get hit bit. */
   1340     if (SOC_MEM_FIELD_VALID(unit, view_id, HITf)) {
   1341         if (soc_mem_field32_get(unit, view_id, lpm_entry, HITf)) {
   1342             lpm_cfg->defip_flags |= BCM_L3_HIT;
   1343         }
   1344     }
   1345 
   1346     if (SOC_MEM_FIELD_VALID(unit, view_id, HIT0f)) {
   1347         if (soc_mem_field32_get(unit, view_id, lpm_entry, HIT0f)) {
   1348             lpm_cfg->defip_flags |= BCM_L3_HIT;
   1349         }
   1350     }
   1351 
   1352     /* Get destination discard field. */
   1353     if (SOC_MEM_FIELD_VALID(unit, view_id, FWD_ATTRIBUTES_ACTION_SETf)) {
   1354         action_set = soc_mem_field32_get(unit, view_id, lpm_entry,
   1355                              FWD_ATTRIBUTES_ACTION_SETf);
   1356 
   1357         if (soc_format_field32_get(unit, FWD_ATTRIBUTES_ACTION_SETfmt,
   1358                                    &action_set, DST_DISCARDf)) {
   1359             lpm_cfg->defip_flags |= BCM_L3_DST_DISCARD;
   1360         }
   1361     }
   1362 
   1363     /* Get the logical fields */
   1364     lpm_cfg->defip_num_of_fields = 0;
   1365     BCM_IF_ERROR_RETURN(
   1366            soc_flow_db_mem_view_field_list_get(unit,
   1367                             view_id,
   1368                             SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY,
   1369                             BCM_FLOW_MAX_NOF_LOGICAL_FIELDS,
   1370                             key_ids,
   1371                             &key_cnt));
   1372 
   1373     if (key_cnt) {
   1374         for (i = 0;
   1375              (i <  key_cnt) ; i++) {
   1376             lpm_cfg->defip_logical_fields[i].id =  key_ids[i];
   1377             lpm_cfg->defip_logical_fields[i].value =
   1378                          soc_mem_field32_get(unit, view_id, lpm_entry,
   1379                          key_ids[i]);
   1380 
   1381         }
   1382         lpm_cfg->defip_num_of_fields = key_cnt;
   1383     }
   1384     BCM_IF_ERROR_RETURN(
   1385            soc_flow_db_mem_view_field_list_get(unit,
   1386                       view_id,
   1387                       SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
   1388                       BCM_FLOW_MAX_NOF_LOGICAL_FIELDS, data_ids, &data_cnt));
   1389     if (data_cnt) {
   1390         /* Entry traverse */
   1391         for ( ;
   1392              ((i < data_cnt) &&
   1393               ( i < SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA));
   1394               i++) {
   1395             lpm_cfg->defip_logical_fields[i].id = data_ids[i];
   1396             lpm_cfg->defip_logical_fields[i].value =
   1397                          soc_mem_field32_get(unit, view_id, lpm_entry,
   1398                          data_ids[i]);
   1399         }
   1400         lpm_cfg->defip_num_of_fields += data_cnt;
   1401     }
   1402 
   1403     SOC_IF_ERROR_RETURN(_bcm_flow_mem_view_to_flow_info_get(unit, view_id,
   1404                SOC_FLOW_DB_FUNC_L3_ROUTE_ID,
   1405                &lpm_cfg->defip_flow_handle, &lpm_cfg->defip_flow_option_handle, 1));
   1406 
   1407     return (BCM_E_NONE);
   1408 }
   1409 /*
   1410  * Function:
   1411  *     _bcm_td3_flex_ip6_defip_get
   1412  * Purpose:
   1413  *    Set an IP6 address field in L3_DEFIPm
   1414  * Note:
   1415  *    See soc_mem_ip6_addr_set()
   1416  */
   1417 STATIC void
   1418 _bcm_td3_flex_ip6_defip_get(int unit, const void *lpm_key, soc_mem_t view_id,
   1419                           _bcm_defip_cfg_t *lpm_cfg)
   1420 {
   1421     uint8 *ip6;                 /* Ip6 address.       */
   1422     uint8 mask[BCM_IP6_ADDRLEN];        /* Subnet mask.       */
   1423     uint32 ip6_word;            /* Temp storage.      */
   1424 
   1425     sal_memset(mask, 0, sizeof (bcm_ip6_t));
   1426 
   1427     /* Just to keep variable name short. */
   1428     ip6 = lpm_cfg->defip_ip6_addr;
   1429     sal_memset(ip6, 0, sizeof (bcm_ip6_t));
   1430 
   1431     ip6_word = soc_mem_field32_get(unit, view_id, lpm_key, IP_ADDR1f);
   1432     ip6[0] = (uint8) ((ip6_word >> 24) & 0xff);
   1433     ip6[1] = (uint8) ((ip6_word >> 16) & 0xff);
   1434     ip6[2] = (uint8) ((ip6_word >> 8) & 0xff);
   1435     ip6[3] = (uint8) (ip6_word & 0xff);
   1436 
   1437     ip6_word = soc_mem_field32_get(unit, view_id, lpm_key, IP_ADDR0f);
   1438     ip6[4] = (uint8) ((ip6_word >> 24) & 0xff);
   1439     ip6[5] = (uint8) ((ip6_word >> 16) & 0xff);
   1440     ip6[6] = (uint8) ((ip6_word >> 8) & 0xff);
   1441     ip6[7] = (uint8) (ip6_word & 0xff);
   1442 
   1443     ip6_word = soc_mem_field32_get(unit, view_id, lpm_key, IP_ADDR_MASK1f);
   1444     mask[0] = (uint8) ((ip6_word >> 24) & 0xff);
   1445     mask[1] = (uint8) ((ip6_word >> 16) & 0xff);
   1446     mask[2] = (uint8) ((ip6_word >> 8) & 0xff);
   1447     mask[3] = (uint8) (ip6_word & 0xff);
   1448 
   1449     ip6_word = soc_mem_field32_get(unit, view_id, lpm_key, IP_ADDR_MASK0f);
   1450     mask[4] = (uint8) ((ip6_word >> 24) & 0xff);
   1451     mask[5] = (uint8) ((ip6_word >> 16) & 0xff);
   1452     mask[6] = (uint8) ((ip6_word >> 8) & 0xff);
   1453     mask[7] = (uint8) (ip6_word & 0xff);
   1454 
   1455     lpm_cfg->defip_sub_len = bcm_ip6_mask_length(mask);
   1456 }
   1457 /*
   1458  * Function:
   1459  *      _bcm_td3_lpm_flex_vrf_get
   1460  * Purpose:
   1461  *      Service routine used to translate hw specific vrf id to API format.
   1462  * Parameters:
   1463  *      unit      - (IN)SOC unit number.
   1464  *      lpm_entry - (IN)Route info buffer from hw.
   1465  *      vrf_id    - (OUT)Virtual router id.
   1466  * Returns:
   1467  *      BCM_E_XXX
   1468  */
   1469 STATIC int
   1470 _bcm_td3_lpm_flex_vrf_get(int unit, void *lpm_entry, int *vrf, soc_mem_t view_id)
   1471 {
   1472     int vrf_id;
   1473 
   1474     /* Get Virtual Router id if supported. */
   1475     if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_MASK0f)){
   1476         vrf_id = soc_mem_field32_get(unit, view_id, lpm_entry, VRF_ID_0f);
   1477 
   1478         /* Special vrf's handling. */
   1479         if (soc_mem_field32_get(unit, view_id, lpm_entry, VRF_ID_MASK0f)) {
   1480             *vrf = vrf_id;    
   1481         } else if (SOC_VRF_MAX(unit) == vrf_id) {
   1482             *vrf = BCM_L3_VRF_GLOBAL;
   1483         } else {
   1484             *vrf = BCM_L3_VRF_OVERRIDE;    
   1485             if (SOC_MEM_FIELD_VALID(unit, view_id, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf)) {
   1486                 uint32 action_set = soc_mem_field32_get(unit, view_id, lpm_entry,
   1487                                                 FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf);
   1488                 if (soc_format_field32_get(unit, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETfmt,
   1489                                            &action_set, GLOBAL_ROUTEf)) {
   1490                     *vrf = BCM_L3_VRF_GLOBAL; 
   1491                 }
   1492             }
   1493 #if 0 
   1494             if (SOC_MEM_FIELD_VALID(unit, L3_DEFIPm, GLOBAL_HIGH0f)) {
   1495                 if (soc_mem_field32_get(unit, view_id, lpm_entry, GLOBAL_HIGH0f)){
   1496                     *vrf = BCM_L3_VRF_OVERRIDE;
   1497                 }
   1498             }
   1499 #endif
   1500         }
   1501     } else {
   1502         /* No vrf support on this device. */
   1503         *vrf = BCM_L3_VRF_DEFAULT;
   1504     }
   1505     return (BCM_E_NONE);
   1506 }
   1507 /*
   1508  * Function:
   1509  *      _bcm_fb_lpm_flex_ent_get_key
   1510  * Purpose:
   1511  *      Get flex entry key from DEFIP table.
   1512  * Parameters:
   1513  *      unit        - (IN)SOC unit number.
   1514  *      lpm_cfg     - (OUT)Buffer to fill defip information.
   1515  *      lpm_entry   - (IN) Buffer read from hw.
   1516  * Returns:
   1517  *      void
   1518  */
   1519 int
   1520 _bcm_td3_lpm_flex_ent_get_key(int unit, _bcm_defip_cfg_t *lpm_cfg,
   1521                         uint32  *lpm_entry, uint32 key_type)
   1522 {
   1523     bcm_ip_t v4_mask;
   1524     int ipv6 = lpm_cfg->defip_flags & BCM_L3_IP6;
   1525     soc_mem_t view_id;
   1526 
   1527     BCM_IF_ERROR_RETURN (
   1528         soc_flow_db_mem_to_view_id_get(unit,
   1529                     L3_DEFIPm,
   1530                     key_type,
   1531                     SOC_FLOW_DB_DATA_TYPE_INVALID,
   1532                     0,
   1533                     NULL,
   1534                     (uint32 *)&view_id));
   1535 
   1536     /* Set prefix ip address & mask. */
   1537     if (ipv6) {
   1538         _bcm_td3_flex_ip6_defip_get(unit, lpm_entry, view_id, lpm_cfg);
   1539     } else {
   1540         /* Get ipv4 address. */
   1541         lpm_cfg->defip_ip_addr =
   1542             soc_mem_field32_get(unit, view_id, lpm_entry, IP_ADDR0f);
   1543 
   1544         /* Get subnet mask. */
   1545         v4_mask = soc_mem_field32_get(unit, view_id, lpm_entry, IP_ADDR_MASK0f);
   1546 
   1547         /* Fill mask length. */
   1548         lpm_cfg->defip_sub_len = bcm_ip_mask_length(v4_mask);
   1549     }
   1550 
   1551     /* Get Virtual Router id */
   1552     _bcm_td3_lpm_flex_vrf_get(unit, lpm_entry, &lpm_cfg->defip_vrf, view_id);
   1553 
   1554     return BCM_E_NONE;
   1555 }
   1556 
   1557 #endif