lsquic_packet_common.c revision 50aadb33
150aadb33SDmitri Tikhonov/* Copyright (c) 2017 LiteSpeed Technologies Inc.  See LICENSE. */
250aadb33SDmitri Tikhonov/*
350aadb33SDmitri Tikhonov * lsquic_packet_common.c -- some common packet-related routines
450aadb33SDmitri Tikhonov */
550aadb33SDmitri Tikhonov
650aadb33SDmitri Tikhonov#include <stdio.h>
750aadb33SDmitri Tikhonov#include <stdlib.h>
850aadb33SDmitri Tikhonov
950aadb33SDmitri Tikhonov#include "lsquic_logger.h"
1050aadb33SDmitri Tikhonov#include "lsquic_packet_common.h"
1150aadb33SDmitri Tikhonov
1250aadb33SDmitri Tikhonov
1350aadb33SDmitri Tikhonovstatic const char * const frame_type_2_str[N_QUIC_FRAMES] = {
1450aadb33SDmitri Tikhonov    [QUIC_FRAME_INVALID]           =  "QUIC_FRAME_INVALID",
1550aadb33SDmitri Tikhonov    [QUIC_FRAME_STREAM]            =  "QUIC_FRAME_STREAM",
1650aadb33SDmitri Tikhonov    [QUIC_FRAME_ACK]               =  "QUIC_FRAME_ACK",
1750aadb33SDmitri Tikhonov    [QUIC_FRAME_PADDING]           =  "QUIC_FRAME_PADDING",
1850aadb33SDmitri Tikhonov    [QUIC_FRAME_RST_STREAM]        =  "QUIC_FRAME_RST_STREAM",
1950aadb33SDmitri Tikhonov    [QUIC_FRAME_CONNECTION_CLOSE]  =  "QUIC_FRAME_CONNECTION_CLOSE",
2050aadb33SDmitri Tikhonov    [QUIC_FRAME_GOAWAY]            =  "QUIC_FRAME_GOAWAY",
2150aadb33SDmitri Tikhonov    [QUIC_FRAME_WINDOW_UPDATE]     =  "QUIC_FRAME_WINDOW_UPDATE",
2250aadb33SDmitri Tikhonov    [QUIC_FRAME_BLOCKED]           =  "QUIC_FRAME_BLOCKED",
2350aadb33SDmitri Tikhonov    [QUIC_FRAME_STOP_WAITING]      =  "QUIC_FRAME_STOP_WAITING",
2450aadb33SDmitri Tikhonov    [QUIC_FRAME_PING]              =  "QUIC_FRAME_PING",
2550aadb33SDmitri Tikhonov};
2650aadb33SDmitri Tikhonov
2750aadb33SDmitri Tikhonov
2850aadb33SDmitri Tikhonov#define SLEN(x) (sizeof(#x) - sizeof("QUIC_FRAME_"))
2950aadb33SDmitri Tikhonov
3050aadb33SDmitri Tikhonov
3150aadb33SDmitri Tikhonovconst size_t lsquic_frame_types_str_sz =
3250aadb33SDmitri Tikhonov    /* We don't need to include INVALID frame in this list because it is
3350aadb33SDmitri Tikhonov     * never a part of any frame list bitmask (e.g. po_frame_types).
3450aadb33SDmitri Tikhonov     */
3550aadb33SDmitri Tikhonov    SLEN(QUIC_FRAME_STREAM)           + 1 +
3650aadb33SDmitri Tikhonov    SLEN(QUIC_FRAME_ACK)              + 1 +
3750aadb33SDmitri Tikhonov    SLEN(QUIC_FRAME_PADDING)          + 1 +
3850aadb33SDmitri Tikhonov    SLEN(QUIC_FRAME_RST_STREAM)       + 1 +
3950aadb33SDmitri Tikhonov    SLEN(QUIC_FRAME_CONNECTION_CLOSE) + 1 +
4050aadb33SDmitri Tikhonov    SLEN(QUIC_FRAME_GOAWAY)           + 1 +
4150aadb33SDmitri Tikhonov    SLEN(QUIC_FRAME_WINDOW_UPDATE)    + 1 +
4250aadb33SDmitri Tikhonov    SLEN(QUIC_FRAME_BLOCKED)          + 1 +
4350aadb33SDmitri Tikhonov    SLEN(QUIC_FRAME_STOP_WAITING)     + 1 +
4450aadb33SDmitri Tikhonov    SLEN(QUIC_FRAME_PING)             + 1;
4550aadb33SDmitri Tikhonov
4650aadb33SDmitri Tikhonov
4750aadb33SDmitri Tikhonovconst char *
4850aadb33SDmitri Tikhonovlsquic_frame_types_to_str (char *buf, size_t bufsz, short frame_types)
4950aadb33SDmitri Tikhonov{
5050aadb33SDmitri Tikhonov    char *p;
5150aadb33SDmitri Tikhonov    int i, w;
5250aadb33SDmitri Tikhonov    size_t sz;
5350aadb33SDmitri Tikhonov
5450aadb33SDmitri Tikhonov    if (bufsz > 0)
5550aadb33SDmitri Tikhonov        buf[0] = '\0';
5650aadb33SDmitri Tikhonov
5750aadb33SDmitri Tikhonov    p = buf;
5850aadb33SDmitri Tikhonov    for (i = 0; i < N_QUIC_FRAMES; ++i)
5950aadb33SDmitri Tikhonov    {
6050aadb33SDmitri Tikhonov        if (frame_types & (1 << i))
6150aadb33SDmitri Tikhonov        {
6250aadb33SDmitri Tikhonov            sz = bufsz - (p - buf);
6350aadb33SDmitri Tikhonov            w = snprintf(p, sz, "%.*s%s", p > buf, " ",
6450aadb33SDmitri Tikhonov                            frame_type_2_str[i] + sizeof("QUIC_FRAME_") - 1);
6550aadb33SDmitri Tikhonov            if (w > (int) sz)
6650aadb33SDmitri Tikhonov            {
6750aadb33SDmitri Tikhonov                LSQ_WARN("not enough room for all frame types");
6850aadb33SDmitri Tikhonov                break;
6950aadb33SDmitri Tikhonov            }
7050aadb33SDmitri Tikhonov            p += w;
7150aadb33SDmitri Tikhonov        }
7250aadb33SDmitri Tikhonov        frame_types &= ~(1 << i);
7350aadb33SDmitri Tikhonov    }
7450aadb33SDmitri Tikhonov
7550aadb33SDmitri Tikhonov    return buf;
7650aadb33SDmitri Tikhonov}
7750aadb33SDmitri Tikhonov
7850aadb33SDmitri Tikhonov
7950aadb33SDmitri Tikhonovenum lsquic_packno_bits
8050aadb33SDmitri Tikhonovcalc_packno_bits (lsquic_packno_t packno, lsquic_packno_t least_unacked,
8150aadb33SDmitri Tikhonov                  uint64_t n_in_flight)
8250aadb33SDmitri Tikhonov{
8350aadb33SDmitri Tikhonov    uint64_t delta;
8450aadb33SDmitri Tikhonov    unsigned bits;
8550aadb33SDmitri Tikhonov
8650aadb33SDmitri Tikhonov    delta = packno - least_unacked;
8750aadb33SDmitri Tikhonov    if (n_in_flight > delta)
8850aadb33SDmitri Tikhonov        delta = n_in_flight;
8950aadb33SDmitri Tikhonov
9050aadb33SDmitri Tikhonov    delta *= 4;
9150aadb33SDmitri Tikhonov    bits = (delta > (1ULL <<  8))
9250aadb33SDmitri Tikhonov         + (delta > (1ULL << 16))
9350aadb33SDmitri Tikhonov         + (delta > (1ULL << 32));
9450aadb33SDmitri Tikhonov
9550aadb33SDmitri Tikhonov    return bits;
9650aadb33SDmitri Tikhonov}
9750aadb33SDmitri Tikhonov
9850aadb33SDmitri Tikhonov
9950aadb33SDmitri Tikhonovlsquic_packno_t
10050aadb33SDmitri Tikhonovrestore_packno (lsquic_packno_t cur_packno,
10150aadb33SDmitri Tikhonov                enum lsquic_packno_bits cur_packno_bits,
10250aadb33SDmitri Tikhonov                lsquic_packno_t max_packno)
10350aadb33SDmitri Tikhonov{
10450aadb33SDmitri Tikhonov    lsquic_packno_t candidates[3], epoch_delta;
10550aadb33SDmitri Tikhonov    int64_t diffs[3];
10650aadb33SDmitri Tikhonov    unsigned min, len;
10750aadb33SDmitri Tikhonov
10850aadb33SDmitri Tikhonov    len = packno_bits2len(cur_packno_bits);
10950aadb33SDmitri Tikhonov    epoch_delta = 1ULL << (len << 3);
11050aadb33SDmitri Tikhonov    candidates[1] = (max_packno & ~(epoch_delta - 1)) + cur_packno;
11150aadb33SDmitri Tikhonov    candidates[0] = candidates[1] - epoch_delta;
11250aadb33SDmitri Tikhonov    candidates[2] = candidates[1] + epoch_delta;
11350aadb33SDmitri Tikhonov
11450aadb33SDmitri Tikhonov    diffs[0] = llabs((int64_t) candidates[0] - (int64_t) max_packno);
11550aadb33SDmitri Tikhonov    diffs[1] = llabs((int64_t) candidates[1] - (int64_t) max_packno);
11650aadb33SDmitri Tikhonov    diffs[2] = llabs((int64_t) candidates[2] - (int64_t) max_packno);
11750aadb33SDmitri Tikhonov
11850aadb33SDmitri Tikhonov    min = diffs[1] < diffs[0];
11950aadb33SDmitri Tikhonov    if (diffs[2] < diffs[min])
12050aadb33SDmitri Tikhonov        min = 2;
12150aadb33SDmitri Tikhonov
12250aadb33SDmitri Tikhonov    return candidates[min];
12350aadb33SDmitri Tikhonov}
124