Skip to content

Commit 6cb1b31

Browse files
authored
Add support for port remove and port create (no warm boot) (#500)
* Add support for port remove and port create * Fix aspell dictionary * Remove invalid comments * fix merge issues
1 parent 83d86ed commit 6cb1b31

File tree

10 files changed

+1132
-76
lines changed

10 files changed

+1132
-76
lines changed

meta/sai_meta.cpp

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,17 @@ bool meta_unittests_enabled()
4444
return unittests_enabled;
4545
}
4646

47+
/**
48+
* @brief Port map to related objects set.
49+
*
50+
* Key in map is port OID, and value is set of related objects ids
51+
* like queues, ipgs and scheduler groups.
52+
*
53+
* This map will help to identify objects to be automatically removed
54+
* when port will be removed.
55+
*/
56+
std::map<sai_object_id_t, std::set<sai_object_id_t>> map_port_to_related_set;
57+
4758
sai_status_t meta_unittests_allow_readonly_set_once(
4859
_In_ sai_object_type_t object_type,
4960
_In_ int32_t attr_id)
@@ -206,6 +217,13 @@ class SaiAttrWrapper
206217
return &m_attr;
207218
}
208219

220+
const sai_attr_metadata_t* getMeta() const
221+
{
222+
SWSS_LOG_ENTER();
223+
224+
return m_meta;
225+
}
226+
209227
private:
210228

211229
SaiAttrWrapper(const SaiAttrWrapper&);
@@ -453,6 +471,8 @@ sai_status_t meta_init_db()
453471
ObjectAttrHash.clear();
454472
AttributeKeys.clear();
455473

474+
map_port_to_related_set.clear();
475+
456476
return SAI_STATUS_SUCCESS;
457477
}
458478

@@ -1705,6 +1725,147 @@ sai_status_t meta_generic_validation_create(
17051725
return SAI_STATUS_SUCCESS;
17061726
}
17071727

1728+
bool meta_is_object_in_default_state(
1729+
_In_ sai_object_id_t oid)
1730+
{
1731+
SWSS_LOG_ENTER();
1732+
1733+
if (oid == SAI_NULL_OBJECT_ID)
1734+
SWSS_LOG_THROW("not expected NULL object id");
1735+
1736+
if (!object_reference_exists(oid))
1737+
{
1738+
SWSS_LOG_WARN("object %s refrence not exists, bug!",
1739+
sai_serialize_object_id(oid).c_str());
1740+
return false;
1741+
}
1742+
1743+
sai_object_meta_key_t meta_key;
1744+
1745+
meta_key.objecttype = sai_object_type_query(oid);
1746+
meta_key.objectkey.key.object_id = oid;
1747+
1748+
std::string key = sai_serialize_object_meta_key(meta_key);
1749+
1750+
if (!object_exists(key))
1751+
{
1752+
SWSS_LOG_WARN("object %s don't exists in local database, bug!",
1753+
sai_serialize_object_id(oid).c_str());
1754+
return false;
1755+
}
1756+
1757+
auto& attrs = ObjectAttrHash[key];
1758+
1759+
for (const auto& attr: attrs)
1760+
{
1761+
auto &md = *attr.second->getMeta();
1762+
1763+
auto *a = attr.second->getattr();
1764+
1765+
if (md.isreadonly)
1766+
continue;
1767+
1768+
if (!md.isoidattribute)
1769+
continue;
1770+
1771+
if (md.attrvaluetype == SAI_ATTR_VALUE_TYPE_OBJECT_ID)
1772+
{
1773+
if (a->value.oid != SAI_NULL_OBJECT_ID)
1774+
{
1775+
SWSS_LOG_ERROR("object %s has non default state on %s: %s, expected NULL",
1776+
sai_serialize_object_id(oid).c_str(),
1777+
md.attridname,
1778+
sai_serialize_object_id(a->value.oid).c_str());
1779+
1780+
return false;
1781+
}
1782+
}
1783+
else if (md.attrvaluetype == SAI_ATTR_VALUE_TYPE_OBJECT_LIST)
1784+
{
1785+
for (uint32_t i = 0; i < a->value.objlist.count; i++)
1786+
{
1787+
if (a->value.objlist.list[i] != SAI_NULL_OBJECT_ID)
1788+
{
1789+
SWSS_LOG_ERROR("object %s has non default state on %s[%u]: %s, expected NULL",
1790+
sai_serialize_object_id(oid).c_str(),
1791+
md.attridname,
1792+
i,
1793+
sai_serialize_object_id(a->value.objlist.list[i]).c_str());
1794+
1795+
return false;
1796+
}
1797+
}
1798+
}
1799+
else
1800+
{
1801+
// unable to check whether object is in default state, need fix
1802+
1803+
SWSS_LOG_ERROR("unsupported oid attribute: %s, FIX ME!", md.attridname);
1804+
return false;
1805+
}
1806+
}
1807+
1808+
return true;
1809+
}
1810+
1811+
sai_status_t meta_port_remove_validation(
1812+
_In_ const sai_object_meta_key_t& meta_key)
1813+
{
1814+
SWSS_LOG_ENTER();
1815+
1816+
sai_object_id_t port_id = meta_key.objectkey.key.object_id;
1817+
1818+
auto it = map_port_to_related_set.find(port_id);
1819+
1820+
if (it == map_port_to_related_set.end())
1821+
{
1822+
// user didn't query any queues, ipgs or scheduler groups
1823+
// for this port, then we can just skip this
1824+
return SAI_STATUS_SUCCESS;
1825+
}
1826+
1827+
if (object_reference_count(port_id) != 0)
1828+
{
1829+
SWSS_LOG_ERROR("port %s reference count is not zero, can't remove",
1830+
sai_serialize_object_id(port_id).c_str());
1831+
1832+
return SAI_STATUS_FAILURE;
1833+
}
1834+
1835+
if (!meta_is_object_in_default_state(port_id))
1836+
{
1837+
SWSS_LOG_ERROR("port %s is not in default state, can't remove",
1838+
sai_serialize_object_id(port_id).c_str());
1839+
1840+
return SAI_STATUS_FAILURE;
1841+
}
1842+
1843+
for (auto oid: it->second)
1844+
{
1845+
if (object_reference_count(oid) != 0)
1846+
{
1847+
SWSS_LOG_ERROR("port %s related object %s reference count is not zero, can't remove",
1848+
sai_serialize_object_id(port_id).c_str(),
1849+
sai_serialize_object_id(oid).c_str());
1850+
1851+
return SAI_STATUS_FAILURE;
1852+
}
1853+
1854+
if (!meta_is_object_in_default_state(oid))
1855+
{
1856+
SWSS_LOG_ERROR("port related object %s is not in default state, can't remove",
1857+
sai_serialize_object_id(oid).c_str());
1858+
1859+
return SAI_STATUS_FAILURE;
1860+
}
1861+
}
1862+
1863+
SWSS_LOG_NOTICE("all objects related to port %s are in default state, can be remove",
1864+
sai_serialize_object_id(port_id).c_str());
1865+
1866+
return SAI_STATUS_SUCCESS;
1867+
}
1868+
17081869
sai_status_t meta_generic_validation_remove(
17091870
_In_ const sai_object_meta_key_t& meta_key)
17101871
{
@@ -1785,6 +1946,11 @@ sai_status_t meta_generic_validation_remove(
17851946
return SAI_STATUS_INVALID_PARAMETER;
17861947
}
17871948

1949+
if (meta_key.objecttype == SAI_OBJECT_TYPE_PORT)
1950+
{
1951+
return meta_port_remove_validation(meta_key);
1952+
}
1953+
17881954
// should be safe to remove
17891955

17901956
return SAI_STATUS_SUCCESS;
@@ -2816,6 +2982,51 @@ void meta_generic_validation_post_create(
28162982
}
28172983
}
28182984

2985+
void meta_generic_validation_post_remove(
2986+
_In_ const sai_object_meta_key_t& meta_key);
2987+
2988+
void post_port_remove(
2989+
_In_ const sai_object_meta_key_t& meta_key)
2990+
{
2991+
SWSS_LOG_ENTER();
2992+
2993+
sai_object_id_t port_id = meta_key.objectkey.key.object_id;
2994+
2995+
auto it = map_port_to_related_set.find(port_id);
2996+
2997+
if (it == map_port_to_related_set.end())
2998+
{
2999+
// user didn't query any queues, ipgs or scheduler groups
3000+
// for this port, then we can just skip this
3001+
3002+
return;
3003+
}
3004+
3005+
for (auto oid: it->second)
3006+
{
3007+
// to remove existing objects, let's just call post remove for them
3008+
// and metadata will take the rest
3009+
3010+
sai_object_meta_key_t meta;
3011+
3012+
meta.objecttype = sai_object_type_query(oid);
3013+
meta.objectkey.key.object_id = oid;
3014+
3015+
SWSS_LOG_INFO("attempt to remove port related object: %s: %s",
3016+
sai_serialize_object_type(meta.objecttype).c_str(),
3017+
sai_serialize_object_id(oid).c_str());
3018+
3019+
meta_generic_validation_post_remove(meta);
3020+
}
3021+
3022+
// all related objects were removed, we need to clear current state
3023+
3024+
it->second.clear();
3025+
3026+
SWSS_LOG_NOTICE("success executing post port remove actions: %s",
3027+
sai_serialize_object_id(port_id).c_str());
3028+
}
3029+
28193030
void meta_generic_validation_post_remove(
28203031
_In_ const sai_object_meta_key_t& meta_key)
28213032
{
@@ -2992,6 +3203,11 @@ void meta_generic_validation_post_remove(
29923203

29933204
AttributeKeys.erase(ok);
29943205
}
3206+
3207+
if (meta_key.objecttype == SAI_OBJECT_TYPE_PORT)
3208+
{
3209+
post_port_remove(meta_key);
3210+
}
29953211
}
29963212

29973213
void meta_generic_validation_post_set(
@@ -3337,6 +3553,69 @@ void meta_generic_validation_post_get_objlist(
33373553
}\
33383554
}
33393555

3556+
void meta_add_port_to_related_map(
3557+
_In_ sai_object_id_t port_id,
3558+
_In_ const sai_object_list_t& list)
3559+
{
3560+
SWSS_LOG_ENTER();
3561+
3562+
for (uint32_t i = 0; i < list.count; i++)
3563+
{
3564+
sai_object_id_t rel = list.list[i];
3565+
3566+
if (rel == SAI_NULL_OBJECT_ID)
3567+
SWSS_LOG_THROW("not expected NULL oid on the list");
3568+
3569+
map_port_to_related_set[port_id].insert(rel);
3570+
}
3571+
}
3572+
3573+
void meta_post_port_get(
3574+
_In_ const sai_object_meta_key_t& meta_key,
3575+
_In_ sai_object_id_t switch_id,
3576+
_In_ const uint32_t attr_count,
3577+
_In_ const sai_attribute_t *attr_list)
3578+
{
3579+
SWSS_LOG_ENTER();
3580+
3581+
/*
3582+
* User may or may not query one of below attributes to get some port
3583+
* objects, and those objects are special since when user decide to remove
3584+
* port, then those object will be removed automatically by vendor SAI, and
3585+
* this action needs to be reflected here too, so if user will remove port,
3586+
* those objects would need to be remove from local database too.
3587+
*
3588+
* TODO: There will be issue here, since we need to know which of those
3589+
* objects are user created, for example if user will create some extra
3590+
* queues with specific port, and then query queues list, those extra
3591+
* queues would need to be explicitly removed first by user, otherwise this
3592+
* logic here will also consider those user created queues as switch
3593+
* default, and it will remove them when port will be removed. Such action
3594+
* should be prevented.
3595+
*/
3596+
3597+
const sai_object_id_t port_id = meta_key.objectkey.key.object_id;
3598+
3599+
for (uint32_t idx = 0; idx < attr_count; ++idx)
3600+
{
3601+
const sai_attribute_t& attr = attr_list[idx];
3602+
3603+
auto& md = *sai_metadata_get_attr_metadata(meta_key.objecttype, attr.id);
3604+
3605+
switch (md.attrid)
3606+
{
3607+
case SAI_PORT_ATTR_QOS_QUEUE_LIST:
3608+
case SAI_PORT_ATTR_QOS_SCHEDULER_GROUP_LIST:
3609+
case SAI_PORT_ATTR_INGRESS_PRIORITY_GROUP_LIST:
3610+
meta_add_port_to_related_map(port_id, attr.value.objlist);
3611+
break;
3612+
3613+
default:
3614+
break;
3615+
}
3616+
}
3617+
}
3618+
33403619
void meta_generic_validation_post_get(
33413620
_In_ const sai_object_meta_key_t& meta_key,
33423621
_In_ sai_object_id_t switch_id,
@@ -3573,6 +3852,11 @@ void meta_generic_validation_post_get(
35733852
}
35743853
}
35753854
}
3855+
3856+
if (meta_key.objecttype == SAI_OBJECT_TYPE_PORT)
3857+
{
3858+
meta_post_port_get(meta_key, switch_id, attr_count, attr_list);
3859+
}
35763860
}
35773861

35783862
// FDB ENTRY

0 commit comments

Comments
 (0)