From 1e8193d001a68a52ecfe0675e6a409e1384f186d Mon Sep 17 00:00:00 2001 From: Andrii Savka Date: Fri, 14 Jul 2017 18:06:05 +0300 Subject: [PATCH 1/2] Added SAI dump support to syncd --- .gitignore | 1 + syncd/Makefile.am | 6 +- syncd/syncd.cpp | 39 +++++++++++- syncd/syncd_request_saidump.cpp | 109 ++++++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 syncd/syncd_request_saidump.cpp diff --git a/.gitignore b/.gitignore index 3bf6401fda..92b14ada6d 100644 --- a/.gitignore +++ b/.gitignore @@ -65,6 +65,7 @@ deps/ ############### syncd/syncd syncd/syncd_request_shutdown +syncd/syncd_request_saidump saiplayer/saiplayer saidump/saidump meta/tests diff --git a/syncd/Makefile.am b/syncd/Makefile.am index ae9377c8ae..fc7b158f8c 100644 --- a/syncd/Makefile.am +++ b/syncd/Makefile.am @@ -1,6 +1,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/vslib/inc -I$(top_srcdir)/lib/inc -I$(top_srcdir)/SAI/inc -I$(top_srcdir)/SAI/meta -bin_PROGRAMS = syncd syncd_request_shutdown +bin_PROGRAMS = syncd syncd_request_shutdown syncd_request_saidump if DEBUG DBGFLAGS = -ggdb -DDEBUG @@ -33,3 +33,7 @@ endif syncd_request_shutdown_SOURCES = syncd_request_shutdown.cpp syncd_request_shutdown_CPPFLAGS = $(DBGFLAGS) $(AM_CPPFLAGS) $(CFLAGS_COMMON) syncd_request_shutdown_LDADD = -lhiredis -lswsscommon -lpthread + +syncd_request_saidump_SOURCES = syncd_request_saidump.cpp +syncd_request_saidump_CPPFLAGS = $(DBGFLAGS) $(AM_CPPFLAGS) $(CFLAGS_COMMON) +syncd_request_saidump_LDADD = -lhiredis -lswsscommon -lpthread diff --git a/syncd/syncd.cpp b/syncd/syncd.cpp index 8cb0423b0b..d6a4de9e6f 100644 --- a/syncd/syncd.cpp +++ b/syncd/syncd.cpp @@ -2597,6 +2597,31 @@ bool handleRestartQuery(swss::NotificationConsumer &restartQuery) return false; } +bool handleSaiDumpQuery(swss::NotificationConsumer &saiDumpQuery) +{ + SWSS_LOG_ENTER(); + + std::string dumpFile; + std::vector values; + saiDumpQuery.pop(dumpFile, dumpFile, values); + + if (switches.size() == 0) + { + SWSS_LOG_ERROR("Failed to generate SAI dump because switch is not initialized yet"); + return false; + } + + sai_status_t sai_status = sai_dbg_generate_dump(dumpFile.c_str()); + if (sai_status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to generate SAI dump, error 0x%x", sai_status); + return false; + } + + SWSS_LOG_NOTICE("Generated SAI dump file", dumpFile.c_str()); + return true; +} + bool isVeryFirstRun() { std::lock_guard lock(g_mutex); @@ -2888,6 +2913,7 @@ int main(int argc, char **argv) std::shared_ptr asicState = std::make_shared(db.get(), ASIC_STATE_TABLE); std::shared_ptr restartQuery = std::make_shared(db.get(), "RESTARTQUERY"); + std::shared_ptr saiDumpQuery = std::make_shared(db.get(), "SAIDUMPQUERY"); /* * At the end we cant use producer consumer concept since if one proces @@ -2981,6 +3007,7 @@ int main(int argc, char **argv) s.addSelectable(asicState.get()); s.addSelectable(restartQuery.get()); + s.addSelectable(saiDumpQuery.get()); SWSS_LOG_NOTICE("starting main loop"); @@ -3006,7 +3033,17 @@ int main(int argc, char **argv) break; } - if (result == swss::Select::OBJECT) + if (sel == saiDumpQuery.get()) + { + bool success = handleSaiDumpQuery(*saiDumpQuery); + if (success) + { + swss::NotificationProducer saiDumpResp (dbNtf.get(), "SAIDUMPRESP"); + std::vector values; + saiDumpResp.send("success", "success", values); + } + } + else if (result == swss::Select::OBJECT) { processEvent(*(swss::ConsumerTable*)sel); } diff --git a/syncd/syncd_request_saidump.cpp b/syncd/syncd_request_saidump.cpp new file mode 100644 index 0000000000..91b67ec10d --- /dev/null +++ b/syncd/syncd_request_saidump.cpp @@ -0,0 +1,109 @@ +#include +#include +#include +#include + +#include +#include + +#include "swss/redisclient.h" +#include "swss/dbconnector.h" +#include "swss/notificationconsumer.h" +#include "swss/notificationproducer.h" +#include "swss/selectableevent.h" +#include "swss/select.h" +#include "swss/logger.h" + +void print_usage() +{ + std::cerr << "Following SAI dump options can be specified:" << std::endl; + std::cerr << "-------------------------------------------" << std::endl; + std::cerr << "--dump_file -f Full path for dump file" << std::endl; + std::cerr << "--help -h usage" << std::endl; +} + +/* Parse the response and check if SAI dump was generated successfully */ +bool handleDumpResponse(swss::NotificationConsumer &dumpResp) +{ + std::string respons; + std::vector values; + dumpResp.pop(respons, respons, values); + return (respons == "success"); +} + +int main(int argc, char **argv) +{ + swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_NOTICE); + + SWSS_LOG_ENTER(); + + static struct option longOptions[] = + { + { "help", no_argument, 0, 'h' }, + { "dump_file", required_argument, 0, 'f' } + }; + + bool fileSpecified = false; + std::string fileName; + int option_index = 0; + int c = 0; + + while((c = getopt_long(argc, argv, "hf:", longOptions, &option_index)) != -1) + { + switch (c) + { + case 'f': + if (optarg != NULL) + { + fileName = std::string(optarg); + fileSpecified = true; + } + break; + + case 'h': + print_usage(); + break; + + default: + SWSS_LOG_ERROR("getopt failure"); + exit(EXIT_FAILURE); + } + } + + if (!fileSpecified) + { + std::ostringstream strStream; + time_t t = time(NULL); + struct tm *now = localtime(&t); + strStream << "/tmp/syncd_saidump_" << now->tm_mday << "_" << now->tm_mon + 1 << "_" << now->tm_year + 1900 << "_" << now->tm_hour << "_" << now->tm_min << "_" << now->tm_sec; + fileName = strStream.str(); + SWSS_LOG_INFO("The dump file is not specified, generated \"%s\" file name", fileName.c_str()); + } + + /* Send the request to generate the SAI dump and wait for response */ + swss::DBConnector db(ASIC_DB, swss::DBConnector::DEFAULT_UNIXSOCKET, 0); + swss::NotificationProducer dumpQuery(&db, "SAIDUMPQUERY"); + swss::NotificationConsumer dumpResp(&db, "SAIDUMPRESP"); + swss::Select s; + s.addSelectable(&dumpResp); + + std::vector values; + dumpQuery.send(fileName, fileName, values); + + swss::Selectable *sel = NULL; + int fd; + int rc = s.select(&sel, &fd, 5000); + if (rc != swss::Select::ERROR && rc != swss::Select::TIMEOUT && sel == &dumpResp && handleDumpResponse(dumpResp)) + { + SWSS_LOG_NOTICE("The SAI dump is generated to %s", fileName.c_str()); + std::cout << "The SAI dump is generated to " << fileName << std::endl; + } + else + { + SWSS_LOG_ERROR("Error! The SAI dump is not generated!"); + std::cerr << "Error! The SAI dump is not generated!" << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} From f5600673d19915b5079d72238f3636b8187c7351 Mon Sep 17 00:00:00 2001 From: andrii savka Date: Sun, 30 Jul 2017 19:14:09 +0300 Subject: [PATCH 2/2] Refactored sai_sdk_dump tool to use SAI directly --- .gitignore | 2 +- Makefile.am | 2 +- configure.ac | 1 + debian/syncd.install | 1 + saisdkdump/Makefile.am | 19 ++++ saisdkdump/saisdkdump.cpp | 159 ++++++++++++++++++++++++++++++++ syncd/Makefile.am | 6 +- syncd/syncd.cpp | 39 +------- syncd/syncd_request_saidump.cpp | 109 ---------------------- 9 files changed, 184 insertions(+), 154 deletions(-) create mode 100644 saisdkdump/Makefile.am create mode 100644 saisdkdump/saisdkdump.cpp delete mode 100644 syncd/syncd_request_saidump.cpp diff --git a/.gitignore b/.gitignore index 92b14ada6d..c67ae2e917 100644 --- a/.gitignore +++ b/.gitignore @@ -65,9 +65,9 @@ deps/ ############### syncd/syncd syncd/syncd_request_shutdown -syncd/syncd_request_saidump saiplayer/saiplayer saidump/saidump +saisdkdump/saisdkdump meta/tests # Temporary files # diff --git a/Makefile.am b/Makefile.am index 71bc8bf3ac..ecb2060794 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1 +1 @@ -SUBDIRS = meta lib vslib syncd saiplayer saidump +SUBDIRS = meta lib vslib syncd saiplayer saidump saisdkdump diff --git a/configure.ac b/configure.ac index 0de2344b7d..0b5da0da6f 100644 --- a/configure.ac +++ b/configure.ac @@ -96,4 +96,5 @@ AC_OUTPUT(Makefile syncd/Makefile saiplayer/Makefile saidump/Makefile + saisdkdump/Makefile saidiscovery/Makefile) diff --git a/debian/syncd.install b/debian/syncd.install index 293e9d3077..b38437844c 100644 --- a/debian/syncd.install +++ b/debian/syncd.install @@ -1,4 +1,5 @@ usr/bin/saidump usr/bin/saiplayer +usr/bin/saisdkdump usr/bin/syncd* syncd/scripts/* usr/bin diff --git a/saisdkdump/Makefile.am b/saisdkdump/Makefile.am new file mode 100644 index 0000000000..a7bc6d07d1 --- /dev/null +++ b/saisdkdump/Makefile.am @@ -0,0 +1,19 @@ +AM_CPPFLAGS = -I$(top_srcdir)/vslib/inc -I$(top_srcdir)/lib/inc -I$(top_srcdir)/SAI/inc -I$(top_srcdir)/SAI/meta + +bin_PROGRAMS = saisdkdump + +if DEBUG +DBGFLAGS = -ggdb -DDEBUG +else +DBGFLAGS = -g +endif + +if SAIVS +SAILIB=-L$(top_srcdir)/vslib/src/.libs -lsaivs +else +SAILIB=-lsai +endif + +saisdkdump_SOURCES = saisdkdump.cpp +saisdkdump_CPPFLAGS = $(DBGFLAGS) $(AM_CPPFLAGS) $(CFLAGS_COMMON) $(SAIFLAGS) +saisdkdump_LDADD = -lhiredis -lswsscommon $(SAILIB) -lpthread -L$(top_srcdir)/meta/.libs -lsaimetadata -lsaimeta diff --git a/saisdkdump/saisdkdump.cpp b/saisdkdump/saisdkdump.cpp new file mode 100644 index 0000000000..d4ce98d5dd --- /dev/null +++ b/saisdkdump/saisdkdump.cpp @@ -0,0 +1,159 @@ +#include +#include +#include +#include + +#include +#include + +#include "swss/logger.h" + +extern "C" { +#include +} + +std::string sai_profile = "/tmp/sai.profile"; + +void print_usage() +{ + std::cerr << "Following SAI dump options can be specified:" << std::endl; + std::cerr << "-------------------------------------------" << std::endl; + std::cerr << "--dump_file -f Full path for dump file" << std::endl; + std::cerr << "--profile -p Full path to SAI profile file [ default is " << sai_profile << " ]" << std::endl; + std::cerr << "--help -h usage" << std::endl; +} + +__attribute__((__noreturn__)) void exit_with_sai_failure(const char *msg, sai_status_t status) +{ + if (msg) + { + std::cerr << msg << " rc=" << status << std::endl; + } + SWSS_LOG_ERROR("saisdkdump exited with SAI rc: 0x%x, msg: %s .", status, (msg != NULL ? msg : "")); + exit(EXIT_FAILURE); +} + +const char* profile_get_value( + _In_ sai_switch_profile_id_t profile_id, + _In_ const char* variable) +{ + return sai_profile.c_str(); +} + +int profile_get_next_value( + _In_ sai_switch_profile_id_t profile_id, + _Out_ const char** variable, + _Out_ const char** value) +{ + return -1; +} + +service_method_table_t test_services = { + profile_get_value, + profile_get_next_value +}; + +int main(int argc, char **argv) +{ + swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_NOTICE); + + SWSS_LOG_ENTER(); + + static struct option longOptions[] = + { + { "help", no_argument, 0, 'h' }, + { "dump_file", required_argument, 0, 'f' }, + { "profile", required_argument, 0, 'p' } + }; + + bool fileSpecified = false; + std::string fileName; + int option_index = 0; + int c = 0; + + while((c = getopt_long(argc, argv, "hf:p:", longOptions, &option_index)) != -1) + { + switch (c) + { + case 'f': + if (optarg != NULL) + { + fileName = std::string(optarg); + fileSpecified = true; + } + break; + case 'p': + if (optarg != NULL) + { + sai_profile = std::string(optarg); + } + break; + + case 'h': + print_usage(); + break; + + default: + SWSS_LOG_ERROR("getopt failure"); + exit(EXIT_FAILURE); + } + } + + if (!fileSpecified) + { + std::ostringstream strStream; + time_t t = time(NULL); + struct tm *now = localtime(&t); + strStream << "/tmp/saisdkdump_" << now->tm_mday << "_" << now->tm_mon + 1 << "_" << now->tm_year + 1900 << "_" << now->tm_hour << "_" << now->tm_min << "_" << now->tm_sec; + fileName = strStream.str(); + SWSS_LOG_INFO("The dump file is not specified, generated \"%s\" file name", fileName.c_str()); + } + + sai_status_t status = sai_api_initialize(0, (service_method_table_t*)&test_services); + if (status != SAI_STATUS_SUCCESS) + { + exit_with_sai_failure("Failed to initialize SAI api", status); + } + + sai_switch_api_t* switch_api; + status = sai_api_query(SAI_API_SWITCH, (void**) &switch_api); + if (status != SAI_STATUS_SUCCESS) + { + exit_with_sai_failure("Failed to query switch api", status); + } + + sai_object_id_t switch_id; + const uint32_t AttributesCount = 1; + sai_attribute_t attrs[AttributesCount]; + attrs[0].id = SAI_SWITCH_ATTR_INIT_SWITCH; + attrs[0].value.booldata = false; + + status = switch_api->create_switch(&switch_id, AttributesCount, attrs); + if (status != SAI_STATUS_SUCCESS) + { + exit_with_sai_failure("Failed to create a switch", status); + } + + status = sai_dbg_generate_dump(fileName.c_str()); + if (status != SAI_STATUS_SUCCESS) + { + exit_with_sai_failure("Failed to generate SAI dump", status); + } + + SWSS_LOG_NOTICE("The SAI dump is generated to %s .", fileName.c_str()); + std::cout << "The SAI dump is generated to " << fileName << std::endl; + + status = switch_api->remove_switch(switch_id); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("remove switch 0x%x failed: 0x%x", switch_id, status); + } + + status = sai_api_uninitialize(); + if (status != SAI_STATUS_SUCCESS) + { + exit_with_sai_failure("SAI api uninitialize failed", status); + } + + return EXIT_SUCCESS; +} diff --git a/syncd/Makefile.am b/syncd/Makefile.am index fc7b158f8c..ae9377c8ae 100644 --- a/syncd/Makefile.am +++ b/syncd/Makefile.am @@ -1,6 +1,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/vslib/inc -I$(top_srcdir)/lib/inc -I$(top_srcdir)/SAI/inc -I$(top_srcdir)/SAI/meta -bin_PROGRAMS = syncd syncd_request_shutdown syncd_request_saidump +bin_PROGRAMS = syncd syncd_request_shutdown if DEBUG DBGFLAGS = -ggdb -DDEBUG @@ -33,7 +33,3 @@ endif syncd_request_shutdown_SOURCES = syncd_request_shutdown.cpp syncd_request_shutdown_CPPFLAGS = $(DBGFLAGS) $(AM_CPPFLAGS) $(CFLAGS_COMMON) syncd_request_shutdown_LDADD = -lhiredis -lswsscommon -lpthread - -syncd_request_saidump_SOURCES = syncd_request_saidump.cpp -syncd_request_saidump_CPPFLAGS = $(DBGFLAGS) $(AM_CPPFLAGS) $(CFLAGS_COMMON) -syncd_request_saidump_LDADD = -lhiredis -lswsscommon -lpthread diff --git a/syncd/syncd.cpp b/syncd/syncd.cpp index d6a4de9e6f..8cb0423b0b 100644 --- a/syncd/syncd.cpp +++ b/syncd/syncd.cpp @@ -2597,31 +2597,6 @@ bool handleRestartQuery(swss::NotificationConsumer &restartQuery) return false; } -bool handleSaiDumpQuery(swss::NotificationConsumer &saiDumpQuery) -{ - SWSS_LOG_ENTER(); - - std::string dumpFile; - std::vector values; - saiDumpQuery.pop(dumpFile, dumpFile, values); - - if (switches.size() == 0) - { - SWSS_LOG_ERROR("Failed to generate SAI dump because switch is not initialized yet"); - return false; - } - - sai_status_t sai_status = sai_dbg_generate_dump(dumpFile.c_str()); - if (sai_status != SAI_STATUS_SUCCESS) - { - SWSS_LOG_ERROR("Failed to generate SAI dump, error 0x%x", sai_status); - return false; - } - - SWSS_LOG_NOTICE("Generated SAI dump file", dumpFile.c_str()); - return true; -} - bool isVeryFirstRun() { std::lock_guard lock(g_mutex); @@ -2913,7 +2888,6 @@ int main(int argc, char **argv) std::shared_ptr asicState = std::make_shared(db.get(), ASIC_STATE_TABLE); std::shared_ptr restartQuery = std::make_shared(db.get(), "RESTARTQUERY"); - std::shared_ptr saiDumpQuery = std::make_shared(db.get(), "SAIDUMPQUERY"); /* * At the end we cant use producer consumer concept since if one proces @@ -3007,7 +2981,6 @@ int main(int argc, char **argv) s.addSelectable(asicState.get()); s.addSelectable(restartQuery.get()); - s.addSelectable(saiDumpQuery.get()); SWSS_LOG_NOTICE("starting main loop"); @@ -3033,17 +3006,7 @@ int main(int argc, char **argv) break; } - if (sel == saiDumpQuery.get()) - { - bool success = handleSaiDumpQuery(*saiDumpQuery); - if (success) - { - swss::NotificationProducer saiDumpResp (dbNtf.get(), "SAIDUMPRESP"); - std::vector values; - saiDumpResp.send("success", "success", values); - } - } - else if (result == swss::Select::OBJECT) + if (result == swss::Select::OBJECT) { processEvent(*(swss::ConsumerTable*)sel); } diff --git a/syncd/syncd_request_saidump.cpp b/syncd/syncd_request_saidump.cpp deleted file mode 100644 index 91b67ec10d..0000000000 --- a/syncd/syncd_request_saidump.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include -#include -#include -#include - -#include -#include - -#include "swss/redisclient.h" -#include "swss/dbconnector.h" -#include "swss/notificationconsumer.h" -#include "swss/notificationproducer.h" -#include "swss/selectableevent.h" -#include "swss/select.h" -#include "swss/logger.h" - -void print_usage() -{ - std::cerr << "Following SAI dump options can be specified:" << std::endl; - std::cerr << "-------------------------------------------" << std::endl; - std::cerr << "--dump_file -f Full path for dump file" << std::endl; - std::cerr << "--help -h usage" << std::endl; -} - -/* Parse the response and check if SAI dump was generated successfully */ -bool handleDumpResponse(swss::NotificationConsumer &dumpResp) -{ - std::string respons; - std::vector values; - dumpResp.pop(respons, respons, values); - return (respons == "success"); -} - -int main(int argc, char **argv) -{ - swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_NOTICE); - - SWSS_LOG_ENTER(); - - static struct option longOptions[] = - { - { "help", no_argument, 0, 'h' }, - { "dump_file", required_argument, 0, 'f' } - }; - - bool fileSpecified = false; - std::string fileName; - int option_index = 0; - int c = 0; - - while((c = getopt_long(argc, argv, "hf:", longOptions, &option_index)) != -1) - { - switch (c) - { - case 'f': - if (optarg != NULL) - { - fileName = std::string(optarg); - fileSpecified = true; - } - break; - - case 'h': - print_usage(); - break; - - default: - SWSS_LOG_ERROR("getopt failure"); - exit(EXIT_FAILURE); - } - } - - if (!fileSpecified) - { - std::ostringstream strStream; - time_t t = time(NULL); - struct tm *now = localtime(&t); - strStream << "/tmp/syncd_saidump_" << now->tm_mday << "_" << now->tm_mon + 1 << "_" << now->tm_year + 1900 << "_" << now->tm_hour << "_" << now->tm_min << "_" << now->tm_sec; - fileName = strStream.str(); - SWSS_LOG_INFO("The dump file is not specified, generated \"%s\" file name", fileName.c_str()); - } - - /* Send the request to generate the SAI dump and wait for response */ - swss::DBConnector db(ASIC_DB, swss::DBConnector::DEFAULT_UNIXSOCKET, 0); - swss::NotificationProducer dumpQuery(&db, "SAIDUMPQUERY"); - swss::NotificationConsumer dumpResp(&db, "SAIDUMPRESP"); - swss::Select s; - s.addSelectable(&dumpResp); - - std::vector values; - dumpQuery.send(fileName, fileName, values); - - swss::Selectable *sel = NULL; - int fd; - int rc = s.select(&sel, &fd, 5000); - if (rc != swss::Select::ERROR && rc != swss::Select::TIMEOUT && sel == &dumpResp && handleDumpResponse(dumpResp)) - { - SWSS_LOG_NOTICE("The SAI dump is generated to %s", fileName.c_str()); - std::cout << "The SAI dump is generated to " << fileName << std::endl; - } - else - { - SWSS_LOG_ERROR("Error! The SAI dump is not generated!"); - std::cerr << "Error! The SAI dump is not generated!" << std::endl; - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -}