Home | History | Annotate | Download | only in quic
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/quic/quic_connection_logger.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/callback.h"
      9 #include "base/metrics/histogram.h"
     10 #include "base/strings/string_number_conversions.h"
     11 #include "base/values.h"
     12 #include "net/base/net_log.h"
     13 
     14 namespace net {
     15 
     16 namespace {
     17 
     18 base::Value* NetLogQuicPacketCallback(const IPEndPoint* self_address,
     19                                       const IPEndPoint* peer_address,
     20                                       size_t packet_size,
     21                                       NetLog::LogLevel /* log_level */) {
     22   base::DictionaryValue* dict = new base::DictionaryValue();
     23   dict->SetString("self_address", self_address->ToString());
     24   dict->SetString("peer_address", peer_address->ToString());
     25   dict->SetInteger("size", packet_size);
     26   return dict;
     27 }
     28 
     29 base::Value* NetLogQuicPacketSentCallback(
     30     QuicPacketSequenceNumber sequence_number,
     31     EncryptionLevel level,
     32     size_t packet_size,
     33     int rv,
     34     NetLog::LogLevel /* log_level */) {
     35   base::DictionaryValue* dict = new base::DictionaryValue();
     36   dict->SetInteger("encryption_level", level);
     37   dict->SetString("packet_sequence_number",
     38                   base::Uint64ToString(sequence_number));
     39   dict->SetInteger("size", packet_size);
     40   if (rv < 0) {
     41     dict->SetInteger("net_error", rv);
     42   }
     43   return dict;
     44 }
     45 
     46 base::Value* NetLogQuicPacketHeaderCallback(const QuicPacketHeader* header,
     47                                             NetLog::LogLevel /* log_level */) {
     48   base::DictionaryValue* dict = new base::DictionaryValue();
     49   dict->SetString("guid",
     50                   base::Uint64ToString(header->public_header.guid));
     51   dict->SetInteger("reset_flag", header->public_header.reset_flag);
     52   dict->SetInteger("version_flag", header->public_header.version_flag);
     53   dict->SetString("packet_sequence_number",
     54                   base::Uint64ToString(header->packet_sequence_number));
     55   dict->SetInteger("entropy_flag", header->entropy_flag);
     56   dict->SetInteger("fec_flag", header->fec_flag);
     57   dict->SetInteger("fec_group", header->fec_group);
     58   return dict;
     59 }
     60 
     61 base::Value* NetLogQuicStreamFrameCallback(const QuicStreamFrame* frame,
     62                                            NetLog::LogLevel /* log_level */) {
     63   base::DictionaryValue* dict = new base::DictionaryValue();
     64   dict->SetInteger("stream_id", frame->stream_id);
     65   dict->SetBoolean("fin", frame->fin);
     66   dict->SetString("offset", base::Uint64ToString(frame->offset));
     67   dict->SetInteger("length", frame->data.length());
     68   return dict;
     69 }
     70 
     71 base::Value* NetLogQuicAckFrameCallback(const QuicAckFrame* frame,
     72                                         NetLog::LogLevel /* log_level */) {
     73   base::DictionaryValue* dict = new base::DictionaryValue();
     74   base::DictionaryValue* sent_info = new base::DictionaryValue();
     75   dict->Set("sent_info", sent_info);
     76   sent_info->SetString("least_unacked",
     77                        base::Uint64ToString(frame->sent_info.least_unacked));
     78   base::DictionaryValue* received_info = new base::DictionaryValue();
     79   dict->Set("received_info", received_info);
     80   received_info->SetString(
     81       "largest_observed",
     82       base::Uint64ToString(frame->received_info.largest_observed));
     83   base::ListValue* missing = new base::ListValue();
     84   received_info->Set("missing_packets", missing);
     85   const SequenceNumberSet& missing_packets =
     86       frame->received_info.missing_packets;
     87   for (SequenceNumberSet::const_iterator it = missing_packets.begin();
     88        it != missing_packets.end(); ++it) {
     89     missing->Append(new base::StringValue(base::Uint64ToString(*it)));
     90   }
     91   return dict;
     92 }
     93 
     94 base::Value* NetLogQuicCongestionFeedbackFrameCallback(
     95     const QuicCongestionFeedbackFrame* frame,
     96     NetLog::LogLevel /* log_level */) {
     97   base::DictionaryValue* dict = new base::DictionaryValue();
     98   switch (frame->type) {
     99     case kInterArrival: {
    100       dict->SetString("type", "InterArrival");
    101       dict->SetInteger("accumulated_number_of_lost_packets",
    102                        frame->inter_arrival.accumulated_number_of_lost_packets);
    103       base::ListValue* received = new base::ListValue();
    104       dict->Set("received_packets", received);
    105       for (TimeMap::const_iterator it =
    106                frame->inter_arrival.received_packet_times.begin();
    107            it != frame->inter_arrival.received_packet_times.end(); ++it) {
    108         std::string value = base::Uint64ToString(it->first) + "@" +
    109             base::Uint64ToString(it->second.ToDebuggingValue());
    110         received->Append(new base::StringValue(value));
    111       }
    112       break;
    113     }
    114     case kFixRate:
    115       dict->SetString("type", "FixRate");
    116       dict->SetInteger("bitrate_in_bytes_per_second",
    117                        frame->fix_rate.bitrate.ToBytesPerSecond());
    118       break;
    119     case kTCP:
    120       dict->SetString("type", "TCP");
    121       dict->SetInteger("accumulated_number_of_lost_packets",
    122                        frame->tcp.accumulated_number_of_lost_packets);
    123       dict->SetInteger("receive_window", frame->tcp.receive_window);
    124       break;
    125   }
    126 
    127   return dict;
    128 }
    129 
    130 base::Value* NetLogQuicRstStreamFrameCallback(
    131     const QuicRstStreamFrame* frame,
    132     NetLog::LogLevel /* log_level */) {
    133   base::DictionaryValue* dict = new base::DictionaryValue();
    134   dict->SetInteger("stream_id", frame->stream_id);
    135   dict->SetInteger("quic_rst_stream_error", frame->error_code);
    136   dict->SetString("details", frame->error_details);
    137   return dict;
    138 }
    139 
    140 base::Value* NetLogQuicConnectionCloseFrameCallback(
    141     const QuicConnectionCloseFrame* frame,
    142     NetLog::LogLevel /* log_level */) {
    143   base::DictionaryValue* dict = new base::DictionaryValue();
    144   dict->SetInteger("quic_error", frame->error_code);
    145   dict->SetString("details", frame->error_details);
    146   return dict;
    147 }
    148 
    149 void UpdatePacketGapSentHistogram(size_t num_consecutive_missing_packets) {
    150   UMA_HISTOGRAM_COUNTS("Net.QuicSession.PacketGapSent",
    151                        num_consecutive_missing_packets);
    152 }
    153 
    154 }  // namespace
    155 
    156 QuicConnectionLogger::QuicConnectionLogger(const BoundNetLog& net_log)
    157     : net_log_(net_log),
    158       last_received_packet_sequence_number_(0),
    159       largest_received_packet_sequence_number_(0),
    160       largest_received_missing_packet_sequence_number_(0),
    161       out_of_order_recieved_packet_count_(0) {
    162 }
    163 
    164 QuicConnectionLogger::~QuicConnectionLogger() {
    165   UMA_HISTOGRAM_COUNTS("Net.QuicSession.OutOfOrderPacketsReceived",
    166                        out_of_order_recieved_packet_count_);
    167 }
    168 
    169 void QuicConnectionLogger::OnFrameAddedToPacket(const QuicFrame& frame) {
    170   switch (frame.type) {
    171     case PADDING_FRAME:
    172       break;
    173     case STREAM_FRAME:
    174       net_log_.AddEvent(
    175           NetLog::TYPE_QUIC_SESSION_STREAM_FRAME_SENT,
    176           base::Bind(&NetLogQuicStreamFrameCallback, frame.stream_frame));
    177       break;
    178     case ACK_FRAME:
    179       net_log_.AddEvent(
    180           NetLog::TYPE_QUIC_SESSION_ACK_FRAME_SENT,
    181           base::Bind(&NetLogQuicAckFrameCallback, frame.ack_frame));
    182       break;
    183     case CONGESTION_FEEDBACK_FRAME:
    184       net_log_.AddEvent(
    185           NetLog::TYPE_QUIC_SESSION_CONGESTION_FEEDBACK_FRAME_SENT,
    186           base::Bind(&NetLogQuicCongestionFeedbackFrameCallback,
    187                      frame.congestion_feedback_frame));
    188       break;
    189     case RST_STREAM_FRAME:
    190       net_log_.AddEvent(
    191           NetLog::TYPE_QUIC_SESSION_RST_STREAM_FRAME_SENT,
    192           base::Bind(&NetLogQuicRstStreamFrameCallback,
    193                      frame.rst_stream_frame));
    194       break;
    195     case CONNECTION_CLOSE_FRAME:
    196       net_log_.AddEvent(
    197           NetLog::TYPE_QUIC_SESSION_CONNECTION_CLOSE_FRAME_SENT,
    198           base::Bind(&NetLogQuicConnectionCloseFrameCallback,
    199                      frame.connection_close_frame));
    200       break;
    201     case GOAWAY_FRAME:
    202       break;
    203     default:
    204       DCHECK(false) << "Illegal frame type: " << frame.type;
    205   }
    206 }
    207 
    208 void QuicConnectionLogger::OnPacketSent(
    209     QuicPacketSequenceNumber sequence_number,
    210     EncryptionLevel level,
    211     const QuicEncryptedPacket& packet,
    212     int rv) {
    213   net_log_.AddEvent(
    214       NetLog::TYPE_QUIC_SESSION_PACKET_SENT,
    215       base::Bind(&NetLogQuicPacketSentCallback, sequence_number, level,
    216                  packet.length(), rv));
    217 }
    218 
    219 void QuicConnectionLogger::OnPacketReceived(const IPEndPoint& self_address,
    220                                             const IPEndPoint& peer_address,
    221                                             const QuicEncryptedPacket& packet) {
    222   net_log_.AddEvent(
    223       NetLog::TYPE_QUIC_SESSION_PACKET_RECEIVED,
    224       base::Bind(&NetLogQuicPacketCallback, &self_address, &peer_address,
    225                  packet.length()));
    226 }
    227 
    228 void QuicConnectionLogger::OnProtocolVersionMismatch(
    229     QuicVersion received_version) {
    230   // TODO(rtenneti): Add logging.
    231 }
    232 
    233 void QuicConnectionLogger::OnPacketHeader(const QuicPacketHeader& header) {
    234   net_log_.AddEvent(
    235       NetLog::TYPE_QUIC_SESSION_PACKET_HEADER_RECEIVED,
    236       base::Bind(&NetLogQuicPacketHeaderCallback, &header));
    237   if (largest_received_packet_sequence_number_ <
    238       header.packet_sequence_number) {
    239     QuicPacketSequenceNumber delta = header.packet_sequence_number -
    240         largest_received_packet_sequence_number_;
    241     if (delta > 1) {
    242       // There is a gap between the largest packet previously received and
    243       // the current packet.  This indicates either loss, or out-of-order
    244       // delivery.
    245       UMA_HISTOGRAM_COUNTS("Net.QuicSession.PacketGapReceived", delta - 1);
    246     }
    247     largest_received_packet_sequence_number_ = header.packet_sequence_number;
    248   }
    249   if (header.packet_sequence_number < last_received_packet_sequence_number_) {
    250     ++out_of_order_recieved_packet_count_;
    251   }
    252   last_received_packet_sequence_number_ = header.packet_sequence_number;
    253 }
    254 
    255 void QuicConnectionLogger::OnStreamFrame(const QuicStreamFrame& frame) {
    256   net_log_.AddEvent(
    257       NetLog::TYPE_QUIC_SESSION_STREAM_FRAME_RECEIVED,
    258       base::Bind(&NetLogQuicStreamFrameCallback, &frame));
    259 }
    260 
    261 void QuicConnectionLogger::OnAckFrame(const QuicAckFrame& frame) {
    262   net_log_.AddEvent(
    263       NetLog::TYPE_QUIC_SESSION_ACK_FRAME_RECEIVED,
    264       base::Bind(&NetLogQuicAckFrameCallback, &frame));
    265 
    266   if (frame.received_info.missing_packets.empty())
    267     return;
    268 
    269   SequenceNumberSet missing_packets = frame.received_info.missing_packets;
    270   SequenceNumberSet::const_iterator it = missing_packets.lower_bound(
    271       largest_received_missing_packet_sequence_number_);
    272   if (it == missing_packets.end())
    273     return;
    274 
    275   if (*it == largest_received_missing_packet_sequence_number_) {
    276     ++it;
    277     if (it == missing_packets.end())
    278       return;
    279   }
    280   // Scan through the list and log consecutive ranges of missing packets.
    281   size_t num_consecutive_missing_packets = 0;
    282   QuicPacketSequenceNumber previous_missing_packet = *it - 1;
    283   while (it != missing_packets.end()) {
    284     if (previous_missing_packet == *it - 1) {
    285       ++num_consecutive_missing_packets;
    286     } else {
    287       DCHECK_NE(0u, num_consecutive_missing_packets);
    288       UpdatePacketGapSentHistogram(num_consecutive_missing_packets);
    289       // Make sure this packet it included in the count.
    290       num_consecutive_missing_packets = 1;
    291     }
    292     previous_missing_packet = *it;
    293     ++it;
    294   }
    295   if (num_consecutive_missing_packets != 0) {
    296     UpdatePacketGapSentHistogram(num_consecutive_missing_packets);
    297   }
    298   largest_received_missing_packet_sequence_number_ =
    299         *missing_packets.rbegin();
    300 }
    301 
    302 void QuicConnectionLogger::OnCongestionFeedbackFrame(
    303     const QuicCongestionFeedbackFrame& frame) {
    304   net_log_.AddEvent(
    305       NetLog::TYPE_QUIC_SESSION_CONGESTION_FEEDBACK_FRAME_RECEIVED,
    306       base::Bind(&NetLogQuicCongestionFeedbackFrameCallback, &frame));
    307 }
    308 
    309 void QuicConnectionLogger::OnRstStreamFrame(const QuicRstStreamFrame& frame) {
    310   net_log_.AddEvent(
    311       NetLog::TYPE_QUIC_SESSION_RST_STREAM_FRAME_RECEIVED,
    312       base::Bind(&NetLogQuicRstStreamFrameCallback, &frame));
    313 }
    314 
    315 void QuicConnectionLogger::OnConnectionCloseFrame(
    316     const QuicConnectionCloseFrame& frame) {
    317   net_log_.AddEvent(
    318       NetLog::TYPE_QUIC_SESSION_CONNECTION_CLOSE_FRAME_RECEIVED,
    319       base::Bind(&NetLogQuicConnectionCloseFrameCallback, &frame));
    320 }
    321 
    322 void QuicConnectionLogger::OnPublicResetPacket(
    323     const QuicPublicResetPacket& packet) {
    324 }
    325 
    326 void QuicConnectionLogger::OnVersionNegotiationPacket(
    327     const QuicVersionNegotiationPacket& packet) {
    328 }
    329 
    330 void QuicConnectionLogger::OnRevivedPacket(
    331     const QuicPacketHeader& revived_header,
    332     base::StringPiece payload) {
    333 }
    334 
    335 }  // namespace net
    336