wireguard: add dos mitigation support
[vpp.git] / src / plugins / wireguard / wireguard_if.h
1 /*
2  * Copyright (c) 2020 Cisco and/or its affiliates.
3  * Copyright (c) 2020 Doc.ai and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef __WG_ITF_H__
18 #define __WG_ITF_H__
19
20 #include <wireguard/wireguard_index_table.h>
21 #include <wireguard/wireguard_messages.h>
22
23 typedef struct wg_if_t_
24 {
25   int user_instance;
26   u32 sw_if_index;
27
28   // Interface params
29   /* noise_local_pool elt index */
30   u32 local_idx;
31   cookie_checker_t cookie_checker;
32   u16 port;
33
34   /* Source IP address for originated packets */
35   ip_address_t src_ip;
36
37   /* hash table of peers on this link */
38   uword *peers;
39
40   /* Under load params */
41   f64 handshake_counting_end;
42   u32 handshake_num;
43 } wg_if_t;
44
45
46 int wg_if_create (u32 user_instance,
47                   const u8 private_key_64[NOISE_PUBLIC_KEY_LEN],
48                   u16 port, const ip_address_t * src_ip, u32 * sw_if_indexp);
49 int wg_if_delete (u32 sw_if_index);
50 index_t wg_if_find_by_sw_if_index (u32 sw_if_index);
51
52 u8 *format_wg_if (u8 * s, va_list * va);
53
54 typedef walk_rc_t (*wg_if_walk_cb_t) (index_t wgi, void *data);
55 void wg_if_walk (wg_if_walk_cb_t fn, void *data);
56
57 typedef walk_rc_t (*wg_if_peer_walk_cb_t) (index_t peeri, void *data);
58 index_t wg_if_peer_walk (wg_if_t * wgi, wg_if_peer_walk_cb_t fn, void *data);
59
60 void wg_if_peer_add (wg_if_t * wgi, index_t peeri);
61 void wg_if_peer_remove (wg_if_t * wgi, index_t peeri);
62
63 /**
64  * Data-plane exposed functions
65  */
66 extern wg_if_t *wg_if_pool;
67
68 static_always_inline wg_if_t *
69 wg_if_get (index_t wgii)
70 {
71   if (INDEX_INVALID == wgii)
72     return (NULL);
73   return (pool_elt_at_index (wg_if_pool, wgii));
74 }
75
76 extern index_t **wg_if_indexes_by_port;
77
78 static_always_inline index_t *
79 wg_if_indexes_get_by_port (u16 port)
80 {
81   if (vec_len (wg_if_indexes_by_port) == 0)
82     return (NULL);
83   if (vec_len (wg_if_indexes_by_port[port]) == 0)
84     return (NULL);
85   return (wg_if_indexes_by_port[port]);
86 }
87
88 #define HANDSHAKE_COUNTING_INTERVAL             0.5
89 #define UNDER_LOAD_INTERVAL                     1.0
90 #define HANDSHAKE_NUM_PER_PEER_UNTIL_UNDER_LOAD 40
91
92 static_always_inline bool
93 wg_if_is_under_load (vlib_main_t *vm, wg_if_t *wgi)
94 {
95   static f64 wg_under_load_end;
96   f64 now = vlib_time_now (vm);
97   u32 num_until_under_load =
98     hash_elts (wgi->peers) * HANDSHAKE_NUM_PER_PEER_UNTIL_UNDER_LOAD;
99
100   if (wgi->handshake_counting_end < now)
101     {
102       wgi->handshake_counting_end = now + HANDSHAKE_COUNTING_INTERVAL;
103       wgi->handshake_num = 0;
104     }
105   wgi->handshake_num++;
106
107   if (wgi->handshake_num >= num_until_under_load)
108     {
109       wg_under_load_end = now + UNDER_LOAD_INTERVAL;
110       return true;
111     }
112
113   if (wg_under_load_end > now)
114     {
115       return true;
116     }
117
118   return false;
119 }
120
121 static_always_inline void
122 wg_if_dec_handshake_num (wg_if_t *wgi)
123 {
124   wgi->handshake_num--;
125 }
126
127 #endif
128
129 /*
130  * fd.io coding-style-patch-verification: ON
131  *
132  * Local Variables:
133  * eval: (c-set-style "gnu")
134  * End:
135  */