summaryrefslogtreecommitdiffstats
path: root/libtransport/src/protocols/rtc/congestion_detection.cc
blob: e2d44ae66d895efd0d8e1c751df7e715524b2dfe (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
/*
 * Copyright (c) 2017-2019 Cisco and/or its affiliates.
 * 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.
 */

#include <hicn/transport/utils/log.h>
#include <protocols/rtc/congestion_detection.h>

namespace transport {

namespace protocol {

namespace rtc {

CongestionDetection::CongestionDetection()
    : cc_estimator_(), last_processed_chunk_() {}

CongestionDetection::~CongestionDetection() {}

void CongestionDetection::updateStats() {
  uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
                     std::chrono::steady_clock::now().time_since_epoch())
                     .count();

  if (chunks_number_.empty()) return;

  uint32_t chunk_number = chunks_number_.front();

  while (chunks_[chunk_number].getReceivedTime() + HICN_CC_STATS_MAX_DELAY_MS <
             now ||
         chunks_[chunk_number].isComplete()) {
    if (chunk_number == last_processed_chunk_.getFrameSeqNum() + 1) {
      chunks_[chunk_number].setPreviousSentTime(
          last_processed_chunk_.getSentTime());

      chunks_[chunk_number].setPreviousReceivedTime(
          last_processed_chunk_.getReceivedTime());
      cc_estimator_.Update(chunks_[chunk_number].getReceivedDelta(),
                           chunks_[chunk_number].getSentDelta(),
                           chunks_[chunk_number].getSentTime(),
                           chunks_[chunk_number].getReceivedTime(),
                           chunks_[chunk_number].getFrameSize(), true);

    } else {
      TRANSPORT_LOGD(
          "CongestionDetection::updateStats frame %u but not the \
      previous one, last one was %u currentFrame %u",
          chunk_number, last_processed_chunk_.getFrameSeqNum(),
          chunks_[chunk_number].getFrameSeqNum());
    }

    last_processed_chunk_ = chunks_[chunk_number];

    chunks_.erase(chunk_number);

    chunks_number_.pop();
    if (chunks_number_.empty()) break;

    chunk_number = chunks_number_.front();
  }
}

void CongestionDetection::addPacket(const core::ContentObject &content_object) {
  auto payload = content_object.getPayload();
  uint32_t payload_size = (uint32_t)payload->length();
  uint32_t segmentNumber = content_object.getName().getSuffix();
  // uint32_t pkt = segmentNumber & modMask_;
  uint64_t *sentTimePtr = (uint64_t *)payload->data();

  // this is just for testing with hiperf, assuming a frame is 10 pkts
  // in the final version, the split should be based on the timestamp in the pkt
  uint32_t frameNum = (int)(segmentNumber / HICN_CC_STATS_CHUNK_SIZE);
  uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
                     std::chrono::steady_clock::now().time_since_epoch())
                     .count();

  if (chunks_.find(frameNum) == chunks_.end()) {
    // new chunk of pkts or out of order
    if (last_processed_chunk_.getFrameSeqNum() > frameNum)
      return;  // out of order and we already processed the chunk

    chunks_[frameNum] = FrameStats(frameNum, HICN_CC_STATS_CHUNK_SIZE);
    chunks_number_.push(frameNum);
  }

  chunks_[frameNum].addPacket(*sentTimePtr, now, payload_size);
}

}  // namespace rtc
}  // namespace protocol
}  // namespace transport