blob: be314f864818cd04646984d811101258f281d94e [file] [log] [blame]
Brandon Kimdab96f12021-02-18 11:21:37 -08001/*
2 * Copyright 2021 Google LLC
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
William A. Kennington III7d6fa422021-02-08 17:04:02 -080017#pragma once
18
19#include "platforms/nemora/portable/ncsi.h"
20#include "platforms/nemora/portable/ncsi_fsm.h"
Willy Tuadb8ffe2023-07-17 13:44:22 -070021#include "platforms/nemora/portable/net_types.h"
William A. Kennington III7d6fa422021-02-08 17:04:02 -080022
23#include <netinet/in.h>
24
25#include <cstdint>
William A. Kennington III7d6fa422021-02-08 17:04:02 -080026#include <vector>
27
28namespace mock
29{
30
31class NCSIFrame
32{
33 public:
34 mac_addr_t get_dst_mac() const
35 {
36 return dst_mac_;
37 }
38
39 mac_addr_t get_src_mac() const
40 {
41 return src_mac_;
42 }
43
44 uint16_t get_ethertype() const
45 {
46 return ethertype_;
47 }
48
49 bool is_ncsi() const
50 {
51 return ethertype_ == NCSI_ETHERTYPE;
52 }
53
54 uint8_t get_control_packet_type() const
55 {
56 return control_packet_type_;
57 }
58
59 void set_conrol_packet_type(uint8_t control_packet_type)
60 {
61 control_packet_type_ = control_packet_type;
62 }
63
64 bool is_oem_command() const
65 {
66 return control_packet_type_ == NCSI_OEM_COMMAND;
67 }
68
69 uint8_t get_channel_id() const
70 {
71 return channel_id_;
72 }
73
74 void set_channel_id(uint8_t channel_id)
75 {
76 channel_id_ = channel_id;
77 }
78
79 uint8_t get_oem_command() const
80 {
81 return oem_command_;
82 }
83
84 void set_oem_command(uint8_t oem_command)
85 {
86 set_conrol_packet_type(NCSI_OEM_COMMAND);
87 oem_command_ = oem_command;
88 }
89
90 uint32_t get_manufacturer_id() const
91 {
92 return manufacturer_id_;
93 }
94
95 std::vector<uint8_t>::size_type get_size() const
96 {
97 return packet_raw_.size();
98 }
99
100 bool is_response() const
101 {
102 return is_response_;
103 }
104
105 uint16_t get_response_code() const
106 {
107 return response_code_;
108 }
109
110 uint16_t get_reason_code() const
111 {
112 return reason_code_;
113 }
114
115 bool parse_ethernet_frame(const ncsi_buf_t& ncsi_buf);
116
117 private:
118 mac_addr_t dst_mac_;
119 mac_addr_t src_mac_;
120 uint16_t ethertype_ = NCSI_ETHERTYPE;
121 uint8_t control_packet_type_;
122 uint8_t channel_id_;
123 uint8_t oem_command_;
124 uint32_t manufacturer_id_;
125 uint16_t response_code_ = 0;
126 uint16_t reason_code_ = 0;
127 bool is_response_ = false;
128 std::vector<uint8_t> packet_raw_;
129};
130
131class NIC
132{
133 public:
134 explicit NIC(bool legacy = false, uint8_t channel_count = 1) :
135 channel_count_{channel_count}
136 {
137 if (legacy)
138 {
139 version_.firmware_version = htonl(0x08000000);
140 }
141 else
142 {
143 version_.firmware_version = 0xabcdef12;
144 }
145
146 is_legacy_ = legacy;
147
148 set_link_up();
149 }
150
151 void set_link_up()
152 {
153 link_status_.link_status |= htonl(NCSI_LINK_STATUS_UP);
154 }
155
156 void set_mac(const mac_addr_t& mac)
157 {
158 mac_ = mac;
159 }
160
161 mac_addr_t get_mac() const
162 {
163 return mac_;
164 }
165
166 uint8_t get_channel_count() const
167 {
168 return channel_count_;
169 }
170
171 // ????? NICs with Google firmware version ????
172 bool is_legacy() const
173 {
174 return is_legacy_;
175 }
176
177 uint32_t handle_request(const ncsi_buf_t& request_buf,
178 ncsi_buf_t* response_buf);
179
180 const std::vector<NCSIFrame>& get_command_log() const
181 {
182 return cmd_log_;
183 }
184
185 bool set_filter(uint8_t channel, const ncsi_oem_filter_t& filter);
186 const ncsi_oem_filter_t& get_filter(uint8_t channel) const;
187
188 void set_hostless(bool is_hostless);
189 void toggle_hostless();
190 bool is_hostless();
191
192 // The NIC itself does not really have a loopback. This is used to emulate
193 // the *absence* of NIC and loopback plug inserted.
194 void set_loopback()
195 {
196 is_loopback_ = true;
197 }
198
199 void reset_loopback()
200 {
201 is_loopback_ = false;
202 }
203
204 bool is_filter_configured(uint8_t channel) const;
205
206 private:
207 static const std::vector<uint8_t> simple_commands_;
208
209 uint32_t handle_oem_request(const ncsi_buf_t& request_buf,
210 ncsi_buf_t* response_buf);
211
212 void save_frame_to_log(const NCSIFrame& frame);
213
214 ncsi_version_id_t version_;
215 ncsi_oem_filter_t ch0_filter_;
216 ncsi_oem_filter_t ch1_filter_;
217 bool is_ch0_filter_configured_ = false;
218 bool is_ch1_filter_configured_ = false;
219 uint8_t channel_count_;
220 mac_addr_t mac_ = {{0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba}};
221 std::vector<NCSIFrame> cmd_log_;
222
223 /* If used in a continuous loop, cmd_log_ may grow too big over time.
224 * This constant determines how many (most recent) commands will be kept. */
225 const uint32_t max_log_size_ = 1000;
226
227 bool is_legacy_;
228 bool is_loopback_ = false;
229
230 // TODO: populate stats somehow.
231 ncsi_passthrough_stats_t stats_;
232 ncsi_passthrough_stats_legacy_t stats_legacy_;
233
234 ncsi_link_status_t link_status_;
235};
236
237} // namespace mock