iT邦幫忙

2022 iThome 鐵人賽

DAY 18
0
Modern Web

快還要更快,讀作 quick 的下一代傳輸層協定: QUIC系列 第 18

【Day 18】Connection Migration(四): ngtcp2 connection migration 片段導讀

  • 分享至 

  • xImage
  •  

前言

昨天我們講解了 Connection Migration 的概念,今天就來帶著讀者簡單看一下對應的 Source code 實現在哪個 function,讓有興趣的讀者可以繼續往下 trace 細節,大概講一下 ngtcp2 中哪幾個 function 負責做 Connection migration,就可以往下研究了(如果研究出心得記得交流一下)

Connection migration

在 ngtcp2 中 Client 要執行 Connection migration 可以呼叫 ngtcp2_conn_initiate_immediate_migration 或者 ngtcp2_conn_initiate_migrationngtcp2_conn_initiate_immediate_migration 遷移前不會執行 path validation, 無法確認 reachabilityngtcp2_conn_initiate_migration 在執行前會執行 path validation 的動作確保 reachability

ngtcp2_conn_initiate_migration

int ngtcp2_conn_initiate_migration(ngtcp2_conn *conn, const ngtcp2_path *path,
                                   ngtcp2_tstamp ts) {
  int rv;
  ngtcp2_dcid *dcid;
  ngtcp2_duration pto, initial_pto, timeout;
  ngtcp2_pv *pv;

  assert(!conn->server);

  conn->log.last_ts = ts;
  conn->qlog.last_ts = ts;

  rv = conn_initiate_migration_precheck(conn, &path->local);
  if (rv != 0) {
    return rv;
  }

  if (conn->pv) {
    rv = conn_abort_pv(conn, ts);
    if (rv != 0) {
      return rv;
    }
  }

  dcid = ngtcp2_ringbuf_get(&conn->dcid.unused.rb, 0);
  ngtcp2_dcid_set_path(dcid, path);

  pto = conn_compute_pto(conn, &conn->pktns);
  initial_pto = conn_compute_initial_pto(conn, &conn->pktns);
  timeout = 3 * ngtcp2_max(pto, initial_pto);

  rv = ngtcp2_pv_new(&pv, dcid, timeout, NGTCP2_PV_FLAG_NONE, &conn->log,
                     conn->mem);
  if (rv != 0) {
    return rv;
  }

  ngtcp2_ringbuf_pop_front(&conn->dcid.unused.rb);
  conn->pv = pv;

  return conn_call_activate_dcid(conn, &pv->dcid);
}

ngtcp2_conn_initiate_immediate_migration

int ngtcp2_conn_initiate_immediate_migration(ngtcp2_conn *conn,
                                             const ngtcp2_path *path,
                                             ngtcp2_tstamp ts) {
  int rv;
  ngtcp2_dcid *dcid;
  ngtcp2_duration pto, initial_pto, timeout;
  ngtcp2_pv *pv;

  assert(!conn->server);

  conn->log.last_ts = ts;
  conn->qlog.last_ts = ts;

  rv = conn_initiate_migration_precheck(conn, &path->local);
  if (rv != 0) {
    return rv;
  }

  ngtcp2_conn_stop_pmtud(conn);

  if (conn->pv) {
    rv = conn_abort_pv(conn, ts);
    if (rv != 0) {
      return rv;
    }
  }

  rv = conn_retire_dcid(conn, &conn->dcid.current, ts);
  if (rv != 0) {
    return rv;
  }

  dcid = ngtcp2_ringbuf_get(&conn->dcid.unused.rb, 0);
  ngtcp2_dcid_set_path(dcid, path);

  ngtcp2_dcid_copy(&conn->dcid.current, dcid);
  ngtcp2_ringbuf_pop_front(&conn->dcid.unused.rb);

  conn_reset_congestion_state(conn, ts);
  conn_reset_ecn_validation_state(conn);

  pto = conn_compute_pto(conn, &conn->pktns);
  initial_pto = conn_compute_initial_pto(conn, &conn->pktns);
  timeout = 3 * ngtcp2_max(pto, initial_pto);

  /* TODO It might be better to add a new flag which indicates that a
     connection should be closed if this path validation failed.  The
     current design allows an application to continue, by migrating
     into yet another path. */
  rv = ngtcp2_pv_new(&pv, dcid, timeout, NGTCP2_PV_FLAG_NONE, &conn->log,
                     conn->mem);
  if (rv != 0) {
    return rv;
  }

  conn->pv = pv;

  return conn_call_activate_dcid(conn, &conn->dcid.current);
}

在程式碼片段中常看到關於 ngtcp2_pv 這個 struct 是專門負責存放 path validation 相關資料的,詳細請看 ngtcp2_pv.h, ngtcp2_pv.c 這兩個檔案。


上一篇
【Day 17】Connection Migration(三): 流程簡介
下一篇
【Day 19】Connection Migration(四): 可能會出現的安全問題
系列文
快還要更快,讀作 quick 的下一代傳輸層協定: QUIC23
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言