1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */ 250aadb33SDmitri Tikhonov/* 350aadb33SDmitri Tikhonov * lsquic_packet_in.h 450aadb33SDmitri Tikhonov */ 550aadb33SDmitri Tikhonov 650aadb33SDmitri Tikhonov#ifndef LSQUIC_PACKET_IN_H 750aadb33SDmitri Tikhonov#define LSQUIC_PACKET_IN_H 1 850aadb33SDmitri Tikhonov 95392f7a3SLiteSpeed Tech 1050aadb33SDmitri Tikhonovstruct lsquic_packet_in; 115392f7a3SLiteSpeed Techstruct lsquic_cid; 125392f7a3SLiteSpeed Tech 1350aadb33SDmitri Tikhonov 1450aadb33SDmitri Tikhonovstruct data_frame 1550aadb33SDmitri Tikhonov{ 1650aadb33SDmitri Tikhonov const unsigned char *df_data; /* Pointer to data */ 1750aadb33SDmitri Tikhonov uint64_t df_offset; /* Stream offset */ 1850aadb33SDmitri Tikhonov uint16_t df_read_off; /* Read offset */ 1950aadb33SDmitri Tikhonov uint16_t df_size; /* Size of df_data */ 2050aadb33SDmitri Tikhonov signed char df_fin; /* FIN? */ 2150aadb33SDmitri Tikhonov}; 2250aadb33SDmitri Tikhonov 235392f7a3SLiteSpeed Tech 2450aadb33SDmitri Tikhonovtypedef struct stream_frame 2550aadb33SDmitri Tikhonov{ 26eea99896SDmitri Tikhonov /* Stream frames are stored in a list inside "di nocopy" (if "di nocopy" 27eea99896SDmitri Tikhonov * is used). 28eea99896SDmitri Tikhonov */ 2950aadb33SDmitri Tikhonov TAILQ_ENTRY(stream_frame) next_frame; 3050aadb33SDmitri Tikhonov 31eea99896SDmitri Tikhonov /* `data_frame.df_data' points somewhere into the packet payload. The 32eea99896SDmitri Tikhonov * packet object is reference-counted. When the frame is freed, the 33eea99896SDmitri Tikhonov * packet is released via lsquic_packet_in_put(). 3450aadb33SDmitri Tikhonov */ 3550aadb33SDmitri Tikhonov struct lsquic_packet_in *packet_in; 3650aadb33SDmitri Tikhonov 3750aadb33SDmitri Tikhonov struct data_frame data_frame; 3850aadb33SDmitri Tikhonov 395392f7a3SLiteSpeed Tech lsquic_stream_id_t stream_id; /* Parsed from packet */ 4050aadb33SDmitri Tikhonov} stream_frame_t; 4150aadb33SDmitri Tikhonov 425392f7a3SLiteSpeed Tech 435392f7a3SLiteSpeed Tech#define DF_OFF(frame) (frame)->data_frame.df_offset 445392f7a3SLiteSpeed Tech#define DF_ROFF(frame) (DF_OFF(frame) + (frame)->data_frame.df_read_off) 455392f7a3SLiteSpeed Tech#define DF_FIN(frame) (frame)->data_frame.df_fin 465392f7a3SLiteSpeed Tech#define DF_SIZE(frame) (frame)->data_frame.df_size 475392f7a3SLiteSpeed Tech#define DF_END(frame) (DF_OFF(frame) + DF_SIZE(frame)) 485392f7a3SLiteSpeed Tech 495392f7a3SLiteSpeed Tech 5050aadb33SDmitri Tikhonovtypedef struct lsquic_packet_in 5150aadb33SDmitri Tikhonov{ 5250aadb33SDmitri Tikhonov TAILQ_ENTRY(lsquic_packet_in) pi_next; 5350aadb33SDmitri Tikhonov lsquic_time_t pi_received; /* Time received */ 545392f7a3SLiteSpeed Tech lsquic_cid_t pi_dcid; 555392f7a3SLiteSpeed Tech#define pi_conn_id pi_dcid 5650aadb33SDmitri Tikhonov lsquic_packno_t pi_packno; 575392f7a3SLiteSpeed Tech enum quic_ft_bit pi_frame_types; 5850aadb33SDmitri Tikhonov unsigned short pi_header_sz; /* Points to payload */ 5950aadb33SDmitri Tikhonov unsigned short pi_data_sz; /* Data plus header */ 6050aadb33SDmitri Tikhonov /* A packet may be referred to by one or more frames and packets_in 6150aadb33SDmitri Tikhonov * list. 6250aadb33SDmitri Tikhonov */ 6350aadb33SDmitri Tikhonov unsigned short pi_refcnt; 6450aadb33SDmitri Tikhonov unsigned short pi_hsk_stream; /* Offset to handshake stream 6550aadb33SDmitri Tikhonov * frame, only valid if 6650aadb33SDmitri Tikhonov * PI_HSK_STREAM is set. 6750aadb33SDmitri Tikhonov */ 6850aadb33SDmitri Tikhonov enum { 6950aadb33SDmitri Tikhonov PI_DECRYPTED = (1 << 0), 7050aadb33SDmitri Tikhonov PI_OWN_DATA = (1 << 1), /* We own pi_data */ 7150aadb33SDmitri Tikhonov PI_CONN_ID = (1 << 2), /* pi_conn_id is set */ 725392f7a3SLiteSpeed Tech PI_HSK_STREAM = (1 << 3), /* Has handshake data (mini only) */ 735392f7a3SLiteSpeed Tech PI_FROM_MINI = (1 << 4), /* Handed off by mini connection */ 74c51ce338SDmitri Tikhonov#define PIBIT_ENC_LEV_SHIFT 5 75c51ce338SDmitri Tikhonov PI_ENC_LEV_BIT_0= (1 << 5), /* Encodes encryption level */ 76c51ce338SDmitri Tikhonov PI_ENC_LEV_BIT_1= (1 << 6), /* (see enum enc_level). */ 779626cfc2SDmitri Tikhonov PI_GQUIC = (1 << 7), 785392f7a3SLiteSpeed Tech PI_UNUSED_8 = (1 << 8), /* <-- hole, reuse me! */ 795392f7a3SLiteSpeed Tech#define PIBIT_ECN_SHIFT 9 805392f7a3SLiteSpeed Tech PI_ECN_BIT_0 = (1 << 9), 815392f7a3SLiteSpeed Tech PI_ECN_BIT_1 = (1 <<10), 825392f7a3SLiteSpeed Tech#define PIBIT_SPIN_SHIFT 11 835392f7a3SLiteSpeed Tech PI_SPIN_BIT = (1 <<11), 845392f7a3SLiteSpeed Tech#define PIBIT_BITS_SHIFT 12 855392f7a3SLiteSpeed Tech PI_BITS_BIT_0 = (1 <<12), 865392f7a3SLiteSpeed Tech PI_BITS_BIT_1 = (1 <<13), 8702b6086dSDmitri Tikhonov /* Square bit and loss bit flags are used for logging */ 8802b6086dSDmitri Tikhonov PI_LOG_QL_BITS = (1 <<14), 8902b6086dSDmitri Tikhonov PI_SQUARE_BIT = (1 <<15), 9002b6086dSDmitri Tikhonov PI_LOSS_BIT = (1 <<16), 9102b6086dSDmitri Tikhonov } pi_flags; 925392f7a3SLiteSpeed Tech /* pi_token and pi_token_size are set in Initial and Retry packets */ 935392f7a3SLiteSpeed Tech unsigned short pi_token_size; /* Size of the token */ 945392f7a3SLiteSpeed Tech unsigned char pi_token; /* Offset to token */ 959fc12041SDmitri Tikhonov /* pi_odcid and pi_odcid_len are only set in Retry packets for I-D < 25 */ 965392f7a3SLiteSpeed Tech unsigned char pi_odcid; /* Offset to Original DCID */ 975392f7a3SLiteSpeed Tech unsigned char pi_odcid_len; /* Size of ODCID */ 985392f7a3SLiteSpeed Tech unsigned char pi_scid_off; /* Offset to SCID */ 995392f7a3SLiteSpeed Tech unsigned char pi_scid_len; /* Size of SCID */ 1005392f7a3SLiteSpeed Tech unsigned char pi_quic_ver; /* Offset to QUIC version */ 1015392f7a3SLiteSpeed Tech unsigned char pi_nonce; /* Offset to nonce */ 1029626cfc2SDmitri Tikhonov enum header_type pi_header_type:8; 1035392f7a3SLiteSpeed Tech unsigned char pi_path_id; 10450aadb33SDmitri Tikhonov /* If PI_OWN_DATA flag is not set, `pi_data' points to user-supplied 10550aadb33SDmitri Tikhonov * packet data, which is NOT TO BE MODIFIED. 10650aadb33SDmitri Tikhonov */ 10750aadb33SDmitri Tikhonov unsigned char *pi_data; 10850aadb33SDmitri Tikhonov} lsquic_packet_in_t; 10950aadb33SDmitri Tikhonov 1105392f7a3SLiteSpeed Tech 11150aadb33SDmitri Tikhonov#define lsquic_packet_in_public_flags(p) ((p)->pi_data[0]) 11250aadb33SDmitri Tikhonov 1139626cfc2SDmitri Tikhonov#define lsquic_packet_in_is_gquic_prst(p) \ 1149626cfc2SDmitri Tikhonov (((p)->pi_flags & PI_GQUIC) \ 1159626cfc2SDmitri Tikhonov && (lsquic_packet_in_public_flags(p) & PACKET_PUBLIC_FLAGS_RST)) 1169626cfc2SDmitri Tikhonov 1179626cfc2SDmitri Tikhonov#define lsquic_packet_in_is_verneg(p) \ 1189626cfc2SDmitri Tikhonov (((p)->pi_flags & PI_GQUIC) ? \ 1199626cfc2SDmitri Tikhonov lsquic_packet_in_public_flags(p) & PACKET_PUBLIC_FLAGS_VERSION : \ 1209626cfc2SDmitri Tikhonov (p)->pi_header_type == HETY_VERNEG) 12150aadb33SDmitri Tikhonov 12250aadb33SDmitri Tikhonov#define lsquic_packet_in_packno_bits(p) \ 123c7d81ce1SDmitri Tikhonov (((p)->pi_flags >> PIBIT_BITS_SHIFT) & 3) 12450aadb33SDmitri Tikhonov 12550aadb33SDmitri Tikhonov#define lsquic_packet_in_upref(p) (++(p)->pi_refcnt) 12650aadb33SDmitri Tikhonov 12750aadb33SDmitri Tikhonov#define lsquic_packet_in_get(p) (lsquic_packet_in_upref(p), (p)) 12850aadb33SDmitri Tikhonov 12950aadb33SDmitri Tikhonov#define lsquic_packet_in_nonce(p) \ 13050aadb33SDmitri Tikhonov ((p)->pi_nonce ? (p)->pi_data + (p)->pi_nonce : NULL) 13150aadb33SDmitri Tikhonov 132c51ce338SDmitri Tikhonov#define lsquic_packet_in_enc_level(p) \ 133c51ce338SDmitri Tikhonov (((p)->pi_flags >> PIBIT_ENC_LEV_SHIFT) & 0x3) 134c51ce338SDmitri Tikhonov 1355392f7a3SLiteSpeed Tech#define lsquic_packet_in_ecn(p) \ 1365392f7a3SLiteSpeed Tech (((p)->pi_flags >> PIBIT_ECN_SHIFT) & 0x3) 1375392f7a3SLiteSpeed Tech 1385392f7a3SLiteSpeed Tech#define lsquic_packet_in_spin_bit(p) (((p)->pi_flags & PI_SPIN_BIT) > 0) 1395392f7a3SLiteSpeed Tech 1405392f7a3SLiteSpeed Tech/* PATH_CHALLENGE, PATH_RESPONSE, NEW_CONNECTION_ID, and PADDING frames 1415392f7a3SLiteSpeed Tech * are "probing frames", and all other frames are "non-probing frames". 1425392f7a3SLiteSpeed Tech * A packet containing only probing frames is a "probing packet", and a 1435392f7a3SLiteSpeed Tech * packet containing any other frame is a "non-probing packet". 1445392f7a3SLiteSpeed Tech * 1455392f7a3SLiteSpeed Tech * [draft-ietf-quic-transport-20], Section 9.1 1465392f7a3SLiteSpeed Tech */ 1475392f7a3SLiteSpeed Tech#define lsquic_packet_in_non_probing(p) \ 1485392f7a3SLiteSpeed Tech (!!((p)->pi_frame_types & ~(QUIC_FTBIT_PATH_CHALLENGE \ 1495392f7a3SLiteSpeed Tech |QUIC_FTBIT_PATH_RESPONSE|QUIC_FTBIT_PADDING \ 1505392f7a3SLiteSpeed Tech |QUIC_FTBIT_NEW_CONNECTION_ID))) 1515392f7a3SLiteSpeed Tech 15250aadb33SDmitri Tikhonov/* The version iterator is used on a version negotiation packet only. 15350aadb33SDmitri Tikhonov * The iterator functions return 1 when next version is returned and 15450aadb33SDmitri Tikhonov * 0 when there are no more versions. 15550aadb33SDmitri Tikhonov */ 15650aadb33SDmitri Tikhonovstruct ver_iter 15750aadb33SDmitri Tikhonov{ 15850aadb33SDmitri Tikhonov const struct lsquic_packet_in *packet_in; 15950aadb33SDmitri Tikhonov unsigned off; 16050aadb33SDmitri Tikhonov}; 16150aadb33SDmitri Tikhonov 16250aadb33SDmitri Tikhonovint 163a5fa05f9SDmitri Tikhonovlsquic_packet_in_ver_first (const lsquic_packet_in_t *packet_in, 164a5fa05f9SDmitri Tikhonov struct ver_iter *, lsquic_ver_tag_t *ver_tag); 16550aadb33SDmitri Tikhonov 16650aadb33SDmitri Tikhonovint 167a5fa05f9SDmitri Tikhonovlsquic_packet_in_ver_next (struct ver_iter *, lsquic_ver_tag_t *ver_tag); 16850aadb33SDmitri Tikhonov 169c51ce338SDmitri Tikhonovsize_t 170c51ce338SDmitri Tikhonovlsquic_packet_in_mem_used (const struct lsquic_packet_in *); 171c51ce338SDmitri Tikhonov 1725392f7a3SLiteSpeed Techvoid 1735392f7a3SLiteSpeed Techlsquic_scid_from_packet_in (const struct lsquic_packet_in *, 1745392f7a3SLiteSpeed Tech struct lsquic_cid *); 1755392f7a3SLiteSpeed Tech 17650aadb33SDmitri Tikhonov#endif 177