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