示例#1
0
/**
 * @brief Remove Qos Map
 *
 *  @param[in] qos_map_id Qos Map id to be removed.
 *
 *  @return  SAI_STATUS_SUCCESS on success
 *           Failure status code on error
 */
sai_status_t sai_remove_qos_map(_In_ sai_object_id_t qos_map_id) {
  SAI_LOG_ENTER();

  sai_status_t status = SAI_STATUS_SUCCESS;

  SAI_ASSERT(sai_object_type_query(qos_map_id) == SAI_OBJECT_TYPE_QOS_MAPS);

  status = switch_api_qos_map_ingress_delete(device, qos_map_id);
  if (status != SWITCH_STATUS_SUCCESS &&
      status != SWITCH_STATUS_INVALID_HANDLE) {
    SAI_LOG_ERROR("failed to remove ingress qos map %s",
                  sai_status_to_string(status));
    return status;
  }

  status = switch_api_qos_map_egress_delete(device, qos_map_id);
  if (status != SWITCH_STATUS_SUCCESS) {
    SAI_LOG_ERROR("failed to remove egress qos map %s",
                  sai_status_to_string(status));
    return status;
  }

  SAI_LOG_EXIT();

  return (sai_status_t)status;
}
void redisSetDummyAsicStateForRealObjectId(sai_object_id_t rid)
{
    SWSS_LOG_ENTER();

    sai_object_type_t objectType = sai_object_type_query(rid);

    if (objectType == SAI_OBJECT_TYPE_NULL)
    {
        SWSS_LOG_ERROR("sai_object_type_query returned NULL type for RID %llx", rid);

        exit(EXIT_FAILURE);
    }

    std::string strObjectType;

    sai_serialize_primitive(objectType, strObjectType);

    sai_object_id_t vid = redis_create_virtual_object_id(objectType);

    std::string strVid;

    sai_serialize_primitive(vid, strVid);

    std::string strKey = "ASIC_STATE:" + strObjectType + ":" + strVid;

    g_redisClient->hset(strKey, "NULL", "NULL");

    redisCreateRidAndVidMapping(rid, vid);
}
示例#3
0
sai_object_id_t translate_rid_to_vid(
        _In_ sai_object_id_t rid)
{
    SWSS_LOG_ENTER();

    if (rid == SAI_NULL_OBJECT_ID)
    {
        SWSS_LOG_DEBUG("translated RID null to VID null");

        return SAI_NULL_OBJECT_ID;
    }

    sai_object_id_t vid;

    std::string str_rid;
    std::string str_vid;

    sai_serialize_primitive(rid, str_rid);

    auto pvid = g_redisClient->hget(RIDTOVID, str_rid);

    if (pvid != NULL)
    {
        // object exists
        str_vid = *pvid;

        int index = 0;
        sai_deserialize_primitive(str_vid, index, vid);

        SWSS_LOG_DEBUG("translated RID %llx to VID %llx", rid, vid);

        return vid;
    }

    SWSS_LOG_INFO("spotted new RID %llx", rid);

    sai_object_type_t object_type = sai_object_type_query(rid);

    if (object_type == SAI_OBJECT_TYPE_NULL)
    {
        SWSS_LOG_ERROR("sai_object_type_query returned NULL type for RID %llx", rid);

        exit(EXIT_FAILURE);
    }

    vid = redis_create_virtual_object_id(object_type);

    SWSS_LOG_DEBUG("translated RID %llx to VID %llx", rid, vid);

    sai_serialize_primitive(vid, str_vid);

    g_redisClient->hset(RIDTOVID, str_rid, str_vid);
    g_redisClient->hset(VIDTORID, str_vid, str_rid);

    return vid;
}
示例#4
0
static void sai_neighbor_entry_parse(
        const sai_neighbor_entry_t *neighbor_entry,
        switch_api_neighbor_t *api_neighbor) {

    SAI_ASSERT(sai_object_type_query(neighbor_entry->rif_id) == 
               SAI_OBJECT_TYPE_ROUTER_INTERFACE);

    api_neighbor->interface = (switch_handle_t) neighbor_entry->rif_id;
    api_neighbor->rw_type = SWITCH_API_NEIGHBOR_RW_TYPE_L3;
    sai_ip_addr_to_switch_ip_addr(&neighbor_entry->ip_address, &api_neighbor->ip_addr);
}
示例#5
0
sai_status_t sai_set_qos_map_attribute(_In_ sai_object_id_t qos_map_id,
                                       _In_ const sai_attribute_t *attr) {
  SAI_LOG_ENTER();

  sai_status_t status = SAI_STATUS_SUCCESS;

  SAI_ASSERT(sai_object_type_query(qos_map_id) == SAI_OBJECT_TYPE_QOS_MAPS);

  SAI_LOG_EXIT();

  return (sai_status_t)status;
}
示例#6
0
文件: saibuffer.c 项目: p4lang/switch
/**
 * @brief Set buffer pool attribute
 * @param[in] pool_id buffer pool id
 * @param[in] attr attribute
 * @return SAI_STATUS_SUCCESS on success
 *           Failure status code on error
 */
sai_status_t sai_set_buffer_pool_attribute(_In_ sai_object_id_t pool_id,
                                           _In_ const sai_attribute_t *attr) {
  SAI_LOG_ENTER();

  sai_status_t status = SAI_STATUS_SUCCESS;

  SAI_ASSERT(sai_object_type_query(pool_id) == SAI_OBJECT_TYPE_BUFFER_POOL);

  SAI_LOG_EXIT();

  return status;
}
示例#7
0
文件: saibuffer.c 项目: p4lang/switch
/**
 * @brief Set ingress priority group attribute
 * @param[in] ingress_pg_id ingress priority group id
 * @param[in] attr attribute to set
 *
 * @return  SAI_STATUS_SUCCESS on success
 *           Failure status code on error
 */
sai_status_t sai_set_ingress_priority_group_attribute(
    _In_ sai_object_id_t ingress_pg_id, _In_ const sai_attribute_t *attr) {
  SAI_LOG_ENTER();

  sai_status_t status = SAI_STATUS_SUCCESS;

  SAI_ASSERT(sai_object_type_query(ingress_pg_id) ==
             SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP);
  SAI_ASSERT(sai_object_type_query(attr->value.oid) ==
             SAI_OBJECT_TYPE_BUFFER_PROFILE);

  status = switch_api_priority_group_buffer_profile_set(
      device, ingress_pg_id, attr->value.oid);
  if (status != SAI_STATUS_SUCCESS) {
    SAI_LOG_ERROR("failed to set pg buffer profile :%s",
                  sai_status_to_string(status));
  }

  SAI_LOG_EXIT();

  return status;
}
示例#8
0
/*
* Routine Description:
*    Set router interface attribute
*
* Arguments:
*    [in] rif_id - router interface id
*    [in] attr - attribute
*
* Return Values:
*    SAI_STATUS_SUCCESS on success
*    Failure status code on error
*/
sai_status_t sai_set_router_interface_attribute(
    _In_ sai_object_id_t rif_id, _In_ const sai_attribute_t *attr) {
  SAI_LOG_ENTER();

  sai_status_t status = SAI_STATUS_SUCCESS;
  switch_status_t switch_status = SWITCH_STATUS_SUCCESS;

  if (!attr) {
    status = SAI_STATUS_INVALID_PARAMETER;
    SAI_LOG_ERROR("null attribute: %s", sai_status_to_string(status));
    return status;
  }

  SAI_ASSERT(sai_object_type_query(rif_id) == SAI_OBJECT_TYPE_ROUTER_INTERFACE);

  switch (attr->id) {
    case SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE:
      switch_status = switch_api_interface_ipv4_unicast_enabled_set(
          rif_id, attr->value.booldata);
      break;
    case SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE:
      switch_status = switch_api_interface_ipv6_unicast_enabled_set(
          rif_id, attr->value.booldata);
      break;
    case SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_MULTICAST_STATE:
      switch_status = switch_api_interface_ipv4_multicast_enabled_set(
          rif_id, attr->value.booldata);
      break;
    case SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_MULTICAST_STATE:
      switch_status = switch_api_interface_ipv6_multicast_enabled_set(
          rif_id, attr->value.booldata);
      break;
    case SAI_ROUTER_INTERFACE_ATTR_V4_URPF_MODE:
      switch_status = switch_api_interface_ipv4_urpf_mode_set(
          rif_id, sai_to_switch_urpf_mode(attr->value.s32));
      break;
    case SAI_ROUTER_INTERFACE_ATTR_V6_URPF_MODE:
      switch_status = switch_api_interface_ipv6_urpf_mode_set(
          rif_id, sai_to_switch_urpf_mode(attr->value.s32));
      break;
    default:
      return SAI_STATUS_INVALID_PARAMETER;
  }

  SAI_LOG_EXIT();

  status = sai_switch_status_to_sai_status(switch_status);
  return status;
}
示例#9
0
文件: saibuffer.c 项目: p4lang/switch
/**
 * @brief Get buffer profile attributes
 * @param[in] buffer_profile_id buffer profile id
 * @param[in] attr_count number of attributes
 * @param[inout] attr_list array of attributes
 * @return SAI_STATUS_SUCCESS on success
 *           Failure status code on error
 */
sai_status_t sai_get_buffer_profile_attribute(
    _In_ sai_object_id_t buffer_profile_id,
    _In_ uint32_t attr_count,
    _Inout_ sai_attribute_t *attr_list) {
  SAI_LOG_ENTER();

  sai_status_t status = SAI_STATUS_SUCCESS;

  SAI_ASSERT(sai_object_type_query(buffer_profile_id) ==
             SAI_OBJECT_TYPE_BUFFER_PROFILE);

  SAI_LOG_EXIT();

  return status;
}
示例#10
0
/**
 * @brief  Set Policer attribute
 *
 * @param[in] policer_id - Policer id
 * @param[in] attr - attribute
 *
 * @return SAI_STATUS_SUCCESS on success
 *        Failure status code on error
 */
sai_status_t sai_set_policer_attribute(_In_ sai_object_id_t policer_id,
                                       _In_ const sai_attribute_t *attr) {
  SAI_LOG_ENTER();

  sai_status_t status = SAI_STATUS_SUCCESS;

  if (!attr) {
    status = SAI_STATUS_INVALID_PARAMETER;
    SAI_LOG_ERROR("null attribute: %s", sai_status_to_string(status));
    return status;
  }

  SAI_ASSERT(sai_object_type_query(policer_id) == SAI_OBJECT_TYPE_POLICER);

  SAI_LOG_EXIT();
  return (sai_status_t)status;
}
示例#11
0
文件: saibuffer.c 项目: p4lang/switch
/**
 * @brief Remove buffer pool
 * @param[in] pool_id buffer pool id
 * @return SAI_STATUS_SUCCESS on success
 *           Failure status code on error
 */
sai_status_t sai_remove_buffer_pool(_In_ sai_object_id_t pool_id) {
  SAI_LOG_ENTER();

  sai_status_t status = SAI_STATUS_SUCCESS;

  SAI_ASSERT(sai_object_type_query(pool_id) == SAI_OBJECT_TYPE_BUFFER_POOL);

  status = switch_api_buffer_pool_delete(device, pool_id);
  if (status != SAI_STATUS_SUCCESS) {
    SAI_LOG_ERROR("failed to delete buffer pool: %s",
                  sai_status_to_string(status));
  }

  SAI_LOG_EXIT();

  return status;
}
示例#12
0
文件: sairouter.c 项目: krambn/switch
/*
* Routine Description:
*    Set virtual router attribute Value
*
* Arguments:
*    [in] vr_id - virtual router id
*    [in] attr - attribute
*
* Return Values:
*    SAI_STATUS_SUCCESS on success
*    Failure status code on error
*/
sai_status_t sai_set_virtual_router_entry_attribute(
    _In_ sai_object_id_t vr_id, _In_ const sai_attribute_t *attr) {
  SAI_LOG_ENTER();

  sai_status_t status = SAI_STATUS_SUCCESS;

  if (!attr) {
    status = SAI_STATUS_INVALID_PARAMETER;
    SAI_LOG_ERROR("null attribute: %s", sai_status_to_string(status));
    return status;
  }

  SAI_ASSERT(sai_object_type_query(vr_id) == SAI_OBJECT_TYPE_VIRTUAL_ROUTER);

  SAI_LOG_EXIT();

  return (sai_status_t)status;
}
示例#13
0
文件: saiipmc.c 项目: p4lang/switch
static void sai_ipmc_entry_parse(_In_ const sai_ipmc_entry_t *ipmc_entry,
                                 _Out_ switch_handle_t *vrf_handle,
                                 _Out_ switch_ip_addr_t *src_addr,
                                 _Out_ switch_ip_addr_t *grp_addr) {
  SAI_ASSERT(sai_object_type_query(ipmc_entry->vr_id) ==
             SAI_OBJECT_TYPE_VIRTUAL_ROUTER);
  *vrf_handle = (switch_handle_t)ipmc_entry->vr_id;

  memset(src_addr, 0, sizeof(switch_ip_addr_t));
  sai_ip_addr_to_switch_ip_addr(&(ipmc_entry->source), src_addr);
  if (((src_addr->type == SWITCH_API_IP_ADDR_V4) &&
       (src_addr->ip.v4addr == 0)) ||
      ((src_addr->type == SWITCH_API_IP_ADDR_V6) &&
       (memcmp(src_addr->ip.v6addr, &in6addr_any, sizeof(in6addr_any)) == 0))) {
    src_addr->prefix_len = 0;
  }
  sai_ip_prefix_to_switch_ip_addr(&(ipmc_entry->group), grp_addr);
}
示例#14
0
文件: sairouter.c 项目: krambn/switch
/*
* Routine Description:
*    Remove virtual router
*
* Arguments:
*    [in] vr_id - virtual router id
*
* Return Values:
*    SAI_STATUS_SUCCESS on success
*    Failure status code on error
*/
sai_status_t sai_remove_virtual_router_entry(_In_ sai_object_id_t vr_id) {
  SAI_LOG_ENTER();

  sai_status_t status = SAI_STATUS_SUCCESS;
  switch_status_t switch_status = SWITCH_STATUS_SUCCESS;

  SAI_ASSERT(sai_object_type_query(vr_id) == SAI_OBJECT_TYPE_VIRTUAL_ROUTER);

  switch_status = switch_api_vrf_delete(device, vr_id);
  status = sai_switch_status_to_sai_status(switch_status);

  if (status != SAI_STATUS_SUCCESS) {
    SAI_LOG_ERROR("failed to remove virtual router entry %lx : %s",
                  vr_id,
                  sai_status_to_string(status));
  }

  SAI_LOG_EXIT();
  return (sai_status_t)status;
}
示例#15
0
/*
* Routine Description:
*    Remove router interface
*
* Arguments:
*    [in] rif_id - router interface id
*
* Return Values:
*    SAI_STATUS_SUCCESS on success
*    Failure status code on error
*/
sai_status_t sai_remove_router_interface(_In_ sai_object_id_t rif_id) {
  SAI_LOG_ENTER();

  sai_status_t status = SAI_STATUS_SUCCESS;
  switch_status_t switch_status = SWITCH_STATUS_SUCCESS;

  SAI_ASSERT(sai_object_type_query(rif_id) == SAI_OBJECT_TYPE_ROUTER_INTERFACE);

  switch_status = switch_api_interface_delete(device, (switch_handle_t)rif_id);
  status = sai_switch_status_to_sai_status(switch_status);

  if (status != SAI_STATUS_SUCCESS) {
    SAI_LOG_ERROR("failed to remove router interface: %s",
                  sai_status_to_string(status));
  }

  SAI_LOG_EXIT();

  return (sai_status_t)status;
}
示例#16
0
/**
 * @brief Delete policer
 *
 * @param[in] policer_id - Policer id
 *
 * @return  SAI_STATUS_SUCCESS on success
 *         Failure status code on error
 */
sai_status_t sai_remove_policer(_In_ sai_object_id_t policer_id) {
  SAI_LOG_ENTER();

  sai_status_t status = SAI_STATUS_SUCCESS;
  switch_status_t switch_status = SWITCH_STATUS_SUCCESS;

  SAI_ASSERT(sai_object_type_query(policer_id) == SAI_OBJECT_TYPE_POLICER);

  switch_status = switch_api_meter_delete(device, policer_id);
  status = sai_switch_status_to_sai_status(switch_status);
  if (status != SAI_STATUS_SUCCESS) {
    SAI_LOG_ERROR("failed to delete policer %lx: %s",
                  policer_id,
                  sai_status_to_string(status));
  }

  SAI_LOG_EXIT();

  return (sai_status_t)status;
}
void helperCheckPortIds()
{
    SWSS_LOG_ENTER();

    auto laneMap = saiGetHardwareLaneMap();

    for (auto kv: laneMap)
    {
        sai_object_id_t portId = kv.second;

        // translate will create entry if missing
        // we assume here that port numbers didn't changed
        // during restarts
        sai_object_id_t vid = translate_rid_to_vid(portId);

        sai_object_type_t objectType = sai_object_type_query(portId);

        if (objectType == SAI_OBJECT_TYPE_NULL)
        {
            SWSS_LOG_ERROR("sai_object_type_query returned NULL type for RID %llx", portId);

            exit(EXIT_FAILURE);
        }

        std::string strObjectType;

        sai_serialize_primitive(objectType, strObjectType);

        std::string strVid;

        sai_serialize_primitive(vid, strVid);

        std::string strKey = "ASIC_STATE:" + strObjectType + ":" + strVid;

        g_redisClient->hset(strKey, "NULL", "NULL");
    }
}
/*
 * Routine Description:
 *    Create host interface.
 *
 * Arguments:
 *    [out] hif_id - host interface id
 *    [in] attr_count - number of attributes
 *    [in] attr_list - array of attributes
 *
 * Return Values:
 *    SAI_STATUS_SUCCESS on success
 *    Failure status code on error
 */
sai_status_t stub_create_host_interface(_Out_ sai_object_id_t     * hif_id,
                                        _In_ uint32_t               attr_count,
                                        _In_ const sai_attribute_t *attr_list)
{
    sai_status_t                 status;
    int                          ret;
    const sai_attribute_value_t *type, *rif_port, *name;
    uint32_t                     type_index, rif_port_index, name_index, rif_data;
    char                         key_str[MAX_KEY_STR_LEN];
    char                         list_str[MAX_LIST_VALUE_STR_LEN];
    static uint32_t              next_id = 0;
    char                         system_cmd[1024];

    STUB_LOG_ENTER();

    if (NULL == hif_id) {
        STUB_LOG_ERR("NULL host interface ID param\n");
        return SAI_STATUS_INVALID_PARAMETER;
    }

    if (SAI_STATUS_SUCCESS !=
        (status =
             check_attribs_metadata(attr_count, attr_list, host_interface_attribs, host_interface_vendor_attribs,
                                    SAI_OPERATION_CREATE))) {
        STUB_LOG_ERR("Failed attribs check\n");
        return status;
    }

    sai_attr_list_to_str(attr_count, attr_list, host_interface_attribs, MAX_LIST_VALUE_STR_LEN, list_str);
    STUB_LOG_NTC("Create host interface, %s\n", list_str);

    assert(SAI_STATUS_SUCCESS ==
           find_attrib_in_list(attr_count, attr_list, SAI_HOSTIF_ATTR_TYPE, &type, &type_index));
    assert(SAI_STATUS_SUCCESS ==
           find_attrib_in_list(attr_count, attr_list, SAI_HOSTIF_ATTR_NAME, &name, &name_index));

    if (SAI_HOSTIF_TYPE_NETDEV == type->s32) {
        if (SAI_STATUS_SUCCESS !=
            (status =
                 find_attrib_in_list(attr_count, attr_list, SAI_HOSTIF_ATTR_RIF_OR_PORT_ID, &rif_port,
                                     &rif_port_index))) {
            STUB_LOG_ERR("Missing mandatory attribute rif port id on create of host if netdev type\n");
            return SAI_STATUS_MANDATORY_ATTRIBUTE_MISSING;
        }

        if (SAI_OBJECT_TYPE_ROUTER_INTERFACE == sai_object_type_query(rif_port->oid)) {
            if (SAI_STATUS_SUCCESS !=
                (status = stub_object_to_type(rif_port->oid, SAI_OBJECT_TYPE_ROUTER_INTERFACE, &rif_data))) {
                return status;
            }
        } else if (SAI_OBJECT_TYPE_PORT == sai_object_type_query(rif_port->oid)) {
            if (SAI_STATUS_SUCCESS != (status = stub_object_to_type(rif_port->oid, SAI_OBJECT_TYPE_PORT, &rif_data))) {
                return status;
            }
        } else {
            STUB_LOG_ERR("Invalid rif port object type %s", SAI_TYPE_STR(sai_object_type_query(rif_port->oid)));
            return SAI_STATUS_INVALID_ATTR_VALUE_0 + rif_port_index;
        }
        snprintf(system_cmd, sizeof(system_cmd), "ip link add name %s type dummy", name->chardata);
        ret = system(system_cmd);
        if (0 != ret) {
            STUB_LOG_INF("Error on attempt to create dummy interface. Possibly interface already exists");
            return SAI_STATUS_SUCCESS;
        }

    } else if (SAI_HOSTIF_TYPE_FD == type->s32) {
    } else {
        STUB_LOG_ERR("Invalid host interface type %d\n", type->s32);
        return SAI_STATUS_INVALID_ATTR_VALUE_0 + type_index;
    }

    if (SAI_STATUS_SUCCESS != (status = stub_create_object(SAI_OBJECT_TYPE_HOST_INTERFACE, next_id++, hif_id))) {
        return status;
    }
    host_interface_key_to_str(*hif_id, key_str);
    STUB_LOG_NTC("Created host interface %s\n", key_str);

    STUB_LOG_EXIT();
    return SAI_STATUS_SUCCESS;
}
sai_status_t redis_generic_stats_function(
        _In_ sai_object_type_t object_type,
        _In_ sai_object_id_t object_id,
        _In_ const sai_enum_metadata_t *enum_metadata,
        _In_ uint32_t number_of_counters,
        _In_ const int32_t *counter_ids,
        _In_ sai_stats_mode_t mode,
        _Out_ uint64_t *counters)
{
    SWSS_LOG_ENTER();

    /*
     * Do all parameter validation.
     */

    if (object_id == SAI_NULL_OBJECT_ID)
    {
        SWSS_LOG_ERROR("object id is NULL");

        return SAI_STATUS_INVALID_PARAMETER;
    }

    sai_object_type_t ot = sai_object_type_query(object_id);

    if (ot != object_type)
    {
        SWSS_LOG_ERROR("object %s is %s but expected %s",
                sai_serialize_object_id(object_id).c_str(),
                sai_serialize_object_type(ot).c_str(),
                sai_serialize_object_type(object_type).c_str());

        return SAI_STATUS_INVALID_PARAMETER;
    }

    sai_object_id_t switch_id = sai_switch_id_query(object_id);

    if (switch_id == SAI_NULL_OBJECT_ID)
    {
        SWSS_LOG_ERROR("object %s does not correspond to any switch object",
                sai_serialize_object_id(object_id).c_str());

        return SAI_STATUS_INVALID_PARAMETER;
    }

    uint32_t count = number_of_counters & ~REDIS_COUNTERS_COUNT_MSB;

    if (count > REDIS_MAX_COUNTERS)
    {
        SWSS_LOG_ERROR("max supported counters to get/clear is %u, but %u given",
                REDIS_MAX_COUNTERS,
                count);

        return SAI_STATUS_INVALID_PARAMETER;
    }

    if (counter_ids == NULL)
    {
        SWSS_LOG_ERROR("counter ids pointer is NULL");

        return SAI_STATUS_INVALID_PARAMETER;
    }

    if (counters == NULL)
    {
        SWSS_LOG_ERROR("counters output pointer is NULL");

        return SAI_STATUS_INVALID_PARAMETER;
    }

    if (enum_metadata == NULL)
    {
        SWSS_LOG_ERROR("enum metadata pointer is NULL, bug?");

        return SAI_STATUS_FAILURE;
    }

    for (uint32_t i = 0; i < count; i++)
    {
        if (sai_metadata_get_enum_value_name(enum_metadata, counter_ids[i]) == NULL)
        {
            SWSS_LOG_ERROR("counter id %u is not allowed on %s", counter_ids[i], enum_metadata->name);

            return SAI_STATUS_INVALID_PARAMETER;
        }
    }

    switch (mode)
    {
        case SAI_STATS_MODE_READ:
        case SAI_STATS_MODE_READ_AND_CLEAR:
            break;

        default:

            SWSS_LOG_ERROR("counters mode is invalid %d", mode);

            return SAI_STATUS_INVALID_PARAMETER;
    }

    return internal_redis_generic_stats_function(
            object_type,
            object_id,
            switch_id,
            enum_metadata,
            number_of_counters,
            counter_ids,
            mode,
            counters);
}
示例#20
0
/*
* Routine Description:
*    Get router interface attribute
*
* Arguments:
*    [in] rif_id - router interface id
*    [in] attr_count - number of attributes
*    [inout] attr_list - array of attributes
*
* Return Values:
*    SAI_STATUS_SUCCESS on success
*    Failure status code on error
*/
sai_status_t sai_get_router_interface_attribute(
    _In_ sai_object_id_t rif_id,
    _In_ uint32_t attr_count,
    _Inout_ sai_attribute_t *attr_list) {
  SAI_LOG_ENTER();

  sai_status_t status = SAI_STATUS_SUCCESS;

  if (!attr_list) {
    status = SAI_STATUS_INVALID_PARAMETER;
    SAI_LOG_ERROR("null attribute: %s", sai_status_to_string(status));
    return status;
  }

  uint32_t index;
  uint64_t value;
  switch_status_t switch_status = -1;
  sai_attribute_t *attribute;
  for (index = 0; index < attr_count; index++) {
    attribute = &attr_list[index];
    switch (attribute->id) {
      case SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID:
        switch_status = switch_api_interface_attribute_get(
            (switch_handle_t)rif_id, SWITCH_INTF_ATTR_VRF, &value);
        attribute->value.oid = value;
        break;
      case SAI_ROUTER_INTERFACE_ATTR_TYPE:
        break;
      case SAI_ROUTER_INTERFACE_ATTR_PORT_ID:
        switch_status = switch_api_interface_attribute_get(
            (switch_handle_t)rif_id, SWITCH_INTF_ATTR_PORT_ID, &value);
        attribute->value.oid = value;
        break;
      case SAI_ROUTER_INTERFACE_ATTR_VLAN_ID:
        switch_status = switch_api_interface_attribute_get(
            (switch_handle_t)rif_id, SWITCH_INTF_ATTR_VLAN_ID, &value);
        attribute->value.u16 = value;
        break;
      case SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS:
        switch_status = switch_api_interface_attribute_get(
            (switch_handle_t)rif_id, SWITCH_INTF_ATTR_RMAC_ADDR, &value);
        memcpy(attribute->value.mac, (uint8_t *)&value, sizeof(sai_mac_t));
        break;
      case SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE:
        switch_status = switch_api_interface_attribute_get(
            (switch_handle_t)rif_id, SWITCH_INTF_ATTR_V4_UNICAST, &value);
        attribute->value.booldata = value;
        break;
      case SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE:
        switch_status = switch_api_interface_attribute_get(
            (switch_handle_t)rif_id, SWITCH_INTF_ATTR_V6_UNICAST, &value);
        attribute->value.booldata = value;
        break;
      case SAI_ROUTER_INTERFACE_ATTR_MTU:
        // return the default for now
        attribute->value.u32 = 1514;
        break;
      default:
        return SAI_STATUS_INVALID_PARAMETER;
    }

    if ((status = sai_switch_status_to_sai_status(switch_status)) !=
        SAI_STATUS_SUCCESS) {
      return status;
    }
  }

  SAI_ASSERT(sai_object_type_query(rif_id) == SAI_OBJECT_TYPE_ROUTER_INTERFACE);

  SAI_LOG_EXIT();

  return (sai_status_t)status;
}
void channelOpSetReadOnlyAttribute(
        _In_ const std::string &key,
        _In_ const std::vector<swss::FieldValueTuple> &values)
{
    SWSS_LOG_ENTER();

    for (const auto &v: values)
    {
        SWSS_LOG_DEBUG("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str());
    }

    if (values.size() != 1)
    {
        SWSS_LOG_ERROR("expected 1 value only, but given: %zu", values.size());
        return;
    }

    const std::string &str_object_type = key.substr(0, key.find(":"));
    const std::string &str_object_id = key.substr(key.find(":") + 1);

    sai_object_type_t object_type;
    sai_deserialize_object_type(str_object_type, object_type);

    if (object_type == SAI_OBJECT_TYPE_NULL || object_type >= SAI_OBJECT_TYPE_EXTENSIONS_MAX)
    {
        SWSS_LOG_ERROR("invalid object type: %d", object_type);
        return;
    }

    auto info = sai_metadata_get_object_type_info(object_type);

    if (info->isnonobjectid)
    {
        SWSS_LOG_ERROR("non object id %s is not supported yet", str_object_type.c_str());
        return;
    }

    sai_object_id_t object_id;

    sai_deserialize_object_id(str_object_id, object_id);

    sai_object_type_t ot = sai_object_type_query(object_id);

    if (ot != object_type)
    {
        SWSS_LOG_ERROR("object type is differnt than provided %s, but oid is %s",
                str_object_type.c_str(), sai_serialize_object_type(ot).c_str());
        return;
    }

    sai_object_id_t switch_id = sai_switch_id_query(object_id);

    if (switch_id == SAI_NULL_OBJECT_ID)
    {
        SWSS_LOG_ERROR("failed to find switch id for oid %s", str_object_id.c_str());
        return;
    }

    // oid is validated and we got switch id

    const std::string &str_attr_id = fvField(values.at(0));
    const std::string &str_attr_value = fvValue(values.at(0));

    auto meta = sai_metadata_get_attr_metadata_by_attr_id_name(str_attr_id.c_str());

    if (meta == NULL)
    {
        SWSS_LOG_ERROR("failed to find attr %s", str_attr_id.c_str());
        return;
    }

    if (meta->objecttype != ot)
    {
        SWSS_LOG_ERROR("attr %s belongs to differnt object type than oid: %s",
                str_attr_id.c_str(), sai_serialize_object_type(ot).c_str());
        return;
    }

    // we got attr metadata

    sai_attribute_t attr;

    attr.id = meta->attrid;

    sai_deserialize_attr_value(str_attr_value, *meta, attr);

    SWSS_LOG_NOTICE("switch id is %s", sai_serialize_object_id(switch_id).c_str());

    sai_status_t status = meta_unittests_allow_readonly_set_once(meta->objecttype, meta->attrid);

    if (status != SAI_STATUS_SUCCESS)
    {
        SWSS_LOG_ERROR("failed to enable SET readonly attribute once: %s", sai_serialize_status(status).c_str());
        return;
    }

    sai_object_meta_key_t meta_key = { .objecttype = ot, .objectkey = { .key = { .object_id = object_id } } };

    status = info->set(&meta_key, &attr);

    if (status != SAI_STATUS_SUCCESS)
    {
        SWSS_LOG_ERROR("failed to set %s to %s on %s",
                str_attr_id.c_str(), str_attr_value.c_str(), str_object_id.c_str());
    }
    else
    {
        SWSS_LOG_NOTICE("SUCCESS to set %s to %s on %s",
                str_attr_id.c_str(), str_attr_value.c_str(), str_object_id.c_str());
    }

    sai_deserialize_free_attribute_value(meta->attrvaluetype, attr);
}
void channelOpSetStats(
        _In_ const std::string &key,
        _In_ const std::vector<swss::FieldValueTuple> &values)
{
    SWSS_LOG_ENTER();

    // NOTE: we need to find stats for specific object, later SAI already have
    // this feature and this search could be optimized here:
    // https://github.com/opencomputeproject/SAI/commit/acc83933ff21c68e8ef10c9826de45807fdc0438

    sai_object_id_t oid;

    sai_deserialize_object_id(key, oid);

    sai_object_type_t ot = sai_object_type_query(oid);

    if (ot == SAI_OBJECT_TYPE_NULL)
    {
        SWSS_LOG_ERROR("invalid object id: %s", key.c_str());
        return;
    }

    sai_object_id_t switch_id = sai_switch_id_query(oid);

    if (switch_id == SAI_NULL_OBJECT_ID)
    {
        SWSS_LOG_ERROR("unable to get switch_id from oid: %s", key.c_str());
        return;
    }

    /*
     * Check if object for statistics was created and exists on switch.
     */

    auto &objectHash = g_switch_state_map.at(switch_id)->objectHash.at(ot);

    auto it = objectHash.find(key.c_str());

    if (it == objectHash.end())
    {
        SWSS_LOG_ERROR("object not found: %s", key.c_str());
        return;
    }

    /*
     * Check if object for statistics have statistic map created, if not
     * create empty map.
     */

    auto &countersMap = g_switch_state_map.at(switch_id)->countersMap;

    auto mapit = countersMap.find(key);

    if (mapit == countersMap.end())
        countersMap[key] = std::map<int,uint64_t>();

    /*
     * Find stats enum based on object type.  In new metadata we have enum on
     * object type, but here we need to find it manually enum is in format
     * "sai_" + object_type + "_stat_t"
     */

    std::string lower_ot = sai_serialize_object_type(ot).substr(16);  // 16 = skip "SAI_OBJECT_TYPE_"

    std::transform(lower_ot.begin(), lower_ot.end(), lower_ot.begin(), ::tolower);

    std::string stat_enum_name = "sai_" + lower_ot + "_stat_t";

    const sai_enum_metadata_t* statenum = NULL;

    for (size_t i = 0; i < sai_metadata_all_enums_count; ++i)
    {
        if (sai_metadata_all_enums[i]->name == stat_enum_name)
        {
            SWSS_LOG_INFO("found enum %s", stat_enum_name.c_str());
            // found
            statenum = sai_metadata_all_enums[i];
            break;
        }
    }

    if (statenum == NULL)
    {
        SWSS_LOG_ERROR("failed to find stat enum: %s", stat_enum_name.c_str());
        return;
    }

    for (auto v: values)
    {
        // value format: stat_enum_name:uint64

        auto name = fvField(v);

        uint64_t value;

        if (sscanf(fvValue(v).c_str(), "%lu", &value) != 1)
        {
            SWSS_LOG_ERROR("failed to deserialize %s as couner value uint64_t", fvValue(v).c_str());
        }

        // linear search

        int enumvalue = -1;

        for (size_t i = 0; i < statenum->valuescount; ++i)
        {
            if (statenum->valuesnames[i] == name)
            {
                enumvalue = statenum->values[i];
                break;
            }
        }

        if (enumvalue == -1)
        {
            SWSS_LOG_ERROR("failed to find enum value: %s", name.c_str());
            continue;
        }

        SWSS_LOG_DEBUG("writting %s = %lu on %s", name.c_str(), value, key.c_str());

        countersMap.at(key)[enumvalue] = value;
    }
}
void handleUnittestChannelOp(
        _In_ const std::string &op,
        _In_ const std::string &key,
        _In_ const std::vector<swss::FieldValueTuple> &values)
{
    /*
     * Since we will access and modify DB we need to be under mutex.
     *
     * NOTE: since this unittest channel is handled in thread, then that means
     * there is a DELAY from producer and consumer thread in VS, so if user
     * will set value on the specific READ_ONLY value he should wait for some
     * time until that value will be propagated to virtual switch.
     */

    MUTEX();

    SWSS_LOG_ENTER();

    SWSS_LOG_NOTICE("read only SET: op = %s, key = %s", op.c_str(), key.c_str());

    if (op == SAI_VS_UNITTEST_ENABLE_UNITTESTS)
    {
        bool enable = (key == "true");

        meta_unittests_enable(enable);
    }
    else if (op == SAI_VS_UNITTEST_SET_RO_OP)
    {
        for (const auto &v: values)
        {
            SWSS_LOG_DEBUG("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str());
        }

        if (values.size() != 1)
        {
            SWSS_LOG_ERROR("expected 1 value only, but given: %zu", values.size());
            return;
        }

        const std::string &str_object_type = key.substr(0, key.find(":"));
        const std::string &str_object_id = key.substr(key.find(":") + 1);

        sai_object_type_t object_type;
        sai_deserialize_object_type(str_object_type, object_type);

        if (object_type == SAI_OBJECT_TYPE_NULL || object_type >= SAI_OBJECT_TYPE_MAX)
        {
            SWSS_LOG_ERROR("invalid object type: %d", object_type);
            return;
        }

        auto info = sai_metadata_get_object_type_info(object_type);

        if (info->isnonobjectid)
        {
            SWSS_LOG_ERROR("non object id %s is not supported yet", str_object_type.c_str());
            return;
        }

        sai_object_id_t object_id;

        sai_deserialize_object_id(str_object_id, object_id);

        sai_object_type_t ot = sai_object_type_query(object_id);

        if (ot != object_type)
        {
            SWSS_LOG_ERROR("object type is differnt than provided %s, but oid is %s",
                    str_object_type.c_str(), sai_serialize_object_type(ot).c_str());
            return;
        }

        sai_object_id_t switch_id = sai_switch_id_query(object_id);

        if (switch_id == SAI_NULL_OBJECT_ID)
        {
            SWSS_LOG_ERROR("failed to find switch id for oid %s", str_object_id.c_str());
            return;
        }

        // oid is validated and we got switch id

        const std::string &str_attr_id = fvField(values.at(0));
        const std::string &str_attr_value = fvValue(values.at(0));

        auto meta = sai_metadata_get_attr_metadata_by_attr_id_name(str_attr_id.c_str());

        if (meta == NULL)
        {
            SWSS_LOG_ERROR("failed to find attr %s", str_attr_id.c_str());
            return;
        }

        if (meta->objecttype != ot)
        {
            SWSS_LOG_ERROR("attr %s belongs to differnt object type than oid: %s",
                    str_attr_id.c_str(), sai_serialize_object_type(ot).c_str());
            return;
        }

        // we got attr metadata

        sai_attribute_t attr;

        attr.id = meta->attrid;

        sai_deserialize_attr_value(str_attr_value, *meta, attr);

        SWSS_LOG_NOTICE("switch id is %s", sai_serialize_object_id(switch_id).c_str());

        sai_status_t status = meta_unittests_allow_readonly_set_once(meta->objecttype, meta->attrid);

        if (status != SAI_STATUS_SUCCESS)
        {
            SWSS_LOG_ERROR("failed to enable SET readonly attribute once: %s", sai_serialize_status(status).c_str());
            return;
        }

        sai_object_meta_key_t meta_key = { .objecttype = ot, .objectkey = { .key = { .object_id = object_id } } };

        status = info->set(&meta_key, &attr);

        if (status != SAI_STATUS_SUCCESS)
        {
            SWSS_LOG_ERROR("failed to set %s to %s on %s",
                    str_attr_id.c_str(), str_attr_value.c_str(), str_object_id.c_str());
        }
        else
        {
            SWSS_LOG_NOTICE("SUCCESS to set %s to %s on %s",
                    str_attr_id.c_str(), str_attr_value.c_str(), str_object_id.c_str());
        }

        sai_deserialize_free_attribute_value(meta->attrvaluetype, attr);
    }
    else
    {
示例#24
0
sai_status_t sai_value_to_str(_In_ sai_attribute_value_t      value,
                              _In_ sai_attribute_value_type_t type,
                              _In_ uint32_t                   max_length,
                              _Out_ char                     *value_str)
{
    uint32_t          ii;
    uint32_t          pos = 0;
    uint32_t          count;
    stub_object_id_t *stub_object_id;

    if (NULL == value_str) {
        STUB_LOG_ERR("NULL value str");
        return SAI_STATUS_INVALID_PARAMETER;
    }

    *value_str = '\0';

    switch (type) {
    case SAI_ATTR_VAL_TYPE_BOOL:
        snprintf(value_str, max_length, "%u", value.booldata);
        break;

    case SAI_ATTR_VAL_TYPE_CHARDATA:
        snprintf(value_str, max_length, "%s", value.chardata);
        break;

    case SAI_ATTR_VAL_TYPE_U8:
        snprintf(value_str, max_length, "%u", value.u8);
        break;

    case SAI_ATTR_VAL_TYPE_S8:
        snprintf(value_str, max_length, "%d", value.s8);
        break;

    case SAI_ATTR_VAL_TYPE_U16:
        snprintf(value_str, max_length, "%u", value.u16);
        break;

    case SAI_ATTR_VAL_TYPE_S16:
        snprintf(value_str, max_length, "%d", value.s16);
        break;

    case SAI_ATTR_VAL_TYPE_U32:
        snprintf(value_str, max_length, "%u", value.u32);
        break;

    case SAI_ATTR_VAL_TYPE_S32:
        snprintf(value_str, max_length, "%d", value.s32);
        break;

    case SAI_ATTR_VAL_TYPE_U64:
        snprintf(value_str, max_length, "%" PRIu64, value.u64);
        break;

    case SAI_ATTR_VAL_TYPE_S64:
        snprintf(value_str, max_length, "%" PRId64, value.s64);
        break;

    case SAI_ATTR_VAL_TYPE_MAC:
        snprintf(value_str, max_length, "[%02x:%02x:%02x:%02x:%02x:%02x]",
                 value.mac[0],
                 value.mac[1],
                 value.mac[2],
                 value.mac[3],
                 value.mac[4],
                 value.mac[5]);
        break;

    /* IP is in network order */
    case SAI_ATTR_VAL_TYPE_IPV4:
        sai_ipv4_to_str(value.ip4, max_length, value_str, NULL);
        break;

    case SAI_ATTR_VAL_TYPE_IPV6:
        sai_ipv6_to_str(value.ip6, max_length, value_str, NULL);
        break;

    case SAI_ATTR_VAL_TYPE_IPADDR:
        sai_ipaddr_to_str(value.ipaddr, max_length, value_str, NULL);
        break;

    case SAI_ATTR_VAL_TYPE_OID:
        stub_object_id = (stub_object_id_t*)&value.oid;
        snprintf(value_str, max_length, "%s %x",
                 SAI_TYPE_STR(sai_object_type_query(value.oid)), stub_object_id->data);
        break;

    case SAI_ATTR_VAL_TYPE_OBJLIST:
    case SAI_ATTR_VAL_TYPE_U32LIST:
    case SAI_ATTR_VAL_TYPE_S32LIST:
    case SAI_ATTR_VAL_TYPE_VLANLIST:
    case SAI_ATTR_VAL_TYPE_PORTBREAKOUT:
        if (SAI_ATTR_VAL_TYPE_PORTBREAKOUT == type) {
            pos += snprintf(value_str, max_length, "breakout mode %d.", value.portbreakout.breakout_mode);
        }
        if (pos > max_length) {
            return SAI_STATUS_SUCCESS;
        }

        count = (SAI_ATTR_VAL_TYPE_OBJLIST == type) ? value.objlist.count :
                (SAI_ATTR_VAL_TYPE_U32LIST == type) ? value.u32list.count :
                (SAI_ATTR_VAL_TYPE_S32LIST == type) ? value.s32list.count :
                (SAI_ATTR_VAL_TYPE_VLANLIST == type) ? value.vlanlist.count :
                value.portbreakout.port_list.count;
        pos += snprintf(value_str + pos, max_length - pos, "%u : [", count);
        if (pos > max_length) {
            return SAI_STATUS_SUCCESS;
        }

        for (ii = 0; ii < count; ii++) {
            if (SAI_ATTR_VAL_TYPE_OBJLIST == type) {
                pos += snprintf(value_str + pos, max_length - pos, " %" PRIx64, value.objlist.list[ii]);
            } else if (SAI_ATTR_VAL_TYPE_U32LIST == type) {
                pos += snprintf(value_str + pos, max_length - pos, " %u", value.u32list.list[ii]);
            } else if (SAI_ATTR_VAL_TYPE_S32LIST == type) {
                pos += snprintf(value_str + pos, max_length - pos, " %d", value.s32list.list[ii]);
            } else if (SAI_ATTR_VAL_TYPE_VLANLIST == type) {
                pos += snprintf(value_str + pos, max_length - pos, " %u", value.vlanlist.list[ii]);
            } else {
                pos += snprintf(value_str + pos, max_length - pos, " %" PRIx64, value.portbreakout.port_list.list[ii]);
            }
            if (pos > max_length) {
                return SAI_STATUS_SUCCESS;
            }
        }
        snprintf(value_str + pos, max_length - pos, "]");
        break;


    case SAI_ATTR_VAL_TYPE_ACLFIELD:
    case SAI_ATTR_VAL_TYPE_ACLACTION:
        /* TODO : implement if in case it is used */
        snprintf(value_str, max_length, "Not implemented value type %d", type);
        return SAI_STATUS_NOT_IMPLEMENTED;

    case SAI_ATTR_VAL_TYPE_UNDETERMINED:
    default:
        snprintf(value_str, max_length, "Invalid/Unsupported value type %d", type);
        return SAI_STATUS_INVALID_PARAMETER;
    }

    return SAI_STATUS_SUCCESS;
}
示例#25
0
/*
* Routine Description:
*    Create router interface.
*
* Arguments:
*    [out] rif_id - router interface id
*    [in] attr_count - number of attributes
*    [in] attr_list - array of attributes
*
* Return Values:
*    SAI_STATUS_SUCCESS on success
*    Failure status code on error
*/
sai_status_t sai_create_router_interface(
    _Out_ sai_object_id_t *rif_id,
    _In_ uint32_t attr_count,
    _In_ const sai_attribute_t *attr_list) {
  SAI_LOG_ENTER();

  sai_status_t status = SAI_STATUS_SUCCESS;
  switch_api_interface_info_t intf_info;
  const sai_attribute_t *attribute;
  sai_router_interface_type_t sai_intf_type = -1;
  uint32_t index = 0;

  if (!attr_list) {
    status = SAI_STATUS_INVALID_PARAMETER;
    SAI_LOG_ERROR("null attribute list: %s", sai_status_to_string(status));
    return status;
  }

  memset(&intf_info, 0, sizeof(switch_api_interface_info_t));
  intf_info.ipv4_unicast_enabled = true;
  intf_info.ipv6_unicast_enabled = true;
  intf_info.ipv4_multicast_enabled = false;
  intf_info.ipv6_multicast_enabled = false;
  intf_info.ipv4_urpf_mode = SWITCH_API_RPF_CHECK_DEFAULT;
  intf_info.ipv6_urpf_mode = SWITCH_API_RPF_CHECK_DEFAULT;
  for (index = 0; index < attr_count; index++) {
    attribute = &attr_list[index];
    switch (attribute->id) {
      case SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID:
        SAI_ASSERT(sai_object_type_query(attribute->value.oid) ==
                   SAI_OBJECT_TYPE_VIRTUAL_ROUTER);
        intf_info.vrf_handle = (switch_handle_t)attribute->value.oid;
        break;
      case SAI_ROUTER_INTERFACE_ATTR_TYPE:
        sai_intf_type = attribute->value.s32;
        break;
      case SAI_ROUTER_INTERFACE_ATTR_PORT_ID:
        SAI_ASSERT(sai_intf_type == SAI_ROUTER_INTERFACE_TYPE_PORT);
        intf_info.type = SWITCH_API_INTERFACE_L3;
        intf_info.u.port_lag_handle = attribute->value.oid;
        break;
      case SAI_ROUTER_INTERFACE_ATTR_VLAN_ID:
        SAI_ASSERT(sai_intf_type == SAI_ROUTER_INTERFACE_TYPE_VLAN);
        intf_info.type = SWITCH_API_INTERFACE_L3_VLAN;
        intf_info.u.vlan_id = attribute->value.u16;
        break;
      case SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS:
        intf_info.mac_valid = TRUE;
        memcpy(&intf_info.mac, &attribute->value.mac, 6);
        break;
      case SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE:
        intf_info.ipv4_unicast_enabled = attribute->value.booldata;
        break;
      case SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE:
        intf_info.ipv6_unicast_enabled = attribute->value.booldata;
        break;
      case SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_MULTICAST_STATE:
        intf_info.ipv4_multicast_enabled = attribute->value.booldata;
        break;
      case SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_MULTICAST_STATE:
        intf_info.ipv6_multicast_enabled = attribute->value.booldata;
        break;
      case SAI_ROUTER_INTERFACE_ATTR_V4_URPF_MODE:
        intf_info.ipv4_urpf_mode =
            sai_to_switch_urpf_mode(attribute->value.s32);
        break;
      case SAI_ROUTER_INTERFACE_ATTR_V6_URPF_MODE:
        intf_info.ipv6_urpf_mode =
            sai_to_switch_urpf_mode(attribute->value.s32);
        break;
      case SAI_ROUTER_INTERFACE_ATTR_MTU:
        // TODO:
        break;
      default:
        return SAI_STATUS_INVALID_PARAMETER;
    }
  }

  *rif_id = (sai_object_id_t)switch_api_interface_create(device, &intf_info);
  status = (*rif_id == SWITCH_API_INVALID_HANDLE) ? SAI_STATUS_FAILURE
                                                  : SAI_STATUS_SUCCESS;

  if (status != SAI_STATUS_SUCCESS) {
    SAI_LOG_ERROR("failed to create router interface: %s",
                  sai_status_to_string(status));
  }

  SAI_LOG_EXIT();

  return (sai_status_t)status;
}