• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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