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