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