in vslib/SwitchStateBaseHostif.cpp [516:694]
sai_status_t SwitchStateBase::vs_create_hostif_tap_interface(
_In_ uint32_t attr_count,
_In_ const sai_attribute_t *attr_list)
{
SWSS_LOG_ENTER();
// validate SAI_HOSTIF_ATTR_TYPE
auto attr_type = sai_metadata_get_attr_by_id(SAI_HOSTIF_ATTR_TYPE, attr_count, attr_list);
if (attr_type == NULL)
{
SWSS_LOG_ERROR("attr SAI_HOSTIF_ATTR_TYPE was not passed");
return SAI_STATUS_FAILURE;
}
/* The genetlink host interface is created to associate trap group to genetlink family and multicast group
* created by driver. It does not create any netdev interface. Hence skipping tap interface creation
*/
if (attr_type->value.s32 == SAI_HOSTIF_TYPE_GENETLINK)
{
SWSS_LOG_DEBUG("Skipping tap create for hostif type genetlink");
return SAI_STATUS_SUCCESS;
}
if (attr_type->value.s32 != SAI_HOSTIF_TYPE_NETDEV)
{
SWSS_LOG_ERROR("only SAI_HOSTIF_TYPE_NETDEV is supported");
return SAI_STATUS_FAILURE;
}
// validate SAI_HOSTIF_ATTR_OBJ_ID
auto attr_obj_id = sai_metadata_get_attr_by_id(SAI_HOSTIF_ATTR_OBJ_ID, attr_count, attr_list);
if (attr_obj_id == NULL)
{
SWSS_LOG_ERROR("attr SAI_HOSTIF_ATTR_OBJ_ID was not passed");
return SAI_STATUS_FAILURE;
}
sai_object_id_t obj_id = attr_obj_id->value.oid;
sai_object_type_t ot = objectTypeQuery(obj_id);
if (ot == SAI_OBJECT_TYPE_VLAN)
{
SWSS_LOG_DEBUG("Skipping tap creation for hostif with object type VLAN");
return SAI_STATUS_SUCCESS;
}
if (ot != SAI_OBJECT_TYPE_PORT)
{
SWSS_LOG_ERROR("SAI_HOSTIF_ATTR_OBJ_ID=%s expected to be PORT but is: %s",
sai_serialize_object_id(obj_id).c_str(),
sai_serialize_object_type(ot).c_str());
return SAI_STATUS_FAILURE;
}
// validate SAI_HOSTIF_ATTR_NAME
auto attr_name = sai_metadata_get_attr_by_id(SAI_HOSTIF_ATTR_NAME, attr_count, attr_list);
if (attr_name == NULL)
{
SWSS_LOG_ERROR("attr SAI_HOSTIF_ATTR_NAME was not passed");
return SAI_STATUS_FAILURE;
}
if (strnlen(attr_name->value.chardata, sizeof(attr_name->value.chardata)) >= MAX_INTERFACE_NAME_LEN)
{
SWSS_LOG_ERROR("interface name is too long: %.*s", MAX_INTERFACE_NAME_LEN, attr_name->value.chardata);
return SAI_STATUS_FAILURE;
}
std::string name = std::string(attr_name->value.chardata);
// create TAP device
SWSS_LOG_INFO("creating hostif %s", name.c_str());
int tapfd = vs_create_tap_device(name.c_str(), IFF_TAP | IFF_MULTI_QUEUE | IFF_NO_PI);
if (tapfd < 0)
{
SWSS_LOG_ERROR("failed to create TAP device for %s", name.c_str());
return SAI_STATUS_FAILURE;
}
SWSS_LOG_INFO("created TAP device for %s, fd: %d", name.c_str(), tapfd);
sai_attribute_t attr;
memset(&attr, 0, sizeof(attr));
attr.id = SAI_SWITCH_ATTR_SRC_MAC_ADDRESS;
sai_status_t status = get(SAI_OBJECT_TYPE_SWITCH, m_switch_id, 1, &attr);
if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("failed to get SAI_SWITCH_ATTR_SRC_MAC_ADDRESS on switch %s: %s",
sai_serialize_object_id(m_switch_id).c_str(),
sai_serialize_status(status).c_str());
}
int err = vs_set_dev_mac_address(name.c_str(), attr.value.mac);
if (err < 0)
{
SWSS_LOG_ERROR("failed to set MAC address %s for %s",
sai_serialize_mac(attr.value.mac).c_str(),
name.c_str());
close(tapfd);
return SAI_STATUS_FAILURE;
}
std::string vname = vs_get_veth_name(name, obj_id);
int mtu = ETH_FRAME_BUFFER_SIZE;
sai_attribute_t attrmtu;
attrmtu.id = SAI_PORT_ATTR_MTU;
if (get(SAI_OBJECT_TYPE_PORT, obj_id, 1, &attrmtu) == SAI_STATUS_SUCCESS)
{
mtu = attrmtu.value.u32;
SWSS_LOG_INFO("setting new MTU: %d on %s", mtu, vname.c_str());
}
vs_set_dev_mtu(vname.c_str(), mtu);
attr.id = SAI_PORT_ATTR_ADMIN_STATE;
status = get(SAI_OBJECT_TYPE_PORT, obj_id, 1, &attr);
if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("failed to get admin state for port %s",
sai_serialize_object_id(obj_id).c_str());
return status;
}
if (ifup(vname.c_str(), obj_id, attr.value.booldata, false))
{
SWSS_LOG_ERROR("ifup failed on %s", vname.c_str());
return SAI_STATUS_FAILURE;
}
if (!hostif_create_tap_veth_forwarding(name, tapfd, obj_id))
{
SWSS_LOG_ERROR("forwarding rule on %s was not added", name.c_str());
}
SWSS_LOG_INFO("mapping interface %s to port id %s",
vname.c_str(),
sai_serialize_object_id(obj_id).c_str());
setIfNameToPortId(vname, obj_id);
setPortIdToTapName(obj_id, name);
SWSS_LOG_INFO("created tap interface %s", name.c_str());
return SAI_STATUS_SUCCESS;
}