diff options
Diffstat (limited to 'redfish-core/lib/ethernet.hpp')
-rw-r--r-- | redfish-core/lib/ethernet.hpp | 166 |
1 files changed, 117 insertions, 49 deletions
diff --git a/redfish-core/lib/ethernet.hpp b/redfish-core/lib/ethernet.hpp index 876bc2edb4..533c7f5c2e 100644 --- a/redfish-core/lib/ethernet.hpp +++ b/redfish-core/lib/ethernet.hpp @@ -47,6 +47,12 @@ enum class LinkType Global }; +enum class IpVersion +{ + IpV4, + IpV6 +}; + /** * Structure for keeping IPv4 data required by Redfish */ @@ -700,7 +706,30 @@ inline void extractIPData(const std::string& ethifaceId, } /** - * @brief Deletes given IPv4 interface + * @brief Modifies the default gateway assigned to the NIC + * + * @param[in] ifaceId Id of network interface whose default gateway is to be + * changed + * @param[in] gateway The new gateway value. Assigning an empty string + * causes the gateway to be deleted + * @param[io] asyncResp Response object that will be returned to client + * + * @return None + */ +inline void updateIPv4DefaultGateway( + const std::string& ifaceId, const std::string& gateway, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) +{ + setDbusProperty( + asyncResp, "xyz.openbmc_project.Network", + sdbusplus::message::object_path("/xyz/openbmc_project/network") / + ifaceId, + "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway", + "Gateway", gateway); +} + +/** + * @brief Deletes given static IP address for the interface * * @param[in] ifaceId Id of interface whose IP should be deleted * @param[in] ipHash DBus Hash id of IP that should be deleted @@ -724,17 +753,6 @@ inline void deleteIPAddress(const std::string& ifaceId, "xyz.openbmc_project.Object.Delete", "Delete"); } -inline void updateIPv4DefaultGateway( - const std::string& ifaceId, const std::string& gateway, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) -{ - setDbusProperty( - asyncResp, "xyz.openbmc_project.Network", - sdbusplus::message::object_path("/xyz/openbmc_project/network") / - ifaceId, - "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway", - "Gateway", gateway); -} /** * @brief Creates a static IPv4 entry * @@ -757,7 +775,6 @@ inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength, messages::internalError(asyncResp->res); return; } - updateIPv4DefaultGateway(ifaceId, gateway, asyncResp); }; crow::connections::systemBus->async_method_call( @@ -769,24 +786,19 @@ inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength, } /** - * @brief Deletes the IPv6 entry for this interface and creates a replacement - * static IPv6 entry + * @brief Deletes the IP entry for this interface and creates a replacement + * static entry * - * @param[in] ifaceId Id of interface upon which to create the IPv6 entry - * @param[in] id The unique hash entry identifying the DBus entry - * @param[in] prefixLength IPv6 prefix syntax for the subnet mask - * @param[in] address IPv6 address to assign to this interface - * @param[io] asyncResp Response object that will be returned to client + * @param[in] ifaceId Id of interface upon which to create the IPv6 entry + * @param[in] id The unique hash entry identifying the DBus entry + * @param[in] prefixLength Prefix syntax for the subnet mask + * @param[in] address Address to assign to this interface + * @param[in] numStaticAddrs Count of IPv4 static addresses + * @param[io] asyncResp Response object that will be returned to client * * @return None */ -enum class IpVersion -{ - IpV4, - IpV6 -}; - inline void deleteAndCreateIPAddress( IpVersion version, const std::string& ifaceId, const std::string& id, uint8_t prefixLength, const std::string& address, @@ -1391,6 +1403,10 @@ inline void handleDHCPPatch(const std::string& ifaceId, bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true); bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false); + if (ipv4Active) + { + updateIPv4DefaultGateway(ifaceId, "", asyncResp); + } bool nextv4DHCPState = v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active; @@ -1489,6 +1505,7 @@ inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry( inline void handleIPv4StaticPatch( const std::string& ifaceId, std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, + const EthernetInterfaceData& ethData, const std::vector<IPv4AddressData>& ipv4Data, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { @@ -1500,6 +1517,19 @@ inline void handleIPv4StaticPatch( std::vector<IPv4AddressData>::const_iterator nicIpEntry = getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend()); + bool gatewayValueAssigned{}; + std::string activePath{}; + std::string activeGateway{}; + if (!ethData.defaultGateway.empty() && ethData.defaultGateway != "0.0.0.0") + { + // The NIC is already configured with a default gateway. Use this if + // the leading entry in the PATCH is '{}', which is preserving an active + // static address. + activeGateway = ethData.defaultGateway; + activePath = "IPv4StaticAddresses/1"; + gatewayValueAssigned = true; + } + for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson : input) { @@ -1507,7 +1537,32 @@ inline void handleIPv4StaticPatch( std::to_string(entryIdx); nlohmann::json::object_t* obj = std::get_if<nlohmann::json::object_t>(&thisJson); - if (obj != nullptr && !obj->empty()) + if (obj == nullptr) + { + if (nicIpEntry != ipv4Data.cend()) + { + deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); + nicIpEntry = getNextStaticIpEntry(++nicIpEntry, + ipv4Data.cend()); + if (!gatewayValueAssigned && (nicIpEntry == ipv4Data.cend())) + { + // All entries have been processed, and this last has + // requested the IP address be deleted. No prior entry + // performed an action that created or modified a + // gateway. Deleting this IP address means the default + // gateway entry has to be removed as well. + updateIPv4DefaultGateway(ifaceId, "", asyncResp); + } + entryIdx++; + continue; + } + // Received a DELETE action on an entry not assigned to the NIC + messages::resourceCannotBeDeleted(asyncResp->res); + return; + } + + // An Add/Modify action is requested + if (!obj->empty()) { std::optional<std::string> address; std::optional<std::string> subnetMask; @@ -1596,6 +1651,29 @@ inline void handleIPv4StaticPatch( return; } + if (gatewayValueAssigned) + { + if (activeGateway != gateway) + { + // A NIC can only have a single active gateway value. + // If any gateway in the array of static addresses + // mismatch the PATCH is in error. + std::string arg1 = pathString + "/Gateway"; + std::string arg2 = activePath + "/Gateway"; + messages::propertyValueConflict(asyncResp->res, arg1, arg2); + return; + } + } + else + { + // Capture the very first gateway value from the incoming + // JSON record and use it at the default gateway. + updateIPv4DefaultGateway(ifaceId, *gateway, asyncResp); + activeGateway = *gateway; + activePath = pathString; + gatewayValueAssigned = true; + } + if (nicIpEntry != ipv4Data.cend()) { deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId, @@ -1613,31 +1691,21 @@ inline void handleIPv4StaticPatch( } else { - if (nicIpEntry == ipv4Data.cend()) - { - // Requesting a DELETE/DO NOT MODIFY action for an item - // that isn't present on the eth(n) interface. Input JSON is - // in error, so bail out. - if (obj == nullptr) - { - messages::resourceCannotBeDeleted(asyncResp->res); - return; - } - messages::propertyValueFormatError(asyncResp->res, *obj, - pathString); - return; - } - - if (obj == nullptr) - { - deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); - } + // Received {}, do not modify this address if (nicIpEntry != ipv4Data.cend()) { nicIpEntry = getNextStaticIpEntry(++nicIpEntry, ipv4Data.cend()); + entryIdx++; + } + else + { + // Requested a DO NOT MODIFY action on an entry not assigned + // to the NIC + messages::propertyValueFormatError(asyncResp->res, *obj, + pathString); + return; } - entryIdx++; } } } @@ -2268,8 +2336,8 @@ inline void requestEthernetInterfacesRoutes(App& app) if (ipv4StaticAddresses) { - handleIPv4StaticPatch(ifaceId, *ipv4StaticAddresses, ipv4Data, - asyncResp); + handleIPv4StaticPatch(ifaceId, *ipv4StaticAddresses, ethData, + ipv4Data, asyncResp); } if (staticNameServers) |