/** * @brief SILA inventory table implementation. * * This file is part of sila-snmp project. * * Copyright (c) 2022 SILA * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "tracing.hpp" #include "data/table.hpp" #include "data/table/item.hpp" #include "sila/sila_oid.hpp" #include "snmptrap.hpp" namespace sila { namespace inventory { using OID = phosphor::snmp::agent::OID; static const OID NOTIFY_OID = SILA_OID(0, 7); struct InventoryItem : public phosphor::snmp::data::table::Item< std::string, std::string, std::string, std::string, std::string, std::string, std::string, bool, bool> { // Indexes of fields in tuble enum Fields { FIELD_INVENTORY_PRETTY_NAME = 0, FIELD_INVENTORY_MANUFACTURER, FIELD_INVENTORY_BUILD_DATE, FIELD_INVENTORY_MODEL, FIELD_INVENTORY_PART_NUMBER, FIELD_INVENTORY_SERIAL_NUMBER, FIELD_INVENTORY_VERSION, FIELD_INVENTORY_PRESENT, FIELD_INVENTORY_FUNCTIONAL, }; enum Columns { COLUMN_SILAINVENTORY_PATH = 1, COLUMN_SILAINVENTORY_NAME, COLUMN_SILAINVENTORY_MANUFACTURER, COLUMN_SILAINVENTORY_BUILD_DATE, COLUMN_SILAINVENTORY_MODEL, COLUMN_SILAINVENTORY_PART_NUMBER, COLUMN_SILAINVENTORY_SERIAL_NUMBER, COLUMN_SILAINVENTORY_VERSION, COLUMN_SILAINVENTORY_PRESENT, COLUMN_SILAINVENTORY_FUNCTIONAL, }; InventoryItem(const std::string& folder, const std::string& name) : phosphor::snmp::data::table::Item( folder, name, "", // Pretty Name "", // Manufacturer "", // Build date "", // Model "", // Part number "", // Serial number "", // Version false, // Present false) // Functional { phosphor::snmp::agent::make_oid( _presentOid, ".1.3.6.1.4.1.49769.4.1.%lu.\"%s\"", COLUMN_SILAINVENTORY_PRESENT, name.c_str()); phosphor::snmp::agent::make_oid( _functionalOid, ".1.3.6.1.4.1.49769.4.1.%lu.\"%s\"", COLUMN_SILAINVENTORY_FUNCTIONAL, name.c_str()); } void setFields(const fields_map_t& fields) override { bool isPresent = std::get(data); bool isFunctional = std::get(data); setField(fields, "PrettyName"); setField(fields, "Manufacturer"); setField(fields, "BuildDate"); setField(fields, "Model"); setField(fields, "PartNumber"); setField(fields, "SerialNumber"); setField(fields, "Version"); setField(fields, "Present"); setField(fields, "Functional"); if (isPresent != std::get(data) || isFunctional != std::get(data)) { DEBUGMSGTL(("sila:inventory", "Inventory item '%s' at '%s': " "present %d -> %d, function %d -> %d\n", std::get(data).c_str(), name.c_str(), isPresent, std::get(data), isFunctional, std::get(data))); phosphor::snmp::agent::Trap trap(NOTIFY_OID); trap.add_field(_presentOid, std::get(data)); trap.add_field(_functionalOid, std::get(data)); trap.send(); } } void get_snmp_reply(netsnmp_agent_request_info* reqinfo, netsnmp_request_info* request) const override { using namespace phosphor::snmp::agent; netsnmp_table_request_info* tinfo = netsnmp_extract_table_info(request); switch (tinfo->colnum) { case COLUMN_SILAINVENTORY_PATH: VariableList::set(request->requestvb, name); break; case COLUMN_SILAINVENTORY_NAME: VariableList::set(request->requestvb, std::get(data)); break; case COLUMN_SILAINVENTORY_MANUFACTURER: VariableList::set(request->requestvb, std::get(data)); break; case COLUMN_SILAINVENTORY_BUILD_DATE: VariableList::set(request->requestvb, std::get(data)); break; case COLUMN_SILAINVENTORY_MODEL: VariableList::set(request->requestvb, std::get(data)); break; case COLUMN_SILAINVENTORY_PART_NUMBER: VariableList::set(request->requestvb, std::get(data)); break; case COLUMN_SILAINVENTORY_SERIAL_NUMBER: VariableList::set( request->requestvb, std::get(data)); break; case COLUMN_SILAINVENTORY_VERSION: VariableList::set(request->requestvb, std::get(data)); break; case COLUMN_SILAINVENTORY_PRESENT: VariableList::set(request->requestvb, std::get(data)); break; case COLUMN_SILAINVENTORY_FUNCTIONAL: VariableList::set(request->requestvb, std::get(data)); break; default: netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); break; } } void onCreate() override { DEBUGMSGTL( ("sila:inventory", "Inventory item '%s' added.\n", name.c_str())); } void onDestroy() override { DEBUGMSGTL(("sila:inventory", "Inventory item '%s' removed.\n", name.c_str())); if (std::get(data) || std::get(data)) { phosphor::snmp::agent::Trap trap(NOTIFY_OID); trap.add_field(_presentOid, false); trap.add_field(_functionalOid, false); trap.send(); } } OID _presentOid; OID _functionalOid; }; static phosphor::snmp::agent::OID inventoryTableOid = SILA_OID(4); static phosphor::snmp::data::Table inventoryTable("/xyz/openbmc_project/inventory", { "xyz.openbmc_project.Inventory.Item", "xyz.openbmc_project.Inventory.Decorator.Asset", "xyz.openbmc_project.Inventory.Decorator.Revision", "xyz.openbmc_project.State.Decorator.OperationalStatus", }); /** * @brief Initialize inventory table */ void init() { DEBUGMSGTL(("sila:init", "Initialize silaInventoryTable\n")); inventoryTable.update(); inventoryTable.init_mib("silaInventoryTable", inventoryTableOid.data(), inventoryTableOid.size(), InventoryItem::COLUMN_SILAINVENTORY_PATH, InventoryItem::COLUMN_SILAINVENTORY_FUNCTIONAL); } /** * @brief Deinitialize inventory table */ void destroy() { DEBUGMSGTL(("sila:shutdown", "Deinitialize silaInventoryTable\n")); unregister_mib(inventoryTableOid.data(), inventoryTableOid.size()); } } // namespace inventory } // namespace sila