You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by ma...@apache.org on 2018/04/09 03:12:51 UTC

[trafficserver] branch quic-latest updated: Catch up draft-10

This is an automated email from the ASF dual-hosted git repository.

maskit pushed a commit to branch quic-latest
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/quic-latest by this push:
     new 4a3ea0e  Catch up draft-10
4a3ea0e is described below

commit 4a3ea0e945557f3934f23d683bb586074dc511d3
Author: Masakazu Kitajo <ma...@apache.org>
AuthorDate: Wed Apr 4 14:14:03 2018 +0900

    Catch up draft-10
---
 iocore/net/quic/QUICDebugNames.cc             |  10 +-
 iocore/net/quic/QUICFrame.cc                  | 146 ++++++++++++++------------
 iocore/net/quic/QUICFrame.h                   |  84 +++++++++------
 iocore/net/quic/QUICHKDF.cc                   |   2 -
 iocore/net/quic/QUICKeyGenerator.cc           |   2 +-
 iocore/net/quic/QUICPacket.cc                 |   3 +-
 iocore/net/quic/QUICTypes.h                   |  13 +--
 iocore/net/quic/test/test_QUICFrame.cc        | 141 ++++++++++++++++---------
 iocore/net/quic/test/test_QUICKeyGenerator.cc |  12 +--
 iocore/net/quic/test/test_QUICPacket.cc       |   4 +-
 lib/ts/ink_inet.cc                            |   2 +-
 11 files changed, 251 insertions(+), 168 deletions(-)

diff --git a/iocore/net/quic/QUICDebugNames.cc b/iocore/net/quic/QUICDebugNames.cc
index f7ec117..664f034 100644
--- a/iocore/net/quic/QUICDebugNames.cc
+++ b/iocore/net/quic/QUICDebugNames.cc
@@ -58,6 +58,8 @@ QUICDebugNames::frame_type(QUICFrameType type)
     return "RST_STREAM";
   case QUICFrameType::CONNECTION_CLOSE:
     return "CONNECTION_CLOSE";
+  case QUICFrameType::APPLICATION_CLOSE:
+    return "APPLICATION_CLOSE";
   case QUICFrameType::MAX_DATA:
     return "MAX_DATA";
   case QUICFrameType::MAX_STREAM_DATA:
@@ -74,12 +76,16 @@ QUICDebugNames::frame_type(QUICFrameType type)
     return "STREAM_ID_BLOCKED";
   case QUICFrameType::NEW_CONNECTION_ID:
     return "NEW_CONNECTION_ID";
+  case QUICFrameType::STOP_SENDING:
+    return "STOP_SENDING";
   case QUICFrameType::ACK:
     return "ACK";
+  case QUICFrameType::PATH_CHALLENGE:
+    return "PATH_CHALLENGE";
+  case QUICFrameType::PATH_RESPONSE:
+    return "PATH_RESPONSE";
   case QUICFrameType::STREAM:
     return "STREAM";
-  case QUICFrameType::PONG:
-    return "PONG";
   case QUICFrameType::UNKNOWN:
   default:
     return "UNKNOWN";
diff --git a/iocore/net/quic/QUICFrame.cc b/iocore/net/quic/QUICFrame.cc
index c0d6fe6..0bb7cef 100644
--- a/iocore/net/quic/QUICFrame.cc
+++ b/iocore/net/quic/QUICFrame.cc
@@ -40,7 +40,8 @@ ClassAllocator<QUICStreamBlockedFrame> quicStreamBlockedFrameAllocator("quicStre
 ClassAllocator<QUICStreamIdBlockedFrame> quicStreamIdBlockedFrameAllocator("quicStreamIdBlockedFrameAllocator");
 ClassAllocator<QUICNewConnectionIdFrame> quicNewConnectionIdFrameAllocator("quicNewConnectionIdFrameAllocator");
 ClassAllocator<QUICStopSendingFrame> quicStopSendingFrameAllocator("quicStopSendingFrameAllocator");
-ClassAllocator<QUICPongFrame> quicPongFrameAllocator("quicPongFrameAllocator");
+ClassAllocator<QUICPathChallengeFrame> quicPathChallengeFrameAllocator("quicPathChallengeFrameAllocator");
+ClassAllocator<QUICPathResponseFrame> quicPathResponseFrameAllocator("quicPathResponseFrameAllocator");
 ClassAllocator<QUICRetransmissionFrame> quicRetransmissionFrameAllocator("quicRetransmissionFrameAllocator");
 
 QUICFrameType
@@ -56,8 +57,6 @@ QUICFrame::type(const uint8_t *buf)
     return QUICFrameType::UNKNOWN;
   } else if (buf[0] >= static_cast<uint8_t>(QUICFrameType::STREAM)) {
     return QUICFrameType::STREAM;
-  } else if (buf[0] > static_cast<uint8_t>(QUICFrameType::ACK)) {
-    return QUICFrameType::UNKNOWN;
   } else {
     return static_cast<QUICFrameType>(buf[0]);
   }
@@ -857,7 +856,7 @@ QUICPingFrame::type() const
 size_t
 QUICPingFrame::size() const
 {
-  return this->_data_offset() + this->data_length();
+  return 1;
 }
 
 void
@@ -869,38 +868,9 @@ QUICPingFrame::store(uint8_t *buf, size_t *len) const
     memcpy(buf, this->_buf, *len);
   } else {
     buf[0] = static_cast<uint8_t>(QUICFrameType::PING);
-    buf[1] = this->data_length();
-
-    memcpy(buf + this->_data_offset(), this->data(), this->data_length());
-  }
-}
-
-const uint8_t *
-QUICPingFrame::data() const
-{
-  if (this->_buf) {
-    return this->_buf + this->_data_offset();
-  } else {
-    return this->_data.get();
-  }
-}
-
-uint8_t
-QUICPingFrame::data_length() const
-{
-  if (this->_buf) {
-    return QUICIntUtil::read_nbytes_as_uint(this->_buf + sizeof(QUICFrameType), 1);
-  } else {
-    return this->_data_len;
   }
 }
 
-const size_t
-QUICPingFrame::_data_offset() const
-{
-  return sizeof(QUICFrameType) + sizeof(this->_data_len);
-}
-
 //
 // PADDING frame
 //
@@ -1686,37 +1656,35 @@ QUICStopSendingFrame::_get_error_code_field_offset() const
 }
 
 //
-// PONG frame
+// PATH_CHALLENGE frame
 //
 QUICFrameType
-QUICPongFrame::type() const
+QUICPathChallengeFrame::type() const
 {
-  return QUICFrameType::PONG;
+  return QUICFrameType::PATH_CHALLENGE;
 }
 
 size_t
-QUICPongFrame::size() const
+QUICPathChallengeFrame::size() const
 {
-  return this->_data_offset() + this->data_length();
+  return this->_data_offset() + QUICPathChallengeFrame::DATA_LEN;
 }
 
 void
-QUICPongFrame::store(uint8_t *buf, size_t *len) const
+QUICPathChallengeFrame::store(uint8_t *buf, size_t *len) const
 {
   *len = this->size();
 
   if (this->_buf) {
     memcpy(buf, this->_buf, *len);
   } else {
-    buf[0] = static_cast<uint8_t>(QUICFrameType::PONG);
-    buf[1] = this->data_length();
-
-    memcpy(buf + this->_data_offset(), this->data(), this->data_length());
+    buf[0] = static_cast<uint8_t>(QUICFrameType::PATH_CHALLENGE);
+    memcpy(buf + this->_data_offset(), this->data(), QUICPathChallengeFrame::DATA_LEN);
   }
 }
 
 const uint8_t *
-QUICPongFrame::data() const
+QUICPathChallengeFrame::data() const
 {
   if (this->_buf) {
     return this->_buf + this->_data_offset();
@@ -1725,20 +1693,54 @@ QUICPongFrame::data() const
   }
 }
 
-uint8_t
-QUICPongFrame::data_length() const
+const size_t
+QUICPathChallengeFrame::_data_offset() const
 {
+  return sizeof(QUICFrameType);
+}
+
+//
+// PATH_RESPONSE frame
+//
+QUICFrameType
+QUICPathResponseFrame::type() const
+{
+  return QUICFrameType::PATH_RESPONSE;
+}
+
+size_t
+QUICPathResponseFrame::size() const
+{
+  return this->_data_offset() + 8;
+}
+
+void
+QUICPathResponseFrame::store(uint8_t *buf, size_t *len) const
+{
+  *len = this->size();
+
   if (this->_buf) {
-    return QUICIntUtil::read_nbytes_as_uint(this->_buf + sizeof(QUICFrameType), 1);
+    memcpy(buf, this->_buf, *len);
   } else {
-    return this->_data_len;
+    buf[0] = static_cast<uint8_t>(QUICFrameType::PATH_RESPONSE);
+    memcpy(buf + this->_data_offset(), this->data(), QUICPathResponseFrame::DATA_LEN);
+  }
+}
+
+const uint8_t *
+QUICPathResponseFrame::data() const
+{
+  if (this->_buf) {
+    return this->_buf + this->_data_offset();
+  } else {
+    return this->_data.get();
   }
 }
 
 const size_t
-QUICPongFrame::_data_offset() const
+QUICPathResponseFrame::_data_offset() const
 {
-  return sizeof(QUICFrameType) + sizeof(this->_data_len);
+  return sizeof(QUICFrameType);
 }
 
 //
@@ -1855,10 +1857,14 @@ QUICFrameFactory::create(const uint8_t *buf, size_t len)
     frame = quicStopSendingFrameAllocator.alloc();
     new (frame) QUICStopSendingFrame(buf, len);
     return QUICFrameUPtr(frame, &QUICFrameDeleter::delete_stop_sending_frame);
-  case QUICFrameType::PONG:
-    frame = quicPongFrameAllocator.alloc();
-    new (frame) QUICPongFrame(buf, len);
-    return QUICFrameUPtr(frame, &QUICFrameDeleter::delete_pong_frame);
+  case QUICFrameType::PATH_CHALLENGE:
+    frame = quicPathChallengeFrameAllocator.alloc();
+    new (frame) QUICPathChallengeFrame(buf, len);
+    return QUICFrameUPtr(frame, &QUICFrameDeleter::delete_path_challenge_frame);
+  case QUICFrameType::PATH_RESPONSE:
+    frame = quicPathResponseFrameAllocator.alloc();
+    new (frame) QUICPathResponseFrame(buf, len);
+    return QUICFrameUPtr(frame, &QUICFrameDeleter::delete_path_response_frame);
   default:
     // Unknown frame
     Debug("quic_frame_factory", "Unknown frame type %x", buf[0]);
@@ -1965,25 +1971,33 @@ QUICFrameFactory::create_max_stream_data_frame(QUICStreamId stream_id, uint64_t
 }
 
 std::unique_ptr<QUICPingFrame, QUICFrameDeleterFunc>
-QUICFrameFactory::create_ping_frame(const uint8_t *data, size_t data_len)
+QUICFrameFactory::create_ping_frame()
 {
-  ats_unique_buf buf = ats_unique_malloc(data_len);
-  memcpy(buf.get(), data, data_len);
-
   QUICPingFrame *frame = quicPingFrameAllocator.alloc();
-  new (frame) QUICPingFrame(std::move(buf), data_len);
+  new (frame) QUICPingFrame(true);
   return std::unique_ptr<QUICPingFrame, QUICFrameDeleterFunc>(frame, &QUICFrameDeleter::delete_ping_frame);
 }
 
-std::unique_ptr<QUICPongFrame, QUICFrameDeleterFunc>
-QUICFrameFactory::create_pong_frame(const QUICPingFrame &ping_frame)
+std::unique_ptr<QUICPathChallengeFrame, QUICFrameDeleterFunc>
+QUICFrameFactory::create_path_challenge_frame(const uint8_t *data)
+{
+  ats_unique_buf buf = ats_unique_malloc(QUICPathChallengeFrame::DATA_LEN);
+  memcpy(buf.get(), data, QUICPathChallengeFrame::DATA_LEN);
+
+  QUICPathChallengeFrame *frame = quicPathChallengeFrameAllocator.alloc();
+  new (frame) QUICPathChallengeFrame(std::move(buf));
+  return std::unique_ptr<QUICPathChallengeFrame, QUICFrameDeleterFunc>(frame, &QUICFrameDeleter::delete_path_challenge_frame);
+}
+
+std::unique_ptr<QUICPathResponseFrame, QUICFrameDeleterFunc>
+QUICFrameFactory::create_path_response_frame(const QUICPathChallengeFrame &path_challenge_frame)
 {
-  ats_unique_buf buf = ats_unique_malloc(ping_frame.data_length());
-  memcpy(buf.get(), ping_frame.data(), ping_frame.data_length());
+  ats_unique_buf buf = ats_unique_malloc(QUICPathResponseFrame::DATA_LEN);
+  memcpy(buf.get(), path_challenge_frame.data(), QUICPathResponseFrame::DATA_LEN);
 
-  QUICPongFrame *frame = quicPongFrameAllocator.alloc();
-  new (frame) QUICPongFrame(std::move(buf), ping_frame.data_length());
-  return std::unique_ptr<QUICPongFrame, QUICFrameDeleterFunc>(frame, &QUICFrameDeleter::delete_pong_frame);
+  QUICPathResponseFrame *frame = quicPathResponseFrameAllocator.alloc();
+  new (frame) QUICPathResponseFrame(std::move(buf));
+  return std::unique_ptr<QUICPathResponseFrame, QUICFrameDeleterFunc>(frame, &QUICFrameDeleter::delete_path_challenge_frame);
 }
 
 std::unique_ptr<QUICBlockedFrame, QUICFrameDeleterFunc>
diff --git a/iocore/net/quic/QUICFrame.h b/iocore/net/quic/QUICFrame.h
index 5e21ef4..2cc50fd 100644
--- a/iocore/net/quic/QUICFrame.h
+++ b/iocore/net/quic/QUICFrame.h
@@ -260,23 +260,13 @@ class QUICPingFrame : public QUICFrame
 public:
   QUICPingFrame() : QUICFrame() {}
   QUICPingFrame(const uint8_t *buf, size_t len, bool protection = true) : QUICFrame(buf, len, protection) {}
-  QUICPingFrame(ats_unique_buf data, size_t data_len, bool protection = true)
-    : QUICFrame(protection), _data(std::move(data)), _data_len(data_len)
-  {
-  }
+  QUICPingFrame(bool protection) : QUICFrame(protection) {}
 
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
   virtual void store(uint8_t *buf, size_t *len) const override;
 
-  const uint8_t *data() const;
-  uint8_t data_length() const;
-
 private:
-  const size_t _data_offset() const;
-
-  ats_unique_buf _data = {nullptr, [](void *p) { ats_free(p); }};
-  uint8_t _data_len    = 0;
 };
 
 // PADDING
@@ -541,38 +531,58 @@ private:
   QUICAppErrorCode _error_code = 0;
 };
 
-using QUICFrameDeleterFunc = void (*)(QUICFrame *p);
-using QUICFrameUPtr        = std::unique_ptr<QUICFrame, QUICFrameDeleterFunc>;
-using QUICStreamFrameUPtr  = std::unique_ptr<QUICStreamFrame, QUICFrameDeleterFunc>;
+//
+// PATH_CHALLENGE
+//
+
+class QUICPathChallengeFrame : public QUICFrame
+{
+public:
+  static constexpr uint8_t DATA_LEN = 8;
+  QUICPathChallengeFrame() : QUICFrame() {}
+  QUICPathChallengeFrame(const uint8_t *buf, size_t len, bool protection = true) : QUICFrame(buf, len, protection) {}
+  QUICPathChallengeFrame(ats_unique_buf data, bool protection = true) : QUICFrame(protection), _data(std::move(data)) {}
+
+  virtual QUICFrameType type() const override;
+  virtual size_t size() const override;
+  virtual void store(uint8_t *buf, size_t *len) const override;
+
+  const uint8_t *data() const;
+
+private:
+  const size_t _data_offset() const;
+
+  ats_unique_buf _data = {nullptr, [](void *p) { ats_free(p); }};
+};
 
 //
-// PONG
+// PATH_RESPONSE
 //
 
-class QUICPongFrame : public QUICFrame
+class QUICPathResponseFrame : public QUICFrame
 {
 public:
-  QUICPongFrame() : QUICFrame() {}
-  QUICPongFrame(const uint8_t *buf, size_t len, bool protection = true) : QUICFrame(buf, len, protection) {}
-  QUICPongFrame(ats_unique_buf data, size_t data_len, bool protection = true)
-    : QUICFrame(protection), _data(std::move(data)), _data_len(data_len)
-  {
-  }
+  static constexpr uint8_t DATA_LEN = 8;
+  QUICPathResponseFrame() : QUICFrame() {}
+  QUICPathResponseFrame(const uint8_t *buf, size_t len, bool protection = true) : QUICFrame(buf, len, protection) {}
+  QUICPathResponseFrame(ats_unique_buf data, bool protection = true) : QUICFrame(protection), _data(std::move(data)) {}
 
   virtual QUICFrameType type() const override;
   virtual size_t size() const override;
   virtual void store(uint8_t *buf, size_t *len) const override;
 
   const uint8_t *data() const;
-  uint8_t data_length() const;
 
 private:
   const size_t _data_offset() const;
 
   ats_unique_buf _data = {nullptr, [](void *p) { ats_free(p); }};
-  uint8_t _data_len    = 0;
 };
 
+using QUICFrameDeleterFunc = void (*)(QUICFrame *p);
+using QUICFrameUPtr        = std::unique_ptr<QUICFrame, QUICFrameDeleterFunc>;
+using QUICStreamFrameUPtr  = std::unique_ptr<QUICStreamFrame, QUICFrameDeleterFunc>;
+
 //
 // Retransmission Frame
 //
@@ -608,7 +618,8 @@ extern ClassAllocator<QUICStreamBlockedFrame> quicStreamBlockedFrameAllocator;
 extern ClassAllocator<QUICStreamIdBlockedFrame> quicStreamIdBlockedFrameAllocator;
 extern ClassAllocator<QUICNewConnectionIdFrame> quicNewConnectionIdFrameAllocator;
 extern ClassAllocator<QUICStopSendingFrame> quicStopSendingFrameAllocator;
-extern ClassAllocator<QUICPongFrame> quicPongFrameAllocator;
+extern ClassAllocator<QUICPathChallengeFrame> quicPathChallengeFrameAllocator;
+extern ClassAllocator<QUICPathResponseFrame> quicPathResponseFrameAllocator;
 extern ClassAllocator<QUICRetransmissionFrame> quicRetransmissionFrameAllocator;
 
 class QUICFrameDeleter
@@ -727,10 +738,17 @@ public:
   }
 
   static void
-  delete_pong_frame(QUICFrame *frame)
+  delete_path_challenge_frame(QUICFrame *frame)
+  {
+    frame->~QUICFrame();
+    quicPathChallengeFrameAllocator.free(static_cast<QUICPathChallengeFrame *>(frame));
+  }
+
+  static void
+  delete_path_response_frame(QUICFrame *frame)
   {
     frame->~QUICFrame();
-    quicPongFrameAllocator.free(static_cast<QUICPongFrame *>(frame));
+    quicPathResponseFrameAllocator.free(static_cast<QUICPathResponseFrame *>(frame));
   }
 
   static void
@@ -809,12 +827,18 @@ public:
   /*
    * Creates a PING frame
    */
-  static std::unique_ptr<QUICPingFrame, QUICFrameDeleterFunc> create_ping_frame(const uint8_t *data, size_t data_len);
+  static std::unique_ptr<QUICPingFrame, QUICFrameDeleterFunc> create_ping_frame();
+
+  /*
+   * Creates a PATH_CHALLENGE frame
+   */
+  static std::unique_ptr<QUICPathChallengeFrame, QUICFrameDeleterFunc> create_path_challenge_frame(const uint8_t *data);
 
   /*
-   * Creates a PONG frame
+   * Creates a PATH_RESPONSE frame
    */
-  static std::unique_ptr<QUICPongFrame, QUICFrameDeleterFunc> create_pong_frame(const QUICPingFrame &ping_frame);
+  static std::unique_ptr<QUICPathResponseFrame, QUICFrameDeleterFunc> create_path_response_frame(
+    const QUICPathChallengeFrame &path_challenge_frame);
 
   /*
    * Creates a BLOCKED frame.
diff --git a/iocore/net/quic/QUICHKDF.cc b/iocore/net/quic/QUICHKDF.cc
index adb2cff..fd0bd9d 100644
--- a/iocore/net/quic/QUICHKDF.cc
+++ b/iocore/net/quic/QUICHKDF.cc
@@ -38,8 +38,6 @@ QUICHKDF::expand(uint8_t *dst, size_t *dst_len, const uint8_t *secret, size_t se
   // "QUIC " + Label
   hkdf_label_len += sprintf(reinterpret_cast<char *>(hkdf_label + hkdf_label_len), "%cQUIC %.*s", static_cast<int>(5 + label_len),
                             static_cast<int>(label_len), label);
-  // Hash Value
-  hkdf_label_len += sprintf(reinterpret_cast<char *>(hkdf_label + hkdf_label_len), "%c%.*s", 0, 0, "");
 
   HKDF::expand(dst, dst_len, secret, secret_len, hkdf_label, hkdf_label_len, length);
   return 1;
diff --git a/iocore/net/quic/QUICKeyGenerator.cc b/iocore/net/quic/QUICKeyGenerator.cc
index 9cd1f37..bd5fb28 100644
--- a/iocore/net/quic/QUICKeyGenerator.cc
+++ b/iocore/net/quic/QUICKeyGenerator.cc
@@ -27,7 +27,7 @@
 #include "QUICHKDF.h"
 
 constexpr static uint8_t QUIC_VERSION_1_SALT[] = {
-  0xaf, 0xc8, 0x24, 0xec, 0x5f, 0xc7, 0x7e, 0xca, 0x1e, 0x9d, 0x36, 0xf3, 0x7f, 0xb2, 0xd4, 0x65, 0x18, 0xc3, 0x66, 0x39,
+  0x9c, 0x10, 0x8f, 0x98, 0x52, 0x0a, 0x5c, 0x5c, 0x32, 0x96, 0x8e, 0x95, 0x0e, 0x8a, 0x2c, 0x5f, 0xe0, 0x6d, 0x6c, 0x38,
 };
 constexpr static ts::string_view LABEL_FOR_CLIENT_CLEARTEXT_SECRET("client hs"_sv);
 constexpr static ts::string_view LABEL_FOR_SERVER_CLEARTEXT_SECRET("server hs"_sv);
diff --git a/iocore/net/quic/QUICPacket.cc b/iocore/net/quic/QUICPacket.cc
index 61e19ba..380cbe8 100644
--- a/iocore/net/quic/QUICPacket.cc
+++ b/iocore/net/quic/QUICPacket.cc
@@ -363,7 +363,7 @@ QUICPacketShortHeader::_packet_number_len() const
 {
   QUICPacketShortHeaderType type;
   if (this->_buf) {
-    type = static_cast<QUICPacketShortHeaderType>(this->_buf.get()[0] & 0x1F);
+    type = static_cast<QUICPacketShortHeaderType>(this->_buf.get()[0] & 0x07);
   } else {
     type = this->_packet_number_type;
   }
@@ -463,6 +463,7 @@ QUICPacketShortHeader::store(uint8_t *buf, size_t *len) const
   if (this->_key_phase == QUICKeyPhase::PHASE_1) {
     buf[0] += 0x20;
   }
+  buf[0] += 0x10;
   buf[0] += static_cast<uint8_t>(this->_packet_number_type);
   *len += 1;
   if (this->_has_connection_id) {
diff --git a/iocore/net/quic/QUICTypes.h b/iocore/net/quic/QUICTypes.h
index 57de391..80101da 100644
--- a/iocore/net/quic/QUICTypes.h
+++ b/iocore/net/quic/QUICTypes.h
@@ -47,7 +47,7 @@ using QUICOffset       = uint64_t;
 // Note: You also need to update tests for VersionNegotiationPacket creation, if you change the number of versions
 // Prefix for drafts (0xff000000) + draft number
 constexpr QUICVersion QUIC_SUPPORTED_VERSIONS[] = {
-  0xff000009,
+  0xff00000a,
 };
 constexpr QUICVersion QUIC_EXERCISE_VERSIONS = 0x1a2a3a4a;
 
@@ -74,10 +74,10 @@ enum class QUICPacketType : uint8_t {
 
 // To detect length of Packet Number
 enum class QUICPacketShortHeaderType : int {
-  ONE           = 0x1F,
-  TWO           = 0x1E,
-  THREE         = 0x1D,
-  UNINITIALIZED = 0x1C,
+  ONE           = 0x0,
+  TWO           = 0x1,
+  THREE         = 0x2,
+  UNINITIALIZED = 0x3,
 };
 
 // XXX If you add or remove QUICFrameType, you might also need to change QUICFrame::type(const uint8_t *)
@@ -95,8 +95,9 @@ enum class QUICFrameType : uint8_t {
   STREAM_ID_BLOCKED,
   NEW_CONNECTION_ID,
   STOP_SENDING,
-  PONG,
   ACK,
+  PATH_CHALLENGE,
+  PATH_RESPONSE,
   STREAM  = 0x10, // 0x10 - 0x17
   UNKNOWN = 0x18,
 };
diff --git a/iocore/net/quic/test/test_QUICFrame.cc b/iocore/net/quic/test/test_QUICFrame.cc
index dcd12b4..fd4f4e5 100644
--- a/iocore/net/quic/test/test_QUICFrame.cc
+++ b/iocore/net/quic/test/test_QUICFrame.cc
@@ -42,10 +42,9 @@ TEST_CASE("QUICFrame Type", "[quic]")
   CHECK(QUICFrame::type(reinterpret_cast<const uint8_t *>("\x0a")) == QUICFrameType::STREAM_ID_BLOCKED);
   CHECK(QUICFrame::type(reinterpret_cast<const uint8_t *>("\x0b")) == QUICFrameType::NEW_CONNECTION_ID);
   CHECK(QUICFrame::type(reinterpret_cast<const uint8_t *>("\x0c")) == QUICFrameType::STOP_SENDING);
-  CHECK(QUICFrame::type(reinterpret_cast<const uint8_t *>("\x0d")) == QUICFrameType::PONG);
-  CHECK(QUICFrame::type(reinterpret_cast<const uint8_t *>("\x0e")) == QUICFrameType::ACK);
-  // Undefined ragne
-  CHECK(QUICFrame::type(reinterpret_cast<const uint8_t *>("\x0f")) == QUICFrameType::UNKNOWN);
+  CHECK(QUICFrame::type(reinterpret_cast<const uint8_t *>("\x0d")) == QUICFrameType::ACK);
+  CHECK(QUICFrame::type(reinterpret_cast<const uint8_t *>("\x0e")) == QUICFrameType::PATH_CHALLENGE);
+  CHECK(QUICFrame::type(reinterpret_cast<const uint8_t *>("\x0f")) == QUICFrameType::PATH_RESPONSE);
   // Range of STREAM
   CHECK(QUICFrame::type(reinterpret_cast<const uint8_t *>("\x10")) == QUICFrameType::STREAM);
   CHECK(QUICFrame::type(reinterpret_cast<const uint8_t *>("\x17")) == QUICFrameType::STREAM);
@@ -328,7 +327,7 @@ TEST_CASE("Load Ack Frame 1", "[quic]")
   SECTION("0 Ack Block, 8 bit packet number length, 8 bit block length")
   {
     uint8_t buf1[] = {
-      0x0e,       // Type
+      0x0d,       // Type
       0x12,       // Largest Acknowledged
       0x74, 0x56, // Ack Delay
       0x00,       // Ack Block Count
@@ -347,7 +346,7 @@ TEST_CASE("Load Ack Frame 1", "[quic]")
   SECTION("0 Ack Block, 8 bit packet number length, 8 bit block length")
   {
     uint8_t buf1[] = {
-      0x0e,                   // Type
+      0x0d,                   // Type
       0x80, 0x00, 0x00, 0x01, // Largest Acknowledged
       0x41, 0x71,             // Ack Delay
       0x00,                   // Ack Block Count
@@ -370,7 +369,7 @@ TEST_CASE("Load Ack Frame 1", "[quic]")
   SECTION("2 Ack Block, 8 bit packet number length, 8 bit block length")
   {
     uint8_t buf1[] = {
-      0x0e,                                           // Type
+      0x0d,                                           // Type
       0x12,                                           // Largest Acknowledged
       0x74, 0x56,                                     // Ack Delay
       0x02,                                           // Ack Block Count
@@ -413,7 +412,7 @@ TEST_CASE("Store Ack Frame", "[quic]")
     size_t len;
 
     uint8_t expected[] = {
-      0x0e,       // Type
+      0x0d,       // Type
       0x12,       // Largest Acknowledged
       0x74, 0x56, // Ack Delay
       0x00,       // Ack Block Count
@@ -434,7 +433,7 @@ TEST_CASE("Store Ack Frame", "[quic]")
     size_t len;
 
     uint8_t expected[] = {
-      0x0e,                                           // Type
+      0x0d,                                           // Type
       0x12,                                           // Largest Acknowledged
       0x74, 0x56,                                     // Ack Delay
       0x02,                                           // Ack Block Count
@@ -496,18 +495,14 @@ TEST_CASE("Store RST_STREAM Frame", "[quic]")
 TEST_CASE("Load Ping Frame", "[quic]")
 {
   uint8_t buf[] = {
-    0x07,                                           // Type
-    0x08,                                           // Length
-    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, // Data
+    0x07, // Type
   };
   std::shared_ptr<const QUICFrame> frame = QUICFrameFactory::create(buf, sizeof(buf));
   CHECK(frame->type() == QUICFrameType::PING);
-  CHECK(frame->size() == 10);
+  CHECK(frame->size() == 1);
 
   std::shared_ptr<const QUICPingFrame> ping_frame = std::dynamic_pointer_cast<const QUICPingFrame>(frame);
   CHECK(ping_frame != nullptr);
-  CHECK(ping_frame->data_length() == 8);
-  CHECK(memcmp(ping_frame->data(), "\x01\x23\x45\x67\x89\xab\xcd\xef", 8) == 0);
 }
 
 TEST_CASE("Store Ping Frame", "[quic]")
@@ -516,21 +511,14 @@ TEST_CASE("Store Ping Frame", "[quic]")
   size_t len;
 
   uint8_t expected[] = {
-    0x07,                                           // Type
-    0x08,                                           // Length
-    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, // Data
+    0x07, // Type
   };
 
-  uint8_t raw[]       = "\x01\x23\x45\x67\x89\xab\xcd\xef";
-  size_t raw_len      = sizeof(raw) - 1;
-  ats_unique_buf data = ats_unique_malloc(raw_len);
-  memcpy(data.get(), raw, raw_len);
-
-  QUICPingFrame frame(std::move(data), 8);
-  CHECK(frame.size() == 10);
+  QUICPingFrame frame(true);
+  CHECK(frame.size() == 1);
 
   frame.store(buf, &len);
-  CHECK(len == 10);
+  CHECK(len == 1);
   CHECK(memcmp(buf, expected, len) == 0);
 }
 
@@ -989,31 +977,29 @@ TEST_CASE("Store STOP_SENDING Frame", "[quic]")
   CHECK(memcmp(buf, expected, len) == 0);
 }
 
-TEST_CASE("Load Pong Frame", "[quic]")
+TEST_CASE("Load PATH_CHALLENGE Frame", "[quic]")
 {
   uint8_t buf[] = {
-    0x0d,                                           // Type
-    0x08,                                           // Length
+    0x0e,                                           // Type
     0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, // Data
   };
   std::shared_ptr<const QUICFrame> frame = QUICFrameFactory::create(buf, sizeof(buf));
-  CHECK(frame->type() == QUICFrameType::PONG);
-  CHECK(frame->size() == 10);
+  CHECK(frame->type() == QUICFrameType::PATH_CHALLENGE);
+  CHECK(frame->size() == 9);
 
-  std::shared_ptr<const QUICPongFrame> pong_frame = std::dynamic_pointer_cast<const QUICPongFrame>(frame);
-  CHECK(pong_frame != nullptr);
-  CHECK(pong_frame->data_length() == 8);
-  CHECK(memcmp(pong_frame->data(), "\x01\x23\x45\x67\x89\xab\xcd\xef", 8) == 0);
+  std::shared_ptr<const QUICPathChallengeFrame> path_challenge_frame =
+    std::dynamic_pointer_cast<const QUICPathChallengeFrame>(frame);
+  CHECK(path_challenge_frame != nullptr);
+  CHECK(memcmp(path_challenge_frame->data(), "\x01\x23\x45\x67\x89\xab\xcd\xef", QUICPathChallengeFrame::DATA_LEN) == 0);
 }
 
-TEST_CASE("Store Pong Frame", "[quic]")
+TEST_CASE("Store PATH_CHALLENGE Frame", "[quic]")
 {
   uint8_t buf[16];
   size_t len;
 
   uint8_t expected[] = {
-    0x0d,                                           // Type
-    0x08,                                           // Length
+    0x0e,                                           // Type
     0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, // Data
   };
 
@@ -1022,18 +1008,56 @@ TEST_CASE("Store Pong Frame", "[quic]")
   ats_unique_buf data = ats_unique_malloc(raw_len);
   memcpy(data.get(), raw, raw_len);
 
-  QUICPongFrame frame(std::move(data), 8);
-  CHECK(frame.size() == 10);
+  QUICPathChallengeFrame frame(std::move(data), QUICPathChallengeFrame::DATA_LEN);
+  CHECK(frame.size() == 9);
 
   frame.store(buf, &len);
-  CHECK(len == 10);
+  CHECK(len == 9);
+  CHECK(memcmp(buf, expected, len) == 0);
+}
+
+TEST_CASE("Load PATH_RESPONSE Frame", "[quic]")
+{
+  uint8_t buf[] = {
+    0x0f,                                           // Type
+    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, // Data
+  };
+  std::shared_ptr<const QUICFrame> frame = QUICFrameFactory::create(buf, sizeof(buf));
+  CHECK(frame->type() == QUICFrameType::PATH_RESPONSE);
+  CHECK(frame->size() == 9);
+
+  std::shared_ptr<const QUICPathResponseFrame> path_response_frame = std::dynamic_pointer_cast<const QUICPathResponseFrame>(frame);
+  CHECK(path_response_frame != nullptr);
+  CHECK(memcmp(path_response_frame->data(), "\x01\x23\x45\x67\x89\xab\xcd\xef", QUICPathResponseFrame::DATA_LEN) == 0);
+}
+
+TEST_CASE("Store PATH_RESPONSE Frame", "[quic]")
+{
+  uint8_t buf[16];
+  size_t len;
+
+  uint8_t expected[] = {
+    0x0f,                                           // Type
+    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, // Data
+  };
+
+  uint8_t raw[]       = "\x01\x23\x45\x67\x89\xab\xcd\xef";
+  size_t raw_len      = sizeof(raw) - 1;
+  ats_unique_buf data = ats_unique_malloc(raw_len);
+  memcpy(data.get(), raw, raw_len);
+
+  QUICPathResponseFrame frame(std::move(data), QUICPathResponseFrame::DATA_LEN);
+  CHECK(frame.size() == 9);
+
+  frame.store(buf, &len);
+  CHECK(len == 9);
   CHECK(memcmp(buf, expected, len) == 0);
 }
 
 TEST_CASE("QUICFrameFactory Create Unknown Frame", "[quic]")
 {
   uint8_t buf1[] = {
-    0x0f, // Type
+    0x20, // Type
   };
   std::shared_ptr<const QUICFrame> frame1 = QUICFrameFactory::create(buf1, sizeof(buf1));
   CHECK(frame1 == nullptr);
@@ -1073,7 +1097,7 @@ TEST_CASE("QUICFrameFactory Fast Create Unknown Frame", "[quic]")
   QUICFrameFactory factory;
 
   uint8_t buf1[] = {
-    0x0f, // Type
+    0x20, // Type
   };
   std::shared_ptr<const QUICFrame> frame1 = factory.fast_create(buf1, sizeof(buf1));
   CHECK(frame1 == nullptr);
@@ -1255,9 +1279,7 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
   SECTION("PING frame")
   {
     uint8_t frame_buf[] = {
-      0x07,                                           // Type
-      0x08,                                           // Length
-      0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, // Data
+      0x07, // Type
     };
 
     QUICFrameUPtr frame = QUICFrameFactory::create(frame_buf, sizeof(frame_buf));
@@ -1267,7 +1289,7 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
     size_t len;
     frame->store(buf, &len);
 
-    CHECK(len == 10);
+    CHECK(len == 1);
     CHECK(memcmp(buf, frame_buf, len) == 0);
   }
 
@@ -1366,11 +1388,28 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
     CHECK(memcmp(buf, frame_buf, len) == 0);
   }
 
-  SECTION("PONG frame")
+  SECTION("PATH_CHALLENGE frame")
   {
     uint8_t frame_buf[] = {
-      0x0d,                                           // Type
-      0x08,                                           // Length
+      0x0e,                                           // Type
+      0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, // Data
+    };
+
+    QUICFrameUPtr frame = QUICFrameFactory::create(frame_buf, sizeof(frame_buf));
+    frame               = QUICFrameFactory::create_retransmission_frame(std::move(frame), *packet);
+
+    uint8_t buf[32] = {0};
+    size_t len;
+    frame->store(buf, &len);
+
+    CHECK(len == 9);
+    CHECK(memcmp(buf, frame_buf, len) == 0);
+  }
+
+  SECTION("PATH_RESPONSE frame")
+  {
+    uint8_t frame_buf[] = {
+      0x0f,                                           // Type
       0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, // Data
     };
 
@@ -1381,7 +1420,7 @@ TEST_CASE("Retransmit", "[quic][frame][retransmit]")
     size_t len;
     frame->store(buf, &len);
 
-    CHECK(len == 10);
+    CHECK(len == 9);
     CHECK(memcmp(buf, frame_buf, len) == 0);
   }
 }
diff --git a/iocore/net/quic/test/test_QUICKeyGenerator.cc b/iocore/net/quic/test/test_QUICKeyGenerator.cc
index f364f0c..1f94296 100644
--- a/iocore/net/quic/test/test_QUICKeyGenerator.cc
+++ b/iocore/net/quic/test/test_QUICKeyGenerator.cc
@@ -57,9 +57,9 @@ TEST_CASE("QUICKeyGenerator", "[quic]")
     QUICKeyGenerator keygen(QUICKeyGenerator::Context::CLIENT);
 
     QUICConnectionId cid          = 0x8394c8f03e515708;
-    uint8_t expected_client_key[] = {0x6b, 0x6a, 0xbc, 0x50, 0xf7, 0xac, 0x46, 0xd1,
-                                     0x10, 0x8c, 0x19, 0xcc, 0x63, 0x64, 0xbd, 0xe3};
-    uint8_t expected_client_iv[] = {0xb1, 0xf9, 0xa7, 0xe2, 0x7c, 0xc2, 0x33, 0xbb, 0x99, 0xe2, 0x03, 0x71};
+    uint8_t expected_client_key[] = {0x3a, 0xd0, 0x54, 0x2c, 0x4a, 0x85, 0x84, 0x74,
+                                     0x00, 0x63, 0x04, 0x9e, 0x3b, 0x3c, 0xaa, 0xb2};
+    uint8_t expected_client_iv[] = {0xd1, 0xfd, 0x26, 0x05, 0x42, 0x75, 0x3a, 0xba, 0x38, 0x58, 0x9b, 0xad};
 
     std::unique_ptr<KeyMaterial> actual_km = keygen.generate(cid);
 
@@ -74,9 +74,9 @@ TEST_CASE("QUICKeyGenerator", "[quic]")
     QUICKeyGenerator keygen(QUICKeyGenerator::Context::SERVER);
 
     QUICConnectionId cid          = 0x8394c8f03e515708;
-    uint8_t expected_server_key[] = {0x9e, 0xe7, 0xe8, 0x57, 0x72, 0x00, 0x59, 0xaf,
-                                     0x30, 0x11, 0xfb, 0x26, 0xe1, 0x21, 0x42, 0xc9};
-    uint8_t expected_server_iv[] = {0xd5, 0xee, 0xe8, 0xb5, 0x7c, 0x9e, 0xc7, 0xc4, 0xbe, 0x98, 0x4a, 0xa5};
+    uint8_t expected_server_key[] = {0xbe, 0xe4, 0xc2, 0x4d, 0x2a, 0xf1, 0x33, 0x80,
+                                     0xa9, 0xfa, 0x24, 0xa5, 0xe2, 0xba, 0x2c, 0xff};
+    uint8_t expected_server_iv[] = {0x25, 0xb5, 0x8e, 0x24, 0x6d, 0x9e, 0x7d, 0x5f, 0xfe, 0x43, 0x23, 0xfe};
 
     std::unique_ptr<KeyMaterial> actual_km = keygen.generate(cid);
 
diff --git a/iocore/net/quic/test/test_QUICPacket.cc b/iocore/net/quic/test/test_QUICPacket.cc
index 1d79ac2..3b95181 100644
--- a/iocore/net/quic/test/test_QUICPacket.cc
+++ b/iocore/net/quic/test/test_QUICPacket.cc
@@ -109,7 +109,7 @@ TEST_CASE("QUICPacketHeader - Short", "[quic]")
   SECTION("Short Header (load)")
   {
     const uint8_t input[] = {
-      0x1D,                                           // Short header with (C=0, K=0, Type=0x1D)
+      0x12,                                           // Short header with (C=0, K=0, Type=0x2)
       0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Connection ID
       0x12, 0x34, 0x56, 0x78,                         // Packet number
       0xff, 0xff,                                     // Payload (dummy)
@@ -132,7 +132,7 @@ TEST_CASE("QUICPacketHeader - Short", "[quic]")
     size_t len      = 0;
 
     const uint8_t expected[] = {
-      0x1D,                                           // Short header with (C=0, K=0, Type=0x1D)
+      0x12,                                           // Short header with (C=0, K=0, Type=0x2)
       0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Connection ID
       0x12, 0x34, 0x56, 0x78,                         // Packet number
       0x11, 0x22, 0x33, 0x44, 0x55,                   // Protected Payload
diff --git a/lib/ts/ink_inet.cc b/lib/ts/ink_inet.cc
index 9346923..947bf45 100644
--- a/lib/ts/ink_inet.cc
+++ b/lib/ts/ink_inet.cc
@@ -45,7 +45,7 @@ const ts::string_view IP_PROTO_TAG_HTTP_0_9("http/0.9"_sv);
 const ts::string_view IP_PROTO_TAG_HTTP_1_0("http/1.0"_sv);
 const ts::string_view IP_PROTO_TAG_HTTP_1_1("http/1.1"_sv);
 const ts::string_view IP_PROTO_TAG_HTTP_2_0("h2"_sv);     // HTTP/2 over TLS
-const ts::string_view IP_PROTO_TAG_HTTP_QUIC("hq-09"_sv); // HTTP over QUIC
+const ts::string_view IP_PROTO_TAG_HTTP_QUIC("hq-10"_sv); // HTTP over QUIC
 
 uint32_t
 ink_inet_addr(const char *s)

-- 
To stop receiving notification emails like this one, please contact
maskit@apache.org.