1 // 2 // 3 // Copyright 2018 gRPC authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // 17 // 18 19 #ifndef GRPC_SRC_CORE_LIB_IOMGR_BUFFER_LIST_H 20 #define GRPC_SRC_CORE_LIB_IOMGR_BUFFER_LIST_H 21 22 #include <grpc/support/port_platform.h> 23 #include <grpc/support/time.h> 24 25 #include "absl/types/optional.h" 26 #include "src/core/lib/iomgr/error.h" 27 #include "src/core/lib/iomgr/internal_errqueue.h" 28 #include "src/core/lib/iomgr/port.h" 29 #include "src/core/util/sync.h" 30 31 namespace grpc_core { 32 33 struct ConnectionMetrics { 34 // Delivery rate in Bytes/s. 35 absl::optional<uint64_t> delivery_rate; 36 // If the delivery rate is limited by the application, this is set to true. 37 absl::optional<bool> is_delivery_rate_app_limited; 38 // Total packets retransmitted. 39 absl::optional<uint32_t> packet_retx; 40 // Total packets retransmitted spuriously. This metric is smaller than or 41 // equal to packet_retx. 42 absl::optional<uint32_t> packet_spurious_retx; 43 // Total packets sent. 44 absl::optional<uint32_t> packet_sent; 45 // Total packets delivered. 46 absl::optional<uint32_t> packet_delivered; 47 // Total packets delivered with ECE marked. This metric is smaller than or 48 // equal to packet_delivered. 49 absl::optional<uint32_t> packet_delivered_ce; 50 // Total bytes lost so far. 51 absl::optional<uint64_t> data_retx; 52 // Total bytes sent so far. 53 absl::optional<uint64_t> data_sent; 54 // Total bytes in write queue but not sent. 55 absl::optional<uint64_t> data_notsent; 56 // Pacing rate of the connection in Bps 57 absl::optional<uint64_t> pacing_rate; 58 // Minimum RTT observed in usec. 59 absl::optional<uint32_t> min_rtt; 60 // Smoothed RTT in usec 61 absl::optional<uint32_t> srtt; 62 // Send congestion window. 63 absl::optional<uint32_t> congestion_window; 64 // Slow start threshold in packets. 65 absl::optional<uint32_t> snd_ssthresh; 66 // Maximum degree of reordering (i.e., maximum number of packets reodered) 67 // on the connection. 68 absl::optional<uint32_t> reordering; 69 // Represents the number of recurring retransmissions of the first sequence 70 // that is not acknowledged yet. 71 absl::optional<uint8_t> recurring_retrans; 72 // The cumulative time (in usec) that the transport protocol was busy 73 // sending data. 74 absl::optional<uint64_t> busy_usec; 75 // The cumulative time (in usec) that the transport protocol was limited by 76 // the receive window size. 77 absl::optional<uint64_t> rwnd_limited_usec; 78 // The cumulative time (in usec) that the transport protocol was limited by 79 // the send buffer size. 80 absl::optional<uint64_t> sndbuf_limited_usec; 81 }; 82 83 struct BufferTimestamp { 84 gpr_timespec time; 85 ConnectionMetrics metrics; // Metrics collected with this timestamp 86 }; 87 88 struct Timestamps { 89 BufferTimestamp sendmsg_time; 90 BufferTimestamp scheduled_time; 91 BufferTimestamp sent_time; 92 BufferTimestamp acked_time; 93 94 uint32_t byte_offset; // byte offset relative to the start of the RPC 95 96 #ifdef GRPC_LINUX_ERRQUEUE 97 tcp_info info; // tcp_info collected on sendmsg 98 #endif // GRPC_LINUX_ERRQUEUE 99 }; 100 101 // TracedBuffer is a class to keep track of timestamps for a specific buffer in 102 // the TCP layer. We are only tracking timestamps for Linux kernels and hence 103 // this class would only be used by Linux platforms. For all other platforms, 104 // TracedBuffer would be an empty class. 105 // The timestamps collected are according to Timestamps declared above A 106 // TracedBuffer list is kept track of using the head element of the list. If 107 // *the head element of the list is nullptr, then the list is empty. 108 #ifdef GRPC_LINUX_ERRQUEUE 109 110 class TracedBufferList { 111 public: 112 TracedBufferList() = default; 113 ~TracedBufferList() = default; 114 // Add a new entry in the TracedBuffer list pointed to by head. Also saves 115 // sendmsg_time with the current timestamp. 116 void AddNewEntry(int32_t seq_no, int fd, void* arg); 117 // Processes a received timestamp based on sock_extended_err and 118 // scm_timestamping structures. It will invoke the timestamps callback if the 119 // timestamp type is SCM_TSTAMP_ACK. 120 void ProcessTimestamp(struct sock_extended_err* serr, 121 struct cmsghdr* opt_stats, 122 struct scm_timestamping* tss); 123 // The Size() operation is slow and is used only in tests. Size()124 int Size() { 125 MutexLock lock(&mu_); 126 int size = 0; 127 TracedBuffer* curr = head_; 128 while (curr) { 129 ++size; 130 curr = curr->next_; 131 } 132 return size; 133 } 134 // Cleans the list by calling the callback for each traced buffer in the list 135 // with timestamps that it has. 136 void Shutdown(void* /*remaining*/, absl::Status /*shutdown_err*/); 137 138 private: 139 class TracedBuffer { 140 public: TracedBuffer(uint32_t seq_no,void * arg)141 TracedBuffer(uint32_t seq_no, void* arg) : seq_no_(seq_no), arg_(arg) {} 142 143 bool Finished(gpr_timespec ts); 144 145 private: 146 friend class TracedBufferList; 147 gpr_timespec last_timestamp_; 148 TracedBuffer* next_ = nullptr; 149 uint32_t seq_no_; // The sequence number for the last byte in the buffer 150 void* arg_; // The arg to pass to timestamps_callback 151 Timestamps ts_; // The timestamps corresponding to this buffer 152 }; 153 Mutex mu_; 154 // TracedBuffers are ordered by sequence number and would need to be processed 155 // in a FIFO order starting with the smallest sequence number. To enable this, 156 // they are stored in a singly linked with head and tail pointers which allows 157 // easy appends and forward iteration operations. 158 TracedBuffer* head_ = nullptr; 159 TracedBuffer* tail_ = nullptr; 160 }; 161 162 #else // GRPC_LINUX_ERRQUEUE 163 // TracedBufferList implementation is a no-op for this platform. 164 class TracedBufferList { 165 public: AddNewEntry(int32_t,int,void *)166 void AddNewEntry(int32_t /*seq_no*/, int /*fd*/, void* /*arg*/) {} ProcessTimestamp(struct sock_extended_err *,struct cmsghdr *,struct scm_timestamping *)167 void ProcessTimestamp(struct sock_extended_err* /*serr*/, 168 struct cmsghdr* /*opt_stats*/, 169 struct scm_timestamping* /*tss*/) {} Size()170 int Size() { return 0; } Shutdown(void *,absl::Status)171 void Shutdown(void* /*remaining*/, absl::Status /*shutdown_err*/) {} 172 }; 173 #endif // GRPC_LINUX_ERRQUEUE 174 175 /// Sets the callback function to call when timestamps for a write are 176 /// collected. The callback does not own a reference to error. 177 void grpc_tcp_set_write_timestamps_callback( 178 void (*fn)(void*, Timestamps*, grpc_error_handle error)); 179 180 } // namespace grpc_core 181 182 #endif // GRPC_SRC_CORE_LIB_IOMGR_BUFFER_LIST_H 183