void WatermarkOrch::doTask(NotificationConsumer &consumer) { if (!gPortsOrch->isPortReady()) { return; } std::string op; std::string data; std::vector<swss::FieldValueTuple> values; consumer.pop(op, data, values); Table * table = NULL; if (op == "PERSISTENT") { table = m_persistentWatermarkTable.get(); } else if (op == "USER") { table = m_userWatermarkTable.get(); } else { SWSS_LOG_WARN("Unknown watermark clear request op: %s", op.c_str()); return; } if(data == CLEAR_PG_HEADROOM_REQUEST) { clearSingleWm(table, "SAI_INGRESS_PRIORITY_GROUP_STAT_XOFF_ROOM_WATERMARK_BYTES", m_pg_ids); } else if(data == CLEAR_PG_SHARED_REQUEST) { clearSingleWm(table, "SAI_INGRESS_PRIORITY_GROUP_STAT_SHARED_WATERMARK_BYTES", m_pg_ids); } else if(data == CLEAR_QUEUE_SHARED_UNI_REQUEST) { clearSingleWm(table, "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES", m_unicast_queue_ids); } else if(data == CLEAR_QUEUE_SHARED_MULTI_REQUEST) { clearSingleWm(table, "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES", m_multicast_queue_ids); } else { SWSS_LOG_WARN("Unknown watermark clear request data: %s", data.c_str()); return; } }
sai_status_t refresh_read_only( _In_ const sai_attr_metadata_t *meta, _In_ sai_object_id_t object_id, _In_ sai_object_id_t switch_id) { SWSS_LOG_ENTER(); /* * Read only, must be per switch since maybe different implemented, * different order maybe on the queues. */ switch (g_vs_switch_type) { case SAI_VS_SWITCH_TYPE_BCM56850: return refresh_read_only_BCM56850(meta, object_id, switch_id); case SAI_VS_SWITCH_TYPE_MLNX2700: return refresh_read_only_MLNX2700(meta, object_id, switch_id); default: break; } SWSS_LOG_WARN("need to recalculate RO: %s", meta->attridname); return SAI_STATUS_NOT_IMPLEMENTED; }
bool handleRestartQuery(swss::NotificationConsumer &restartQuery) { SWSS_LOG_ENTER(); std::string op; std::string data; std::vector<swss::FieldValueTuple> values; restartQuery.pop(op, data, values); SWSS_LOG_DEBUG("op = %d", op.c_str()); if (op == "COLD") { SWSS_LOG_NOTICE("received COLD switch shutdown event"); return false; } if (op == "WARM") { SWSS_LOG_NOTICE("received WARM switch shutdown event"); return true; } SWSS_LOG_WARN("received '%s' unknown switch shutdown event, assuming COLD", op.c_str()); return false; }
void processFdbEntriesForAging() { SWSS_LOG_ENTER(); if (!g_recursive_mutex.try_lock()) { return; } SWSS_LOG_INFO("fdb infos to process: %zu", g_fdb_info_set.size()); uint32_t current = (uint32_t)time(NULL); // find aged fdb entries for (auto it = g_fdb_info_set.begin(); it != g_fdb_info_set.end();) { sai_attribute_t attr; attr.id = SAI_SWITCH_ATTR_FDB_AGING_TIME; sai_status_t status = vs_generic_get(SAI_OBJECT_TYPE_SWITCH, it->fdb_entry.switch_id, 1, &attr); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_WARN("failed to get FDB aging time for switch %s", sai_serialize_object_id(it->fdb_entry.switch_id).c_str()); ++it; continue; } uint32_t aging_time = attr.value.u32; if (aging_time == 0) { // aging is disabled ++it; continue; } if ((current - it->timestamp) >= aging_time) { fdb_info_t fi = *it; processFdbInfo(fi, SAI_FDB_EVENT_AGED); it = g_fdb_info_set.erase(it); } else { ++it; } } g_recursive_mutex.unlock(); }
void Select::addSelectable(Selectable *selectable) { if(find(m_objects.begin(), m_objects.end(), selectable) != m_objects.end()) { SWSS_LOG_WARN("Selectable is already added to the list, ignoring."); return; } m_objects.push_back(selectable); }
void handleCmdLine(int argc, char **argv) { SWSS_LOG_ENTER(); while(true) { static struct option long_options[] = { { "useTempView", no_argument, 0, 'u' }, { "help", no_argument, 0, 'h' }, { "skipNotifySyncd", no_argument, 0, 'C' }, { "enableDebug", no_argument, 0, 'd' }, { 0, 0, 0, 0 } }; const char* const optstring = "hCdu"; int option_index; int c = getopt_long(argc, argv, optstring, long_options, &option_index); if (c == -1) break; switch (c) { case 'd': swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_DEBUG); break; case 'u': g_useTempView = false; break; case 'C': g_notifySyncd = false; break; case 'h': printUsage(); exit(EXIT_SUCCESS); case '?': SWSS_LOG_WARN("unknown option %c", optopt); printUsage(); exit(EXIT_FAILURE); default: SWSS_LOG_ERROR("getopt_long failure"); exit(EXIT_FAILURE); } } }
void handleProfileMap(const std::string& profileMapFile) { SWSS_LOG_ENTER(); if (profileMapFile.size() == 0) return; std::ifstream profile(profileMapFile); if (!profile.is_open()) { SWSS_LOG_ERROR("failed to open profile map file: %s : %s", profileMapFile.c_str(), strerror(errno)); exit(EXIT_FAILURE); } std::string line; while(getline(profile, line)) { if (line.size() > 0 && (line[0] == '#' || line[0] == ';')) continue; size_t pos = line.find("="); if (pos == std::string::npos) { SWSS_LOG_WARN("not found '=' in line %s", line.c_str()); continue; } std::string key = line.substr(0, pos); std::string value = line.substr(pos + 1); gProfileMap[key] = value; SWSS_LOG_INFO("insert: %s:%s", key.c_str(), value.c_str()); } }
static int profile_get_next_value( _In_ sai_switch_profile_id_t profile_id, _Out_ const char** variable, _Out_ const char** value) { SWSS_LOG_ENTER(); if (value == NULL) { SWSS_LOG_INFO("resetting profile map iterator"); return 0; } if (variable == NULL) { SWSS_LOG_WARN("variable is null"); return -1; } SWSS_LOG_INFO("iterator reached end"); return -1; }
int profile_get_next_value( _In_ sai_switch_profile_id_t profile_id, _Out_ const char** variable, _Out_ const char** value) { SWSS_LOG_ENTER(); if (value == NULL) { SWSS_LOG_INFO("resetting profile map iterator"); gProfileIter = gProfileMap.begin(); return 0; } if (variable == NULL) { SWSS_LOG_WARN("variable is null"); return -1; } if (gProfileIter == gProfileMap.end()) { SWSS_LOG_INFO("iterator reached end"); return -1; } *variable = gProfileIter->first.c_str(); *value = gProfileIter->second.c_str(); SWSS_LOG_INFO("key: %s:%s", *variable, *value); gProfileIter++; return 0; }
const char* profile_get_value( _In_ sai_switch_profile_id_t profile_id, _In_ const char* variable) { SWSS_LOG_ENTER(); if (variable == NULL) { SWSS_LOG_WARN("variable is null"); return NULL; } auto it = gProfileMap.find(variable); if (it == gProfileMap.end()) { SWSS_LOG_INFO("%s: NULL", variable); return NULL; } SWSS_LOG_INFO("%s: %s", variable, it->second.c_str()); return it->second.c_str(); }
WatermarkOrch::WatermarkOrch(DBConnector *db, const string tableName): Orch(db, tableName) { SWSS_LOG_ENTER(); m_countersDb = make_shared<DBConnector>(COUNTERS_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); m_appDb = make_shared<DBConnector>(APPL_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); m_countersTable = make_shared<Table>(m_countersDb.get(), COUNTERS_TABLE); m_periodicWatermarkTable = make_shared<Table>(m_countersDb.get(), PERIODIC_WATERMARKS_TABLE); m_persistentWatermarkTable = make_shared<Table>(m_countersDb.get(), PERSISTENT_WATERMARKS_TABLE); m_userWatermarkTable = make_shared<Table>(m_countersDb.get(), USER_WATERMARKS_TABLE); m_clearNotificationConsumer = new swss::NotificationConsumer( m_appDb.get(), "WATERMARK_CLEAR_REQUEST"); auto clearNotifier = new Notifier(m_clearNotificationConsumer, this, "WM_CLEAR_NOTIFIER"); Orch::addExecutor(clearNotifier); auto intervT = timespec { .tv_sec = DEFAULT_TELEMETRY_INTERVAL , .tv_nsec = 0 }; m_telemetryTimer = new SelectableTimer(intervT); auto executorT = new ExecutableTimer(m_telemetryTimer, this, "WM_TELEMETRY_TIMER"); Orch::addExecutor(executorT); m_telemetryTimer->start(); m_telemetryInterval = DEFAULT_TELEMETRY_INTERVAL; } WatermarkOrch::~WatermarkOrch() { SWSS_LOG_ENTER(); } void WatermarkOrch::doTask(Consumer &consumer) { SWSS_LOG_ENTER(); if (!gPortsOrch->isPortReady()) { return; } auto it = consumer.m_toSync.begin(); while (it != consumer.m_toSync.end()) { KeyOpFieldsValuesTuple t = it->second; string key = kfvKey(t); string op = kfvOp(t); std::vector<FieldValueTuple> fvt = kfvFieldsValues(t); if (op == SET_COMMAND) { if (key == "TELEMETRY_INTERVAL") { for (std::pair<std::basic_string<char>, std::basic_string<char> > i: fvt) { if (i.first == "interval") { m_telemetryInterval = to_uint<uint32_t>(i.second.c_str()); } else { SWSS_LOG_WARN("Unsupported key: %s", i.first.c_str()); } } } } else if (op == DEL_COMMAND) { SWSS_LOG_WARN("Unsupported op %s", op.c_str()); } else { SWSS_LOG_ERROR("Unknown operation type %s\n", op.c_str()); } consumer.m_toSync.erase(it++); } }
cmdOptions handleCmdLine(int argc, char **argv) { SWSS_LOG_ENTER(); cmdOptions options = {}; const int defaultCountersThreadIntervalInSeconds = 1; options.countersThreadIntervalInSeconds = defaultCountersThreadIntervalInSeconds; while(true) { static struct option long_options[] = { { "diag", no_argument, 0, 'd' }, { "nocounters", no_argument, 0, 'N' }, { "warmStart", no_argument, 0, 'w' }, { "profile", required_argument, 0, 'p' }, { "countersInterval", required_argument, 0, 'i' }, { 0, 0, 0, 0 } }; int option_index = 0; int c = getopt_long(argc, argv, "dNwp:i:", long_options, &option_index); if (c == -1) break; switch (c) { case 'N': SWSS_LOG_NOTICE("disable counters thread"); options.disableCountersThread = true; break; case 'd': SWSS_LOG_NOTICE("enable diag shell"); options.diagShell = true; break; case 'p': SWSS_LOG_NOTICE("profile map file: %s", optarg); options.profileMapFile = std::string(optarg); break; case 'i': { SWSS_LOG_NOTICE("counters thread interval: %s", optarg); int interval = std::stoi(std::string(optarg)); if (interval == 0) { // use zero interval to disable counters thread options.disableCountersThread = true; } else { options.countersThreadIntervalInSeconds = std::max(defaultCountersThreadIntervalInSeconds, interval); } break; } case 'w': SWSS_LOG_NOTICE("warm start request"); options.warmStart = true; break; case '?': SWSS_LOG_WARN("unknown get opti option %c", optopt); exit(EXIT_FAILURE); break; default: SWSS_LOG_ERROR("getopt_long failure"); exit(EXIT_FAILURE); } } return options; }
int main(int argc, char **argv) { swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_DEBUG); SWSS_LOG_ENTER(); auto options = handleCmdLine(argc, argv); handleProfileMap(options.profileMapFile); swss::DBConnector *db = new swss::DBConnector(ASIC_DB, "localhost", 6379, 0); swss::DBConnector *dbNtf = new swss::DBConnector(ASIC_DB, "localhost", 6379, 0); g_redisClient = new swss::RedisClient(db); updateLogLevel(); swss::ConsumerTable *asicState = new swss::ConsumerTable(db, "ASIC_STATE"); swss::NotificationConsumer *notifySyncdQuery = new swss::NotificationConsumer(db, "NOTIFYSYNCDREQUERY"); swss::NotificationConsumer *restartQuery = new swss::NotificationConsumer(db, "RESTARTQUERY"); // at the end we cant use producer consumer concept since // if one proces will restart there may be something in the queue // also "remove" from response queue will also trigger another "response" getRequest = new swss::ConsumerTable(db, "GETREQUEST"); getResponse = new swss::ProducerTable(db, "GETRESPONSE"); notifications = new swss::NotificationProducer(dbNtf, "NOTIFICATIONS"); notifySyncdResponse = new swss::NotificationProducer(db, "NOTIFYSYNCDRESPONSE"); #ifdef MLNXSAI /* This file is included in Mellanox SAI package. */ std::string mlnx_config_file = "/usr/share/sai_2700.xml"; gProfileMap[SAI_KEY_INIT_CONFIG_FILE] = mlnx_config_file; #endif /* MLNX_SAI */ g_veryFirstRun = isVeryFirstRun(); if (options.warmStart) { const char *warmBootReadFile = profile_get_value(0, SAI_KEY_WARM_BOOT_READ_FILE); SWSS_LOG_NOTICE("using warmBootReadFile: '%s'", warmBootReadFile); if (warmBootReadFile == NULL || access(warmBootReadFile, F_OK) == -1) { SWSS_LOG_WARN("user requested warmStart but warmBootReadFile is not specified or not accesible, forcing cold start"); options.warmStart = false; } } if (options.warmStart && g_veryFirstRun) { SWSS_LOG_WARN("warm start requested, but this is very first syncd start, forcing cold start"); // we force cold start since if it's first run then redis db is not complete // so redis asic view will not reflect warm boot asic state, if this happen // then orch agent needs to be restarted as well to repopulate asic view options.warmStart = false; } // gProfileMap[SAI_KEY_WARM_BOOT] = options.warmStart ? "1" : "0"; sai_api_initialize(0, (service_method_table_t*)&test_services); populate_sai_apis(); initialize_common_api_pointers(); sai_status_t status = sai_switch_api->initialize_switch(0, "0xb850", "", &switch_notifications); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("fail to sai_initialize_switch: %d", status); exit(EXIT_FAILURE); } #ifdef BRCMSAI if (options.diagShell) { SWSS_LOG_NOTICE("starting bcm diag shell thread"); std::thread bcm_diag_shell_thread = std::thread(sai_diag_shell); bcm_diag_shell_thread.detach(); } #endif /* BRCMSAI */ SWSS_LOG_NOTICE("syncd started"); bool warmRestartHint = false; try { onSyncdStart(options.warmStart); if (options.disableCountersThread == false) { SWSS_LOG_NOTICE("starting counters thread"); startCountersThread(options.countersThreadIntervalInSeconds); } SWSS_LOG_NOTICE("syncd listening for events"); swss::Select s; s.addSelectable(getRequest); s.addSelectable(asicState); s.addSelectable(notifySyncdQuery); s.addSelectable(restartQuery); while(true) { swss::Selectable *sel; int fd; int result = s.select(&sel, &fd); if (sel == restartQuery) { warmRestartHint = handleRestartQuery(*restartQuery); break; } if (sel == notifySyncdQuery) { notifySyncd(*notifySyncdQuery); continue; } if (result == swss::Select::OBJECT) { processEvent(*(swss::ConsumerTable*)sel); } } } catch(const std::exception &e) { SWSS_LOG_ERROR("Runtime error: %s", e.what()); exit(EXIT_FAILURE); } endCountersThread(); if (warmRestartHint) { const char *warmBootWriteFile = profile_get_value(0, SAI_KEY_WARM_BOOT_WRITE_FILE); SWSS_LOG_NOTICE("using warmBootWriteFile: '%s'", warmBootWriteFile); if (warmBootWriteFile == NULL) { SWSS_LOG_WARN("user requested warm shutdown but warmBootWriteFile is not specified, forcing cold shutdown"); warmRestartHint = false; } } sai_switch_api->shutdown_switch(warmRestartHint); SWSS_LOG_NOTICE("calling api uninitialize"); sai_api_uninitialize(); SWSS_LOG_NOTICE("uninitialize finished"); return EXIT_SUCCESS; }
/* * Before stopping orchagent for warm restart, basic state check is preferred to * ensure orchagent is not in transient state, so a deterministic state may be restored after restart. * * Here is to implement orchagent_restart_check binary which may talk to orchagent and * ask it to do self-check, return "READY " signal and freeze if everything is ok, * otherwise "NOT_READY" signal should be returned. * * Optionally: * if --noFreeze option is provided, orchagent won't freeze. * if --skipPendingTaskCheck option is provided, orchagent won't use * whether there is pending task existing as state check criterion. */ int main(int argc, char **argv) { swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_INFO); SWSS_LOG_ENTER(); std::string skipPendingTaskCheck = "fasle"; std::string noFreeze = "fasle"; /* Default wait time is 1000 millisecond */ int waitTime = 1000; const char* const optstring = "nsw:"; while(true) { static struct option long_options[] = { { "noFreeze", no_argument, 0, 'n' }, { "skipPendingTaskCheck", no_argument, 0, 's' }, { "waitTime", required_argument, 0, 'w' } }; int option_index = 0; int c = getopt_long(argc, argv, optstring, long_options, &option_index); if (c == -1) { break; } switch (c) { case 'n': SWSS_LOG_NOTICE("Won't freeze orchagent even if check succeeded"); noFreeze = "true"; break; case 's': SWSS_LOG_NOTICE("Skipping pending task check for orchagent"); skipPendingTaskCheck = "true"; break; case 'w': SWSS_LOG_NOTICE("Wait time for response from orchagent set to %s milliseconds", optarg); waitTime = atoi(optarg); break; case 'h': printUsage(); exit(EXIT_SUCCESS); case '?': SWSS_LOG_WARN("unknown option %c", optopt); printUsage(); exit(EXIT_FAILURE); default: SWSS_LOG_ERROR("getopt_long failure"); exit(EXIT_FAILURE); } } swss::DBConnector db(APPL_DB, swss::DBConnector::DEFAULT_UNIXSOCKET, 0); // Send warm restart query via "RESTARTCHECK" notification channel swss::NotificationProducer restartQuery(&db, "RESTARTCHECK"); // Will listen for the reply on "RESTARTCHECKREPLY" channel swss::NotificationConsumer restartQueryReply(&db, "RESTARTCHECKREPLY"); std::vector<swss::FieldValueTuple> values; values.emplace_back("NoFreeze", noFreeze); values.emplace_back("SkipPendingTaskCheck", skipPendingTaskCheck); std::string op = "orchagent"; SWSS_LOG_NOTICE("requested %s to do warm restart state check", op.c_str()); restartQuery.send(op, op, values); swss::Select s; s.addSelectable(&restartQueryReply); swss::Selectable *sel; std::string op_ret, data; values.clear(); int result = s.select(&sel, waitTime); if (result == swss::Select::OBJECT) { restartQueryReply.pop(op_ret, data, values); if (data == "READY") { SWSS_LOG_NOTICE("RESTARTCHECK success, %s is frozen and ready for warm restart", op_ret.c_str()); std::cout << "RESTARTCHECK succeeded" << std::endl; return EXIT_SUCCESS; } else { SWSS_LOG_NOTICE("RESTARTCHECK failed, %s is not ready for warm restart with status %s", op_ret.c_str(), data.c_str()); } } else if (result == swss::Select::TIMEOUT) { SWSS_LOG_NOTICE("RESTARTCHECK for %s timed out", op_ret.c_str()); } else { SWSS_LOG_NOTICE("RESTARTCHECK for %s error", op_ret.c_str()); } std::cout << "RESTARTCHECK failed" << std::endl; return EXIT_FAILURE; }
sai_status_t refresh_read_only_BCM56850( _In_ const sai_attr_metadata_t *meta, _In_ sai_object_id_t object_id, _In_ sai_object_id_t switch_id) { SWSS_LOG_ENTER(); if (meta->objecttype == SAI_OBJECT_TYPE_SWITCH) { switch (meta->attrid) { case SAI_SWITCH_ATTR_PORT_NUMBER: return SAI_STATUS_SUCCESS; case SAI_SWITCH_ATTR_CPU_PORT: case SAI_SWITCH_ATTR_DEFAULT_VIRTUAL_ROUTER_ID: case SAI_SWITCH_ATTR_DEFAULT_TRAP_GROUP: case SAI_SWITCH_ATTR_DEFAULT_VLAN_ID: case SAI_SWITCH_ATTR_DEFAULT_STP_INST_ID: case SAI_SWITCH_ATTR_DEFAULT_1Q_BRIDGE_ID: return SAI_STATUS_SUCCESS; case SAI_SWITCH_ATTR_ACL_ENTRY_MINIMUM_PRIORITY: case SAI_SWITCH_ATTR_ACL_ENTRY_MAXIMUM_PRIORITY: return SAI_STATUS_SUCCESS; case SAI_SWITCH_ATTR_NUMBER_OF_ECMP_GROUPS: return SAI_STATUS_SUCCESS; /* * We don't need to recalculate port list, since now we assume * that port list will not change. */ case SAI_SWITCH_ATTR_PORT_LIST: return SAI_STATUS_SUCCESS; case SAI_SWITCH_ATTR_QOS_MAX_NUMBER_OF_CHILDS_PER_SCHEDULER_GROUP: return SAI_STATUS_SUCCESS; } } if (meta->objecttype == SAI_OBJECT_TYPE_PORT) { switch (meta->attrid) { case SAI_PORT_ATTR_QOS_NUMBER_OF_QUEUES: case SAI_PORT_ATTR_QOS_QUEUE_LIST: return refresh_qos_queues(meta, object_id, switch_id); case SAI_PORT_ATTR_NUMBER_OF_INGRESS_PRIORITY_GROUPS: case SAI_PORT_ATTR_INGRESS_PRIORITY_GROUP_LIST: return refresh_ingress_priority_group(meta, object_id, switch_id); case SAI_PORT_ATTR_QOS_NUMBER_OF_SCHEDULER_GROUPS: case SAI_PORT_ATTR_QOS_SCHEDULER_GROUP_LIST: return refresh_scheduler_groups(meta, object_id, switch_id); /* * This status is based on hostif vEthernetX status. */ case SAI_PORT_ATTR_OPER_STATUS: return SAI_STATUS_SUCCESS; } } if (meta->objecttype == SAI_OBJECT_TYPE_SCHEDULER_GROUP) { switch (meta->attrid) { case SAI_SCHEDULER_GROUP_ATTR_CHILD_COUNT: case SAI_SCHEDULER_GROUP_ATTR_CHILD_LIST: return refresh_scheduler_groups(meta, object_id, switch_id); } } if (meta->objecttype == SAI_OBJECT_TYPE_BRIDGE && meta->attrid == SAI_BRIDGE_ATTR_PORT_LIST) { return refresh_bridge_port_list(meta, object_id, switch_id); } if (meta->objecttype == SAI_OBJECT_TYPE_VLAN && meta->attrid == SAI_VLAN_ATTR_MEMBER_LIST) { return refresh_vlan_member_list(meta, object_id, switch_id); } if (meta_unittests_enabled()) { SWSS_LOG_NOTICE("unittests enabled, SET could be performed on %s, not recalculating", meta->attridname); return SAI_STATUS_SUCCESS; } SWSS_LOG_WARN("need to recalculate RO: %s", meta->attridname); return SAI_STATUS_NOT_IMPLEMENTED; }
cmdOptions handleCmdLine(int argc, char **argv) { SWSS_LOG_ENTER(); cmdOptions options = {}; const int defaultCountersThreadIntervalInSeconds = 1; options.countersThreadIntervalInSeconds = defaultCountersThreadIntervalInSeconds; #ifdef SAITHRIFT options.run_rpc_server = false; const char* const optstring = "dNt:p:i:rm:h"; #else const char* const optstring = "dNt:p:i:h"; #endif // SAITHRIFT while(true) { static struct option long_options[] = { { "diag", no_argument, 0, 'd' }, { "nocounters", no_argument, 0, 'N' }, { "startType", required_argument, 0, 't' }, { "profile", required_argument, 0, 'p' }, { "countersInterval", required_argument, 0, 'i' }, { "help", no_argument, 0, 'h' }, #ifdef SAITHRIFT { "rpcserver", no_argument, 0, 'r' }, { "portmap", required_argument, 0, 'm' }, #endif // SAITHRIFT { 0, 0, 0, 0 } }; int option_index = 0; int c = getopt_long(argc, argv, optstring, long_options, &option_index); if (c == -1) break; switch (c) { case 'N': SWSS_LOG_NOTICE("disable counters thread"); options.disableCountersThread = true; break; case 'd': SWSS_LOG_NOTICE("enable diag shell"); options.diagShell = true; break; case 'p': SWSS_LOG_NOTICE("profile map file: %s", optarg); options.profileMapFile = std::string(optarg); break; case 'i': { SWSS_LOG_NOTICE("counters thread interval: %s", optarg); int interval = std::stoi(std::string(optarg)); if (interval == 0) { // use zero interval to disable counters thread options.disableCountersThread = true; } else { options.countersThreadIntervalInSeconds = std::max(defaultCountersThreadIntervalInSeconds, interval); } break; } case 't': SWSS_LOG_NOTICE("start type: %s", optarg); if (std::string(optarg) == "cold") { options.startType = SAI_COLD_BOOT; } else if (std::string(optarg) == "warm") { options.startType = SAI_WARM_BOOT; } else if (std::string(optarg) == "fast") { options.startType = SAI_FAST_BOOT; } else { SWSS_LOG_ERROR("unknown start type %s", optarg); exit(EXIT_FAILURE); } break; #ifdef SAITHRIFT case 'r': SWSS_LOG_NOTICE("enable rpc server"); options.run_rpc_server = true; break; case 'm': SWSS_LOG_NOTICE("port map file: %s", optarg); options.portMapFile = std::string(optarg); break; #endif // SAITHRIFT case 'h': printUsage(); exit(EXIT_SUCCESS); case '?': SWSS_LOG_WARN("unknown option %c", optopt); printUsage(); exit(EXIT_FAILURE); default: SWSS_LOG_ERROR("getopt_long failure"); exit(EXIT_FAILURE); } } return options; }