11285115cSWilliam A. Kennington III // Copyright 2021 Google LLC 21285115cSWilliam A. Kennington III // 31285115cSWilliam A. Kennington III // Licensed under the Apache License, Version 2.0 (the "License"); 41285115cSWilliam A. Kennington III // you may not use this file except in compliance with the License. 51285115cSWilliam A. Kennington III // You may obtain a copy of the License at 61285115cSWilliam A. Kennington III // 71285115cSWilliam A. Kennington III // http://www.apache.org/licenses/LICENSE-2.0 81285115cSWilliam A. Kennington III // 91285115cSWilliam A. Kennington III // Unless required by applicable law or agreed to in writing, software 101285115cSWilliam A. Kennington III // distributed under the License is distributed on an "AS IS" BASIS, 111285115cSWilliam A. Kennington III // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 121285115cSWilliam A. Kennington III // See the License for the specific language governing permissions and 131285115cSWilliam A. Kennington III // limitations under the License. 141285115cSWilliam A. Kennington III 151285115cSWilliam A. Kennington III #include "nic_mock.h" 161285115cSWilliam A. Kennington III 171285115cSWilliam A. Kennington III #include "platforms/nemora/portable/ncsi.h" 181285115cSWilliam A. Kennington III 191285115cSWilliam A. Kennington III #include <algorithm> 201285115cSWilliam A. Kennington III #include <cstddef> 211285115cSWilliam A. Kennington III #include <stdexcept> 221285115cSWilliam A. Kennington III 231285115cSWilliam A. Kennington III namespace mock 241285115cSWilliam A. Kennington III { 251285115cSWilliam A. Kennington III 261285115cSWilliam A. Kennington III bool NCSIFrame::parse_ethernet_frame(const ncsi_buf_t& ncsi_buf) 271285115cSWilliam A. Kennington III { 281285115cSWilliam A. Kennington III std::memcpy(&dst_mac_, ncsi_buf.data, sizeof(dst_mac_)); 291285115cSWilliam A. Kennington III std::memcpy(&src_mac_, ncsi_buf.data + sizeof(dst_mac_), sizeof(src_mac_)); 301285115cSWilliam A. Kennington III // The constant defined in a way that assumes big-endian platform, so we are 311285115cSWilliam A. Kennington III // just going to calculate it here properly. 321285115cSWilliam A. Kennington III const uint8_t et_hi = *(ncsi_buf.data + 2 * sizeof(mac_addr_t)); 331285115cSWilliam A. Kennington III const uint8_t et_lo = *(ncsi_buf.data + 2 * sizeof(mac_addr_t) + 1); 341285115cSWilliam A. Kennington III ethertype_ = (et_hi << 8) + et_lo; 351285115cSWilliam A. Kennington III 361285115cSWilliam A. Kennington III if (ethertype_ != NCSI_ETHERTYPE) 371285115cSWilliam A. Kennington III { 381285115cSWilliam A. Kennington III return false; 391285115cSWilliam A. Kennington III } 401285115cSWilliam A. Kennington III 411285115cSWilliam A. Kennington III // This code parses the NC-SI command, according to spec and 421285115cSWilliam A. Kennington III // as defined in platforms/nemora/portable/ncsi.h 431285115cSWilliam A. Kennington III // It takes some shortcuts to only retrieve the data we are interested in, 441285115cSWilliam A. Kennington III // such as using offsetof ot get to a particular field. 451285115cSWilliam A. Kennington III control_packet_type_ = 461285115cSWilliam A. Kennington III *(ncsi_buf.data + offsetof(ncsi_header_t, control_packet_type)); 471285115cSWilliam A. Kennington III channel_id_ = *(ncsi_buf.data + offsetof(ncsi_header_t, channel_id)); 481285115cSWilliam A. Kennington III 491285115cSWilliam A. Kennington III size_t payload_offset = sizeof(ncsi_header_t); 501285115cSWilliam A. Kennington III if (control_packet_type_ & NCSI_RESPONSE) 511285115cSWilliam A. Kennington III { 521285115cSWilliam A. Kennington III is_response_ = true; 531285115cSWilliam A. Kennington III control_packet_type_ &= ~NCSI_RESPONSE; 541285115cSWilliam A. Kennington III std::memcpy(&response_code_, ncsi_buf.data + payload_offset, 551285115cSWilliam A. Kennington III sizeof(response_code_)); 561285115cSWilliam A. Kennington III response_code_ = ntohs(response_code_); 571285115cSWilliam A. Kennington III std::memcpy(&reason_code_, 581285115cSWilliam A. Kennington III ncsi_buf.data + payload_offset + sizeof(reason_code_), 591285115cSWilliam A. Kennington III sizeof(reason_code_)); 601285115cSWilliam A. Kennington III reason_code_ = ntohs(reason_code_); 611285115cSWilliam A. Kennington III payload_offset += sizeof(reason_code_) + sizeof(response_code_); 621285115cSWilliam A. Kennington III } 631285115cSWilliam A. Kennington III 641285115cSWilliam A. Kennington III if (control_packet_type_ == NCSI_OEM_COMMAND) 651285115cSWilliam A. Kennington III { 661285115cSWilliam A. Kennington III std::memcpy(&manufacturer_id_, ncsi_buf.data + payload_offset, 671285115cSWilliam A. Kennington III sizeof(manufacturer_id_)); 681285115cSWilliam A. Kennington III manufacturer_id_ = ntohl(manufacturer_id_); 691285115cSWilliam A. Kennington III // Number of reserved bytes after manufacturer_id_ = 3 701285115cSWilliam A. Kennington III oem_command_ = 711285115cSWilliam A. Kennington III *(ncsi_buf.data + payload_offset + sizeof(manufacturer_id_) + 3); 721285115cSWilliam A. Kennington III payload_offset += sizeof(ncsi_oem_extension_header_t); 731285115cSWilliam A. Kennington III } 741285115cSWilliam A. Kennington III 75*2be45238SPatrick Williams packet_raw_ = std::vector<uint8_t>(ncsi_buf.data, 76*2be45238SPatrick Williams ncsi_buf.data + ncsi_buf.len); 771285115cSWilliam A. Kennington III // TODO: Verify payload length. 781285115cSWilliam A. Kennington III 791285115cSWilliam A. Kennington III return true; 801285115cSWilliam A. Kennington III } 811285115cSWilliam A. Kennington III 821285115cSWilliam A. Kennington III uint32_t NIC::handle_request(const ncsi_buf_t& request_buf, 831285115cSWilliam A. Kennington III ncsi_buf_t* response_buf) 841285115cSWilliam A. Kennington III { 851285115cSWilliam A. Kennington III const ncsi_header_t* ncsi_header = 861285115cSWilliam A. Kennington III reinterpret_cast<const ncsi_header_t*>(request_buf.data); 871285115cSWilliam A. Kennington III 881285115cSWilliam A. Kennington III NCSIFrame request_frame; 891285115cSWilliam A. Kennington III request_frame.parse_ethernet_frame(request_buf); 901285115cSWilliam A. Kennington III save_frame_to_log(request_frame); 911285115cSWilliam A. Kennington III 921285115cSWilliam A. Kennington III uint32_t response_size; 931285115cSWilliam A. Kennington III if (is_loopback_) 941285115cSWilliam A. Kennington III { 951285115cSWilliam A. Kennington III std::memcpy(response_buf, &request_buf, sizeof(request_buf)); 961285115cSWilliam A. Kennington III response_size = request_buf.len; 971285115cSWilliam A. Kennington III } 981285115cSWilliam A. Kennington III else if (std::find(simple_commands_.begin(), simple_commands_.end(), 991285115cSWilliam A. Kennington III ncsi_header->control_packet_type) != 1001285115cSWilliam A. Kennington III simple_commands_.end()) 1011285115cSWilliam A. Kennington III { 1021285115cSWilliam A. Kennington III // Simple Response 103*2be45238SPatrick Williams response_size = ncsi_build_simple_ack(request_buf.data, 104*2be45238SPatrick Williams response_buf->data); 1051285115cSWilliam A. Kennington III } 1061285115cSWilliam A. Kennington III else 1071285115cSWilliam A. Kennington III { 1081285115cSWilliam A. Kennington III // Not-so-Simple Response 1091285115cSWilliam A. Kennington III switch (ncsi_header->control_packet_type) 1101285115cSWilliam A. Kennington III { 1111285115cSWilliam A. Kennington III case NCSI_GET_VERSION_ID: 1121285115cSWilliam A. Kennington III response_size = ncsi_build_version_id_ack( 1131285115cSWilliam A. Kennington III request_buf.data, response_buf->data, &version_); 1141285115cSWilliam A. Kennington III break; 1151285115cSWilliam A. Kennington III case NCSI_GET_CAPABILITIES: 1161285115cSWilliam A. Kennington III response_size = sizeof(ncsi_capabilities_response_t); 1171285115cSWilliam A. Kennington III { 1181285115cSWilliam A. Kennington III ncsi_capabilities_response_t response; 1191285115cSWilliam A. Kennington III ncsi_build_response_header( 1201285115cSWilliam A. Kennington III request_buf.data, reinterpret_cast<uint8_t*>(&response), 1211285115cSWilliam A. Kennington III 0, 0, response_size - sizeof(ncsi_header_t)); 1221285115cSWilliam A. Kennington III response.channel_count = channel_count_; 1231285115cSWilliam A. Kennington III std::memcpy(response_buf->data, &response, 1241285115cSWilliam A. Kennington III sizeof(response)); 1251285115cSWilliam A. Kennington III } 1261285115cSWilliam A. Kennington III break; 1271285115cSWilliam A. Kennington III case NCSI_GET_PASSTHROUGH_STATISTICS: 1281285115cSWilliam A. Kennington III if (is_legacy_) 1291285115cSWilliam A. Kennington III { 1301285115cSWilliam A. Kennington III response_size = ncsi_build_pt_stats_legacy_ack( 1311285115cSWilliam A. Kennington III request_buf.data, response_buf->data, &stats_legacy_); 1321285115cSWilliam A. Kennington III } 1331285115cSWilliam A. Kennington III else 1341285115cSWilliam A. Kennington III { 1351285115cSWilliam A. Kennington III response_size = ncsi_build_pt_stats_ack( 1361285115cSWilliam A. Kennington III request_buf.data, response_buf->data, &stats_); 1371285115cSWilliam A. Kennington III } 1381285115cSWilliam A. Kennington III break; 1391285115cSWilliam A. Kennington III case NCSI_GET_LINK_STATUS: 1401285115cSWilliam A. Kennington III response_size = ncsi_build_link_status_ack( 1411285115cSWilliam A. Kennington III request_buf.data, response_buf->data, &link_status_); 1421285115cSWilliam A. Kennington III break; 1431285115cSWilliam A. Kennington III case NCSI_OEM_COMMAND: 1441285115cSWilliam A. Kennington III response_size = handle_oem_request(request_buf, response_buf); 1451285115cSWilliam A. Kennington III break; 1461285115cSWilliam A. Kennington III default: 1471285115cSWilliam A. Kennington III response_size = ncsi_build_simple_nack( 1481285115cSWilliam A. Kennington III request_buf.data, response_buf->data, 1, 1); 1491285115cSWilliam A. Kennington III break; 1501285115cSWilliam A. Kennington III } 1511285115cSWilliam A. Kennington III } 1521285115cSWilliam A. Kennington III 1531285115cSWilliam A. Kennington III response_buf->len = response_size; 1541285115cSWilliam A. Kennington III 1551285115cSWilliam A. Kennington III return response_size; 1561285115cSWilliam A. Kennington III } 1571285115cSWilliam A. Kennington III 1581285115cSWilliam A. Kennington III uint32_t NIC::handle_oem_request(const ncsi_buf_t& request_buf, 1591285115cSWilliam A. Kennington III ncsi_buf_t* response_buf) 1601285115cSWilliam A. Kennington III { 1611285115cSWilliam A. Kennington III const ncsi_oem_simple_cmd_t* oem_cmd = 1621285115cSWilliam A. Kennington III reinterpret_cast<const ncsi_oem_simple_cmd_t*>(request_buf.data); 1631285115cSWilliam A. Kennington III uint32_t response_size; 1641285115cSWilliam A. Kennington III switch (oem_cmd->oem_header.oem_cmd) 1651285115cSWilliam A. Kennington III { 1661285115cSWilliam A. Kennington III case NCSI_OEM_COMMAND_GET_HOST_MAC: 1671285115cSWilliam A. Kennington III response_size = ncsi_build_oem_get_mac_ack( 1681285115cSWilliam A. Kennington III request_buf.data, response_buf->data, &mac_); 1691285115cSWilliam A. Kennington III break; 1701285115cSWilliam A. Kennington III case NCSI_OEM_COMMAND_SET_FILTER: 1711285115cSWilliam A. Kennington III { 1721285115cSWilliam A. Kennington III const ncsi_oem_set_filter_cmd_t* cmd = 1731285115cSWilliam A. Kennington III reinterpret_cast<const ncsi_oem_set_filter_cmd_t*>( 1741285115cSWilliam A. Kennington III request_buf.data); 1751285115cSWilliam A. Kennington III if (set_filter(cmd->hdr.channel_id, cmd->filter)) 1761285115cSWilliam A. Kennington III { 1771285115cSWilliam A. Kennington III response_size = ncsi_build_oem_simple_ack(request_buf.data, 1781285115cSWilliam A. Kennington III response_buf->data); 1791285115cSWilliam A. Kennington III } 1801285115cSWilliam A. Kennington III else 1811285115cSWilliam A. Kennington III { 1821285115cSWilliam A. Kennington III response_size = ncsi_build_simple_nack( 1831285115cSWilliam A. Kennington III request_buf.data, response_buf->data, 3, 4); 1841285115cSWilliam A. Kennington III } 1851285115cSWilliam A. Kennington III } 1861285115cSWilliam A. Kennington III break; 1871285115cSWilliam A. Kennington III case NCSI_OEM_COMMAND_ECHO: 188*2be45238SPatrick Williams response_size = ncsi_build_oem_echo_ack(request_buf.data, 189*2be45238SPatrick Williams response_buf->data); 1901285115cSWilliam A. Kennington III break; 1911285115cSWilliam A. Kennington III case NCSI_OEM_COMMAND_GET_FILTER: 1921285115cSWilliam A. Kennington III { 1931285115cSWilliam A. Kennington III const ncsi_simple_command_t* cmd = 1941285115cSWilliam A. Kennington III reinterpret_cast<const ncsi_simple_command_t*>( 1951285115cSWilliam A. Kennington III request_buf.data); 1961285115cSWilliam A. Kennington III if (cmd->hdr.channel_id == 0) 1971285115cSWilliam A. Kennington III { 1981285115cSWilliam A. Kennington III response_size = ncsi_build_oem_get_filter_ack( 1991285115cSWilliam A. Kennington III request_buf.data, response_buf->data, &ch0_filter_); 2001285115cSWilliam A. Kennington III } 2011285115cSWilliam A. Kennington III else if (cmd->hdr.channel_id == 1) 2021285115cSWilliam A. Kennington III { 2031285115cSWilliam A. Kennington III response_size = ncsi_build_oem_get_filter_ack( 2041285115cSWilliam A. Kennington III request_buf.data, response_buf->data, &ch1_filter_); 2051285115cSWilliam A. Kennington III } 2061285115cSWilliam A. Kennington III else 2071285115cSWilliam A. Kennington III { 2081285115cSWilliam A. Kennington III response_size = ncsi_build_simple_nack( 2091285115cSWilliam A. Kennington III request_buf.data, response_buf->data, 3, 4); 2101285115cSWilliam A. Kennington III } 2111285115cSWilliam A. Kennington III } 2121285115cSWilliam A. Kennington III break; 2131285115cSWilliam A. Kennington III default: 2141285115cSWilliam A. Kennington III response_size = ncsi_build_simple_nack(request_buf.data, 2151285115cSWilliam A. Kennington III response_buf->data, 1, 2); 2161285115cSWilliam A. Kennington III break; 2171285115cSWilliam A. Kennington III } 2181285115cSWilliam A. Kennington III 2191285115cSWilliam A. Kennington III return response_size; 2201285115cSWilliam A. Kennington III } 2211285115cSWilliam A. Kennington III 2221285115cSWilliam A. Kennington III bool NIC::is_filter_configured(uint8_t channel) const 2231285115cSWilliam A. Kennington III { 2241285115cSWilliam A. Kennington III if (channel == 0) 2251285115cSWilliam A. Kennington III { 2261285115cSWilliam A. Kennington III return is_ch0_filter_configured_; 2271285115cSWilliam A. Kennington III } 2281285115cSWilliam A. Kennington III else if (channel == 1) 2291285115cSWilliam A. Kennington III { 2301285115cSWilliam A. Kennington III return is_ch1_filter_configured_; 2311285115cSWilliam A. Kennington III } 2321285115cSWilliam A. Kennington III 2331285115cSWilliam A. Kennington III throw std::invalid_argument("Unsupported channel"); 2341285115cSWilliam A. Kennington III } 2351285115cSWilliam A. Kennington III 2361285115cSWilliam A. Kennington III bool NIC::set_filter(uint8_t channel, const ncsi_oem_filter_t& filter) 2371285115cSWilliam A. Kennington III { 2381285115cSWilliam A. Kennington III ncsi_oem_filter_t* nic_filter; 2391285115cSWilliam A. Kennington III if (channel == 0) 2401285115cSWilliam A. Kennington III { 2411285115cSWilliam A. Kennington III nic_filter = &ch0_filter_; 2421285115cSWilliam A. Kennington III is_ch0_filter_configured_ = true; 2431285115cSWilliam A. Kennington III } 2441285115cSWilliam A. Kennington III else if (channel == 1) 2451285115cSWilliam A. Kennington III { 2461285115cSWilliam A. Kennington III nic_filter = &ch1_filter_; 2471285115cSWilliam A. Kennington III is_ch1_filter_configured_ = true; 2481285115cSWilliam A. Kennington III } 2491285115cSWilliam A. Kennington III else 2501285115cSWilliam A. Kennington III { 2511285115cSWilliam A. Kennington III throw std::invalid_argument("Unsupported channel"); 2521285115cSWilliam A. Kennington III } 2531285115cSWilliam A. Kennington III 2541285115cSWilliam A. Kennington III std::memcpy(nic_filter->mac, filter.mac, MAC_ADDR_SIZE); 2551285115cSWilliam A. Kennington III nic_filter->ip = 0; 2561285115cSWilliam A. Kennington III nic_filter->port = filter.port; 2571285115cSWilliam A. Kennington III return true; 2581285115cSWilliam A. Kennington III } 2591285115cSWilliam A. Kennington III 2601285115cSWilliam A. Kennington III const ncsi_oem_filter_t& NIC::get_filter(uint8_t channel) const 2611285115cSWilliam A. Kennington III { 2621285115cSWilliam A. Kennington III if (channel == 0) 2631285115cSWilliam A. Kennington III { 2641285115cSWilliam A. Kennington III return ch0_filter_; 2651285115cSWilliam A. Kennington III } 2661285115cSWilliam A. Kennington III else if (channel == 1) 2671285115cSWilliam A. Kennington III { 2681285115cSWilliam A. Kennington III return ch1_filter_; 2691285115cSWilliam A. Kennington III } 2701285115cSWilliam A. Kennington III 2711285115cSWilliam A. Kennington III throw std::invalid_argument("Unsupported channel"); 2721285115cSWilliam A. Kennington III } 2731285115cSWilliam A. Kennington III 2741285115cSWilliam A. Kennington III void NIC::set_hostless(bool is_hostless) 2751285115cSWilliam A. Kennington III { 276*2be45238SPatrick Williams auto set_flag_op = [](uint8_t lhs, uint8_t rhs) -> auto { 2771285115cSWilliam A. Kennington III return lhs | rhs; 2781285115cSWilliam A. Kennington III }; 2791285115cSWilliam A. Kennington III 280*2be45238SPatrick Williams auto clear_flag_op = [](uint8_t lhs, uint8_t rhs) -> auto { 2811285115cSWilliam A. Kennington III return lhs & ~rhs; 2821285115cSWilliam A. Kennington III }; 2831285115cSWilliam A. Kennington III 2841285115cSWilliam A. Kennington III auto flag_op = is_hostless ? set_flag_op : clear_flag_op; 2851285115cSWilliam A. Kennington III 2861285115cSWilliam A. Kennington III if (channel_count_ > 0) 2871285115cSWilliam A. Kennington III { 288*2be45238SPatrick Williams ch0_filter_.flags = flag_op(ch0_filter_.flags, 289*2be45238SPatrick Williams NCSI_OEM_FILTER_FLAGS_HOSTLESS); 2901285115cSWilliam A. Kennington III } 2911285115cSWilliam A. Kennington III 2921285115cSWilliam A. Kennington III if (channel_count_ > 1) 2931285115cSWilliam A. Kennington III { 294*2be45238SPatrick Williams ch1_filter_.flags = flag_op(ch1_filter_.flags, 295*2be45238SPatrick Williams NCSI_OEM_FILTER_FLAGS_HOSTLESS); 2961285115cSWilliam A. Kennington III } 2971285115cSWilliam A. Kennington III } 2981285115cSWilliam A. Kennington III 2991285115cSWilliam A. Kennington III void NIC::toggle_hostless() 3001285115cSWilliam A. Kennington III { 3011285115cSWilliam A. Kennington III if (channel_count_ > 0) 3021285115cSWilliam A. Kennington III { 3031285115cSWilliam A. Kennington III ch0_filter_.flags ^= NCSI_OEM_FILTER_FLAGS_HOSTLESS; 3041285115cSWilliam A. Kennington III } 3051285115cSWilliam A. Kennington III 3061285115cSWilliam A. Kennington III if (channel_count_ > 1) 3071285115cSWilliam A. Kennington III { 3081285115cSWilliam A. Kennington III ch1_filter_.flags ^= NCSI_OEM_FILTER_FLAGS_HOSTLESS; 3091285115cSWilliam A. Kennington III } 3101285115cSWilliam A. Kennington III } 3111285115cSWilliam A. Kennington III 3121285115cSWilliam A. Kennington III bool NIC::is_hostless() 3131285115cSWilliam A. Kennington III { 3141285115cSWilliam A. Kennington III return ch0_filter_.flags & NCSI_OEM_FILTER_FLAGS_HOSTLESS; 3151285115cSWilliam A. Kennington III } 3161285115cSWilliam A. Kennington III 3171285115cSWilliam A. Kennington III void NIC::save_frame_to_log(const NCSIFrame& frame) 3181285115cSWilliam A. Kennington III { 3191285115cSWilliam A. Kennington III if (cmd_log_.size() >= max_log_size_) 3201285115cSWilliam A. Kennington III { 3211285115cSWilliam A. Kennington III cmd_log_.erase(cmd_log_.begin()); 3221285115cSWilliam A. Kennington III } 3231285115cSWilliam A. Kennington III 3241285115cSWilliam A. Kennington III cmd_log_.push_back(frame); 3251285115cSWilliam A. Kennington III } 3261285115cSWilliam A. Kennington III 3271285115cSWilliam A. Kennington III const std::vector<uint8_t> NIC::simple_commands_ = { 3281285115cSWilliam A. Kennington III NCSI_CLEAR_INITIAL_STATE, 3291285115cSWilliam A. Kennington III NCSI_SELECT_PACKAGE, 3301285115cSWilliam A. Kennington III NCSI_DESELECT_PACKAGE, 3311285115cSWilliam A. Kennington III NCSI_ENABLE_CHANNEL, 3321285115cSWilliam A. Kennington III NCSI_DISABLE_CHANNEL, 3331285115cSWilliam A. Kennington III NCSI_RESET_CHANNEL, 3341285115cSWilliam A. Kennington III NCSI_ENABLE_CHANNEL_NETWORK_TX, 3351285115cSWilliam A. Kennington III NCSI_DISABLE_CHANNEL_NETWORK_TX, 3361285115cSWilliam A. Kennington III NCSI_AEN_ENABLE, 3371285115cSWilliam A. Kennington III NCSI_SET_LINK, 3381285115cSWilliam A. Kennington III NCSI_SET_VLAN_FILTER, 3391285115cSWilliam A. Kennington III NCSI_ENABLE_VLAN, 3401285115cSWilliam A. Kennington III NCSI_DISABLE_VLAN, 3411285115cSWilliam A. Kennington III NCSI_SET_MAC_ADDRESS, 3421285115cSWilliam A. Kennington III NCSI_ENABLE_BROADCAST_FILTER, 3431285115cSWilliam A. Kennington III NCSI_DISABLE_BROADCAST_FILTER, 3441285115cSWilliam A. Kennington III NCSI_ENABLE_GLOBAL_MULTICAST_FILTER, 3451285115cSWilliam A. Kennington III NCSI_DISABLE_GLOBAL_MULTICAST_FILTER, 3461285115cSWilliam A. Kennington III NCSI_SET_NCSI_FLOW_CONTROL, 3471285115cSWilliam A. Kennington III }; 3481285115cSWilliam A. Kennington III 3491285115cSWilliam A. Kennington III } // namespace mock 350