Line data Source code
1 : #pragma once 2 : 3 : #include <cstdint> 4 : #include <memory> 5 : #include <string> 6 : 7 : #include "envoy/access_log/access_log.h" 8 : #include "envoy/api/io_error.h" 9 : #include "envoy/common/exception.h" 10 : #include "envoy/common/resource.h" 11 : #include "envoy/config/core/v3/base.pb.h" 12 : #include "envoy/config/listener/v3/udp_listener_config.pb.h" 13 : #include "envoy/config/typed_metadata.h" 14 : #include "envoy/init/manager.h" 15 : #include "envoy/network/address.h" 16 : #include "envoy/network/connection.h" 17 : #include "envoy/network/connection_balancer.h" 18 : #include "envoy/network/listen_socket.h" 19 : #include "envoy/network/udp_packet_writer_handler.h" 20 : #include "envoy/server/overload/load_shed_point.h" 21 : #include "envoy/stats/scope.h" 22 : 23 : #include "source/common/common/interval_value.h" 24 : 25 : namespace Envoy { 26 : namespace Network { 27 : 28 : // Set this to the maximum value which effectively accepts all connections. 29 : constexpr uint32_t DefaultMaxConnectionsToAcceptPerSocketEvent = UINT32_MAX; 30 : 31 : class ActiveUdpListenerFactory; 32 : class UdpListenerWorkerRouter; 33 : 34 : class ListenSocketFactory; 35 : using ListenSocketFactoryPtr = std::unique_ptr<ListenSocketFactory>; 36 : 37 : /** 38 : * ListenSocketFactory is a member of ListenConfig to provide listen socket. 39 : * Listeners created from the same ListenConfig instance have listening sockets 40 : * provided by the same ListenSocketFactory instance. 41 : */ 42 : class ListenSocketFactory { 43 : public: 44 639 : virtual ~ListenSocketFactory() = default; 45 : 46 : /** 47 : * Called during actual listener creation. 48 : * @param worker_index supplies the worker index to get the socket for. All sockets are created 49 : * ahead of time. 50 : * @return the socket to be used for a certain listener, which might be shared 51 : * with other listeners of the same config on other worker threads. 52 : */ 53 : virtual SocketSharedPtr getListenSocket(uint32_t worker_index) PURE; 54 : 55 : /** 56 : * @return the type of the socket getListenSocket() returns. 57 : */ 58 : virtual Socket::Type socketType() const PURE; 59 : 60 : /** 61 : * @return the listening address of the socket getListenSocket() returns. Before getListenSocket() 62 : * is called, the return value might has 0 as port number if the config doesn't specify it. 63 : */ 64 : virtual const Address::InstanceConstSharedPtr& localAddress() const PURE; 65 : 66 : /** 67 : * Clone this socket factory so it can be used by a new listener (e.g., if the address is shared). 68 : */ 69 : virtual ListenSocketFactoryPtr clone() const PURE; 70 : 71 : /** 72 : * Close all sockets. This is used during draining scenarios. 73 : */ 74 : virtual void closeAllSockets() PURE; 75 : 76 : /** 77 : * Perform any initialization that must occur immediately prior to using the listen socket on 78 : * workers. For example, the actual listen() call, post listen socket options, etc. This is done 79 : * so that all error handling can occur on the main thread and the gap between performing these 80 : * actions and using the socket is minimized. 81 : */ 82 : virtual void doFinalPreWorkerInit() PURE; 83 : }; 84 : 85 : /** 86 : * Configuration for a UDP listener. 87 : */ 88 : class UdpListenerConfig { 89 : public: 90 126 : virtual ~UdpListenerConfig() = default; 91 : 92 : /** 93 : * @return factory for creating a listener. 94 : */ 95 : virtual ActiveUdpListenerFactory& listenerFactory() PURE; 96 : 97 : /** 98 : * @return factory for writing to a UDP socket. 99 : */ 100 : virtual UdpPacketWriterFactory& packetWriterFactory() PURE; 101 : 102 : /** 103 : * @param address is used to query the address specific router. 104 : * @return the UdpListenerWorkerRouter for this listener. 105 : */ 106 : virtual UdpListenerWorkerRouter& 107 : listenerWorkerRouter(const Network::Address::Instance& address) PURE; 108 : 109 : /** 110 : * @return the configuration for the listener. 111 : */ 112 : virtual const envoy::config::listener::v3::UdpListenerConfig& config() PURE; 113 : }; 114 : 115 : using UdpListenerConfigOptRef = OptRef<UdpListenerConfig>; 116 : 117 : // Forward declare. 118 : class InternalListenerRegistry; 119 : 120 : /** 121 : * Configuration for an internal listener. 122 : */ 123 : class InternalListenerConfig { 124 : public: 125 0 : virtual ~InternalListenerConfig() = default; 126 : 127 : /** 128 : * @return InternalListenerRegistry& The internal registry of this internal listener config. The 129 : * registry outlives this listener config. 130 : */ 131 : virtual InternalListenerRegistry& internalListenerRegistry() PURE; 132 : }; 133 : 134 : using InternalListenerConfigOptRef = OptRef<InternalListenerConfig>; 135 : 136 : /** 137 : * Description of the listener. 138 : */ 139 : class ListenerInfo { 140 : public: 141 781 : virtual ~ListenerInfo() = default; 142 : 143 : /** 144 : * @return const envoy::config::core::v3::Metadata& the config metadata associated with this 145 : * listener. 146 : */ 147 : virtual const envoy::config::core::v3::Metadata& metadata() const PURE; 148 : 149 : /** 150 : * @return const Envoy::Config::TypedMetadata& return the typed metadata provided in the config 151 : * for this listener. 152 : */ 153 : virtual const Envoy::Config::TypedMetadata& typedMetadata() const PURE; 154 : 155 : /** 156 : * @return envoy::config::core::v3::TrafficDirection the direction of the traffic relative to 157 : * the local proxy. 158 : */ 159 : virtual envoy::config::core::v3::TrafficDirection direction() const PURE; 160 : 161 : /** 162 : * @return whether the listener is a Quic listener. 163 : */ 164 : virtual bool isQuic() const PURE; 165 : }; 166 : 167 : using ListenerInfoConstSharedPtr = std::shared_ptr<const ListenerInfo>; 168 : 169 : /** 170 : * A configuration for an individual listener. 171 : */ 172 : class ListenerConfig { 173 : public: 174 651 : virtual ~ListenerConfig() = default; 175 : 176 : /** 177 : * @return FilterChainManager& the factory for adding and searching through configured 178 : * filter chains. 179 : */ 180 : virtual FilterChainManager& filterChainManager() PURE; 181 : 182 : /** 183 : * @return FilterChainFactory& the factory for setting up the filter chain on a new 184 : * connection. 185 : */ 186 : virtual FilterChainFactory& filterChainFactory() PURE; 187 : 188 : /** 189 : * @return std::vector<ListenSocketFactoryPtr>& the factories to create listen sockets. 190 : */ 191 : virtual std::vector<ListenSocketFactoryPtr>& listenSocketFactories() PURE; 192 : 193 : /** 194 : * @return bool specifies whether the listener should actually listen on the port. 195 : * A listener that doesn't listen on a port can only receive connections 196 : * redirected from other listeners. 197 : */ 198 : virtual bool bindToPort() const PURE; 199 : 200 : /** 201 : * @return bool if a connection should be handed off to another Listener after the original 202 : * destination address has been restored. 'true' when 'use_original_dst' flag in listener 203 : * configuration is set, false otherwise. 204 : */ 205 : virtual bool handOffRestoredDestinationConnections() const PURE; 206 : 207 : /** 208 : * @return uint32_t providing a soft limit on size of the listener's new connection read and 209 : * write buffers. 210 : */ 211 : virtual uint32_t perConnectionBufferLimitBytes() const PURE; 212 : 213 : /** 214 : * @return std::chrono::milliseconds the time to wait for all listener filters to complete 215 : * operation. If the timeout is reached, the accepted socket is closed without a 216 : * connection being created unless continueOnListenerFiltersTimeout() returns true. 217 : * 0 specifies a disabled timeout. 218 : */ 219 : virtual std::chrono::milliseconds listenerFiltersTimeout() const PURE; 220 : 221 : /** 222 : * @return bool whether the listener should try to create a connection when listener filters 223 : * time out. 224 : */ 225 : virtual bool continueOnListenerFiltersTimeout() const PURE; 226 : 227 : /** 228 : * @return Stats::Scope& the stats scope to use for all listener specific stats. 229 : */ 230 : virtual Stats::Scope& listenerScope() PURE; 231 : 232 : /** 233 : * @return uint64_t the tag the listener should use for connection handler tracking. 234 : */ 235 : virtual uint64_t listenerTag() const PURE; 236 : 237 : /** 238 : * @return const std::string& the listener's name. 239 : */ 240 : virtual const std::string& name() const PURE; 241 : 242 : /** 243 : * @return ListenerInfoConstSharedPtr& description of the listener. 244 : */ 245 : virtual const ListenerInfoConstSharedPtr& listenerInfo() const PURE; 246 : 247 : /** 248 : * @return the UDP configuration for the listener IFF it is a UDP listener. 249 : */ 250 : virtual UdpListenerConfigOptRef udpListenerConfig() PURE; 251 : 252 : /** 253 : * @return the internal configuration for the listener IFF it is an internal listener. 254 : */ 255 : virtual InternalListenerConfigOptRef internalListenerConfig() PURE; 256 : 257 : /** 258 : * @param address is used for query the address specific connection balancer. 259 : * @return the connection balancer for this listener. All listeners have a connection balancer, 260 : * though the implementation may be a NOP balancer. 261 : */ 262 : virtual ConnectionBalancer& connectionBalancer(const Network::Address::Instance& address) PURE; 263 : 264 : /** 265 : * Open connection resources for this listener. 266 : */ 267 : virtual ResourceLimit& openConnections() PURE; 268 : 269 : /** 270 : * @return std::vector<AccessLog::InstanceSharedPtr> access logs emitted by the listener. 271 : */ 272 : virtual const std::vector<AccessLog::InstanceSharedPtr>& accessLogs() const PURE; 273 : 274 : /** 275 : * @return pending connection backlog for TCP listeners. 276 : */ 277 : virtual uint32_t tcpBacklogSize() const PURE; 278 : 279 : /** 280 : * @return the maximum number of connections that will be accepted for a given socket event. 281 : */ 282 : virtual uint32_t maxConnectionsToAcceptPerSocketEvent() const PURE; 283 : 284 : /** 285 : * @return init manager of the listener. 286 : */ 287 : virtual Init::Manager& initManager() PURE; 288 : 289 : /** 290 : * @return bool whether the listener should avoid blocking connections based on the globally set 291 : * limit. 292 : */ 293 : virtual bool ignoreGlobalConnLimit() const PURE; 294 : }; 295 : 296 : /** 297 : * Callbacks invoked by a listener. 298 : */ 299 : class TcpListenerCallbacks { 300 : public: 301 607 : virtual ~TcpListenerCallbacks() = default; 302 : 303 : /** 304 : * Called when a new connection is accepted. 305 : * @param socket supplies the socket that is moved into the callee. 306 : */ 307 : virtual void onAccept(ConnectionSocketPtr&& socket) PURE; 308 : 309 : enum class RejectCause { 310 : GlobalCxLimit, 311 : OverloadAction, 312 : }; 313 : /** 314 : * Called when a new connection is rejected. 315 : */ 316 : virtual void onReject(RejectCause cause) PURE; 317 : 318 : /** 319 : * Called when the listener has finished accepting connections per socket 320 : * event. 321 : * @param connections_accepted number of connections accepted. 322 : */ 323 : virtual void recordConnectionsAcceptedOnSocketEvent(uint32_t connections_accepted) PURE; 324 : }; 325 : 326 : /** 327 : * Utility struct that encapsulates the information from a udp socket's recvmmsg call. 328 : */ 329 : struct UdpRecvData { 330 : struct LocalPeerAddresses { 331 0 : bool operator==(const LocalPeerAddresses& rhs) const { 332 0 : // TODO(mattklein123): Implement a hash directly on Address that does not use strings. 333 0 : return local_->asStringView() == rhs.local_->asStringView() && 334 0 : peer_->asStringView() == rhs.peer_->asStringView(); 335 0 : } 336 : 337 0 : template <typename H> friend H AbslHashValue(H h, const LocalPeerAddresses& addresses) { 338 : // TODO(mattklein123): Implement a hash directly on Address that does not use strings. 339 0 : return H::combine(std::move(h), addresses.local_->asStringView(), 340 0 : addresses.peer_->asStringView()); 341 0 : } 342 : 343 : Address::InstanceConstSharedPtr local_; 344 : Address::InstanceConstSharedPtr peer_; 345 : }; 346 : 347 : LocalPeerAddresses addresses_; 348 : Buffer::InstancePtr buffer_; 349 : MonotonicTime receive_time_; 350 : }; 351 : 352 : /** 353 : * Encapsulates the information needed to send a udp packet to a target 354 : */ 355 : struct UdpSendData { 356 : const Address::Ip* local_ip_; 357 : const Address::Instance& peer_address_; 358 : 359 : // The buffer is a reference so that it can be reused by the sender to send different 360 : // messages 361 : Buffer::Instance& buffer_; 362 : }; 363 : 364 : /** 365 : * UDP listener callbacks. 366 : */ 367 : class UdpListenerCallbacks { 368 : public: 369 91 : virtual ~UdpListenerCallbacks() = default; 370 : 371 : /** 372 : * Called whenever data is received by the underlying udp socket. 373 : * TODO(danzh2010): Consider returning a value to indicate if more work is to 374 : * be done in the next event loop due to a limit on how much processing is 375 : * allowed in each event loop. 376 : * 377 : * @param data UdpRecvData from the underlying socket. 378 : */ 379 : virtual void onData(UdpRecvData&& data) PURE; 380 : 381 : /** 382 : * Called whenever datagrams are dropped due to overflow or truncation. 383 : * @param dropped supplies the number of dropped datagrams. 384 : */ 385 : virtual void onDatagramsDropped(uint32_t dropped) PURE; 386 : 387 : /** 388 : * Called when the underlying socket is ready for read, before onData() is 389 : * called. Called only once per event loop, even if followed by multiple 390 : * onData() calls. 391 : * 392 : */ 393 : virtual void onReadReady() PURE; 394 : 395 : /** 396 : * Called when the underlying socket is ready for write. 397 : * 398 : * @param socket Underlying server socket for the listener. 399 : * 400 : * TODO(conqerAtapple): Maybe we need a UdpWriter here instead of Socket. 401 : */ 402 : virtual void onWriteReady(const Socket& socket) PURE; 403 : 404 : /** 405 : * Called when there is an error event in the receive data path. 406 : * The send side error is a return type on the send method. 407 : * 408 : * @param error_code supplies the received error on the listener. 409 : */ 410 : virtual void onReceiveError(Api::IoError::IoErrorCode error_code) PURE; 411 : 412 : /** 413 : * Returns the pointer to the udp_packet_writer associated with the 414 : * UdpListenerCallback 415 : */ 416 : virtual UdpPacketWriter& udpPacketWriter() PURE; 417 : 418 : /** 419 : * Returns the index of this worker, in the range of [0, concurrency). 420 : */ 421 : virtual uint32_t workerIndex() const PURE; 422 : 423 : /** 424 : * Called whenever data is received on the underlying udp socket, on 425 : * the destination worker for the datagram according to ``destination()``. 426 : */ 427 : virtual void onDataWorker(Network::UdpRecvData&& data) PURE; 428 : 429 : /** 430 : * Posts ``data`` to be delivered on this worker. 431 : */ 432 : virtual void post(Network::UdpRecvData&& data) PURE; 433 : 434 : /** 435 : * An estimated number of UDP packets this callback expects to process in current read event. 436 : */ 437 : virtual size_t numPacketsExpectedPerEventLoop() const PURE; 438 : }; 439 : 440 : using UdpListenerCallbacksOptRef = absl::optional<std::reference_wrapper<UdpListenerCallbacks>>; 441 : 442 : /** 443 : * An abstract socket listener. Free the listener to stop listening on the socket. 444 : */ 445 : class Listener { 446 : public: 447 698 : virtual ~Listener() = default; 448 : 449 : /** 450 : * Temporarily disable accepting new connections. 451 : */ 452 : virtual void disable() PURE; 453 : 454 : /** 455 : * Enable accepting new connections. 456 : */ 457 : virtual void enable() PURE; 458 : 459 : /** 460 : * Set the fraction of incoming connections that will be closed immediately 461 : * after being opened. 462 : */ 463 : virtual void setRejectFraction(UnitFloat reject_fraction) PURE; 464 : 465 : /** 466 : * Configures the LoadShedPoints for this listener. 467 : */ 468 : virtual void 469 : configureLoadShedPoints(Server::LoadShedPointProvider& load_shed_point_provider) PURE; 470 : }; 471 : 472 : using ListenerPtr = std::unique_ptr<Listener>; 473 : 474 : /** 475 : * A UDP listener interface. 476 : */ 477 : class UdpListener : public virtual Listener { 478 : public: 479 91 : ~UdpListener() override = default; 480 : 481 : /** 482 : * @return Event::Dispatcher& the dispatcher backing this listener. 483 : */ 484 : virtual Event::Dispatcher& dispatcher() PURE; 485 : 486 : /** 487 : * @return the local address of the socket. 488 : */ 489 : virtual const Network::Address::InstanceConstSharedPtr& localAddress() const PURE; 490 : 491 : /** 492 : * Send data through the underlying udp socket. If the send buffer of the socket FD is full, an 493 : * error code is returned. 494 : * TODO(sumukhs): We do not currently handle max MTU size of the datagram. Determine if we could 495 : * expose the path MTU information to the caller. 496 : * 497 : * @param data Supplies the data to send to a target using udp. 498 : * @return the error code of the underlying send api. On successfully sending 'n' bytes, the 499 : * underlying buffers in the data are drained by 'n' bytes. The remaining can be retried by the 500 : * sender. 501 : */ 502 : virtual Api::IoCallUint64Result send(const UdpSendData& data) PURE; 503 : 504 : /** 505 : * Flushes out remaining buffered data since last call of send(). 506 : * This is a no-op if the implementation doesn't buffer data while sending. 507 : * 508 : * @return the error code of the underlying flush api. 509 : */ 510 : virtual Api::IoCallUint64Result flush() PURE; 511 : 512 : /** 513 : * Make this listener readable at the beginning of the next event loop. 514 : */ 515 : virtual void activateRead() PURE; 516 : }; 517 : 518 : using UdpListenerPtr = std::unique_ptr<UdpListener>; 519 : 520 : /** 521 : * Handles delivering datagrams to the correct worker. 522 : */ 523 : class UdpListenerWorkerRouter { 524 : public: 525 126 : virtual ~UdpListenerWorkerRouter() = default; 526 : 527 : /** 528 : * Registers a worker's callbacks for this listener. This worker must accept 529 : * packets until it calls ``unregisterWorker``. 530 : */ 531 : virtual void registerWorkerForListener(UdpListenerCallbacks& listener) PURE; 532 : 533 : /** 534 : * Unregisters a worker's callbacks for this listener. 535 : */ 536 : virtual void unregisterWorkerForListener(UdpListenerCallbacks& listener) PURE; 537 : 538 : /** 539 : * Deliver ``data`` to the correct worker by calling ``onDataWorker()`` 540 : * or ``post()`` on one of the registered workers. 541 : */ 542 : virtual void deliver(uint32_t dest_worker_index, UdpRecvData&& data) PURE; 543 : }; 544 : 545 : using UdpListenerWorkerRouterPtr = std::unique_ptr<UdpListenerWorkerRouter>; 546 : 547 : /** 548 : * Base class for all listener typed metadata factories. 549 : */ 550 : class ListenerTypedMetadataFactory : public Envoy::Config::TypedMetadataFactory {}; 551 : 552 : } // namespace Network 553 : } // namespace Envoy