void BcmRoute::programLpmRoute(opennsl_if_t egressId, const RouteNextHopEntry& fwd) { opennsl_l3_route_t rt; initL3RouteT(&rt); rt.l3a_intf = egressId; if (fwd.getNextHopSet().size() > 1) { // multipath rt.l3a_flags |= OPENNSL_L3_MULTIPATH; } bool addRoute = false; const auto warmBootCache = hw_->getWarmBootCache(); auto vrfAndPfx2RouteCitr = warmBootCache->findRoute(vrf_, prefix_, len_); if (vrfAndPfx2RouteCitr != warmBootCache->vrfAndPrefix2Route_end()) { // Lambda to compare if the routes are equivalent and thus we need to // do nothing auto equivalent = [=] (const opennsl_l3_route_t& newRoute, const opennsl_l3_route_t& existingRoute) { // Compare flags (primarily MULTIPATH vs non MULTIPATH // and egress id. return existingRoute.l3a_flags == newRoute.l3a_flags && existingRoute.l3a_intf == newRoute.l3a_intf; }; if (!equivalent(rt, vrfAndPfx2RouteCitr->second)) { VLOG (3) << "Updating route for : " << prefix_ << "/" << static_cast<int>(len_) << " in vrf : " << vrf_; // This is a change rt.l3a_flags |= OPENNSL_L3_REPLACE; addRoute = true; } else { VLOG(3) << " Route for : " << prefix_ << "/" << static_cast<int>(len_) << " in vrf : " << vrf_ << " already exists"; } } else { addRoute = true; } if (addRoute) { if (vrfAndPfx2RouteCitr == warmBootCache->vrfAndPrefix2Route_end()) { VLOG (3) << "Adding route for : " << prefix_ << "/" << static_cast<int>(len_) << " in vrf : " << vrf_; } if (added_) { rt.l3a_flags |= OPENNSL_L3_REPLACE; } auto rc = opennsl_l3_route_add(hw_->getUnit(), &rt); bcmCheckError(rc, "failed to create a route entry for ", prefix_, "/", static_cast<int>(len_), " @ ", fwd, " @egress ", egressId); VLOG(3) << "created a route entry for " << prefix_.str() << "/" << static_cast<int>(len_) << " @egress " << egressId << " with " << fwd; } if (vrfAndPfx2RouteCitr != warmBootCache->vrfAndPrefix2Route_end()) { warmBootCache->programmed(vrfAndPfx2RouteCitr); } }
sai_status_t brcm_sai_create_route(_In_ const sai_unicast_route_entry_t* unicast_route_entry, _In_ sai_uint32_t attr_count, _In_ const sai_attribute_t *attr_list) { int i; sai_status_t rv; opennsl_if_t l3_if_id = -1; opennsl_l3_route_t l3_rt; bool trap = false, drop = false, copy_to_cpu = false; sai_uint32_t vr_id; BRCM_SAI_FUNCTION_ENTER(SAI_API_ROUTE); BRCM_SAI_SWITCH_INIT_CHECK; BRCM_SAI_OBJ_CREATE_PARAM_CHK(unicast_route_entry); opennsl_l3_route_t_init(&l3_rt); for (i=0; i<attr_count; i++) { switch (attr_list[i].id) { case SAI_ROUTE_ATTR_NEXT_HOP_ID: l3_if_id = BRCM_SAI_GET_OBJ_VAL(opennsl_if_t, BRCM_SAI_ATTR_LIST_OBJ(i)); if (SAI_OBJECT_TYPE_NEXT_HOP_GROUP == BRCM_SAI_GET_OBJ_TYPE(BRCM_SAI_ATTR_LIST_OBJ(i))) { l3_rt.l3a_flags |= OPENNSL_L3_MULTIPATH; } break; case SAI_ROUTE_ATTR_PACKET_ACTION: if (SAI_PACKET_ACTION_LOG == attr_list[i].value.u32) { copy_to_cpu = true; } else if (SAI_PACKET_ACTION_TRAP == attr_list[i].value.u32) { trap = true; l3_rt.l3a_flags |= OPENNSL_L3_DEFIP_CPU; } else if (SAI_PACKET_ACTION_DROP == attr_list[i].value.u32) { drop = true; l3_rt.l3a_flags |= OPENNSL_L3_DST_DISCARD; } else { BRCM_SAI_LOG_ROUTE(SAI_LOG_ERROR, "Bad attribute passed\n"); return SAI_STATUS_INVALID_PARAMETER; } break; default: BRCM_SAI_LOG_ROUTE(SAI_LOG_ERROR, "Unimplemented attribute passed\n"); break; } } if (-1 == l3_if_id && FALSE == trap && FALSE == drop) { BRCM_SAI_LOG_ROUTE(SAI_LOG_ERROR, "Missing routing info.\n"); return SAI_STATUS_INVALID_PARAMETER; } if (SAI_IP_ADDR_FAMILY_IPV4 == unicast_route_entry->destination.addr_family) { l3_rt.l3a_ip_mask = ntohl(unicast_route_entry->destination.mask.ip4); l3_rt.l3a_subnet = ntohl(unicast_route_entry->destination.addr.ip4 & unicast_route_entry->destination.mask.ip4); } else if (SAI_IP_ADDR_FAMILY_IPV6 == unicast_route_entry->destination.addr_family) { memcpy(l3_rt.l3a_ip6_net, unicast_route_entry->destination.addr.ip6, sizeof(l3_rt.l3a_ip6_net)); memcpy(l3_rt.l3a_ip6_mask, unicast_route_entry->destination.mask.ip6, sizeof(l3_rt.l3a_ip6_mask)); } else { BRCM_SAI_LOG_ROUTE(SAI_LOG_ERROR, "Bad address family passed\n"); return SAI_STATUS_INVALID_PARAMETER; } vr_id = BRCM_SAI_GET_OBJ_VAL(sai_uint32_t, unicast_route_entry->vr_id); if (false == _brcm_sai_vr_id_valid(vr_id)) { BRCM_SAI_LOG_ROUTE(SAI_LOG_ERROR, "Invalid VR id passed during route create %d\n", vr_id); return SAI_STATUS_INVALID_PARAMETER; } l3_rt.l3a_vrf = vr_id; if (trap) { l3_rt.l3a_intf = _brcm_sai_vrf_if_get(l3_rt.l3a_vrf); } else if (drop) { l3_rt.l3a_intf = _brcm_sai_vrf_drop_if_get(l3_rt.l3a_vrf); } else { l3_rt.l3a_intf = l3_if_id; if (TRUE == copy_to_cpu) { opennsl_l3_egress_t l3_egr; uint32 flags = OPENNSL_L3_REPLACE | OPENNSL_L3_WITH_ID; rv = opennsl_l3_egress_get(0, l3_if_id, &l3_egr); BRCM_SAI_API_CHK(SAI_API_ROUTE, "L3 egress get", rv); l3_egr.flags |= OPENNSL_L3_COPY_TO_CPU; rv = opennsl_l3_egress_create(0, flags, &l3_egr, &l3_if_id); BRCM_SAI_API_CHK(SAI_API_ROUTE, "L3 egress create w/ replace", rv); } } BRCM_SAI_LOG_ROUTE(SAI_LOG_DEBUG, "Add route vrf: %d, egr %s id: %d mask 0x%x, subnet 0x%x\n", l3_rt.l3a_vrf, !(l3_rt.l3a_flags & OPENNSL_L3_MULTIPATH) ? "nh" : "nhg", l3_rt.l3a_intf, l3_rt.l3a_ip_mask, l3_rt.l3a_subnet ); rv = opennsl_l3_route_add(0, &l3_rt); BRCM_SAI_API_CHK(SAI_API_ROUTE, "L3 route add", rv); BRCM_SAI_FUNCTION_EXIT(SAI_API_ROUTE); return rv; }
/* ################################################################################ # Internal functions # ################################################################################ */ sai_status_t _brcm_sai_update_route(const sai_unicast_route_entry_t* unicast_route_entry, sai_uint32_t attr_count, const sai_attribute_t *attr_list) { int i; sai_status_t rv; opennsl_if_t l3_if_id = -1; opennsl_l3_route_t l3_rt; bool trap = false, drop = false; sai_uint32_t vr_id; BRCM_SAI_FUNCTION_ENTER(SAI_API_ROUTE); BRCM_SAI_SWITCH_INIT_CHECK; if ((NULL == unicast_route_entry) || (NULL == attr_list) || (0 == attr_count)) { BRCM_SAI_LOG_ROUTE(SAI_LOG_ERROR, "NULL params passed\n"); return SAI_STATUS_INVALID_PARAMETER; } opennsl_l3_route_t_init(&l3_rt); for (i=0; i<attr_count; i++) { switch (attr_list[i].id) { case SAI_ROUTE_ATTR_NEXT_HOP_ID: l3_if_id = attr_list[i].value.u32; if (SAI_OBJECT_TYPE_NEXT_HOP_GROUP == BRCM_SAI_GET_OBJ_TYPE(BRCM_SAI_ATTR_LIST_OBJ(i))) { l3_rt.l3a_flags |= OPENNSL_L3_MULTIPATH; } break; case SAI_ROUTE_ATTR_PACKET_ACTION: if (SAI_PACKET_ACTION_LOG == attr_list[i].value.u32) { l3_rt.l3a_flags |= OPENNSL_L3_COPY_TO_CPU; } else if (SAI_PACKET_ACTION_TRAP == attr_list[i].value.u32) { trap = true; l3_rt.l3a_flags |= OPENNSL_L3_DEFIP_CPU; } else if (SAI_PACKET_ACTION_DROP == attr_list[i].value.u32) { drop = true; l3_rt.l3a_flags |= OPENNSL_L3_DST_DISCARD; } else { BRCM_SAI_LOG_ROUTE(SAI_LOG_ERROR, "Bad attribute passed\n"); return SAI_STATUS_INVALID_PARAMETER; } default: BRCM_SAI_LOG_ROUTE(SAI_LOG_INFO, "Un-supported attribute %d passed\n", attr_list[i].id); break; } } if (-1 == l3_if_id && FALSE == trap && FALSE == drop) { BRCM_SAI_LOG_ROUTE(SAI_LOG_ERROR, "Missing routing info.\n"); return SAI_STATUS_INVALID_PARAMETER; } if (SAI_IP_ADDR_FAMILY_IPV4 == unicast_route_entry->destination.addr_family) { l3_rt.l3a_ip_mask = ntohl(unicast_route_entry->destination.mask.ip4); l3_rt.l3a_subnet = ntohl(unicast_route_entry->destination.addr.ip4 & unicast_route_entry->destination.mask.ip4); } else if (SAI_IP_ADDR_FAMILY_IPV6 == unicast_route_entry->destination.addr_family) { memcpy(l3_rt.l3a_ip6_net, unicast_route_entry->destination.addr.ip6, sizeof(l3_rt.l3a_ip6_net)); memcpy(l3_rt.l3a_ip6_mask, unicast_route_entry->destination.mask.ip6, sizeof(l3_rt.l3a_ip6_mask)); } else { return SAI_STATUS_INVALID_PARAMETER; } vr_id = BRCM_SAI_GET_OBJ_VAL(sai_uint32_t, unicast_route_entry->vr_id); if (false == _brcm_sai_vr_id_valid(vr_id)) { BRCM_SAI_LOG_ROUTE(SAI_LOG_ERROR, "Invalid VR id passed during route create %d\n", vr_id); return SAI_STATUS_INVALID_PARAMETER; } l3_rt.l3a_vrf = vr_id; if (trap) { l3_rt.l3a_intf = _brcm_sai_vrf_if_get(l3_rt.l3a_vrf); } else if (drop) { l3_rt.l3a_intf = _brcm_sai_vrf_drop_if_get(l3_rt.l3a_vrf); } else { l3_rt.l3a_intf = l3_if_id; } l3_rt.l3a_flags |= OPENNSL_L3_REPLACE; BRCM_SAI_LOG_ROUTE(SAI_LOG_DEBUG, "Update route vrf: %d, egr %s id: %d\n", l3_rt.l3a_vrf, !(l3_rt.l3a_flags & OPENNSL_L3_MULTIPATH) ? "nh" : "nhg", l3_rt.l3a_intf); rv = opennsl_l3_route_add(0, &l3_rt); BRCM_SAI_API_CHK(SAI_API_ROUTE, "L3 route add", rv); BRCM_SAI_FUNCTION_EXIT(SAI_API_ROUTE); return rv; }