/** * Function Description: * @brief adds a decap tunnel to ASIC_DB * * Arguments: * @param[in] type - type of tunnel * @param[in] dst_ip - destination ip address to decap * @param[in] src_ip - source ip address to decap * @param[in] dscp - dscp mode (uniform/pipe) * @param[in] ecn - ecn mode (copy_from_outer/standard) * @param[in] ttl - ttl mode (uniform/pipe) * * Return Values: * @return true on success and false if there's an error */ bool TunnelDecapOrch::addDecapTunnel(string key, string type, IpAddresses dst_ip, IpAddress src_ip, string dscp, string ecn, string ttl) { SWSS_LOG_ENTER(); sai_status_t status; // adding tunnel attributes to array and writing to ASIC_DB sai_attribute_t attr; vector<sai_attribute_t> tunnel_attrs; sai_object_id_t overlayIfId; // create the overlay router interface to create a LOOPBACK type router interface (decap) vector<sai_attribute_t> overlay_intf_attrs; sai_attribute_t overlay_intf_attr; overlay_intf_attr.id = SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID; overlay_intf_attr.value.oid = gVirtualRouterId; overlay_intf_attrs.push_back(overlay_intf_attr); overlay_intf_attr.id = SAI_ROUTER_INTERFACE_ATTR_TYPE; overlay_intf_attr.value.s32 = SAI_ROUTER_INTERFACE_TYPE_LOOPBACK; overlay_intf_attrs.push_back(overlay_intf_attr); status = sai_router_intfs_api->create_router_interface(&overlayIfId, gSwitchId, (uint32_t)overlay_intf_attrs.size(), overlay_intf_attrs.data()); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to create overlay router interface %d", status); return false; } SWSS_LOG_NOTICE("Create overlay loopback router interface oid:%lx", overlayIfId); // tunnel type (only ipinip for now) attr.id = SAI_TUNNEL_ATTR_TYPE; attr.value.s32 = SAI_TUNNEL_TYPE_IPINIP; tunnel_attrs.push_back(attr); attr.id = SAI_TUNNEL_ATTR_OVERLAY_INTERFACE; attr.value.oid = overlayIfId; tunnel_attrs.push_back(attr); attr.id = SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE; attr.value.oid = gUnderlayIfId; tunnel_attrs.push_back(attr); // tunnel src ip attr.id = SAI_TUNNEL_ATTR_ENCAP_SRC_IP; copy(attr.value.ipaddr, src_ip.to_string()); tunnel_attrs.push_back(attr); // decap ecn mode (copy from outer/standard) attr.id = SAI_TUNNEL_ATTR_DECAP_ECN_MODE; if (ecn == "copy_from_outer") { attr.value.s32 = SAI_TUNNEL_DECAP_ECN_MODE_COPY_FROM_OUTER; } else if (ecn == "standard") { attr.value.s32 = SAI_TUNNEL_DECAP_ECN_MODE_STANDARD; } tunnel_attrs.push_back(attr); // ttl mode (uniform/pipe) attr.id = SAI_TUNNEL_ATTR_DECAP_TTL_MODE; if (ttl == "uniform") { attr.value.s32 = SAI_TUNNEL_TTL_MODE_UNIFORM_MODEL; } else if (ttl == "pipe") { attr.value.s32 = SAI_TUNNEL_TTL_MODE_PIPE_MODEL; } tunnel_attrs.push_back(attr); // dscp mode (uniform/pipe) attr.id = SAI_TUNNEL_ATTR_DECAP_DSCP_MODE; if (dscp == "uniform") { attr.value.s32 = SAI_TUNNEL_DSCP_MODE_UNIFORM_MODEL; } else if (dscp == "pipe") { attr.value.s32 = SAI_TUNNEL_DSCP_MODE_PIPE_MODEL; } tunnel_attrs.push_back(attr); // write attributes to ASIC_DB sai_object_id_t tunnel_id; status = sai_tunnel_api->create_tunnel(&tunnel_id, gSwitchId, (uint32_t)tunnel_attrs.size(), tunnel_attrs.data()); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to create tunnel"); return false; } tunnelTable[key] = { tunnel_id, {} }; // TODO: // there should also be "business logic" for netbouncer in the "tunnel application" code, which is a different source file and daemon process // create a decap tunnel entry for every ip if (!addDecapTunnelTermEntries(key, dst_ip, tunnel_id)) { return false; } return true; }
void TunnelDecapOrch::doTask(Consumer& consumer) { SWSS_LOG_ENTER(); if (!gPortsOrch->isInitDone()) { 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); IpAddresses ip_addresses; IpAddress src_ip; string tunnel_type; string dscp_mode; string ecn_mode; string ttl_mode; bool valid = true; // checking to see if the tunnel already exists bool exists = (tunnelTable.find(key) != tunnelTable.end()); if (op == SET_COMMAND) { for (auto i : kfvFieldsValues(t)) { if (fvField(i) == "tunnel_type") { tunnel_type = fvValue(i); if (tunnel_type != "IPINIP") { SWSS_LOG_ERROR("Invalid tunnel type %s", tunnel_type.c_str()); valid = false; break; } } else if (fvField(i) == "dst_ip") { try { ip_addresses = IpAddresses(fvValue(i)); } catch (const std::invalid_argument &e) { SWSS_LOG_ERROR("%s", e.what()); valid = false; break; } if (exists) { setIpAttribute(key, ip_addresses, tunnelTable.find(key)->second.tunnel_id); } } else if (fvField(i) == "src_ip") { try { src_ip = IpAddress(fvValue(i)); } catch (const std::invalid_argument &e) { SWSS_LOG_ERROR("%s", e.what()); valid = false; break; } if (exists) { SWSS_LOG_ERROR("cannot modify src ip for existing tunnel"); } } else if (fvField(i) == "dscp_mode") { dscp_mode = fvValue(i); if (dscp_mode != "uniform" && dscp_mode != "pipe") { SWSS_LOG_ERROR("Invalid dscp mode %s\n", dscp_mode.c_str()); valid = false; break; } if (exists) { setTunnelAttribute(fvField(i), dscp_mode, tunnelTable.find(key)->second.tunnel_id); } } else if (fvField(i) == "ecn_mode") { ecn_mode = fvValue(i); if (ecn_mode != "copy_from_outer" && ecn_mode != "standard") { SWSS_LOG_ERROR("Invalid ecn mode %s\n", ecn_mode.c_str()); valid = false; break; } if (exists) { setTunnelAttribute(fvField(i), ecn_mode, tunnelTable.find(key)->second.tunnel_id); } } else if (fvField(i) == "ttl_mode") { ttl_mode = fvValue(i); if (ttl_mode != "uniform" && ttl_mode != "pipe") { SWSS_LOG_ERROR("Invalid ttl mode %s\n", ttl_mode.c_str()); valid = false; break; } if (exists) { setTunnelAttribute(fvField(i), ttl_mode, tunnelTable.find(key)->second.tunnel_id); } } } // create new tunnel if it doesn't exists already if (valid && !exists) { if (addDecapTunnel(key, tunnel_type, ip_addresses, src_ip, dscp_mode, ecn_mode, ttl_mode)) { SWSS_LOG_NOTICE("Tunnel(s) added to ASIC_DB."); } else { SWSS_LOG_ERROR("Failed to add tunnels to ASIC_DB."); } } } if (op == DEL_COMMAND) { if (exists) { removeDecapTunnel(key); } else { SWSS_LOG_ERROR("Tunnel cannot be removed since it doesn't exist."); } } it = consumer.m_toSync.erase(it); } }
void getPortLaneMap( _Inout_ std::vector<std::vector<uint32_t>> &laneMap) { SWSS_LOG_ENTER(); laneMap.clear(); for (auto v: g_laneMap) { size_t s = v.size(); if (s != 1 && s != 2 && s != 4) { SWSS_LOG_THROW("invald number of lanes for interface: %zu", s); } laneMap.push_back(v); } if (g_laneMap.size()) { SWSS_LOG_NOTICE("got port lane map with %zu interfaces", laneMap.size()); return; } const uint32_t default_port_count = 32; sai_uint32_t default_lanes[] = { 29,30,31,32, 25,26,27,28, 37,38,39,40, 33,34,35,36, 41,42,43,44, 45,46,47,48, 5,6,7,8, 1,2,3,4, 9,10,11,12, 13,14,15,16, 21,22,23,24, 17,18,19,20, 49,50,51,52, 53,54,55,56, 61,62,63,64, 57,58,59,60, 65,66,67,68, 69,70,71,72, 77,78,79,80, 73,74,75,76, 105,106,107,108, 109,110,111,112, 117,118,119,120, 113,114,115,116, 121,122,123,124, 125,126,127,128, 85,86,87,88, 81,82,83,84, 89,90,91,92, 93,94,95,96, 97,98,99,100, 101,102,103,104 }; // populate default lane map for (size_t i = 0; i < default_port_count; i++) { std::vector<uint32_t> portLanes; for(int j = 0; j < 4; j++) portLanes.push_back(default_lanes[4*i + j]); laneMap.push_back(portLanes); } SWSS_LOG_NOTICE("populated default port lane map with %zu interfaces", laneMap.size()); }
sai_status_t sai_api_initialize( _In_ uint64_t flags, _In_ const sai_service_method_table_t *service_method_table) { MUTEX(); SWSS_LOG_ENTER(); if (g_api_initialized) { SWSS_LOG_ERROR("api already initialized"); return SAI_STATUS_FAILURE; } if ((service_method_table == NULL) || (service_method_table->profile_get_next_value == NULL) || (service_method_table->profile_get_value == NULL)) { SWSS_LOG_ERROR("invalid service_method_table handle passed to SAI API initialize"); return SAI_STATUS_INVALID_PARAMETER; } memcpy(&g_service_method_table, service_method_table, sizeof(g_service_method_table)); // TODO maybe this query should be done right before switch create const char *type = service_method_table->profile_get_value(0, SAI_KEY_VS_SWITCH_TYPE); if (type == NULL) { SWSS_LOG_ERROR("failed to obtain service method table value: %s", SAI_KEY_VS_SWITCH_TYPE); return SAI_STATUS_FAILURE; } g_interface_lane_map_file = service_method_table->profile_get_value(0, SAI_KEY_VS_INTERFACE_LANE_MAP_FILE); load_interface_lane_map(); g_boot_type = service_method_table->profile_get_value(0, SAI_KEY_BOOT_TYPE); g_warm_boot_read_file = service_method_table->profile_get_value(0, SAI_KEY_WARM_BOOT_READ_FILE); g_warm_boot_write_file = service_method_table->profile_get_value(0, SAI_KEY_WARM_BOOT_WRITE_FILE); std::string bt = (g_boot_type == NULL) ? "cold" : g_boot_type; if (bt == "cold" || bt == "0") { g_vs_boot_type = SAI_VS_COLD_BOOT; } else if (bt == "warm" || bt == "1") { g_vs_boot_type = SAI_VS_WARM_BOOT; } else if (bt == "fast" || bt == "2") { g_vs_boot_type = SAI_VS_FAST_BOOT; } else { SWSS_LOG_ERROR("unsupported boot type: %s", g_boot_type); return SAI_STATUS_FAILURE; } std::string strType = type; if (strType == SAI_VALUE_VS_SWITCH_TYPE_BCM56850) { g_vs_switch_type = SAI_VS_SWITCH_TYPE_BCM56850; } else if (strType == SAI_VALUE_VS_SWITCH_TYPE_MLNX2700) { g_vs_switch_type = SAI_VS_SWITCH_TYPE_MLNX2700; } else { SWSS_LOG_ERROR("unknown switch type: '%s'", type); return SAI_STATUS_FAILURE; } const char *use_tap_dev = service_method_table->profile_get_value(0, SAI_KEY_VS_HOSTIF_USE_TAP_DEVICE); g_vs_hostif_use_tap_device = use_tap_dev != NULL && strcmp(use_tap_dev, "true") == 0; SWSS_LOG_NOTICE("hostif use TAP device: %s", g_vs_hostif_use_tap_device ? "true" : "false"); if (flags != 0) { SWSS_LOG_ERROR("invalid flags passed to SAI API initialize"); return SAI_STATUS_INVALID_PARAMETER; } clear_local_state(); g_dbNtf = std::make_shared<swss::DBConnector>(ASIC_DB, swss::DBConnector::DEFAULT_UNIXSOCKET, 0); g_unittestChannelNotificationConsumer = std::make_shared<swss::NotificationConsumer>(g_dbNtf.get(), SAI_VS_UNITTEST_CHANNEL); g_unittestChannelRun = true; g_unittestChannelThread = std::make_shared<std::thread>(std::thread(unittestChannelThreadProc)); g_fdb_info_set.clear(); g_fdbAgingThreadRun = true; // TODO should this be moved to create switch and SwitchState? g_fdbAgingThread = std::make_shared<std::thread>(std::thread(fdbAgingThreadProc)); g_api_initialized = true; return SAI_STATUS_SUCCESS; }
void channelOpSetReadOnlyAttribute( _In_ const std::string &key, _In_ const std::vector<swss::FieldValueTuple> &values) { SWSS_LOG_ENTER(); for (const auto &v: values) { SWSS_LOG_DEBUG("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str()); } if (values.size() != 1) { SWSS_LOG_ERROR("expected 1 value only, but given: %zu", values.size()); return; } const std::string &str_object_type = key.substr(0, key.find(":")); const std::string &str_object_id = key.substr(key.find(":") + 1); sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); if (object_type == SAI_OBJECT_TYPE_NULL || object_type >= SAI_OBJECT_TYPE_EXTENSIONS_MAX) { SWSS_LOG_ERROR("invalid object type: %d", object_type); return; } auto info = sai_metadata_get_object_type_info(object_type); if (info->isnonobjectid) { SWSS_LOG_ERROR("non object id %s is not supported yet", str_object_type.c_str()); return; } sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); sai_object_type_t ot = sai_object_type_query(object_id); if (ot != object_type) { SWSS_LOG_ERROR("object type is differnt than provided %s, but oid is %s", str_object_type.c_str(), sai_serialize_object_type(ot).c_str()); return; } sai_object_id_t switch_id = sai_switch_id_query(object_id); if (switch_id == SAI_NULL_OBJECT_ID) { SWSS_LOG_ERROR("failed to find switch id for oid %s", str_object_id.c_str()); return; } // oid is validated and we got switch id const std::string &str_attr_id = fvField(values.at(0)); const std::string &str_attr_value = fvValue(values.at(0)); auto meta = sai_metadata_get_attr_metadata_by_attr_id_name(str_attr_id.c_str()); if (meta == NULL) { SWSS_LOG_ERROR("failed to find attr %s", str_attr_id.c_str()); return; } if (meta->objecttype != ot) { SWSS_LOG_ERROR("attr %s belongs to differnt object type than oid: %s", str_attr_id.c_str(), sai_serialize_object_type(ot).c_str()); return; } // we got attr metadata sai_attribute_t attr; attr.id = meta->attrid; sai_deserialize_attr_value(str_attr_value, *meta, attr); SWSS_LOG_NOTICE("switch id is %s", sai_serialize_object_id(switch_id).c_str()); sai_status_t status = meta_unittests_allow_readonly_set_once(meta->objecttype, meta->attrid); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("failed to enable SET readonly attribute once: %s", sai_serialize_status(status).c_str()); return; } sai_object_meta_key_t meta_key = { .objecttype = ot, .objectkey = { .key = { .object_id = object_id } } }; status = info->set(&meta_key, &attr); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("failed to set %s to %s on %s", str_attr_id.c_str(), str_attr_value.c_str(), str_object_id.c_str()); } else { SWSS_LOG_NOTICE("SUCCESS to set %s to %s on %s", str_attr_id.c_str(), str_attr_value.c_str(), str_object_id.c_str()); } sai_deserialize_free_attribute_value(meta->attrvaluetype, attr); }
void load_interface_lane_map() { SWSS_LOG_ENTER(); if (g_interface_lane_map_file == NULL) { SWSS_LOG_NOTICE("no interface lane map"); return; } std::ifstream lanemap(g_interface_lane_map_file); if (!lanemap.is_open()) { SWSS_LOG_ERROR("failed to open lane map file: %s", g_interface_lane_map_file); return; } std::string line; while(getline(lanemap, line)) { if (line.size() > 0 && (line[0] == '#' || line[0] == ';')) { continue; } auto tokens = swss::tokenize(line, ':'); if (tokens.size() != 2) { SWSS_LOG_ERROR("expected 2 tokens in line %s, got %zu", line.c_str(), tokens.size()); continue; } auto ifname = tokens.at(0); auto lanes = tokens.at(1); if (!check_ifname(ifname)) { continue; } if (g_ifname_to_lanes.find(ifname) != g_ifname_to_lanes.end()) { SWSS_LOG_ERROR("interface %s was already defined", ifname.c_str()); continue; } tokens = swss::tokenize(lanes,','); size_t n = tokens.size(); if (n != 1 && n != 2 && n != 4) { SWSS_LOG_ERROR("invalid number of lanes (%zu) assigned to interface %s", n, ifname.c_str()); continue; } std::vector<uint32_t> lanevec; for (auto l: tokens) { uint32_t lanenumber; if (sscanf(l.c_str(), "%u", &lanenumber) != 1) { SWSS_LOG_ERROR("failed to parse lane number: %s", l.c_str()); continue; } if (g_lane_to_ifname.find(lanenumber) != g_lane_to_ifname.end()) { SWSS_LOG_ERROR("lane number %u used on %s was already defined on %s", lanenumber, ifname.c_str(), g_lane_to_ifname.at(lanenumber).c_str()); continue; } lanevec.push_back(lanenumber); g_lane_order.push_back(lanenumber); g_lane_to_ifname[lanenumber] = ifname; } g_ifname_to_lanes[ifname] = lanevec; g_laneMap.push_back(lanevec); } SWSS_LOG_NOTICE("loaded %zu lanes and %zu interfaces", g_lane_to_ifname.size(), g_ifname_to_lanes.size()); }
void handleUnittestChannelOp( _In_ const std::string &op, _In_ const std::string &key, _In_ const std::vector<swss::FieldValueTuple> &values) { /* * Since we will access and modify DB we need to be under mutex. * * NOTE: since this unittest channel is handled in thread, then that means * there is a DELAY from producer and consumer thread in VS, so if user * will set value on the specific READ_ONLY value he should wait for some * time until that value will be propagated to virtual switch. */ MUTEX(); SWSS_LOG_ENTER(); SWSS_LOG_NOTICE("read only SET: op = %s, key = %s", op.c_str(), key.c_str()); if (op == SAI_VS_UNITTEST_ENABLE_UNITTESTS) { bool enable = (key == "true"); meta_unittests_enable(enable); } else if (op == SAI_VS_UNITTEST_SET_RO_OP) { for (const auto &v: values) { SWSS_LOG_DEBUG("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str()); } if (values.size() != 1) { SWSS_LOG_ERROR("expected 1 value only, but given: %zu", values.size()); return; } const std::string &str_object_type = key.substr(0, key.find(":")); const std::string &str_object_id = key.substr(key.find(":") + 1); sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); if (object_type == SAI_OBJECT_TYPE_NULL || object_type >= SAI_OBJECT_TYPE_MAX) { SWSS_LOG_ERROR("invalid object type: %d", object_type); return; } auto info = sai_metadata_get_object_type_info(object_type); if (info->isnonobjectid) { SWSS_LOG_ERROR("non object id %s is not supported yet", str_object_type.c_str()); return; } sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); sai_object_type_t ot = sai_object_type_query(object_id); if (ot != object_type) { SWSS_LOG_ERROR("object type is differnt than provided %s, but oid is %s", str_object_type.c_str(), sai_serialize_object_type(ot).c_str()); return; } sai_object_id_t switch_id = sai_switch_id_query(object_id); if (switch_id == SAI_NULL_OBJECT_ID) { SWSS_LOG_ERROR("failed to find switch id for oid %s", str_object_id.c_str()); return; } // oid is validated and we got switch id const std::string &str_attr_id = fvField(values.at(0)); const std::string &str_attr_value = fvValue(values.at(0)); auto meta = sai_metadata_get_attr_metadata_by_attr_id_name(str_attr_id.c_str()); if (meta == NULL) { SWSS_LOG_ERROR("failed to find attr %s", str_attr_id.c_str()); return; } if (meta->objecttype != ot) { SWSS_LOG_ERROR("attr %s belongs to differnt object type than oid: %s", str_attr_id.c_str(), sai_serialize_object_type(ot).c_str()); return; } // we got attr metadata sai_attribute_t attr; attr.id = meta->attrid; sai_deserialize_attr_value(str_attr_value, *meta, attr); SWSS_LOG_NOTICE("switch id is %s", sai_serialize_object_id(switch_id).c_str()); sai_status_t status = meta_unittests_allow_readonly_set_once(meta->objecttype, meta->attrid); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("failed to enable SET readonly attribute once: %s", sai_serialize_status(status).c_str()); return; } sai_object_meta_key_t meta_key = { .objecttype = ot, .objectkey = { .key = { .object_id = object_id } } }; status = info->set(&meta_key, &attr); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("failed to set %s to %s on %s", str_attr_id.c_str(), str_attr_value.c_str(), str_object_id.c_str()); } else { SWSS_LOG_NOTICE("SUCCESS to set %s to %s on %s", str_attr_id.c_str(), str_attr_value.c_str(), str_object_id.c_str()); } sai_deserialize_free_attribute_value(meta->attrvaluetype, attr); } else {
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; }
void IntfsOrch::doTask(Consumer &consumer) { SWSS_LOG_ENTER(); if (consumer.m_toSync.empty()) return; if (!m_portsOrch->isInitDone()) return; auto it = consumer.m_toSync.begin(); while (it != consumer.m_toSync.end()) { KeyOpFieldsValuesTuple t = it->second; string key = kfvKey(t); size_t found = key.find(':'); if (found == string::npos) { SWSS_LOG_ERROR("Failed to parse task key %s\n", key.c_str()); it = consumer.m_toSync.erase(it); continue; } string alias = key.substr(0, found); IpPrefix ip_prefix(key.substr(found+1)); if (!ip_prefix.isV4()) { it = consumer.m_toSync.erase(it); continue; } string op = kfvOp(t); if (op == SET_COMMAND) { /* Duplicate entry */ if (m_intfs.find(alias) != m_intfs.end() && m_intfs[alias] == ip_prefix.getIp()) { it = consumer.m_toSync.erase(it); continue; } Port p; if (!m_portsOrch->getPort(alias, p)) { SWSS_LOG_ERROR("Failed to locate interface %s\n", alias.c_str()); it = consumer.m_toSync.erase(it); continue; } sai_unicast_route_entry_t unicast_route_entry; unicast_route_entry.vr_id = gVirtualRouterId; unicast_route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; unicast_route_entry.destination.addr.ip4 = ip_prefix.getIp().getV4Addr() & ip_prefix.getMask().getV4Addr(); unicast_route_entry.destination.mask.ip4 = ip_prefix.getMask().getV4Addr(); sai_attribute_t attr; vector<sai_attribute_t> attrs; attr.id = SAI_ROUTE_ATTR_PACKET_ACTION; attr.value.s32 = SAI_PACKET_ACTION_FORWARD; attrs.push_back(attr); attr.id = SAI_ROUTE_ATTR_NEXT_HOP_ID; attr.value.oid = p.m_rif_id; attrs.push_back(attr); sai_status_t status = sai_route_api->create_route(&unicast_route_entry, attrs.size(), attrs.data()); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to create subnet route pre:%s %d\n", ip_prefix.to_string().c_str(), status); it++; continue; } else { SWSS_LOG_NOTICE("Create subnet route pre:%s\n", ip_prefix.to_string().c_str()); } unicast_route_entry.vr_id = gVirtualRouterId; unicast_route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; unicast_route_entry.destination.addr.ip4 = ip_prefix.getIp().getV4Addr(); unicast_route_entry.destination.mask.ip4 = 0xFFFFFFFF; attr.id = SAI_ROUTE_ATTR_PACKET_ACTION; attr.value.s32 = SAI_PACKET_ACTION_TRAP; status = sai_route_api->create_route(&unicast_route_entry, 1, &attr); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to create packet action trap route ip:%s %d\n", ip_prefix.getIp().to_string().c_str(), status); it++; } else { SWSS_LOG_NOTICE("Create packet action trap route ip:%s\n", ip_prefix.getIp().to_string().c_str()); m_intfs[alias] = ip_prefix.getIp(); it = consumer.m_toSync.erase(it); } } else if (op == DEL_COMMAND) { Port p; if (!m_portsOrch->getPort(alias, p)) { SWSS_LOG_ERROR("Failed to locate interface %s\n", alias.c_str()); it = consumer.m_toSync.erase(it); continue; } sai_unicast_route_entry_t unicast_route_entry; unicast_route_entry.vr_id = gVirtualRouterId; unicast_route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; unicast_route_entry.destination.addr.ip4 = ip_prefix.getIp().getV4Addr() & ip_prefix.getMask().getV4Addr(); unicast_route_entry.destination.mask.ip4 = ip_prefix.getMask().getV4Addr(); sai_status_t status = sai_route_api->remove_route(&unicast_route_entry); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to remove subnet route pre:%s %d\n", ip_prefix.to_string().c_str(), status); it++; continue; } unicast_route_entry.vr_id = gVirtualRouterId; unicast_route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; unicast_route_entry.destination.addr.ip4 = ip_prefix.getIp().getV4Addr(); unicast_route_entry.destination.mask.ip4 = 0xFFFFFFFF; status = sai_route_api->remove_route(&unicast_route_entry); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to remove action trap route ip:%s %d\n", ip_prefix.getIp().to_string().c_str(), status); it++; } else { SWSS_LOG_NOTICE("Remove packet action trap route ip:%s\n", ip_prefix.getIp().to_string().c_str()); m_intfs.erase(alias); it = consumer.m_toSync.erase(it); } } } }
sai_status_t sai_bulk_create_route_entry( _In_ uint32_t object_count, _In_ const sai_route_entry_t *route_entry, _In_ const uint32_t *attr_count, _In_ const sai_attribute_t **attr_list, _In_ sai_bulk_op_error_mode_t mode, _Out_ sai_status_t *object_statuses) { std::lock_guard<std::mutex> lock(g_apimutex); SWSS_LOG_ENTER(); if (object_count < 1) { SWSS_LOG_ERROR("expected at least 1 object to create"); return SAI_STATUS_INVALID_PARAMETER; } if (route_entry == NULL) { SWSS_LOG_ERROR("route_entry is NULL"); return SAI_STATUS_INVALID_PARAMETER; } if (attr_count == NULL) { SWSS_LOG_ERROR("attr_count is NULL"); return SAI_STATUS_INVALID_PARAMETER; } if (attr_list == NULL) { SWSS_LOG_ERROR("attr_list is NULL"); return SAI_STATUS_INVALID_PARAMETER; } switch (mode) { case SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR: case SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR: // ok break; default: SWSS_LOG_ERROR("invalid bulk operation mode %d", mode); return SAI_STATUS_INVALID_PARAMETER; } if (object_statuses == NULL) { SWSS_LOG_ERROR("object_statuses is NULL"); return SAI_STATUS_INVALID_PARAMETER; } std::vector<std::string> serialized_object_ids; for (uint32_t idx = 0; idx < object_count; ++idx) { /* * At the beginning set all statuses to not executed. */ object_statuses[idx] = SAI_STATUS_NOT_EXECUTED; serialized_object_ids.push_back( sai_serialize_route_entry(route_entry[idx])); } for (uint32_t idx = 0; idx < object_count; ++idx) { sai_status_t status = meta_sai_create_route_entry( &route_entry[idx], attr_count[idx], attr_list[idx], &redis_dummy_create_route_entry); object_statuses[idx] = status; if (status != SAI_STATUS_SUCCESS) { // TODO add attr id and value SWSS_LOG_ERROR("failed on index %u: %s", idx, serialized_object_ids[idx].c_str()); if (mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR) { SWSS_LOG_NOTICE("stop on error since previous operation failed"); break; } } } /* * TODO: we need to record operation type */ return internal_redis_bulk_generic_create( SAI_OBJECT_TYPE_ROUTE_ENTRY, serialized_object_ids, attr_count, attr_list, object_statuses); }
sai_status_t internal_vs_generic_get( _In_ sai_object_type_t object_type, _In_ const std::string &serialized_object_id, _In_ sai_object_id_t switch_id, _In_ uint32_t attr_count, _Out_ sai_attribute_t *attr_list) { SWSS_LOG_ENTER(); auto &objectHash = g_switch_state_map.at(switch_id)->objectHash.at(object_type); auto it = objectHash.find(serialized_object_id); if (it == objectHash.end()) { SWSS_LOG_ERROR("not found %s:%s", sai_serialize_object_type(object_type).c_str(), serialized_object_id.c_str()); return SAI_STATUS_ITEM_NOT_FOUND; } /* * We need reference here since we can potentially update attr hash for RO * object. */ AttrHash& attrHash = it->second; /* * Some of the list query maybe for length, so we can't do * normal serialize, maybe with count only. */ sai_status_t final_status = SAI_STATUS_SUCCESS; for (uint32_t idx = 0; idx < attr_count; ++idx) { sai_attr_id_t id = attr_list[idx].id; auto meta = sai_metadata_get_attr_metadata(object_type, id); if (meta == NULL) { SWSS_LOG_ERROR("failed to find attribute %d for %s:%s", id, sai_serialize_object_type(object_type).c_str(), serialized_object_id.c_str()); return SAI_STATUS_FAILURE; } sai_status_t status; if (HAS_FLAG_READ_ONLY(meta->flags)) { /* * Read only attributes may require recalculation. * Metadata makes sure that non object id's can't have * read only attributes. So here is defenetly OID. */ sai_object_id_t oid; sai_deserialize_object_id(serialized_object_id, oid); status = refresh_read_only(meta, oid, switch_id); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("%s read only not implemented on %s", meta->attridname, serialized_object_id.c_str()); return status; } } auto ait = attrHash.find(meta->attridname); if (ait == attrHash.end()) { SWSS_LOG_ERROR("%s not implemented on %s", meta->attridname, serialized_object_id.c_str()); return SAI_STATUS_NOT_IMPLEMENTED; } auto attr = ait->second->getAttr(); status = transfer_attributes(object_type, 1, attr, &attr_list[idx], false); if (status == SAI_STATUS_BUFFER_OVERFLOW) { /* * This is considered partial success, since we get correct list * length. Note that other items ARE processes on the list. */ SWSS_LOG_NOTICE("BUFFER_OVERFLOW %s: %s", serialized_object_id.c_str(), meta->attridname); /* * We still continue processing other attributes for get as long as * we only will be getting buffer overflow error. */ final_status = status; continue; } if (status != SAI_STATUS_SUCCESS) { // all other errors SWSS_LOG_ERROR("get failed %s: %s: %s", serialized_object_id.c_str(), meta->attridname, sai_serialize_status(status).c_str()); return status; } } return final_status; }
static sai_status_t refresh_bridge_port_list( _In_ const sai_attr_metadata_t *meta, _In_ sai_object_id_t bridge_id, _In_ sai_object_id_t switch_id) { SWSS_LOG_ENTER(); /* * TODO possible issues with vxlan and lag. */ auto &all_bridge_ports = g_switch_state_map.at(switch_id)->objectHash.at(SAI_OBJECT_TYPE_BRIDGE_PORT); sai_attribute_t attr; auto m_port_list = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_BRIDGE, SAI_BRIDGE_ATTR_PORT_LIST); auto m_port_id = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_BRIDGE_PORT, SAI_BRIDGE_PORT_ATTR_PORT_ID); auto m_bridge_id = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_BRIDGE_PORT, SAI_BRIDGE_PORT_ATTR_BRIDGE_ID); /* * First get all port's that belong to this bridge id. */ std::map<sai_object_id_t, AttrHash> bridge_port_list_on_bridge_id; for (const auto &bp: all_bridge_ports) { auto it = bp.second.find(m_bridge_id->attridname); if (it == bp.second.end()) { continue; } if (bridge_id == it->second->getAttr()->value.oid) { /* * This bridge port belongs to currently processing bridge ID. */ sai_object_id_t bridge_port; sai_deserialize_object_id(bp.first, bridge_port); bridge_port_list_on_bridge_id[bridge_port] = bp.second; } } /* * Now sort those bridge port id's by port id to be consistent. */ std::vector<sai_object_id_t> bridge_port_list; for (const auto &p: port_list) { for (const auto &bp: bridge_port_list_on_bridge_id) { auto it = bp.second.find(m_port_id->attridname); if (it == bp.second.end()) { SWSS_LOG_THROW("bridge port is missing %s, not supported yet, FIXME", m_port_id->attridname); } if (p == it->second->getAttr()->value.oid) { bridge_port_list.push_back(bp.first); } } } if (bridge_port_list_on_bridge_id.size() != bridge_port_list.size()) { SWSS_LOG_THROW("filter by port id failed size on lists is different: %zu vs %zu", bridge_port_list_on_bridge_id.size(), bridge_port_list.size()); } uint32_t bridge_port_list_count = (uint32_t)bridge_port_list.size(); SWSS_LOG_NOTICE("recalculated %s: %u", m_port_list->attridname, bridge_port_list_count); attr.id = SAI_BRIDGE_ATTR_PORT_LIST; attr.value.objlist.count = bridge_port_list_count; attr.value.objlist.list = bridge_port_list.data(); return vs_generic_set(SAI_OBJECT_TYPE_BRIDGE, bridge_id, &attr); }
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; }
/** * Function Description: * @brief adds a decap tunnel termination entry to ASIC_DB * * Arguments: * @param[in] tunnelKey - key of the tunnel from APP_DB * @param[in] dst_ip - destination ip addresses to decap * @param[in] tunnel_id - the id of the tunnel * * Return Values: * @return true on success and false if there's an error */ bool TunnelDecapOrch::addDecapTunnelTermEntries(string tunnelKey, IpAddresses dst_ip, sai_object_id_t tunnel_id) { SWSS_LOG_ENTER(); sai_attribute_t attr; // adding tunnel table entry attributes to array and writing to ASIC_DB vector<sai_attribute_t> tunnel_table_entry_attrs; attr.id = SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_VR_ID; attr.value.oid = gVirtualRouterId; tunnel_table_entry_attrs.push_back(attr); attr.id = SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_TYPE; attr.value.u32 = SAI_TUNNEL_TERM_TABLE_ENTRY_TYPE_P2MP; tunnel_table_entry_attrs.push_back(attr); attr.id = SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_TUNNEL_TYPE; attr.value.s32 = SAI_TUNNEL_TYPE_IPINIP; tunnel_table_entry_attrs.push_back(attr); attr.id = SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_ACTION_TUNNEL_ID; attr.value.oid = tunnel_id; tunnel_table_entry_attrs.push_back(attr); TunnelEntry *tunnel_info = &tunnelTable.find(tunnelKey)->second; // loop through the IP list and create a new tunnel table entry for every IP (in network byte order) set<IpAddress> tunnel_ips = dst_ip.getIpAddresses(); for (auto it = tunnel_ips.begin(); it != tunnel_ips.end(); ++it) { const IpAddress& ia = *it; string ip = ia.to_string(); // check if the there's an entry already for the ip if (existingIps.find(ip) != existingIps.end()) { SWSS_LOG_ERROR("%s already exists. Did not create entry.", ip.c_str()); } else { attr.id = SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_DST_IP; copy(attr.value.ipaddr, ia); tunnel_table_entry_attrs.push_back(attr); // create the tunnel table entry sai_object_id_t tunnel_term_table_entry_id; sai_status_t status = sai_tunnel_api->create_tunnel_term_table_entry(&tunnel_term_table_entry_id, gSwitchId, (uint32_t)tunnel_table_entry_attrs.size(), tunnel_table_entry_attrs.data()); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to create tunnel entry table for ip: %s", ip.c_str()); return false; } // insert into ip to entry mapping existingIps.insert(ip); // insert entry id and ip into tunnel mapping tunnel_info->tunnel_term_info.push_back({ tunnel_term_table_entry_id, ip }); // pop the last element for the next loop tunnel_table_entry_attrs.pop_back(); SWSS_LOG_NOTICE("Created tunnel entry for ip: %s", ip.c_str()); } } return true; }
/* * 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; }
void cli_thread_function() { SWSS_LOG_ENTER(); cli_server_socket = socket(AF_INET, SOCK_STREAM, 0); if (cli_server_socket < 0) { SWSS_LOG_ERROR("open socket failed, errno: %s", strerror(errno)); return; } struct sockaddr_in serv_addr; memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); serv_addr.sin_port = htons(CLI_PORT); if (bind(cli_server_socket, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) != 0) { SWSS_LOG_ERROR("bind socket failed, errno: %s", strerror(errno)); close(cli_server_socket); return; } const int backlog = 5; if (listen(cli_server_socket, backlog) != 0) { SWSS_LOG_ERROR("listen on socket failed, errno: %s", strerror(errno)); close(cli_server_socket); return; } while (run_cli) { struct sockaddr_in cli_addr; memset(&cli_addr, 0, sizeof(cli_addr)); socklen_t clilen = sizeof(cli_addr); SWSS_LOG_NOTICE("accepting connections for cli"); cli_client_socket = accept(cli_server_socket, (struct sockaddr *) &cli_addr, &clilen); if (cli_client_socket < 0) { // don't log when run is false, that's mean we closed socket if (run_cli) { SWSS_LOG_ERROR("accept failed, errno: %s", strerror(errno)); } break; } SWSS_LOG_NOTICE("client connected to cli"); // we allow only 1 connection at given time handle_cli(); close(cli_client_socket); } close(cli_server_socket); }
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); #ifdef SAITHRIFT if (options.portMapFile.size() > 0) { handlePortMap(options.portMapFile); } #endif // SAITHRIFT 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"); g_veryFirstRun = isVeryFirstRun(); if (options.startType == SAI_WARM_BOOT) { 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.startType = SAI_COLD_BOOT; } } if (options.startType == SAI_WARM_BOOT && 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.startType = SAI_COLD_BOOT; } gProfileMap[SAI_KEY_BOOT_TYPE] = std::to_string(options.startType); 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, "", "", &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 */ #ifdef SAITHRIFT if (options.run_rpc_server) { start_sai_thrift_rpc_server(SWITCH_SAI_THRIFT_RPC_SERVER_PORT); SWSS_LOG_NOTICE("rpcserver started"); } #endif // SAITHRIFT SWSS_LOG_NOTICE("syncd started"); bool warmRestartHint = false; try { onSyncdStart(options.startType == SAI_WARM_BOOT); 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; }