1 /* 2 * SPDX-FileCopyrightText: Copyright OpenBMC Authors 3 * SPDX-License-Identifier: Apache-2.0 4 */ 5 6 #pragma once 7 8 #include <MctpAsioEndpoint.hpp> 9 #include <OcpMctpVdm.hpp> 10 #include <boost/asio/generic/datagram_protocol.hpp> 11 #include <boost/asio/io_context.hpp> 12 #include <boost/asio/steady_timer.hpp> 13 #include <boost/circular_buffer.hpp> 14 #include <boost/container/devector.hpp> 15 #include <boost/container/flat_map.hpp> 16 #include <boost/container/small_vector.hpp> 17 18 #include <cstddef> 19 #include <cstdint> 20 #include <expected> 21 #include <functional> 22 #include <iostream> 23 #include <memory> 24 #include <queue> 25 #include <span> 26 #include <system_error> 27 #include <unordered_map> 28 #include <utility> 29 30 namespace mctp 31 { 32 class MctpRequester 33 { 34 public: 35 MctpRequester() = delete; 36 37 MctpRequester(const MctpRequester&) = delete; 38 39 MctpRequester(MctpRequester&&) = delete; 40 41 MctpRequester& operator=(const MctpRequester&) = delete; 42 43 MctpRequester& operator=(MctpRequester&&) = delete; 44 45 explicit MctpRequester(boost::asio::io_context& ctx); 46 47 void sendRecvMsg(uint8_t eid, std::span<const uint8_t> reqMsg, 48 std::move_only_function<void(const std::error_code&, 49 std::span<const uint8_t>)> 50 callback); 51 52 private: 53 using cb_t = std::move_only_function<void(const std::error_code&, 54 std::span<const uint8_t>)>; 55 56 static constexpr uint8_t msgType = ocp::accelerator_management::messageType; 57 58 struct RequestContext 59 { 60 std::vector<uint8_t> reqMsg; 61 cb_t callback; 62 63 RequestContext(const RequestContext&) = delete; 64 RequestContext& operator=(const RequestContext&) = delete; 65 66 RequestContext(RequestContext&&) = default; 67 RequestContext& operator=(RequestContext&&) = default; 68 ~RequestContext() = default; 69 RequestContextmctp::MctpRequester::RequestContext70 explicit RequestContext(std::span<const uint8_t> req, cb_t&& cb) : 71 reqMsg(req.begin(), req.end()), callback(std::move(cb)) 72 {} 73 }; 74 75 struct EidContext 76 { 77 boost::asio::steady_timer timer; 78 uint8_t iid{}; 79 boost::container::devector<RequestContext> queue; EidContextmctp::MctpRequester::EidContext80 EidContext(boost::asio::io_context& io) : timer{io}, iid{0xFF} {} 81 EidContext(EidContext&&) noexcept = default; 82 EidContext& operator=(EidContext&&) noexcept = default; 83 EidContext& operator=(const EidContext&) = delete; 84 EidContext(const EidContext&) = delete; 85 ~EidContext() = default; 86 }; 87 88 std::optional<uint8_t> getNextIid(uint8_t eid); 89 void startReceive(); 90 void processRecvMsg(const boost::system::error_code& ec, size_t length); 91 void handleSendMsgCompletion(uint8_t eid, 92 const boost::system::error_code& ec, 93 size_t length); 94 95 void handleResult(uint8_t eid, const std::error_code& ec, 96 std::span<const uint8_t> buffer); 97 void processQueue(uint8_t eid); 98 99 boost::asio::io_context& io; 100 101 boost::asio::generic::datagram_protocol::socket mctpSocket; 102 static constexpr size_t maxMessageSize = 65536 + 256; 103 std::array<uint8_t, maxMessageSize> buffer{}; 104 MctpAsioEndpoint recvEndPoint; 105 std::unordered_map<uint8_t, EidContext> requestContextQueues; 106 }; 107 108 } // namespace mctp 109