11285115cSWilliam A. Kennington III /*
21285115cSWilliam A. Kennington III  * Copyright 2021 Google LLC
31285115cSWilliam A. Kennington III  *
41285115cSWilliam A. Kennington III  * Licensed under the Apache License, Version 2.0 (the "License");
51285115cSWilliam A. Kennington III  * you may not use this file except in compliance with the License.
61285115cSWilliam A. Kennington III  * You may obtain a copy of the License at
71285115cSWilliam A. Kennington III  *
81285115cSWilliam A. Kennington III  *      http://www.apache.org/licenses/LICENSE-2.0
91285115cSWilliam A. Kennington III  *
101285115cSWilliam A. Kennington III  * Unless required by applicable law or agreed to in writing, software
111285115cSWilliam A. Kennington III  * distributed under the License is distributed on an "AS IS" BASIS,
121285115cSWilliam A. Kennington III  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131285115cSWilliam A. Kennington III  * See the License for the specific language governing permissions and
141285115cSWilliam A. Kennington III  * limitations under the License.
151285115cSWilliam A. Kennington III  */
161285115cSWilliam A. Kennington III 
171285115cSWilliam A. Kennington III #pragma once
181285115cSWilliam A. Kennington III 
191285115cSWilliam A. Kennington III #include "platforms/nemora/portable/ncsi.h"
201285115cSWilliam A. Kennington III #include "platforms/nemora/portable/ncsi_fsm.h"
21*adb8ffe4SWilly Tu #include "platforms/nemora/portable/net_types.h"
221285115cSWilliam A. Kennington III 
231285115cSWilliam A. Kennington III #include <netinet/in.h>
241285115cSWilliam A. Kennington III 
251285115cSWilliam A. Kennington III #include <cstdint>
261285115cSWilliam A. Kennington III #include <vector>
271285115cSWilliam A. Kennington III 
281285115cSWilliam A. Kennington III namespace mock
291285115cSWilliam A. Kennington III {
301285115cSWilliam A. Kennington III 
311285115cSWilliam A. Kennington III class NCSIFrame
321285115cSWilliam A. Kennington III {
331285115cSWilliam A. Kennington III   public:
341285115cSWilliam A. Kennington III     mac_addr_t get_dst_mac() const
351285115cSWilliam A. Kennington III     {
361285115cSWilliam A. Kennington III         return dst_mac_;
371285115cSWilliam A. Kennington III     }
381285115cSWilliam A. Kennington III 
391285115cSWilliam A. Kennington III     mac_addr_t get_src_mac() const
401285115cSWilliam A. Kennington III     {
411285115cSWilliam A. Kennington III         return src_mac_;
421285115cSWilliam A. Kennington III     }
431285115cSWilliam A. Kennington III 
441285115cSWilliam A. Kennington III     uint16_t get_ethertype() const
451285115cSWilliam A. Kennington III     {
461285115cSWilliam A. Kennington III         return ethertype_;
471285115cSWilliam A. Kennington III     }
481285115cSWilliam A. Kennington III 
491285115cSWilliam A. Kennington III     bool is_ncsi() const
501285115cSWilliam A. Kennington III     {
511285115cSWilliam A. Kennington III         return ethertype_ == NCSI_ETHERTYPE;
521285115cSWilliam A. Kennington III     }
531285115cSWilliam A. Kennington III 
541285115cSWilliam A. Kennington III     uint8_t get_control_packet_type() const
551285115cSWilliam A. Kennington III     {
561285115cSWilliam A. Kennington III         return control_packet_type_;
571285115cSWilliam A. Kennington III     }
581285115cSWilliam A. Kennington III 
591285115cSWilliam A. Kennington III     void set_conrol_packet_type(uint8_t control_packet_type)
601285115cSWilliam A. Kennington III     {
611285115cSWilliam A. Kennington III         control_packet_type_ = control_packet_type;
621285115cSWilliam A. Kennington III     }
631285115cSWilliam A. Kennington III 
641285115cSWilliam A. Kennington III     bool is_oem_command() const
651285115cSWilliam A. Kennington III     {
661285115cSWilliam A. Kennington III         return control_packet_type_ == NCSI_OEM_COMMAND;
671285115cSWilliam A. Kennington III     }
681285115cSWilliam A. Kennington III 
691285115cSWilliam A. Kennington III     uint8_t get_channel_id() const
701285115cSWilliam A. Kennington III     {
711285115cSWilliam A. Kennington III         return channel_id_;
721285115cSWilliam A. Kennington III     }
731285115cSWilliam A. Kennington III 
741285115cSWilliam A. Kennington III     void set_channel_id(uint8_t channel_id)
751285115cSWilliam A. Kennington III     {
761285115cSWilliam A. Kennington III         channel_id_ = channel_id;
771285115cSWilliam A. Kennington III     }
781285115cSWilliam A. Kennington III 
791285115cSWilliam A. Kennington III     uint8_t get_oem_command() const
801285115cSWilliam A. Kennington III     {
811285115cSWilliam A. Kennington III         return oem_command_;
821285115cSWilliam A. Kennington III     }
831285115cSWilliam A. Kennington III 
841285115cSWilliam A. Kennington III     void set_oem_command(uint8_t oem_command)
851285115cSWilliam A. Kennington III     {
861285115cSWilliam A. Kennington III         set_conrol_packet_type(NCSI_OEM_COMMAND);
871285115cSWilliam A. Kennington III         oem_command_ = oem_command;
881285115cSWilliam A. Kennington III     }
891285115cSWilliam A. Kennington III 
901285115cSWilliam A. Kennington III     uint32_t get_manufacturer_id() const
911285115cSWilliam A. Kennington III     {
921285115cSWilliam A. Kennington III         return manufacturer_id_;
931285115cSWilliam A. Kennington III     }
941285115cSWilliam A. Kennington III 
951285115cSWilliam A. Kennington III     std::vector<uint8_t>::size_type get_size() const
961285115cSWilliam A. Kennington III     {
971285115cSWilliam A. Kennington III         return packet_raw_.size();
981285115cSWilliam A. Kennington III     }
991285115cSWilliam A. Kennington III 
1001285115cSWilliam A. Kennington III     bool is_response() const
1011285115cSWilliam A. Kennington III     {
1021285115cSWilliam A. Kennington III         return is_response_;
1031285115cSWilliam A. Kennington III     }
1041285115cSWilliam A. Kennington III 
1051285115cSWilliam A. Kennington III     uint16_t get_response_code() const
1061285115cSWilliam A. Kennington III     {
1071285115cSWilliam A. Kennington III         return response_code_;
1081285115cSWilliam A. Kennington III     }
1091285115cSWilliam A. Kennington III 
1101285115cSWilliam A. Kennington III     uint16_t get_reason_code() const
1111285115cSWilliam A. Kennington III     {
1121285115cSWilliam A. Kennington III         return reason_code_;
1131285115cSWilliam A. Kennington III     }
1141285115cSWilliam A. Kennington III 
1151285115cSWilliam A. Kennington III     bool parse_ethernet_frame(const ncsi_buf_t& ncsi_buf);
1161285115cSWilliam A. Kennington III 
1171285115cSWilliam A. Kennington III   private:
1181285115cSWilliam A. Kennington III     mac_addr_t dst_mac_;
1191285115cSWilliam A. Kennington III     mac_addr_t src_mac_;
1201285115cSWilliam A. Kennington III     uint16_t ethertype_ = NCSI_ETHERTYPE;
1211285115cSWilliam A. Kennington III     uint8_t control_packet_type_;
1221285115cSWilliam A. Kennington III     uint8_t channel_id_;
1231285115cSWilliam A. Kennington III     uint8_t oem_command_;
1241285115cSWilliam A. Kennington III     uint32_t manufacturer_id_;
1251285115cSWilliam A. Kennington III     uint16_t response_code_ = 0;
1261285115cSWilliam A. Kennington III     uint16_t reason_code_ = 0;
1271285115cSWilliam A. Kennington III     bool is_response_ = false;
1281285115cSWilliam A. Kennington III     std::vector<uint8_t> packet_raw_;
1291285115cSWilliam A. Kennington III };
1301285115cSWilliam A. Kennington III 
1311285115cSWilliam A. Kennington III class NIC
1321285115cSWilliam A. Kennington III {
1331285115cSWilliam A. Kennington III   public:
1341285115cSWilliam A. Kennington III     explicit NIC(bool legacy = false, uint8_t channel_count = 1) :
1351285115cSWilliam A. Kennington III         channel_count_{channel_count}
1361285115cSWilliam A. Kennington III     {
1371285115cSWilliam A. Kennington III         if (legacy)
1381285115cSWilliam A. Kennington III         {
1391285115cSWilliam A. Kennington III             version_.firmware_version = htonl(0x08000000);
1401285115cSWilliam A. Kennington III         }
1411285115cSWilliam A. Kennington III         else
1421285115cSWilliam A. Kennington III         {
1431285115cSWilliam A. Kennington III             version_.firmware_version = 0xabcdef12;
1441285115cSWilliam A. Kennington III         }
1451285115cSWilliam A. Kennington III 
1461285115cSWilliam A. Kennington III         is_legacy_ = legacy;
1471285115cSWilliam A. Kennington III 
1481285115cSWilliam A. Kennington III         set_link_up();
1491285115cSWilliam A. Kennington III     }
1501285115cSWilliam A. Kennington III 
1511285115cSWilliam A. Kennington III     void set_link_up()
1521285115cSWilliam A. Kennington III     {
1531285115cSWilliam A. Kennington III         link_status_.link_status |= htonl(NCSI_LINK_STATUS_UP);
1541285115cSWilliam A. Kennington III     }
1551285115cSWilliam A. Kennington III 
1561285115cSWilliam A. Kennington III     void set_mac(const mac_addr_t& mac)
1571285115cSWilliam A. Kennington III     {
1581285115cSWilliam A. Kennington III         mac_ = mac;
1591285115cSWilliam A. Kennington III     }
1601285115cSWilliam A. Kennington III 
1611285115cSWilliam A. Kennington III     mac_addr_t get_mac() const
1621285115cSWilliam A. Kennington III     {
1631285115cSWilliam A. Kennington III         return mac_;
1641285115cSWilliam A. Kennington III     }
1651285115cSWilliam A. Kennington III 
1661285115cSWilliam A. Kennington III     uint8_t get_channel_count() const
1671285115cSWilliam A. Kennington III     {
1681285115cSWilliam A. Kennington III         return channel_count_;
1691285115cSWilliam A. Kennington III     }
1701285115cSWilliam A. Kennington III 
1711285115cSWilliam A. Kennington III     // ????? NICs with Google firmware version ????
1721285115cSWilliam A. Kennington III     bool is_legacy() const
1731285115cSWilliam A. Kennington III     {
1741285115cSWilliam A. Kennington III         return is_legacy_;
1751285115cSWilliam A. Kennington III     }
1761285115cSWilliam A. Kennington III 
1771285115cSWilliam A. Kennington III     uint32_t handle_request(const ncsi_buf_t& request_buf,
1781285115cSWilliam A. Kennington III                             ncsi_buf_t* response_buf);
1791285115cSWilliam A. Kennington III 
1801285115cSWilliam A. Kennington III     const std::vector<NCSIFrame>& get_command_log() const
1811285115cSWilliam A. Kennington III     {
1821285115cSWilliam A. Kennington III         return cmd_log_;
1831285115cSWilliam A. Kennington III     }
1841285115cSWilliam A. Kennington III 
1851285115cSWilliam A. Kennington III     bool set_filter(uint8_t channel, const ncsi_oem_filter_t& filter);
1861285115cSWilliam A. Kennington III     const ncsi_oem_filter_t& get_filter(uint8_t channel) const;
1871285115cSWilliam A. Kennington III 
1881285115cSWilliam A. Kennington III     void set_hostless(bool is_hostless);
1891285115cSWilliam A. Kennington III     void toggle_hostless();
1901285115cSWilliam A. Kennington III     bool is_hostless();
1911285115cSWilliam A. Kennington III 
1921285115cSWilliam A. Kennington III     // The NIC itself does not really have a loopback. This is used to emulate
1931285115cSWilliam A. Kennington III     // the *absence* of NIC and loopback plug inserted.
1941285115cSWilliam A. Kennington III     void set_loopback()
1951285115cSWilliam A. Kennington III     {
1961285115cSWilliam A. Kennington III         is_loopback_ = true;
1971285115cSWilliam A. Kennington III     }
1981285115cSWilliam A. Kennington III 
1991285115cSWilliam A. Kennington III     void reset_loopback()
2001285115cSWilliam A. Kennington III     {
2011285115cSWilliam A. Kennington III         is_loopback_ = false;
2021285115cSWilliam A. Kennington III     }
2031285115cSWilliam A. Kennington III 
2041285115cSWilliam A. Kennington III     bool is_filter_configured(uint8_t channel) const;
2051285115cSWilliam A. Kennington III 
2061285115cSWilliam A. Kennington III   private:
2071285115cSWilliam A. Kennington III     static const std::vector<uint8_t> simple_commands_;
2081285115cSWilliam A. Kennington III 
2091285115cSWilliam A. Kennington III     uint32_t handle_oem_request(const ncsi_buf_t& request_buf,
2101285115cSWilliam A. Kennington III                                 ncsi_buf_t* response_buf);
2111285115cSWilliam A. Kennington III 
2121285115cSWilliam A. Kennington III     void save_frame_to_log(const NCSIFrame& frame);
2131285115cSWilliam A. Kennington III 
2141285115cSWilliam A. Kennington III     ncsi_version_id_t version_;
2151285115cSWilliam A. Kennington III     ncsi_oem_filter_t ch0_filter_;
2161285115cSWilliam A. Kennington III     ncsi_oem_filter_t ch1_filter_;
2171285115cSWilliam A. Kennington III     bool is_ch0_filter_configured_ = false;
2181285115cSWilliam A. Kennington III     bool is_ch1_filter_configured_ = false;
2191285115cSWilliam A. Kennington III     uint8_t channel_count_;
2201285115cSWilliam A. Kennington III     mac_addr_t mac_ = {{0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba}};
2211285115cSWilliam A. Kennington III     std::vector<NCSIFrame> cmd_log_;
2221285115cSWilliam A. Kennington III 
2231285115cSWilliam A. Kennington III     /* If used in a continuous loop, cmd_log_ may grow too big over time.
2241285115cSWilliam A. Kennington III      * This constant determines how many (most recent) commands will be kept. */
2251285115cSWilliam A. Kennington III     const uint32_t max_log_size_ = 1000;
2261285115cSWilliam A. Kennington III 
2271285115cSWilliam A. Kennington III     bool is_legacy_;
2281285115cSWilliam A. Kennington III     bool is_loopback_ = false;
2291285115cSWilliam A. Kennington III 
2301285115cSWilliam A. Kennington III     // TODO: populate stats somehow.
2311285115cSWilliam A. Kennington III     ncsi_passthrough_stats_t stats_;
2321285115cSWilliam A. Kennington III     ncsi_passthrough_stats_legacy_t stats_legacy_;
2331285115cSWilliam A. Kennington III 
2341285115cSWilliam A. Kennington III     ncsi_link_status_t link_status_;
2351285115cSWilliam A. Kennington III };
2361285115cSWilliam A. Kennington III 
2371285115cSWilliam A. Kennington III } // namespace mock
238