@@ -44,6 +44,17 @@ bool meta_unittests_enabled()
44
44
return unittests_enabled;
45
45
}
46
46
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
+
47
58
sai_status_t meta_unittests_allow_readonly_set_once (
48
59
_In_ sai_object_type_t object_type,
49
60
_In_ int32_t attr_id)
@@ -206,6 +217,13 @@ class SaiAttrWrapper
206
217
return &m_attr;
207
218
}
208
219
220
+ const sai_attr_metadata_t * getMeta () const
221
+ {
222
+ SWSS_LOG_ENTER ();
223
+
224
+ return m_meta;
225
+ }
226
+
209
227
private:
210
228
211
229
SaiAttrWrapper (const SaiAttrWrapper&);
@@ -453,6 +471,8 @@ sai_status_t meta_init_db()
453
471
ObjectAttrHash.clear ();
454
472
AttributeKeys.clear ();
455
473
474
+ map_port_to_related_set.clear ();
475
+
456
476
return SAI_STATUS_SUCCESS;
457
477
}
458
478
@@ -1705,6 +1725,147 @@ sai_status_t meta_generic_validation_create(
1705
1725
return SAI_STATUS_SUCCESS;
1706
1726
}
1707
1727
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
+
1708
1869
sai_status_t meta_generic_validation_remove (
1709
1870
_In_ const sai_object_meta_key_t & meta_key)
1710
1871
{
@@ -1785,6 +1946,11 @@ sai_status_t meta_generic_validation_remove(
1785
1946
return SAI_STATUS_INVALID_PARAMETER;
1786
1947
}
1787
1948
1949
+ if (meta_key.objecttype == SAI_OBJECT_TYPE_PORT)
1950
+ {
1951
+ return meta_port_remove_validation (meta_key);
1952
+ }
1953
+
1788
1954
// should be safe to remove
1789
1955
1790
1956
return SAI_STATUS_SUCCESS;
@@ -2816,6 +2982,51 @@ void meta_generic_validation_post_create(
2816
2982
}
2817
2983
}
2818
2984
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
+
2819
3030
void meta_generic_validation_post_remove (
2820
3031
_In_ const sai_object_meta_key_t & meta_key)
2821
3032
{
@@ -2992,6 +3203,11 @@ void meta_generic_validation_post_remove(
2992
3203
2993
3204
AttributeKeys.erase (ok);
2994
3205
}
3206
+
3207
+ if (meta_key.objecttype == SAI_OBJECT_TYPE_PORT)
3208
+ {
3209
+ post_port_remove (meta_key);
3210
+ }
2995
3211
}
2996
3212
2997
3213
void meta_generic_validation_post_set (
@@ -3337,6 +3553,69 @@ void meta_generic_validation_post_get_objlist(
3337
3553
}\
3338
3554
}
3339
3555
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
+
3340
3619
void meta_generic_validation_post_get (
3341
3620
_In_ const sai_object_meta_key_t & meta_key,
3342
3621
_In_ sai_object_id_t switch_id,
@@ -3573,6 +3852,11 @@ void meta_generic_validation_post_get(
3573
3852
}
3574
3853
}
3575
3854
}
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
+ }
3576
3860
}
3577
3861
3578
3862
// FDB ENTRY
0 commit comments