quic.h revision d1b9e706
1/*
2 * Copyright (c) 2019 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef __included_quic_h__
17#define __included_quic_h__
18
19#include <vnet/session/application_interface.h>
20
21#include <vppinfra/lock.h>
22#include <vppinfra/tw_timer_1t_3w_1024sl_ov.h>
23#include <vppinfra/bihash_16_8.h>
24
25#include <quicly.h>
26
27/* QUIC log levels
28 * 1 - errors
29 * 2 - connection/stream events
30 * 3 - packet events
31 * 4 - timer events
32 **/
33
34#define QUIC_DEBUG               0
35#define QUIC_TSTAMP_RESOLUTION  0.001	/* QUIC tick resolution (1ms) */
36#define QUIC_TIMER_HANDLE_INVALID ((u32) ~0)
37#define QUIC_SESSION_INVALID ((u32) ~0 - 1)
38#define QUIC_MAX_PACKET_SIZE 1280
39
40#define QUIC_INT_MAX  0x3FFFFFFFFFFFFFFF
41#define QUIC_DEFAULT_FIFO_SIZE (64 << 10)
42#define QUIC_SEND_PACKET_VEC_SIZE 16
43#define QUIC_IV_LEN 17
44
45#define QUIC_SEND_MAX_BATCH_PACKETS 16
46#define QUIC_RCV_MAX_BATCH_PACKETS 16
47#define QUIC_DEFAULT_CONN_TIMEOUT (30 * 1000)	/* 30 seconds */
48
49/* Taken from quicly.c */
50#define QUICLY_QUIC_BIT 0x40
51
52#define QUICLY_PACKET_TYPE_INITIAL (QUICLY_LONG_HEADER_BIT | QUICLY_QUIC_BIT | 0)
53#define QUICLY_PACKET_TYPE_0RTT (QUICLY_LONG_HEADER_BIT | QUICLY_QUIC_BIT | 0x10)
54#define QUICLY_PACKET_TYPE_HANDSHAKE (QUICLY_LONG_HEADER_BIT | QUICLY_QUIC_BIT | 0x20)
55#define QUICLY_PACKET_TYPE_RETRY (QUICLY_LONG_HEADER_BIT | QUICLY_QUIC_BIT | 0x30)
56#define QUICLY_PACKET_TYPE_BITMASK 0xf0
57
58/* error codes */
59#define QUIC_ERROR_FULL_FIFO 0xff10
60#define QUIC_APP_ERROR_CLOSE_NOTIFY QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0)
61#define QUIC_APP_ALLOCATION_ERROR QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x1)
62#define QUIC_APP_ACCEPT_NOTIFY_ERROR QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x2)
63#define QUIC_APP_CONNECT_NOTIFY_ERROR QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x3)
64
65#if QUIC_DEBUG
66#define QUIC_DBG(_lvl, _fmt, _args...)   \
67  if (_lvl <= QUIC_DEBUG)                \
68    clib_warning (_fmt, ##_args)
69#else
70#define QUIC_DBG(_lvl, _fmt, _args...)
71#endif
72
73#if CLIB_ASSERT_ENABLE
74#define QUIC_ASSERT(truth) ASSERT (truth)
75#else
76#define QUIC_ASSERT(truth)                        \
77  do {                                            \
78    if (PREDICT_FALSE (! (truth)))                \
79      QUIC_ERR ("ASSERT(%s) failed", # truth);    \
80  } while (0)
81#endif
82
83#define QUIC_ERR(_fmt, _args...)                \
84  do {                                          \
85    clib_warning ("QUIC-ERR: " _fmt, ##_args);  \
86  } while (0)
87
88
89
90extern vlib_node_registration_t quic_input_node;
91
92typedef enum
93{
94#define quic_error(n,s) QUIC_ERROR_##n,
95#include <plugins/quic/quic_error.def>
96#undef quic_error
97  QUIC_N_ERROR,
98} quic_error_t;
99
100typedef enum quic_ctx_conn_state_
101{
102  QUIC_CONN_STATE_OPENED,
103  QUIC_CONN_STATE_HANDSHAKE,
104  QUIC_CONN_STATE_READY,
105  QUIC_CONN_STATE_PASSIVE_CLOSING,
106  QUIC_CONN_STATE_PASSIVE_CLOSING_APP_CLOSED,
107  QUIC_CONN_STATE_PASSIVE_CLOSING_QUIC_CLOSED,
108  QUIC_CONN_STATE_ACTIVE_CLOSING,
109} quic_ctx_conn_state_t;
110
111typedef enum quic_packet_type_
112{
113  QUIC_PACKET_TYPE_NONE,
114  QUIC_PACKET_TYPE_RECEIVE,
115  QUIC_PACKET_TYPE_MIGRATE,
116  QUIC_PACKET_TYPE_ACCEPT,
117  QUIC_PACKET_TYPE_RESET,
118  QUIC_PACKET_TYPE_DROP,
119} quic_packet_type_t;
120
121typedef enum quic_ctx_flags_
122{
123  QUIC_F_IS_STREAM = (1 << 0),
124  QUIC_F_IS_LISTENER = (1 << 1),
125} quic_ctx_flags_t;
126
127/* This structure is used to implement the concept of VPP connection for QUIC.
128 * We create one per connection and one per stream. */
129typedef struct quic_ctx_
130{
131  union
132  {
133    transport_connection_t connection;
134    struct
135    {	      /** QUIC ctx case */
136      quicly_conn_t *conn;
137      u32 listener_ctx_id;
138      u32 client_opaque;
139      u8 *srv_hostname;
140      u8 conn_state;
141      u8 udp_is_ip4;
142      u8 _qctx_end_marker;	/* Leave this at the end */
143    };
144    struct
145    {	      /** STREAM ctx case */
146      quicly_stream_t *stream;
147      u32 quic_connection_ctx_id;
148      u8 _sctx_end_marker;	/* Leave this at the end */
149    };
150  };
151  session_handle_t udp_session_handle;
152  u32 timer_handle;
153  u32 parent_app_wrk_id;
154  u32 parent_app_id;
155  u32 ckpair_index;
156  u32 crypto_engine;
157  u32 crypto_context_index;
158  u8 flags;
159} quic_ctx_t;
160
161/* Make sure our custom fields don't overlap with the fields we use in
162   .connection
163*/
164STATIC_ASSERT (offsetof (quic_ctx_t, _qctx_end_marker) <=
165	       TRANSPORT_CONN_ID_LEN,
166	       "connection data must be less than TRANSPORT_CONN_ID_LEN bytes");
167STATIC_ASSERT (offsetof (quic_ctx_t, _sctx_end_marker) <=
168	       TRANSPORT_CONN_ID_LEN,
169	       "connection data must be less than TRANSPORT_CONN_ID_LEN bytes");
170
171/* single-entry session cache */
172typedef struct quic_session_cache_
173{
174  ptls_encrypt_ticket_t super;
175  uint8_t id[32];
176  ptls_iovec_t data;
177} quic_session_cache_t;
178
179typedef struct quic_stream_data_
180{
181  u32 ctx_id;
182  u32 thread_index;
183  u32 app_rx_data_len;		/**< bytes received, to be read by external app */
184  u32 app_tx_data_len;		/**< bytes sent */
185} quic_stream_data_t;
186
187typedef struct quic_crypto_context_data_
188{
189  quicly_context_t quicly_ctx;
190  char cid_key[QUIC_IV_LEN];
191  ptls_context_t ptls_ctx;
192} quic_crypto_context_data_t;
193
194typedef struct quic_worker_ctx_
195{
196  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
197  int64_t time_now;				   /**< worker time */
198  tw_timer_wheel_1t_3w_1024sl_ov_t timer_wheel;	   /**< worker timer wheel */
199  quicly_cid_plaintext_t next_cid;
200  crypto_context_t *crypto_ctx_pool;		/**< per thread pool of crypto contexes */
201  clib_bihash_24_8_t crypto_context_hash;	/**< per thread [params:crypto_ctx_index] hash */
202} quic_worker_ctx_t;
203
204typedef struct quic_rx_packet_ctx_
205{
206  quicly_decoded_packet_t packet;
207  u8 data[QUIC_MAX_PACKET_SIZE];
208  u32 ctx_index;
209  u32 thread_index;
210  union
211  {
212    struct sockaddr sa;
213    struct sockaddr_in6 sa6;
214  };
215  socklen_t salen;
216  u8 ptype;
217  session_dgram_hdr_t ph;
218} quic_rx_packet_ctx_t;
219
220typedef struct quic_main_
221{
222  u32 app_index;
223  quic_ctx_t **ctx_pool;
224  quic_worker_ctx_t *wrk_ctx;
225  clib_bihash_16_8_t connection_hash;	/**< quic connection id -> conn handle */
226  f64 tstamp_ticks_per_clock;
227
228  ptls_cipher_suite_t ***quic_ciphers;	/**< available ciphers by crypto engine */
229  uword *available_crypto_engines;	/**< Bitmap for registered engines */
230  u8 default_crypto_engine;		/**< Used if you do connect with CRYPTO_ENGINE_NONE (0) */
231
232  ptls_handshake_properties_t hs_properties;
233  quic_session_cache_t session_cache;
234
235  u32 udp_fifo_size;
236  u32 udp_fifo_prealloc;
237  u32 connection_timeout;
238} quic_main_t;
239
240#endif /* __included_quic_h__ */
241
242/*
243 * fd.io coding-style-patch-verification: ON
244 *
245 * Local Variables:
246 * eval: (c-set-style "gnu")
247 * End:
248 */
249