|
35 | 35 | #define RECOVERY_POLLS_CFG 8 |
36 | 36 | #define ERROR_RATE_CRC_CELLS_CFG 1 |
37 | 37 | #define ERROR_RATE_RX_CELLS_CFG 61035156 |
| 38 | +#define FABRIC_LINK_RATE 44316 |
38 | 39 |
|
39 | 40 | extern sai_object_id_t gSwitchId; |
40 | 41 | extern sai_switch_api_t *sai_switch_api; |
@@ -76,6 +77,7 @@ FabricPortsOrch::FabricPortsOrch(DBConnector *appl_db, vector<table_name_with_pr |
76 | 77 |
|
77 | 78 | m_state_db = shared_ptr<DBConnector>(new DBConnector("STATE_DB", 0)); |
78 | 79 | m_stateTable = unique_ptr<Table>(new Table(m_state_db.get(), APP_FABRIC_PORT_TABLE_NAME)); |
| 80 | + m_fabricCapacityTable = unique_ptr<Table>(new Table(m_state_db.get(), STATE_FABRIC_CAPACITY_TABLE_NAME)); |
79 | 81 |
|
80 | 82 | m_counter_db = shared_ptr<DBConnector>(new DBConnector("COUNTERS_DB", 0)); |
81 | 83 | m_portNameQueueCounterTable = unique_ptr<Table>(new Table(m_counter_db.get(), COUNTERS_FABRIC_QUEUE_NAME_MAP)); |
@@ -836,6 +838,185 @@ void FabricPortsOrch::updateFabricDebugCounters() |
836 | 838 | } |
837 | 839 | } |
838 | 840 |
|
| 841 | +void FabricPortsOrch::updateFabricCapacity() |
| 842 | +{ |
| 843 | + // Init value for fabric capacity monitoring |
| 844 | + int capacity = 0; |
| 845 | + int downCapacity = 0; |
| 846 | + string lnkStatus = "down"; |
| 847 | + string configIsolated = "0"; |
| 848 | + string isolated = "0"; |
| 849 | + string autoIsolated = "0"; |
| 850 | + int operating_links = 0; |
| 851 | + int total_links = 0; |
| 852 | + int threshold = 100; |
| 853 | + std::vector<FieldValueTuple> constValues; |
| 854 | + string applKey = FABRIC_MONITOR_DATA; |
| 855 | + |
| 856 | + // Get capacity warning threshold from APPL_DB table FABRIC_MONITOR_DATA |
| 857 | + // By default, this threshold is 100 (percentage). |
| 858 | + bool cfgVal = m_applMonitorConstTable->get("FABRIC_MONITOR_DATA", constValues); |
| 859 | + if(!cfgVal) |
| 860 | + { |
| 861 | + SWSS_LOG_INFO("%s default values not set", applKey.c_str()); |
| 862 | + } |
| 863 | + else |
| 864 | + { |
| 865 | + SWSS_LOG_INFO("%s has default values", applKey.c_str()); |
| 866 | + } |
| 867 | + string configVal = "1"; |
| 868 | + for (auto cv : constValues) |
| 869 | + { |
| 870 | + configVal = fvValue(cv); |
| 871 | + if (fvField(cv) == "monCapacityThreshWarn") |
| 872 | + { |
| 873 | + threshold = stoi(configVal); |
| 874 | + SWSS_LOG_INFO("monCapacityThreshWarn: %s %s", configVal.c_str(), fvField(cv).c_str()); |
| 875 | + continue; |
| 876 | + } |
| 877 | + } |
| 878 | + |
| 879 | + // Check fabric capacity. |
| 880 | + SWSS_LOG_INFO("FabricPortsOrch::updateFabricCapacity start"); |
| 881 | + for (auto p : m_fabricLanePortMap) |
| 882 | + { |
| 883 | + int lane = p.first; |
| 884 | + string key = FABRIC_PORT_PREFIX + to_string(lane); |
| 885 | + std::vector<FieldValueTuple> values; |
| 886 | + string valuePt; |
| 887 | + |
| 888 | + // Get fabric serdes link status from STATE_DB |
| 889 | + bool exist = m_stateTable->get(key, values); |
| 890 | + if (!exist) |
| 891 | + { |
| 892 | + SWSS_LOG_INFO("No state infor for port %s", key.c_str()); |
| 893 | + return; |
| 894 | + } |
| 895 | + for (auto val : values) |
| 896 | + { |
| 897 | + valuePt = fvValue(val); |
| 898 | + if (fvField(val) == "STATUS") |
| 899 | + { |
| 900 | + lnkStatus = valuePt; |
| 901 | + continue; |
| 902 | + } |
| 903 | + if (fvField(val) == "CONFIG_ISOLATED") |
| 904 | + { |
| 905 | + configIsolated = valuePt; |
| 906 | + continue; |
| 907 | + } |
| 908 | + if (fvField(val) == "ISOLATED") |
| 909 | + { |
| 910 | + isolated = valuePt; |
| 911 | + continue; |
| 912 | + } |
| 913 | + if (fvField(val) == "AUTO_ISOLATED") |
| 914 | + { |
| 915 | + autoIsolated = valuePt; |
| 916 | + continue; |
| 917 | + } |
| 918 | + } |
| 919 | + // Calculate total number of serdes link, number of operational links, |
| 920 | + // total fabric capacity. |
| 921 | + bool linkIssue = false; |
| 922 | + if (configIsolated == "1" || isolated == "1" || autoIsolated == "1") |
| 923 | + { |
| 924 | + linkIssue = true; |
| 925 | + } |
| 926 | + |
| 927 | + if (lnkStatus == "down" || linkIssue == true) |
| 928 | + { |
| 929 | + downCapacity += FABRIC_LINK_RATE; |
| 930 | + } |
| 931 | + else |
| 932 | + { |
| 933 | + capacity += FABRIC_LINK_RATE; |
| 934 | + operating_links += 1; |
| 935 | + } |
| 936 | + total_links += 1; |
| 937 | + } |
| 938 | + |
| 939 | + SWSS_LOG_INFO("Capacity: %d Missing %d", capacity, downCapacity); |
| 940 | + |
| 941 | + // Get LAST_EVENT from STATE_DB |
| 942 | + |
| 943 | + // Calculate the current capacity to see if |
| 944 | + // it is lower or higher than the threshold |
| 945 | + string cur_event = "None"; |
| 946 | + string event = "None"; |
| 947 | + int expect_links = total_links * threshold / 100; |
| 948 | + if (expect_links > operating_links) |
| 949 | + { |
| 950 | + cur_event = "Lower"; |
| 951 | + } |
| 952 | + else |
| 953 | + { |
| 954 | + cur_event = "Higher"; |
| 955 | + } |
| 956 | + |
| 957 | + SWSS_LOG_NOTICE(" total link %d expected link %d oper link %d event %s", total_links, expect_links, operating_links, cur_event.c_str()); |
| 958 | + |
| 959 | + // Update the capacity data in this poll to STATE_DB |
| 960 | + SWSS_LOG_INFO("Capacity: %d Missing %d", capacity, downCapacity); |
| 961 | + |
| 962 | + string lastEvent = "None"; |
| 963 | + string lastTime = "Never"; |
| 964 | + // Get the last event and time that event happend from STATE_DB |
| 965 | + bool capacity_data = m_fabricCapacityTable->get("FABRIC_CAPACITY_DATA", constValues); |
| 966 | + if (capacity_data) |
| 967 | + { |
| 968 | + for (auto cv : constValues) |
| 969 | + { |
| 970 | + if(fvField(cv) == "last_event") |
| 971 | + { |
| 972 | + lastEvent = fvValue(cv); |
| 973 | + continue; |
| 974 | + } |
| 975 | + if(fvField(cv) == "last_event_time") |
| 976 | + { |
| 977 | + lastTime = fvValue(cv); |
| 978 | + continue; |
| 979 | + } |
| 980 | + } |
| 981 | + } |
| 982 | + |
| 983 | + auto now = std::chrono::system_clock::now(); |
| 984 | + auto now_s = std::chrono::time_point_cast<std::chrono::seconds>(now); |
| 985 | + auto nse = now_s.time_since_epoch(); |
| 986 | + |
| 987 | + // If last event is None or higher, but the capacity is lower in this poll, |
| 988 | + // update the STATE_DB with the event (lower) and the time. |
| 989 | + // If the last event is lower, and the capacity is back to higher than the threshold, |
| 990 | + // update the STATE_DB with the event (higher) and the time. |
| 991 | + event = lastEvent; |
| 992 | + if (cur_event == "Lower") |
| 993 | + { |
| 994 | + if (lastEvent == "None" || lastEvent == "Higher") |
| 995 | + { |
| 996 | + event = "Lower"; |
| 997 | + lastTime = to_string(nse.count()); |
| 998 | + } |
| 999 | + } |
| 1000 | + else if (cur_event == "Higher") |
| 1001 | + { |
| 1002 | + if (lastEvent == "Lower") |
| 1003 | + { |
| 1004 | + event = "Higher"; |
| 1005 | + lastTime = to_string(nse.count()); |
| 1006 | + } |
| 1007 | + } |
| 1008 | + |
| 1009 | + // Update STATE_DB |
| 1010 | + SWSS_LOG_INFO("FabricPortsOrch::updateFabricCapacity now update STATE_DB"); |
| 1011 | + m_fabricCapacityTable->hset("FABRIC_CAPACITY_DATA", "fabric_capacity", to_string(capacity)); |
| 1012 | + m_fabricCapacityTable->hset("FABRIC_CAPACITY_DATA", "missing_capacity", to_string(downCapacity)); |
| 1013 | + m_fabricCapacityTable->hset("FABRIC_CAPACITY_DATA", "operating_links", to_string(operating_links)); |
| 1014 | + m_fabricCapacityTable->hset("FABRIC_CAPACITY_DATA", "number_of_links", to_string(total_links)); |
| 1015 | + m_fabricCapacityTable->hset("FABRIC_CAPACITY_DATA", "warning_threshold", to_string(threshold)); |
| 1016 | + m_fabricCapacityTable->hset("FABRIC_CAPACITY_DATA", "last_event", event); |
| 1017 | + m_fabricCapacityTable->hset("FABRIC_CAPACITY_DATA", "last_event_time", lastTime); |
| 1018 | +} |
| 1019 | + |
839 | 1020 | void FabricPortsOrch::doTask() |
840 | 1021 | { |
841 | 1022 | } |
@@ -1039,6 +1220,7 @@ void FabricPortsOrch::doTask(swss::SelectableTimer &timer) |
1039 | 1220 | if (m_getFabricPortListDone) |
1040 | 1221 | { |
1041 | 1222 | updateFabricDebugCounters(); |
| 1223 | + updateFabricCapacity(); |
1042 | 1224 | } |
1043 | 1225 | } |
1044 | 1226 | } |
0 commit comments