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/metrics/sparse_histogram.h"
     11 #include "base/strings/string_number_conversions.h"
     12 #include "base/values.h"
     13 #include "net/base/net_log.h"
     14 #include "net/quic/crypto/crypto_handshake.h"
     15 
     16 using std::string;
     17 
     18 namespace net {
     19 
     20 namespace {
     21 
     22 base::Value* NetLogQuicPacketCallback(const IPEndPoint* self_address,
     23                                       const IPEndPoint* peer_address,
     24                                       size_t packet_size,
     25                                       NetLog::LogLevel /* log_level */) {
     26   base::DictionaryValue* dict = new base::DictionaryValue();
     27   dict->SetString("self_address", self_address->ToString());
     28   dict->SetString("peer_address", peer_address->ToString());
     29   dict->SetInteger("size", packet_size);
     30   return dict;
     31 }
     32 
     33 base::Value* NetLogQuicPacketSentCallback(
     34     QuicPacketSequenceNumber sequence_number,
     35     EncryptionLevel level,
     36     size_t packet_size,
     37     WriteResult result,
     38     NetLog::LogLevel /* log_level */) {
     39   base::DictionaryValue* dict = new base::DictionaryValue();
     40   dict->SetInteger("encryption_level", level);
     41   dict->SetString("packet_sequence_number",
     42                   base::Uint64ToString(sequence_number));
     43   dict->SetInteger("size", packet_size);
     44   if (result.status != WRITE_STATUS_OK) {
     45     dict->SetInteger("net_error", result.error_code);
     46   }
     47   return dict;
     48 }
     49 
     50 base::Value* NetLogQuicPacketRetransmittedCallback(
     51     QuicPacketSequenceNumber old_sequence_number,
     52     QuicPacketSequenceNumber new_sequence_number,
     53     NetLog::LogLevel /* log_level */) {
     54  base::DictionaryValue* dict = new base::DictionaryValue();
     55  dict->SetString("old_packet_sequence_number",
     56                  base::Uint64ToString(old_sequence_number));
     57  dict->SetString("new_packet_sequence_number",
     58                  base::Uint64ToString(new_sequence_number));
     59  return dict;
     60 }
     61 
     62 base::Value* NetLogQuicPacketHeaderCallback(const QuicPacketHeader* header,
     63                                             NetLog::LogLevel /* log_level */) {
     64   base::DictionaryValue* dict = new base::DictionaryValue();
     65   dict->SetString("guid",
     66                   base::Uint64ToString(header->public_header.guid));
     67   dict->SetInteger("reset_flag", header->public_header.reset_flag);
     68   dict->SetInteger("version_flag", header->public_header.version_flag);
     69   dict->SetString("packet_sequence_number",
     70                   base::Uint64ToString(header->packet_sequence_number));
     71   dict->SetInteger("entropy_flag", header->entropy_flag);
     72   dict->SetInteger("fec_flag", header->fec_flag);
     73   dict->SetInteger("fec_group", header->fec_group);
     74   return dict;
     75 }
     76 
     77 base::Value* NetLogQuicStreamFrameCallback(const QuicStreamFrame* frame,
     78                                            NetLog::LogLevel /* log_level */) {
     79   base::DictionaryValue* dict = new base::DictionaryValue();
     80   dict->SetInteger("stream_id", frame->stream_id);
     81   dict->SetBoolean("fin", frame->fin);
     82   dict->SetString("offset", base::Uint64ToString(frame->offset));
     83   dict->SetInteger("length", frame->data.TotalBufferSize());
     84   return dict;
     85 }
     86 
     87 base::Value* NetLogQuicAckFrameCallback(const QuicAckFrame* frame,
     88                                         NetLog::LogLevel /* log_level */) {
     89   base::DictionaryValue* dict = new base::DictionaryValue();
     90   base::DictionaryValue* sent_info = new base::DictionaryValue();
     91   dict->Set("sent_info", sent_info);
     92   sent_info->SetString("least_unacked",
     93                        base::Uint64ToString(frame->sent_info.least_unacked));
     94   base::DictionaryValue* received_info = new base::DictionaryValue();
     95   dict->Set("received_info", received_info);
     96   received_info->SetString(
     97       "largest_observed",
     98       base::Uint64ToString(frame->received_info.largest_observed));
     99   base::ListValue* missing = new base::ListValue();
    100   received_info->Set("missing_packets", missing);
    101   const SequenceNumberSet& missing_packets =
    102       frame->received_info.missing_packets;
    103   for (SequenceNumberSet::const_iterator it = missing_packets.begin();
    104        it != missing_packets.end(); ++it) {
    105     missing->AppendString(base::Uint64ToString(*it));
    106   }
    107   return dict;
    108 }
    109 
    110 base::Value* NetLogQuicCongestionFeedbackFrameCallback(
    111     const QuicCongestionFeedbackFrame* frame,
    112     NetLog::LogLevel /* log_level */) {
    113   base::DictionaryValue* dict = new base::DictionaryValue();
    114   switch (frame->type) {
    115     case kInterArrival: {
    116       dict->SetString("type", "InterArrival");
    117       dict->SetInteger("accumulated_number_of_lost_packets",
    118                        frame->inter_arrival.accumulated_number_of_lost_packets);
    119       base::ListValue* received = new base::ListValue();
    120       dict->Set("received_packets", received);
    121       for (TimeMap::const_iterator it =
    122                frame->inter_arrival.received_packet_times.begin();
    123            it != frame->inter_arrival.received_packet_times.end(); ++it) {
    124         std::string value = base::Uint64ToString(it->first) + "@" +
    125             base::Uint64ToString(it->second.ToDebuggingValue());
    126         received->AppendString(value);
    127       }
    128       break;
    129     }
    130     case kFixRate:
    131       dict->SetString("type", "FixRate");
    132       dict->SetInteger("bitrate_in_bytes_per_second",
    133                        frame->fix_rate.bitrate.ToBytesPerSecond());
    134       break;
    135     case kTCP:
    136       dict->SetString("type", "TCP");
    137       dict->SetInteger("accumulated_number_of_lost_packets",
    138                        frame->tcp.accumulated_number_of_lost_packets);
    139       dict->SetInteger("receive_window", frame->tcp.receive_window);
    140       break;
    141   }
    142 
    143   return dict;
    144 }
    145 
    146 base::Value* NetLogQuicRstStreamFrameCallback(
    147     const QuicRstStreamFrame* frame,
    148     NetLog::LogLevel /* log_level */) {
    149   base::DictionaryValue* dict = new base::DictionaryValue();
    150   dict->SetInteger("stream_id", frame->stream_id);
    151   dict->SetInteger("quic_rst_stream_error", frame->error_code);
    152   dict->SetString("details", frame->error_details);
    153   return dict;
    154 }
    155 
    156 base::Value* NetLogQuicConnectionCloseFrameCallback(
    157     const QuicConnectionCloseFrame* frame,
    158     NetLog::LogLevel /* log_level */) {
    159   base::DictionaryValue* dict = new base::DictionaryValue();
    160   dict->SetInteger("quic_error", frame->error_code);
    161   dict->SetString("details", frame->error_details);
    162   return dict;
    163 }
    164 
    165 base::Value* NetLogQuicVersionNegotiationPacketCallback(
    166     const QuicVersionNegotiationPacket* packet,
    167     NetLog::LogLevel /* log_level */) {
    168   base::DictionaryValue* dict = new base::DictionaryValue();
    169   base::ListValue* versions = new base::ListValue();
    170   dict->Set("versions", versions);
    171   for (QuicVersionVector::const_iterator it = packet->versions.begin();
    172        it != packet->versions.end(); ++it) {
    173     versions->AppendString(QuicVersionToString(*it));
    174   }
    175   return dict;
    176 }
    177 
    178 base::Value* NetLogQuicCryptoHandshakeMessageCallback(
    179     const CryptoHandshakeMessage* message,
    180     NetLog::LogLevel /* log_level */) {
    181   base::DictionaryValue* dict = new base::DictionaryValue();
    182   dict->SetString("quic_crypto_handshake_message", message->DebugString());
    183   return dict;
    184 }
    185 
    186 base::Value* NetLogQuicOnConnectionClosedCallback(
    187     QuicErrorCode error,
    188     bool from_peer,
    189     NetLog::LogLevel /* log_level */) {
    190   base::DictionaryValue* dict = new base::DictionaryValue();
    191   dict->SetInteger("quic_error", error);
    192   dict->SetBoolean("from_peer", from_peer);
    193   return dict;
    194 }
    195 
    196 void UpdatePacketGapSentHistogram(size_t num_consecutive_missing_packets) {
    197   UMA_HISTOGRAM_COUNTS("Net.QuicSession.PacketGapSent",
    198                        num_consecutive_missing_packets);
    199 }
    200 
    201 }  // namespace
    202 
    203 QuicConnectionLogger::QuicConnectionLogger(const BoundNetLog& net_log)
    204     : net_log_(net_log),
    205       last_received_packet_sequence_number_(0),
    206       largest_received_packet_sequence_number_(0),
    207       largest_received_missing_packet_sequence_number_(0),
    208       out_of_order_recieved_packet_count_(0) {
    209 }
    210 
    211 QuicConnectionLogger::~QuicConnectionLogger() {
    212   UMA_HISTOGRAM_COUNTS("Net.QuicSession.OutOfOrderPacketsReceived",
    213                        out_of_order_recieved_packet_count_);
    214 }
    215 
    216 void QuicConnectionLogger::OnFrameAddedToPacket(const QuicFrame& frame) {
    217   switch (frame.type) {
    218     case PADDING_FRAME:
    219       break;
    220     case STREAM_FRAME:
    221       net_log_.AddEvent(
    222           NetLog::TYPE_QUIC_SESSION_STREAM_FRAME_SENT,
    223           base::Bind(&NetLogQuicStreamFrameCallback, frame.stream_frame));
    224       break;
    225     case ACK_FRAME:
    226       net_log_.AddEvent(
    227           NetLog::TYPE_QUIC_SESSION_ACK_FRAME_SENT,
    228           base::Bind(&NetLogQuicAckFrameCallback, frame.ack_frame));
    229       break;
    230     case CONGESTION_FEEDBACK_FRAME:
    231       net_log_.AddEvent(
    232           NetLog::TYPE_QUIC_SESSION_CONGESTION_FEEDBACK_FRAME_SENT,
    233           base::Bind(&NetLogQuicCongestionFeedbackFrameCallback,
    234                      frame.congestion_feedback_frame));
    235       break;
    236     case RST_STREAM_FRAME:
    237       UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.RstStreamErrorCodeClient",
    238                                   frame.rst_stream_frame->error_code);
    239       net_log_.AddEvent(
    240           NetLog::TYPE_QUIC_SESSION_RST_STREAM_FRAME_SENT,
    241           base::Bind(&NetLogQuicRstStreamFrameCallback,
    242                      frame.rst_stream_frame));
    243       break;
    244     case CONNECTION_CLOSE_FRAME:
    245       net_log_.AddEvent(
    246           NetLog::TYPE_QUIC_SESSION_CONNECTION_CLOSE_FRAME_SENT,
    247           base::Bind(&NetLogQuicConnectionCloseFrameCallback,
    248                      frame.connection_close_frame));
    249       break;
    250     case GOAWAY_FRAME:
    251       break;
    252     default:
    253       DCHECK(false) << "Illegal frame type: " << frame.type;
    254   }
    255 }
    256 
    257 void QuicConnectionLogger::OnPacketSent(
    258     QuicPacketSequenceNumber sequence_number,
    259     EncryptionLevel level,
    260     const QuicEncryptedPacket& packet,
    261     WriteResult result) {
    262   net_log_.AddEvent(
    263       NetLog::TYPE_QUIC_SESSION_PACKET_SENT,
    264       base::Bind(&NetLogQuicPacketSentCallback, sequence_number, level,
    265                  packet.length(), result));
    266 }
    267 
    268 void QuicConnectionLogger:: OnPacketRetransmitted(
    269       QuicPacketSequenceNumber old_sequence_number,
    270       QuicPacketSequenceNumber new_sequence_number) {
    271   net_log_.AddEvent(
    272       NetLog::TYPE_QUIC_SESSION_PACKET_RETRANSMITTED,
    273       base::Bind(&NetLogQuicPacketRetransmittedCallback,
    274                  old_sequence_number, new_sequence_number));
    275 }
    276 
    277 void QuicConnectionLogger::OnPacketReceived(const IPEndPoint& self_address,
    278                                             const IPEndPoint& peer_address,
    279                                             const QuicEncryptedPacket& packet) {
    280   net_log_.AddEvent(
    281       NetLog::TYPE_QUIC_SESSION_PACKET_RECEIVED,
    282       base::Bind(&NetLogQuicPacketCallback, &self_address, &peer_address,
    283                  packet.length()));
    284 }
    285 
    286 void QuicConnectionLogger::OnProtocolVersionMismatch(
    287     QuicVersion received_version) {
    288   // TODO(rtenneti): Add logging.
    289 }
    290 
    291 void QuicConnectionLogger::OnPacketHeader(const QuicPacketHeader& header) {
    292   net_log_.AddEvent(
    293       NetLog::TYPE_QUIC_SESSION_PACKET_HEADER_RECEIVED,
    294       base::Bind(&NetLogQuicPacketHeaderCallback, &header));
    295   if (largest_received_packet_sequence_number_ <
    296       header.packet_sequence_number) {
    297     QuicPacketSequenceNumber delta = header.packet_sequence_number -
    298         largest_received_packet_sequence_number_;
    299     if (delta > 1) {
    300       // There is a gap between the largest packet previously received and
    301       // the current packet.  This indicates either loss, or out-of-order
    302       // delivery.
    303       UMA_HISTOGRAM_COUNTS("Net.QuicSession.PacketGapReceived", delta - 1);
    304     }
    305     largest_received_packet_sequence_number_ = header.packet_sequence_number;
    306   }
    307   if (header.packet_sequence_number < last_received_packet_sequence_number_) {
    308     ++out_of_order_recieved_packet_count_;
    309     UMA_HISTOGRAM_COUNTS("Net.QuicSession.OutOfOrderGapReceived",
    310                          last_received_packet_sequence_number_ -
    311                              header.packet_sequence_number);
    312   }
    313   last_received_packet_sequence_number_ = header.packet_sequence_number;
    314 }
    315 
    316 void QuicConnectionLogger::OnStreamFrame(const QuicStreamFrame& frame) {
    317   net_log_.AddEvent(
    318       NetLog::TYPE_QUIC_SESSION_STREAM_FRAME_RECEIVED,
    319       base::Bind(&NetLogQuicStreamFrameCallback, &frame));
    320 }
    321 
    322 void QuicConnectionLogger::OnAckFrame(const QuicAckFrame& frame) {
    323   net_log_.AddEvent(
    324       NetLog::TYPE_QUIC_SESSION_ACK_FRAME_RECEIVED,
    325       base::Bind(&NetLogQuicAckFrameCallback, &frame));
    326 
    327   if (frame.received_info.missing_packets.empty())
    328     return;
    329 
    330   SequenceNumberSet missing_packets = frame.received_info.missing_packets;
    331   SequenceNumberSet::const_iterator it = missing_packets.lower_bound(
    332       largest_received_missing_packet_sequence_number_);
    333   if (it == missing_packets.end())
    334     return;
    335 
    336   if (*it == largest_received_missing_packet_sequence_number_) {
    337     ++it;
    338     if (it == missing_packets.end())
    339       return;
    340   }
    341   // Scan through the list and log consecutive ranges of missing packets.
    342   size_t num_consecutive_missing_packets = 0;
    343   QuicPacketSequenceNumber previous_missing_packet = *it - 1;
    344   while (it != missing_packets.end()) {
    345     if (previous_missing_packet == *it - 1) {
    346       ++num_consecutive_missing_packets;
    347     } else {
    348       DCHECK_NE(0u, num_consecutive_missing_packets);
    349       UpdatePacketGapSentHistogram(num_consecutive_missing_packets);
    350       // Make sure this packet it included in the count.
    351       num_consecutive_missing_packets = 1;
    352     }
    353     previous_missing_packet = *it;
    354     ++it;
    355   }
    356   if (num_consecutive_missing_packets != 0) {
    357     UpdatePacketGapSentHistogram(num_consecutive_missing_packets);
    358   }
    359   largest_received_missing_packet_sequence_number_ =
    360         *missing_packets.rbegin();
    361 }
    362 
    363 void QuicConnectionLogger::OnCongestionFeedbackFrame(
    364     const QuicCongestionFeedbackFrame& frame) {
    365   net_log_.AddEvent(
    366       NetLog::TYPE_QUIC_SESSION_CONGESTION_FEEDBACK_FRAME_RECEIVED,
    367       base::Bind(&NetLogQuicCongestionFeedbackFrameCallback, &frame));
    368 }
    369 
    370 void QuicConnectionLogger::OnRstStreamFrame(const QuicRstStreamFrame& frame) {
    371   UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.RstStreamErrorCodeServer",
    372                               frame.error_code);
    373   net_log_.AddEvent(
    374       NetLog::TYPE_QUIC_SESSION_RST_STREAM_FRAME_RECEIVED,
    375       base::Bind(&NetLogQuicRstStreamFrameCallback, &frame));
    376 }
    377 
    378 void QuicConnectionLogger::OnConnectionCloseFrame(
    379     const QuicConnectionCloseFrame& frame) {
    380   net_log_.AddEvent(
    381       NetLog::TYPE_QUIC_SESSION_CONNECTION_CLOSE_FRAME_RECEIVED,
    382       base::Bind(&NetLogQuicConnectionCloseFrameCallback, &frame));
    383 }
    384 
    385 void QuicConnectionLogger::OnPublicResetPacket(
    386     const QuicPublicResetPacket& packet) {
    387   net_log_.AddEvent(NetLog::TYPE_QUIC_SESSION_PUBLIC_RESET_PACKET_RECEIVED);
    388 }
    389 
    390 void QuicConnectionLogger::OnVersionNegotiationPacket(
    391     const QuicVersionNegotiationPacket& packet) {
    392   net_log_.AddEvent(
    393       NetLog::TYPE_QUIC_SESSION_VERSION_NEGOTIATION_PACKET_RECEIVED,
    394       base::Bind(&NetLogQuicVersionNegotiationPacketCallback, &packet));
    395 }
    396 
    397 void QuicConnectionLogger::OnRevivedPacket(
    398     const QuicPacketHeader& revived_header,
    399     base::StringPiece payload) {
    400   net_log_.AddEvent(
    401       NetLog::TYPE_QUIC_SESSION_PACKET_HEADER_REVIVED,
    402       base::Bind(&NetLogQuicPacketHeaderCallback, &revived_header));
    403 }
    404 
    405 void QuicConnectionLogger::OnCryptoHandshakeMessageReceived(
    406     const CryptoHandshakeMessage& message) {
    407   net_log_.AddEvent(
    408       NetLog::TYPE_QUIC_SESSION_CRYPTO_HANDSHAKE_MESSAGE_RECEIVED,
    409       base::Bind(&NetLogQuicCryptoHandshakeMessageCallback, &message));
    410 }
    411 
    412 void QuicConnectionLogger::OnCryptoHandshakeMessageSent(
    413     const CryptoHandshakeMessage& message) {
    414   net_log_.AddEvent(
    415       NetLog::TYPE_QUIC_SESSION_CRYPTO_HANDSHAKE_MESSAGE_SENT,
    416       base::Bind(&NetLogQuicCryptoHandshakeMessageCallback, &message));
    417 }
    418 
    419 void QuicConnectionLogger::OnConnectionClosed(QuicErrorCode error,
    420                                               bool from_peer) {
    421   net_log_.AddEvent(
    422       NetLog::TYPE_QUIC_SESSION_CLOSED,
    423       base::Bind(&NetLogQuicOnConnectionClosedCallback, error, from_peer));
    424 }
    425 
    426 void QuicConnectionLogger::OnSuccessfulVersionNegotiation(
    427     const QuicVersion& version) {
    428   string quic_version = QuicVersionToString(version);
    429   net_log_.AddEvent(NetLog::TYPE_QUIC_SESSION_VERSION_NEGOTIATED,
    430                     NetLog::StringCallback("version", &quic_version));
    431 }
    432 
    433 }  // namespace net
    434