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