blob: 175241dc7747f92879c0477aa12619ac5023e429 [file] [log] [blame]
Willy Tua2056e92021-10-10 13:36:16 -07001// 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//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
Patrick Venture4d49ae62018-09-17 11:35:32 -070014
15#include "cable.hpp"
16
Patrick Venture0e9aae52020-08-13 13:07:09 -070017#include "commands.hpp"
Patrick Ventured2037c62019-03-15 10:29:47 -070018#include "errors.hpp"
19#include "handler.hpp"
Patrick Venture4d49ae62018-09-17 11:35:32 -070020
21#include <cstdint>
Patrick Venturece07ee02018-09-19 18:09:32 -070022#include <cstring>
Patrick Venture4d49ae62018-09-17 11:35:32 -070023#include <string>
Patrick Venture4d49ae62018-09-17 11:35:32 -070024
25namespace google
26{
27namespace ipmi
28{
Patrick Venture4d49ae62018-09-17 11:35:32 -070029
30struct CableRequest
31{
32 uint8_t subcommand;
Patrick Venture45fad1b2019-03-18 16:52:14 -070033 uint8_t ifNameLength;
Patrick Venture4d49ae62018-09-17 11:35:32 -070034} __attribute__((packed));
35
Patrick Venture45fad1b2019-03-18 16:52:14 -070036ipmi_ret_t cableCheck(const uint8_t* reqBuf, uint8_t* replyBuf, size_t* dataLen,
Patrick Ventured2037c62019-03-15 10:29:47 -070037 const HandlerInterface* handler)
Patrick Venture4d49ae62018-09-17 11:35:32 -070038{
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
Patrick Venture45fad1b2019-03-18 16:52:14 -070046 // This command is expecting: [0x00][len][ifName]
Patrick Venture4d49ae62018-09-17 11:35:32 -070047 if ((*dataLen) < sizeof(struct CableRequest) + sizeof(uint8_t))
48 {
Patrick Venturece07ee02018-09-19 18:09:32 -070049 std::fprintf(stderr, "Invalid command length: %u\n",
50 static_cast<uint32_t>(*dataLen));
Patrick Venturefff98612018-11-12 09:05:54 -080051 return IPMI_CC_REQ_DATA_LEN_INVALID;
Patrick Venture4d49ae62018-09-17 11:35:32 -070052 }
53
54 const auto request =
55 reinterpret_cast<const struct CableRequest*>(&reqBuf[0]);
56
57 // Sanity check the object contents.
Patrick Venture45fad1b2019-03-18 16:52:14 -070058 if (request->ifNameLength == 0)
Patrick Venture4d49ae62018-09-17 11:35:32 -070059 {
Patrick Venturece07ee02018-09-19 18:09:32 -070060 std::fprintf(stderr, "Invalid string length: %d\n",
Patrick Venture45fad1b2019-03-18 16:52:14 -070061 request->ifNameLength);
Patrick Venturefff98612018-11-12 09:05:54 -080062 return IPMI_CC_REQ_DATA_LEN_INVALID;
Patrick Venture4d49ae62018-09-17 11:35:32 -070063 }
64
65 // Verify the request buffer contains the object and the string.
Patrick Venture45fad1b2019-03-18 16:52:14 -070066 if ((*dataLen) < (sizeof(struct CableRequest) + request->ifNameLength))
Patrick Venture4d49ae62018-09-17 11:35:32 -070067 {
Patrick Venturece07ee02018-09-19 18:09:32 -070068 std::fprintf(stderr, "*dataLen too small: %u\n",
69 static_cast<uint32_t>(*dataLen));
Patrick Venturefff98612018-11-12 09:05:54 -080070 return IPMI_CC_REQ_DATA_LEN_INVALID;
Patrick Venture4d49ae62018-09-17 11:35:32 -070071 }
72
73 // Maximum length one can specify, plus null terminator.
74 char nameBuf[256] = {};
Patrick Venture4d49ae62018-09-17 11:35:32 -070075 // Copy the string out of the request buffer.
William A. Kennington III5d789732021-06-24 03:39:31 -070076 std::memcpy(&nameBuf[0], request + 1, request->ifNameLength);
Patrick Venture4d49ae62018-09-17 11:35:32 -070077 std::string name = nameBuf;
Patrick Ventured2037c62019-03-15 10:29:47 -070078 int64_t count;
Patrick Venture4d49ae62018-09-17 11:35:32 -070079
Patrick Venture4d49ae62018-09-17 11:35:32 -070080 try
81 {
Patrick Ventured2037c62019-03-15 10:29:47 -070082 count = handler->getRxPackets(name);
Patrick Venture4d49ae62018-09-17 11:35:32 -070083 }
Patrick Ventured2037c62019-03-15 10:29:47 -070084 catch (const IpmiException& e)
Patrick Venture4d49ae62018-09-17 11:35:32 -070085 {
Patrick Ventured2037c62019-03-15 10:29:47 -070086 return e.getIpmiError();
Patrick Venture4d49ae62018-09-17 11:35:32 -070087 }
88
89 struct CableReply reply;
90 reply.subcommand = SysCableCheck;
Patrick Venture4d49ae62018-09-17 11:35:32 -070091
92 // If we have received packets then there is a cable present.
93 reply.value = (count > 0) ? 1 : 0;
94
95 // Return the subcommand and the result.
Patrick Venturece07ee02018-09-19 18:09:32 -070096 std::memcpy(&replyBuf[0], &reply, sizeof(struct CableReply));
Patrick Venture4d49ae62018-09-17 11:35:32 -070097 (*dataLen) = sizeof(struct CableReply);
98
99 return IPMI_CC_OK;
100}
101
102} // namespace ipmi
103} // namespace google