cable.cpp (a2056e9ca86e767a774d621c5117939562c5aa54) cable.cpp (ff3cd8e91958cadd6a9f72f2ad69c00abae3c7cf)
1// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//

--- 6 unchanged lines hidden (view full) ---

15#include "cable.hpp"
16
17#include "commands.hpp"
18#include "errors.hpp"
19#include "handler.hpp"
20
21#include <cstdint>
22#include <cstring>
1// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//

--- 6 unchanged lines hidden (view full) ---

15#include "cable.hpp"
16
17#include "commands.hpp"
18#include "errors.hpp"
19#include "handler.hpp"
20
21#include <cstdint>
22#include <cstring>
23#include <ipmid/api-types.hpp>
23#include <string>
24#include <string>
25#include <vector>
24
25namespace google
26{
27namespace ipmi
28{
29
30struct CableRequest
31{
26
27namespace google
28{
29namespace ipmi
30{
31
32struct CableRequest
33{
32 uint8_t subcommand;
33 uint8_t ifNameLength;
34} __attribute__((packed));
35
34 uint8_t ifNameLength;
35} __attribute__((packed));
36
36ipmi_ret_t cableCheck(const uint8_t* reqBuf, uint8_t* replyBuf, size_t* dataLen,
37 const HandlerInterface* handler)
37Resp cableCheck(const std::vector<std::uint8_t>& data,
38 const HandlerInterface* handler)
38{
39 // There is an IPMI LAN channel statistics command which could be used for
40 // this type of check, however, we're not able to wait for the OpenBMC
41 // implementation to stabilize related to the network management.
42 //
43 // There is a link status file, but it is "unknown" to start with...
44 // The path we're checking: /sys/class/net/eth1/statistics/rx_packets
45
46 // This command is expecting: [0x00][len][ifName]
39{
40 // There is an IPMI LAN channel statistics command which could be used for
41 // this type of check, however, we're not able to wait for the OpenBMC
42 // implementation to stabilize related to the network management.
43 //
44 // There is a link status file, but it is "unknown" to start with...
45 // The path we're checking: /sys/class/net/eth1/statistics/rx_packets
46
47 // This command is expecting: [0x00][len][ifName]
47 if ((*dataLen) < sizeof(struct CableRequest) + sizeof(uint8_t))
48 // data should have [len][ifName]
49 if (data.size() < sizeof(struct CableRequest))
48 {
49 std::fprintf(stderr, "Invalid command length: %u\n",
50 {
51 std::fprintf(stderr, "Invalid command length: %u\n",
50 static_cast<uint32_t>(*dataLen));
51 return IPMI_CC_REQ_DATA_LEN_INVALID;
52 static_cast<uint32_t>(data.size()));
53 return ::ipmi::responseReqDataLenInvalid();
52 }
53
54 const auto request =
54 }
55
56 const auto request =
55 reinterpret_cast<const struct CableRequest*>(&reqBuf[0]);
57 reinterpret_cast<const struct CableRequest*>(data.data());
56
57 // Sanity check the object contents.
58 if (request->ifNameLength == 0)
59 {
60 std::fprintf(stderr, "Invalid string length: %d\n",
61 request->ifNameLength);
58
59 // Sanity check the object contents.
60 if (request->ifNameLength == 0)
61 {
62 std::fprintf(stderr, "Invalid string length: %d\n",
63 request->ifNameLength);
62 return IPMI_CC_REQ_DATA_LEN_INVALID;
64 return ::ipmi::responseReqDataLenInvalid();
63 }
64
65 // Verify the request buffer contains the object and the string.
65 }
66
67 // Verify the request buffer contains the object and the string.
66 if ((*dataLen) < (sizeof(struct CableRequest) + request->ifNameLength))
68 if (data.size() < (sizeof(struct CableRequest) + request->ifNameLength))
67 {
68 std::fprintf(stderr, "*dataLen too small: %u\n",
69 {
70 std::fprintf(stderr, "*dataLen too small: %u\n",
69 static_cast<uint32_t>(*dataLen));
70 return IPMI_CC_REQ_DATA_LEN_INVALID;
71 static_cast<uint32_t>(data.size()));
72 return ::ipmi::responseReqDataLenInvalid();
71 }
72
73 // Maximum length one can specify, plus null terminator.
74 char nameBuf[256] = {};
75 // Copy the string out of the request buffer.
76 std::memcpy(&nameBuf[0], request + 1, request->ifNameLength);
77 std::string name = nameBuf;
78 int64_t count;
79
80 try
81 {
82 count = handler->getRxPackets(name);
83 }
84 catch (const IpmiException& e)
85 {
73 }
74
75 // Maximum length one can specify, plus null terminator.
76 char nameBuf[256] = {};
77 // Copy the string out of the request buffer.
78 std::memcpy(&nameBuf[0], request + 1, request->ifNameLength);
79 std::string name = nameBuf;
80 int64_t count;
81
82 try
83 {
84 count = handler->getRxPackets(name);
85 }
86 catch (const IpmiException& e)
87 {
86 return e.getIpmiError();
88 return ::ipmi::response(e.getIpmiError());
87 }
88
89 }
90
89 struct CableReply reply;
90 reply.subcommand = SysCableCheck;
91
92 // If we have received packets then there is a cable present.
91 // If we have received packets then there is a cable present.
93 reply.value = (count > 0) ? 1 : 0;
92 std::uint8_t value = (count > 0) ? 1 : 0;
94
93
95 // Return the subcommand and the result.
96 std::memcpy(&replyBuf[0], &reply, sizeof(struct CableReply));
97 (*dataLen) = sizeof(struct CableReply);
98
99 return IPMI_CC_OK;
94 return ::ipmi::responseSuccess(SysOEMCommands::SysCableCheck,
95 std::vector<std::uint8_t>{value});
100}
101
102} // namespace ipmi
103} // namespace google
96}
97
98} // namespace ipmi
99} // namespace google