network_emulation_manager.h (17679B)
1 /* 2 * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef API_TEST_NETWORK_EMULATION_MANAGER_H_ 12 #define API_TEST_NETWORK_EMULATION_MANAGER_H_ 13 14 #include <cstdint> 15 #include <functional> 16 #include <memory> 17 #include <optional> 18 #include <string> 19 #include <utility> 20 #include <vector> 21 22 #include "absl/base/nullability.h" 23 #include "absl/strings/string_view.h" 24 #include "api/array_view.h" 25 #include "api/field_trials_view.h" 26 #include "api/test/network_emulation/cross_traffic.h" 27 #include "api/test/network_emulation/network_emulation_interfaces.h" 28 #include "api/test/network_emulation/network_queue.h" 29 #include "api/test/peer_network_dependencies.h" 30 #include "api/test/simulated_network.h" 31 #include "api/test/time_controller.h" 32 #include "api/units/data_rate.h" 33 #include "rtc_base/ip_address.h" 34 #include "rtc_base/network_constants.h" 35 #include "rtc_base/socket_address.h" 36 37 namespace webrtc { 38 39 // This API is still in development and can be changed without prior notice. 40 41 // These classes are forward declared here, because they used as handles, to 42 // make it possible for client code to operate with these abstractions and build 43 // required network configuration. With forward declaration here implementation 44 // is more readable, than with interfaces approach and cause user needn't any 45 // API methods on these abstractions it is acceptable here. 46 47 // EmulatedNetworkNode is an abstraction for some network in the real world, 48 // like 3G network between peers, or Wi-Fi for one peer and LTE for another. 49 // Multiple networks can be joined into chain emulating a network path from 50 // one peer to another. 51 class EmulatedNetworkNode; 52 53 // EmulatedRoute is handle for single route from one network interface on one 54 // peer device to another network interface on another peer device. 55 class EmulatedRoute; 56 57 enum class EmulatedNetworkStatsGatheringMode { 58 // Gather main network stats counters. See more details on which particular 59 // metrics are collected in the `EmulatedNetworkStats` and 60 // `EmulatedNetworkNodeStats` documentation. 61 kDefault, 62 // kDefault + also gather per packet statistics. In this mode more memory 63 // will be used. 64 kDebug 65 }; 66 67 struct EmulatedEndpointConfig { 68 enum class IpAddressFamily { kIpv4, kIpv6 }; 69 70 // If specified will be used to name endpoint for logging purposes. 71 std::optional<std::string> name = std::nullopt; 72 IpAddressFamily generated_ip_family = IpAddressFamily::kIpv4; 73 // If specified will be used as IP address for endpoint node. Must be unique 74 // among all created nodes. 75 std::optional<IPAddress> ip; 76 // Should endpoint be enabled or not, when it will be created. 77 // Enabled endpoints will be available for webrtc to send packets. 78 bool start_as_enabled = true; 79 // Network type which will be used to represent endpoint to WebRTC. 80 AdapterType type = AdapterType::ADAPTER_TYPE_UNKNOWN; 81 // Allow endpoint to send packets specifying source IP address different to 82 // the current endpoint IP address. If false endpoint will crash if attempt 83 // to send such packet will be done. 84 bool allow_send_packet_with_different_source_ip = false; 85 // Allow endpoint to receive packet with destination IP address different to 86 // the current endpoint IP address. If false endpoint will crash if such 87 // packet will arrive. 88 bool allow_receive_packets_with_different_dest_ip = false; 89 }; 90 91 struct EmulatedTURNServerConfig { 92 EmulatedEndpointConfig client_config; 93 EmulatedEndpointConfig peer_config; 94 bool enable_permission_checks = true; 95 }; 96 97 // EmulatedTURNServer is an abstraction for a TURN server. 98 class EmulatedTURNServerInterface { 99 public: 100 struct IceServerConfig { 101 std::string username; 102 std::string password; 103 std::string url; 104 }; 105 106 virtual ~EmulatedTURNServerInterface() {} 107 108 // Get an IceServer configuration suitable to add to a PeerConnection. 109 virtual IceServerConfig GetIceServerConfig() const = 0; 110 111 // Get non-null client endpoint, an endpoint that accepts TURN allocations. 112 // This shall typically be connected to one or more webrtc endpoint. 113 virtual EmulatedEndpoint* GetClientEndpoint() const = 0; 114 115 // Returns socket address, which client should use to connect to TURN server 116 // and do TURN allocation. 117 virtual SocketAddress GetClientEndpointAddress() const = 0; 118 119 // Get non-null peer endpoint, that is "connected to the internet". 120 // This shall typically be connected to another TURN server. 121 virtual EmulatedEndpoint* GetPeerEndpoint() const = 0; 122 }; 123 124 // Provide interface to obtain all required objects to inject network emulation 125 // layer into PeerConnection. Also contains information about network interfaces 126 // accessible by PeerConnection. 127 class EmulatedNetworkManagerInterface 128 : public webrtc_pc_e2e::PeerNetworkDependencies { 129 public: 130 ~EmulatedNetworkManagerInterface() override = default; 131 132 // Returns list of endpoints that are associated with this instance. Pointers 133 // are guaranteed to be non-null and are owned by NetworkEmulationManager. 134 virtual std::vector<EmulatedEndpoint*> endpoints() const = 0; 135 136 // Passes summarized network stats for endpoints for this manager into 137 // specified `stats_callback`. Callback will be executed on network emulation 138 // internal task queue. 139 virtual void GetStats( 140 std::function<void(EmulatedNetworkStats)> stats_callback) const = 0; 141 }; 142 143 enum class TimeMode { kRealTime, kSimulated }; 144 145 // Called implicitly when parsing an ABSL_FLAG of type TimeMode. 146 // from the command line flag value `text`. 147 // Returns `true` and sets `*mode` on success; 148 // returns `false` and sets `*error` on failure. 149 bool AbslParseFlag(absl::string_view text, TimeMode* mode, std::string* error); 150 151 // AbslUnparseFlag returns a textual flag value corresponding to the TimeMode 152 // `mode`. 153 std::string AbslUnparseFlag(TimeMode mode); 154 155 // The construction-time configuration options for NetworkEmulationManager. 156 struct NetworkEmulationManagerConfig { 157 // The mode of the underlying time controller. 158 TimeMode time_mode = TimeMode::kRealTime; 159 // The mode that determines the set of metrics to collect into 160 // `EmulatedNetworkStats` and `EmulatedNetworkNodeStats`. 161 EmulatedNetworkStatsGatheringMode stats_gathering_mode = 162 EmulatedNetworkStatsGatheringMode::kDefault; 163 // Field trials that can alter the behavior of NetworkEmulationManager. 164 const FieldTrialsView* field_trials = nullptr; 165 // If this flag is set, NetworkEmulationManager ignores the sizes of peers' 166 // DTLS handshake packets when determining when to let the packets through 167 // a constrained emulated network. Actual hanshake's packet size is ignored 168 // and a hardcoded fake size is used to compute packet's use of link capacity. 169 // This is useful for tests that require deterministic packets scheduling 170 // timing-wise even when the sizes of DTLS hadshake packets are not 171 // deterministic. This mode make sense only together with the simulated time. 172 bool fake_dtls_handshake_sizes = false; 173 }; 174 175 // Provides an API for creating and configuring emulated network layer. 176 // All objects returned by this API are owned by NetworkEmulationManager itself 177 // and will be deleted when manager will be deleted. 178 class NetworkEmulationManager { 179 public: 180 // Helper struct to simplify creation of simulated network behaviors. Contains 181 // non-owning pointers as the underlying instances are owned by the manager. 182 struct SimulatedNetworkNode { 183 SimulatedNetworkInterface* simulation; 184 EmulatedNetworkNode* node; 185 186 class Builder { 187 public: 188 explicit Builder(NetworkEmulationManager* net) : net_(net) {} 189 Builder() : net_(nullptr) {} 190 Builder(const Builder&) = default; 191 // Sets the config state, note that this will replace any previously set 192 // values. 193 Builder& config(BuiltInNetworkBehaviorConfig config); 194 // If set, `queue_factory` must outlive the Builder. 195 Builder& queue_factory(NetworkQueueFactory& queue_factory); 196 Builder& delay_ms(int queue_delay_ms); 197 Builder& capacity(DataRate link_capacity); 198 Builder& capacity_kbps(int link_capacity_kbps); 199 Builder& capacity_Mbps(int link_capacity_Mbps); 200 Builder& loss(double loss_rate); 201 Builder& packet_queue_length(int max_queue_length_in_packets); 202 Builder& delay_standard_deviation_ms(int delay_standard_deviation_ms); 203 Builder& allow_reordering(); 204 Builder& avg_burst_loss_length(int avg_burst_loss_length); 205 Builder& packet_overhead(int packet_overhead); 206 SimulatedNetworkNode Build(uint64_t random_seed = 1) const; 207 SimulatedNetworkNode Build(NetworkEmulationManager* net, 208 uint64_t random_seed = 1) const; 209 210 private: 211 NetworkEmulationManager* const net_; 212 BuiltInNetworkBehaviorConfig config_; 213 NetworkQueueFactory* queue_factory_ = nullptr; 214 }; 215 }; 216 virtual ~NetworkEmulationManager() = default; 217 218 virtual TimeController* time_controller() = 0; 219 // Returns a mode in which underlying time controller operates. 220 virtual TimeMode time_mode() const = 0; 221 222 // Creates an emulated network node, which represents ideal network with 223 // unlimited capacity, no delay and no packet loss. 224 EmulatedNetworkNode* CreateUnconstrainedEmulatedNode() { 225 return CreateEmulatedNode(BuiltInNetworkBehaviorConfig()); 226 } 227 // Creates an emulated network node, which represents single network in 228 // the emulated network layer. Uses default implementation on network behavior 229 // which can be configured with `config`. `random_seed` can be provided to 230 // alter randomization behavior. 231 virtual EmulatedNetworkNode* CreateEmulatedNode( 232 BuiltInNetworkBehaviorConfig config, 233 uint64_t random_seed = 1) = 0; 234 // Creates an emulated network node, which represents single network in 235 // the emulated network layer. `network_behavior` determines how created node 236 // will forward incoming packets to the next receiver. 237 virtual EmulatedNetworkNode* CreateEmulatedNode( 238 std::unique_ptr<NetworkBehaviorInterface> network_behavior) = 0; 239 240 virtual SimulatedNetworkNode::Builder NodeBuilder() = 0; 241 242 // Creates an emulated endpoint, which represents single network interface on 243 // the peer's device. 244 virtual EmulatedEndpoint* CreateEndpoint(EmulatedEndpointConfig config) = 0; 245 // Enable emulated endpoint to make it available for webrtc. 246 // Caller mustn't enable currently enabled endpoint. 247 virtual void EnableEndpoint(EmulatedEndpoint* endpoint) = 0; 248 // Disable emulated endpoint to make it unavailable for webrtc. 249 // Caller mustn't disable currently disabled endpoint. 250 virtual void DisableEndpoint(EmulatedEndpoint* endpoint) = 0; 251 252 // Creates a route between endpoints going through specified network nodes. 253 // This route is single direction only and describe how traffic that was 254 // sent by network interface `from` have to be delivered to the network 255 // interface `to`. Return object can be used to remove created route. The 256 // route must contains at least one network node inside it. 257 // 258 // Assume that E{0-9} are endpoints and N{0-9} are network nodes, then 259 // creation of the route have to follow these rules: 260 // 1. A route consists of a source endpoint, an ordered list of one or 261 // more network nodes, and a destination endpoint. 262 // 2. If (E1, ..., E2) is a route, then E1 != E2. 263 // In other words, the source and the destination may not be the same. 264 // 3. Given two simultaneously existing routes (E1, ..., E2) and 265 // (E3, ..., E4), either E1 != E3 or E2 != E4. 266 // In other words, there may be at most one route from any given source 267 // endpoint to any given destination endpoint. 268 // 4. Given two simultaneously existing routes (E1, ..., N1, ..., E2) 269 // and (E3, ..., N2, ..., E4), either N1 != N2 or E2 != E4. 270 // In other words, a network node may not belong to two routes that lead 271 // to the same destination endpoint. 272 virtual EmulatedRoute* CreateRoute( 273 EmulatedEndpoint* from, 274 const std::vector<EmulatedNetworkNode*>& via_nodes, 275 EmulatedEndpoint* to) = 0; 276 277 // Creates a route over the given `via_nodes` creating the required endpoints 278 // in the process. The returned EmulatedRoute pointer can be used in other 279 // calls as a transport route for message or cross traffic. 280 virtual EmulatedRoute* CreateRoute( 281 const std::vector<EmulatedNetworkNode*>& via_nodes) = 0; 282 283 // Creates a default route between endpoints going through specified network 284 // nodes. Default route is used for packet when there is no known route for 285 // packet's destination IP. 286 // 287 // This route is single direction only and describe how traffic that was 288 // sent by network interface `from` have to be delivered in case if routing 289 // was unspecified. Return object can be used to remove created route. The 290 // route must contains at least one network node inside it. 291 // 292 // Assume that E{0-9} are endpoints and N{0-9} are network nodes, then 293 // creation of the route have to follow these rules: 294 // 1. A route consists of a source endpoint, an ordered list of one or 295 // more network nodes, and a destination endpoint. 296 // 2. If (E1, ..., E2) is a route, then E1 != E2. 297 // In other words, the source and the destination may not be the same. 298 // 3. Given two simultaneously existing routes (E1, ..., E2) and 299 // (E3, ..., E4), either E1 != E3 or E2 != E4. 300 // In other words, there may be at most one route from any given source 301 // endpoint to any given destination endpoint. 302 // 4. Given two simultaneously existing routes (E1, ..., N1, ..., E2) 303 // and (E3, ..., N2, ..., E4), either N1 != N2 or E2 != E4. 304 // In other words, a network node may not belong to two routes that lead 305 // to the same destination endpoint. 306 // 5. Any node N can belong to only one default route. 307 virtual EmulatedRoute* CreateDefaultRoute( 308 EmulatedEndpoint* from, 309 const std::vector<EmulatedNetworkNode*>& via_nodes, 310 EmulatedEndpoint* to) = 0; 311 312 // Removes route previously created by CreateRoute(...). 313 // Caller mustn't call this function with route, that have been already 314 // removed earlier. Removing a route that is currently in use will lead to 315 // packets being dropped. 316 virtual void ClearRoute(EmulatedRoute* route) = 0; 317 318 // Creates a simulated TCP connection using `send_route` for traffic and 319 // `ret_route` for feedback. This can be used to emulate HTTP cross traffic 320 // and to implement realistic reliable signaling over lossy networks. 321 // TODO(srte): Handle clearing of the routes involved. 322 virtual TcpMessageRoute* CreateTcpRoute(EmulatedRoute* send_route, 323 EmulatedRoute* ret_route) = 0; 324 325 // Creates a route over the given `via_nodes`. Returns an object that can be 326 // used to emulate network load with cross traffic over the created route. 327 virtual CrossTrafficRoute* CreateCrossTrafficRoute( 328 const std::vector<EmulatedNetworkNode*>& via_nodes) = 0; 329 330 // Starts generating cross traffic using given `generator`. Takes ownership 331 // over the generator. 332 virtual CrossTrafficGenerator* StartCrossTraffic( 333 std::unique_ptr<CrossTrafficGenerator> generator) = 0; 334 335 // Stops generating cross traffic that was started using given `generator`. 336 // The `generator` shouldn't be used after and the reference may be invalid. 337 virtual void StopCrossTraffic(CrossTrafficGenerator* generator) = 0; 338 339 // Creates EmulatedNetworkManagerInterface which can be used then to inject 340 // network emulation layer into PeerConnectionFactory. `endpoints` are 341 // available network interfaces for PeerConnection. If endpoint is enabled, it 342 // will be immediately available for PeerConnection, otherwise user will be 343 // able to enable endpoint later to make it available for PeerConnection. 344 virtual EmulatedNetworkManagerInterface* absl_nonnull 345 CreateEmulatedNetworkManagerInterface( 346 const std::vector<EmulatedEndpoint*>& endpoints) = 0; 347 348 // Passes combined network stats for all specified `endpoints` into specified 349 // `stats_callback`. Callback will be executed on network emulation 350 // internal task queue. 351 virtual void GetStats( 352 ArrayView<EmulatedEndpoint* const> endpoints, 353 std::function<void(EmulatedNetworkStats)> stats_callback) = 0; 354 355 // Passes combined network stats for all specified `nodes` into specified 356 // `stats_callback`. Callback will be executed on network emulation 357 // internal task queue. 358 virtual void GetStats( 359 ArrayView<EmulatedNetworkNode* const> nodes, 360 std::function<void(EmulatedNetworkNodeStats)> stats_callback) = 0; 361 362 // Create a EmulatedTURNServer. 363 // The TURN server has 2 endpoints that need to be connected with routes, 364 // - GetClientEndpoint() - the endpoint that accepts TURN allocations. 365 // - GetPeerEndpoint() - the endpoint that is "connected to the internet". 366 virtual EmulatedTURNServerInterface* CreateTURNServer( 367 EmulatedTURNServerConfig config) = 0; 368 369 // Create a pair of EmulatedNetworkManagerInterfaces connected to each other. 370 std::pair<EmulatedNetworkManagerInterface*, EmulatedNetworkManagerInterface*> 371 CreateEndpointPairWithTwoWayRoutes( 372 const BuiltInNetworkBehaviorConfig& config); 373 }; 374 375 } // namespace webrtc 376 377 #endif // API_TEST_NETWORK_EMULATION_MANAGER_H_