summaryrefslogtreecommitdiffstats
path: root/libtransport/src/protocols/rtc.h
blob: 9f1bcc25bb36dac7b78f8dc71bcb6b83856488b6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
/*
 * Copyright (c) 2017-2019 Cisco and/or its affiTC_SYNC_STATE
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <protocols/datagram_reassembly.h>
#include <protocols/protocol.h>
#include <protocols/rtc_data_path.h>

#include <map>
#include <queue>
#include <unordered_map>

// algorithm state
#define HICN_RTC_SYNC_STATE 0
#define HICN_RTC_NORMAL_STATE 1
#define HICN_ROUNDS_IN_SYNC_BEFORE_SWITCH 3

// packet constants
#define HICN_INIT_PACKET_SIZE 1300       // bytes
#define HICN_PACKET_HEADER_SIZE 60       // bytes ipv6+tcp
#define HICN_NACK_HEADER_SIZE 8          // bytes
#define HICN_TIMESTAMP_SIZE 8            // bytes
#define HICN_RTC_INTEREST_LIFETIME 1000  // ms

// rtt measurement
// normal interests for data goes from 0 to
// HICN_MIN_PROBE_SEQ, the rest is reserverd for
// probes
#define HICN_MIN_PROBE_SEQ 0xefffffff
#define HICN_MAX_PROBE_SEQ 0xffffffff

// controller constant
#define HICN_ROUND_LEN \
  200  // ms interval of time on which
       // we take decisions / measurements
#define HICN_MAX_RTX 10
#define HICN_MAX_RTX_SIZE 1024
#define HICN_MAX_RTX_MAX_AGE 10000
#define HICN_MIN_RTT_WIN 30             // rounds
#define HICN_MIN_INTER_ARRIVAL_GAP 100  // ms

// cwin
#define HICN_INITIAL_CWIN 1           // packets
#define HICN_INITIAL_CWIN_MAX 100000  // packets
#define HICN_MIN_CWIN 10              // packets
#define HICN_WIN_INCREASE_FACTOR 1.5
#define HICN_WIN_DECREASE_FACTOR 0.9

// statistics constants
#define HICN_BANDWIDTH_SLACK_FACTOR 1.8
#define HICN_ESTIMATED_BW_ALPHA 0.7
#define HICN_ESTIMATED_PACKET_SIZE 0.7
#define HICN_ESTIMATED_LOSSES_ALPHA 0.8
#define HICN_INTEREST_LIFETIME_REDUCTION_FACTOR 0.8

// other constants
#define HICN_NANO_IN_A_SEC 1000000000
#define HICN_MICRO_IN_A_SEC 1000000
#define HICN_MILLI_IN_A_SEC 1000

namespace transport {

namespace protocol {

enum packetState { sent_, nacked_, received_, timeout1_, timeout2_, lost_ };

typedef enum packetState packetState_t;

struct sentInterest {
  uint64_t transmissionTime;
  uint32_t sequence;    // sequence number of the interest sent
                        // to handle seq % buffer_size
  packetState_t state;  // see packet state
};

class RTCTransportProtocol : public TransportProtocol,
                             public DatagramReassembly {
 public:
  RTCTransportProtocol(implementation::ConsumerSocket *icnet_socket);

  ~RTCTransportProtocol();

  using TransportProtocol::start;

  using TransportProtocol::stop;

  void resume() override;

  bool verifyKeyPackets() override;

 private:
  // algo functions
  void initParams();
  void reset() override;

  // CC functions
  void updateDelayStats(const ContentObject &content_object);
  void updateStats(uint32_t round_duration);
  void updateCCState();
  void computeMaxWindow(uint32_t productionRate, uint32_t BDPWin);
  void updateWindow();
  void decreaseWindow();
  void increaseWindow();
  void resetPreviousWindow();

  // packet functions
  void sendInterest(Name *interest_name, bool rtx);
  void scheduleNextInterests() override;
  void sentinelTimer();
  void addRetransmissions(uint32_t val);
  void addRetransmissions(uint32_t start, uint32_t stop);
  uint64_t retransmit();
  void checkRtx();
  void probeRtt();
  void newRound();
  void onTimeout(Interest::Ptr &&interest) override;
  bool onNack(const ContentObject &content_object, bool rtx);
  void onContentObject(Interest::Ptr &&interest,
                       ContentObject::Ptr &&content_object) override;
  void onPacketDropped(Interest::Ptr &&interest,
                       ContentObject::Ptr &&content_object) override {}
  void onReassemblyFailed(std::uint32_t missing_segment) override {}

  TRANSPORT_ALWAYS_INLINE virtual void reassemble(
      ContentObject::Ptr &&content_object) override {
    auto read_buffer = content_object->getPayload();
    read_buffer->trimStart(HICN_TIMESTAMP_SIZE);
    Reassembly::read_buffer_ = std::move(read_buffer);
    Reassembly::notifyApplication();
  }

  // controller var
  std::unique_ptr<asio::steady_timer> round_timer_;
  unsigned currentState_;

  // cwin var
  uint32_t currentCWin_;
  uint32_t maxCWin_;

  // names/packets var
  uint32_t actualSegment_;
  uint32_t inflightInterestsCount_;
  // map seq to rtx
  std::map<uint32_t, uint8_t> interestRetransmissions_;
  bool rtx_timer_used_;
  std::unique_ptr<asio::steady_timer> rtx_timer_;
  std::vector<sentInterest> inflightInterests_;
  uint32_t lastSegNacked_;     // indicates the segment id in the last received
                               // past Nack. we do not ask for retransmissions
                               // for samething that is older than this value.
  uint32_t lastReceived_;      // segment of the last content object received
                               // indicates the base of the window on the client
  uint64_t lastReceivedTime_;  // time at which we recevied the
                               // lastReceived_ packet

  // sentinel
  // if all packets in the window get lost we need something that
  // wakes up our consumer socket. Interest timeouts set to 1 sec
  // expire too late. This timers expire much sooner and if it
  // detects that all the interest in the window may be lost
  // it sends all of them again
  std::unique_ptr<asio::steady_timer> sentinel_timer_;
  uint64_t lastEvent_;  // time at which we removed a pending
                        // interest from the window
  std::unordered_map<uint32_t, uint8_t> packets_in_window_;

  // rtt probes
  // the RTC transport tends to overestimate the RTT
  // du to the production time on the server side
  // once per second we send an interest for wich we know
  // we will get a nack. This nack will keep our estimation
  // close to the reality
  std::unique_ptr<asio::steady_timer> probe_timer_;
  uint64_t time_sent_probe_;
  uint32_t probe_seq_number_;
  bool received_probe_;

  uint32_t modMask_;

  // stats
  bool firstPckReceived_;
  uint32_t receivedBytes_;
  uint32_t sentInterest_;
  uint32_t receivedData_;
  int32_t packetLost_;
  int32_t lossRecovered_;
  uint32_t firstSequenceInRound_;
  uint32_t highestReceived_;
  double avgPacketSize_;
  bool gotNack_;
  uint32_t gotFutureNack_;
  uint32_t rounds_;
  uint32_t roundsWithoutNacks_;

  // we keep track of up two paths (if only one path is in use
  // the two values in the vector will be the same)
  // position 0 stores the path with minRTT
  // position 1 stores the path with maxRTT
  uint32_t producerPathLabels_[2];

  std::unordered_map<uint32_t, std::shared_ptr<RTCDataPath>> pathTable_;
  uint32_t roundCounter_;

  // CC var
  double estimatedBw_;
  double lossRate_;
  double queuingDelay_;
  unsigned protocolState_;

  bool initied;
};

}  // namespace protocol

}  // namespace transport