blob: 9ba2c10bca6659ff0b92412682d34d6023c3aad1 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 * ipsec_if_in.c : IPSec interface input node
3 *
4 * Copyright (c) 2015 Cisco and/or its affiliates.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include <vnet/vnet.h>
19#include <vnet/api_errno.h>
20#include <vnet/ip/ip.h>
21
22#include <vnet/ipsec/ipsec.h>
23#include <vnet/ipsec/esp.h>
Neale Ranns918c1612019-02-21 23:34:59 -080024#include <vnet/ipsec/ipsec_io.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070025
26/* Statistics (not really errors) */
Matthew Smith831fd642018-05-15 22:03:05 -050027#define foreach_ipsec_if_input_error \
28_(RX, "good packets received") \
Neale Ranns8d7c5022019-02-06 01:41:05 -080029_(DISABLED, "ipsec packets received on disabled interface") \
30_(NO_TUNNEL, "no matching tunnel")
Ed Warnickecb9cada2015-12-08 15:45:58 -070031
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070032static char *ipsec_if_input_error_strings[] = {
Ed Warnickecb9cada2015-12-08 15:45:58 -070033#define _(sym,string) string,
34 foreach_ipsec_if_input_error
35#undef _
36};
37
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070038typedef enum
39{
Ed Warnickecb9cada2015-12-08 15:45:58 -070040#define _(sym,str) IPSEC_IF_INPUT_ERROR_##sym,
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070041 foreach_ipsec_if_input_error
Ed Warnickecb9cada2015-12-08 15:45:58 -070042#undef _
43 IPSEC_IF_INPUT_N_ERROR,
44} ipsec_if_input_error_t;
45
Ed Warnickecb9cada2015-12-08 15:45:58 -070046
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070047typedef struct
48{
Ed Warnickecb9cada2015-12-08 15:45:58 -070049 u32 spi;
50 u32 seq;
51} ipsec_if_input_trace_t;
52
Kingwel Xiec69ac312019-02-04 01:49:29 -080053static u8 *
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070054format_ipsec_if_input_trace (u8 * s, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -070055{
56 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
57 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070058 ipsec_if_input_trace_t *t = va_arg (*args, ipsec_if_input_trace_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -070059
60 s = format (s, "IPSec: spi %u seq %u", t->spi, t->seq);
61 return s;
62}
63
Kingwel Xie00bff192019-03-07 01:25:32 -050064
65always_inline uword
Kingwel Xie1ba5bc82019-03-20 07:21:58 -040066ipsec_if_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
67 vlib_frame_t * from_frame, int is_ip6)
Ed Warnickecb9cada2015-12-08 15:45:58 -070068{
69 ipsec_main_t *im = &ipsec_main;
Matthew Smith01034be2017-05-16 11:51:18 -050070 vnet_main_t *vnm = im->vnet_main;
71 vnet_interface_main_t *vim = &vnm->interface_main;
Kingwel Xie00bff192019-03-07 01:25:32 -050072
73 int is_trace = node->flags & VLIB_NODE_FLAG_TRACE;
Damjan Marion067cd622018-07-11 12:47:43 +020074 u32 thread_index = vm->thread_index;
Kingwel Xie00bff192019-03-07 01:25:32 -050075
76 u32 n_left_from, *from;
77 u16 nexts[VLIB_FRAME_SIZE], *next;
78 vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
79
80 from = vlib_frame_vector_args (from_frame);
81 n_left_from = from_frame->n_vectors;
82
83 vlib_get_buffers (vm, from, bufs, n_left_from);
84 b = bufs;
85 next = nexts;
86
87 clib_memset_u16 (nexts, im->esp4_decrypt_next_index, n_left_from);
88
Matthew Smith01034be2017-05-16 11:51:18 -050089 u64 n_bytes = 0, n_packets = 0;
Kingwel Xie00bff192019-03-07 01:25:32 -050090 u32 n_disabled = 0, n_no_tunnel = 0;
91
92 u32 last_sw_if_index = ~0;
93 u32 last_tunnel_id = ~0;
Kingwel Xie1ba5bc82019-03-20 07:21:58 -040094 ipsec4_tunnel_key_t last_key4;
95 ipsec6_tunnel_key_t last_key6;
Kingwel Xie00bff192019-03-07 01:25:32 -050096
Matthew Smith831fd642018-05-15 22:03:05 -050097 vlib_combined_counter_main_t *rx_counter;
98 vlib_combined_counter_main_t *drop_counter;
Matthew Smith831fd642018-05-15 22:03:05 -050099
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400100 if (is_ip6)
101 clib_memset (&last_key6, 0xff, sizeof (last_key6));
102 else
103 last_key4.as_u64 = ~0;
104
Matthew Smith831fd642018-05-15 22:03:05 -0500105 rx_counter = vim->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX;
106 drop_counter = vim->combined_sw_if_counters + VNET_INTERFACE_COUNTER_DROP;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700107
Kingwel Xie00bff192019-03-07 01:25:32 -0500108 while (n_left_from >= 2)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700109 {
Kingwel Xie00bff192019-03-07 01:25:32 -0500110 u32 sw_if_index0, sw_if_index1;
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400111 ip4_header_t *ip40, *ip41;
112 ip6_header_t *ip60, *ip61;
Kingwel Xie00bff192019-03-07 01:25:32 -0500113 esp_header_t *esp0, *esp1;
114 u32 len0, len1;
115 u16 buf_adv0, buf_adv1;
116 u32 tid0, tid1;
117 ipsec_tunnel_if_t *t0, *t1;
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400118 ipsec4_tunnel_key_t key40, key41;
119 ipsec6_tunnel_key_t key60, key61;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700120
Kingwel Xie00bff192019-03-07 01:25:32 -0500121 if (n_left_from >= 4)
Neale Ranns77eb28f2019-03-04 14:13:14 +0000122 {
Kingwel Xie00bff192019-03-07 01:25:32 -0500123 CLIB_PREFETCH (b[2], CLIB_CACHE_LINE_BYTES, STORE);
124 CLIB_PREFETCH (b[2]->data, CLIB_CACHE_LINE_BYTES, LOAD);
125 CLIB_PREFETCH (b[3], CLIB_CACHE_LINE_BYTES, STORE);
126 CLIB_PREFETCH (b[3]->data, CLIB_CACHE_LINE_BYTES, LOAD);
127 }
Neale Ranns77eb28f2019-03-04 14:13:14 +0000128
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400129 ip40 =
130 (ip4_header_t *) (b[0]->data + vnet_buffer (b[0])->l3_hdr_offset);
131 ip41 =
132 (ip4_header_t *) (b[1]->data + vnet_buffer (b[1])->l3_hdr_offset);
Neale Ranns77eb28f2019-03-04 14:13:14 +0000133
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400134 if (is_ip6)
Kingwel Xie00bff192019-03-07 01:25:32 -0500135 {
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400136 ip60 = (ip6_header_t *) ip40;
137 ip61 = (ip6_header_t *) ip41;
138 esp0 = (esp_header_t *) ((u8 *) ip60 + sizeof (ip6_header_t));
139 esp1 = (esp_header_t *) ((u8 *) ip61 + sizeof (ip6_header_t));
140 buf_adv0 = sizeof (ip6_header_t);
141 buf_adv1 = sizeof (ip6_header_t);
Kingwel Xie00bff192019-03-07 01:25:32 -0500142 }
143 else
144 {
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400145 /* NAT UDP port 4500 case, don't advance any more */
146 if (ip40->protocol == IP_PROTOCOL_UDP)
147 {
148 esp0 =
149 (esp_header_t *) ((u8 *) ip40 + ip4_header_bytes (ip40) +
150 sizeof (udp_header_t));
151 buf_adv0 = 0;
152 }
153 else
154 {
155 esp0 = (esp_header_t *) ((u8 *) ip40 + ip4_header_bytes (ip40));
156 buf_adv0 = ip4_header_bytes (ip40);
157 }
158 /* NAT UDP port 4500 case, don't advance any more */
159 if (ip41->protocol == IP_PROTOCOL_UDP)
160 {
161 esp1 =
162 (esp_header_t *) ((u8 *) ip41 + ip4_header_bytes (ip41) +
163 sizeof (udp_header_t));
164 buf_adv1 = 0;
165 }
166 else
167 {
168 esp1 = (esp_header_t *) ((u8 *) ip41 + ip4_header_bytes (ip41));
169 buf_adv1 = ip4_header_bytes (ip41);
170 }
Kingwel Xie00bff192019-03-07 01:25:32 -0500171 }
Neale Ranns77eb28f2019-03-04 14:13:14 +0000172
Kingwel Xie00bff192019-03-07 01:25:32 -0500173 vlib_buffer_advance (b[0], buf_adv0);
174 vlib_buffer_advance (b[1], buf_adv1);
Neale Ranns77eb28f2019-03-04 14:13:14 +0000175
Kingwel Xie00bff192019-03-07 01:25:32 -0500176 len0 = vlib_buffer_length_in_chain (vm, b[0]);
177 len1 = vlib_buffer_length_in_chain (vm, b[1]);
Neale Ranns77eb28f2019-03-04 14:13:14 +0000178
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400179 if (is_ip6)
180 {
181 key60.remote_ip = ip60->src_address;
182 key60.spi = esp0->spi;
Neale Ranns77eb28f2019-03-04 14:13:14 +0000183
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400184 if (memcmp (&key60, &last_key6, sizeof (last_key6)) == 0)
Neale Ranns77eb28f2019-03-04 14:13:14 +0000185 {
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400186 tid0 = last_tunnel_id;
Neale Ranns77eb28f2019-03-04 14:13:14 +0000187 }
188 else
189 {
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400190 uword *p =
191 hash_get_mem (im->ipsec6_if_pool_index_by_key, &key60);
192 if (p)
193 {
194 tid0 = p[0];
195 last_tunnel_id = tid0;
196 clib_memcpy_fast (&last_key6, &key60, sizeof (key60));
197 }
198 else
199 {
Neale Rannse524d452019-02-19 15:22:46 +0000200 b[0]->error = node->errors[IPSEC_IF_INPUT_ERROR_NO_TUNNEL];
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400201 n_no_tunnel++;
202 next[0] = IPSEC_INPUT_NEXT_DROP;
203 goto pkt1;
204 }
205 }
206 }
207 else /* !is_ip6 */
208 {
209 key40.remote_ip = ip40->src_address.as_u32;
210 key40.spi = esp0->spi;
211
212 if (key40.as_u64 == last_key4.as_u64)
213 {
214 tid0 = last_tunnel_id;
215 }
216 else
217 {
218 uword *p =
219 hash_get (im->ipsec4_if_pool_index_by_key, key40.as_u64);
220 if (p)
221 {
222 tid0 = p[0];
223 last_tunnel_id = tid0;
224 last_key4.as_u64 = key40.as_u64;
225 }
226 else
227 {
Neale Rannse524d452019-02-19 15:22:46 +0000228 b[0]->error = node->errors[IPSEC_IF_INPUT_ERROR_NO_TUNNEL];
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400229 n_no_tunnel++;
230 next[0] = IPSEC_INPUT_NEXT_DROP;
231 goto pkt1;
232 }
Kingwel Xie00bff192019-03-07 01:25:32 -0500233 }
234 }
235
236 t0 = pool_elt_at_index (im->tunnel_interfaces, tid0);
237 vnet_buffer (b[0])->ipsec.sad_index = t0->input_sa_index;
238
239 if (PREDICT_TRUE (t0->hw_if_index != ~0))
240 {
Kingwel Xie00bff192019-03-07 01:25:32 -0500241 sw_if_index0 = t0->sw_if_index;
242 vnet_buffer (b[0])->sw_if_index[VLIB_RX] = sw_if_index0;
243
244 if (PREDICT_FALSE (!(t0->flags & VNET_HW_INTERFACE_FLAG_LINK_UP)))
245 {
246 vlib_increment_combined_counter
247 (drop_counter, thread_index, sw_if_index0, 1, len0);
248 n_disabled++;
Neale Rannse524d452019-02-19 15:22:46 +0000249 b[0]->error = node->errors[IPSEC_IF_INPUT_ERROR_DISABLED];
Kingwel Xie00bff192019-03-07 01:25:32 -0500250 next[0] = IPSEC_INPUT_NEXT_DROP;
251 goto pkt1;
Neale Ranns77eb28f2019-03-04 14:13:14 +0000252 }
253
Kingwel Xie00bff192019-03-07 01:25:32 -0500254 if (PREDICT_TRUE (sw_if_index0 == last_sw_if_index))
Neale Ranns77eb28f2019-03-04 14:13:14 +0000255 {
Kingwel Xie00bff192019-03-07 01:25:32 -0500256 n_packets++;
257 n_bytes += len0;
Neale Ranns77eb28f2019-03-04 14:13:14 +0000258 }
259 else
260 {
Kingwel Xie00bff192019-03-07 01:25:32 -0500261 if (n_packets)
262 {
263 vlib_increment_combined_counter
264 (rx_counter, thread_index, last_sw_if_index,
265 n_packets, n_bytes);
266 }
267
268 last_sw_if_index = sw_if_index0;
269 n_packets = 1;
270 n_bytes = len0;
271 }
272 }
Kingwel Xie00bff192019-03-07 01:25:32 -0500273
274 pkt1:
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400275 if (is_ip6)
Kingwel Xie00bff192019-03-07 01:25:32 -0500276 {
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400277 key61.remote_ip = ip61->src_address;
278 key61.spi = esp1->spi;
279
280 if (memcmp (&key61, &last_key6, sizeof (last_key6)) == 0)
Kingwel Xie00bff192019-03-07 01:25:32 -0500281 {
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400282 tid1 = last_tunnel_id;
Kingwel Xie00bff192019-03-07 01:25:32 -0500283 }
284 else
285 {
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400286 uword *p =
287 hash_get_mem (im->ipsec6_if_pool_index_by_key, &key61);
288 if (p)
289 {
290 tid1 = p[0];
291 last_tunnel_id = tid1;
292 clib_memcpy_fast (&last_key6, &key61, sizeof (key61));
293 }
294 else
295 {
Neale Rannse524d452019-02-19 15:22:46 +0000296 b[1]->error = node->errors[IPSEC_IF_INPUT_ERROR_NO_TUNNEL];
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400297 n_no_tunnel++;
298 next[1] = IPSEC_INPUT_NEXT_DROP;
299 goto trace1;
300 }
301 }
302 }
303 else /* !is_ip6 */
304 {
305 key41.remote_ip = ip41->src_address.as_u32;
306 key41.spi = esp1->spi;
307
308 if (key41.as_u64 == last_key4.as_u64)
309 {
310 tid1 = last_tunnel_id;
311 }
312 else
313 {
314 uword *p =
315 hash_get (im->ipsec4_if_pool_index_by_key, key41.as_u64);
316 if (p)
317 {
318 tid1 = p[0];
319 last_tunnel_id = tid1;
320 last_key4.as_u64 = key41.as_u64;
321 }
322 else
323 {
Neale Rannse524d452019-02-19 15:22:46 +0000324 b[1]->error = node->errors[IPSEC_IF_INPUT_ERROR_NO_TUNNEL];
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400325 n_no_tunnel++;
326 next[1] = IPSEC_INPUT_NEXT_DROP;
327 goto trace1;
328 }
Kingwel Xie00bff192019-03-07 01:25:32 -0500329 }
330 }
331
332 t1 = pool_elt_at_index (im->tunnel_interfaces, tid1);
333 vnet_buffer (b[1])->ipsec.sad_index = t1->input_sa_index;
334
335 if (PREDICT_TRUE (t1->hw_if_index != ~0))
336 {
Kingwel Xie00bff192019-03-07 01:25:32 -0500337 sw_if_index1 = t1->sw_if_index;
338 vnet_buffer (b[1])->sw_if_index[VLIB_RX] = sw_if_index1;
339
340 if (PREDICT_FALSE (!(t1->flags & VNET_HW_INTERFACE_FLAG_LINK_UP)))
341 {
342 vlib_increment_combined_counter
343 (drop_counter, thread_index, sw_if_index1, 1, len1);
344 n_disabled++;
Neale Rannse524d452019-02-19 15:22:46 +0000345 b[1]->error = node->errors[IPSEC_IF_INPUT_ERROR_DISABLED];
Kingwel Xie00bff192019-03-07 01:25:32 -0500346 next[1] = IPSEC_INPUT_NEXT_DROP;
347 goto trace1;
Neale Ranns77eb28f2019-03-04 14:13:14 +0000348 }
349
Kingwel Xie00bff192019-03-07 01:25:32 -0500350 if (PREDICT_TRUE (sw_if_index1 == last_sw_if_index))
351 {
352 n_packets++;
353 n_bytes += len1;
354 }
355 else
356 {
357 if (n_packets)
358 {
359 vlib_increment_combined_counter
360 (rx_counter, thread_index, last_sw_if_index,
361 n_packets, n_bytes);
362 }
363
364 last_sw_if_index = sw_if_index1;
365 n_packets = 1;
366 n_bytes = len1;
367 }
368 }
Kingwel Xie00bff192019-03-07 01:25:32 -0500369
370 trace1:
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400371 if (PREDICT_FALSE (is_trace))
Kingwel Xie00bff192019-03-07 01:25:32 -0500372 {
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400373 if (b[0]->flags & VLIB_BUFFER_IS_TRACED)
Neale Ranns77eb28f2019-03-04 14:13:14 +0000374 {
375 ipsec_if_input_trace_t *tr =
Kingwel Xie00bff192019-03-07 01:25:32 -0500376 vlib_add_trace (vm, node, b[0], sizeof (*tr));
Neale Ranns77eb28f2019-03-04 14:13:14 +0000377 tr->spi = clib_host_to_net_u32 (esp0->spi);
378 tr->seq = clib_host_to_net_u32 (esp0->seq);
379 }
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400380 if (b[1]->flags & VLIB_BUFFER_IS_TRACED)
Neale Ranns77eb28f2019-03-04 14:13:14 +0000381 {
382 ipsec_if_input_trace_t *tr =
Kingwel Xie00bff192019-03-07 01:25:32 -0500383 vlib_add_trace (vm, node, b[1], sizeof (*tr));
Neale Ranns77eb28f2019-03-04 14:13:14 +0000384 tr->spi = clib_host_to_net_u32 (esp1->spi);
385 tr->seq = clib_host_to_net_u32 (esp1->seq);
386 }
Neale Ranns77eb28f2019-03-04 14:13:14 +0000387 }
Kingwel Xie00bff192019-03-07 01:25:32 -0500388
389 /* next */
390 b += 2;
391 next += 2;
392 n_left_from -= 2;
393 }
394 while (n_left_from > 0)
395 {
396 u32 sw_if_index0;
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400397 ip4_header_t *ip40;
398 ip6_header_t *ip60;
Kingwel Xie00bff192019-03-07 01:25:32 -0500399 esp_header_t *esp0;
400 u32 len0;
401 u16 buf_adv0;
402 u32 tid0;
403 ipsec_tunnel_if_t *t0;
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400404 ipsec4_tunnel_key_t key40;
405 ipsec6_tunnel_key_t key60;
Kingwel Xie00bff192019-03-07 01:25:32 -0500406
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400407 ip40 =
408 (ip4_header_t *) (b[0]->data + vnet_buffer (b[0])->l3_hdr_offset);
Kingwel Xie00bff192019-03-07 01:25:32 -0500409
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400410 if (is_ip6)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700411 {
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400412 ip60 = (ip6_header_t *) ip40;
413 esp0 = (esp_header_t *) ((u8 *) ip60 + sizeof (ip6_header_t));
414 buf_adv0 = sizeof (ip6_header_t);
Kingwel Xie00bff192019-03-07 01:25:32 -0500415 }
416 else
417 {
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400418 /* NAT UDP port 4500 case, don't advance any more */
419 if (ip40->protocol == IP_PROTOCOL_UDP)
420 {
421 esp0 =
422 (esp_header_t *) ((u8 *) ip40 + ip4_header_bytes (ip40) +
423 sizeof (udp_header_t));
424 buf_adv0 = 0;
425 }
426 else
427 {
428 esp0 = (esp_header_t *) ((u8 *) ip40 + ip4_header_bytes (ip40));
429 buf_adv0 = ip4_header_bytes (ip40);
430 }
Kingwel Xie00bff192019-03-07 01:25:32 -0500431 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700432
Kingwel Xie00bff192019-03-07 01:25:32 -0500433 /* stats for the tunnel include all the data after the IP header
434 just like a norml IP-IP tunnel */
435 vlib_buffer_advance (b[0], buf_adv0);
436 len0 = vlib_buffer_length_in_chain (vm, b[0]);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700437
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400438 if (is_ip6)
Kingwel Xie00bff192019-03-07 01:25:32 -0500439 {
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400440 key60.remote_ip = ip60->src_address;
441 key60.spi = esp0->spi;
442
443 if (memcmp (&key60, &last_key6, sizeof (last_key6)) == 0)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700444 {
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400445 tid0 = last_tunnel_id;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700446 }
Neale Ranns8d7c5022019-02-06 01:41:05 -0800447 else
448 {
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400449 uword *p =
450 hash_get_mem (im->ipsec6_if_pool_index_by_key, &key60);
451 if (p)
452 {
453 tid0 = p[0];
454 last_tunnel_id = tid0;
455 clib_memcpy_fast (&last_key6, &key60, sizeof (key60));
456 }
457 else
458 {
Neale Rannse524d452019-02-19 15:22:46 +0000459 b[0]->error = node->errors[IPSEC_IF_INPUT_ERROR_NO_TUNNEL];
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400460 n_no_tunnel++;
461 next[0] = IPSEC_INPUT_NEXT_DROP;
462 goto trace00;
463 }
464 }
465 }
466 else /* !is_ip6 */
467 {
468 key40.remote_ip = ip40->src_address.as_u32;
469 key40.spi = esp0->spi;
470
471 if (key40.as_u64 == last_key4.as_u64)
472 {
473 tid0 = last_tunnel_id;
474 }
475 else
476 {
477 uword *p =
478 hash_get (im->ipsec4_if_pool_index_by_key, key40.as_u64);
479 if (p)
480 {
481 tid0 = p[0];
482 last_tunnel_id = tid0;
483 last_key4.as_u64 = key40.as_u64;
484 }
485 else
486 {
Neale Rannse524d452019-02-19 15:22:46 +0000487 b[0]->error = node->errors[IPSEC_IF_INPUT_ERROR_NO_TUNNEL];
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400488 n_no_tunnel++;
489 next[0] = IPSEC_INPUT_NEXT_DROP;
490 goto trace00;
491 }
Kingwel Xie00bff192019-03-07 01:25:32 -0500492 }
493 }
494
495 t0 = pool_elt_at_index (im->tunnel_interfaces, tid0);
496 vnet_buffer (b[0])->ipsec.sad_index = t0->input_sa_index;
497
498 if (PREDICT_TRUE (t0->hw_if_index != ~0))
499 {
Kingwel Xie00bff192019-03-07 01:25:32 -0500500 sw_if_index0 = t0->sw_if_index;
501 vnet_buffer (b[0])->sw_if_index[VLIB_RX] = sw_if_index0;
502
503 if (PREDICT_FALSE (!(t0->flags & VNET_HW_INTERFACE_FLAG_LINK_UP)))
504 {
505 vlib_increment_combined_counter
506 (drop_counter, thread_index, sw_if_index0, 1, len0);
507 n_disabled++;
Neale Rannse524d452019-02-19 15:22:46 +0000508 b[0]->error = node->errors[IPSEC_IF_INPUT_ERROR_DISABLED];
Kingwel Xie00bff192019-03-07 01:25:32 -0500509 next[0] = IPSEC_INPUT_NEXT_DROP;
510 goto trace00;
Neale Ranns8d7c5022019-02-06 01:41:05 -0800511 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700512
Kingwel Xie00bff192019-03-07 01:25:32 -0500513 if (PREDICT_TRUE (sw_if_index0 == last_sw_if_index))
514 {
515 n_packets++;
516 n_bytes += len0;
517 }
518 else
519 {
520 if (n_packets)
521 {
522 vlib_increment_combined_counter
523 (rx_counter, thread_index, last_sw_if_index,
524 n_packets, n_bytes);
525 }
526
527 last_sw_if_index = sw_if_index0;
528 n_packets = 1;
529 n_bytes = len0;
530 }
531 }
Kingwel Xie00bff192019-03-07 01:25:32 -0500532
533 trace00:
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400534 if (PREDICT_FALSE (is_trace))
Kingwel Xie00bff192019-03-07 01:25:32 -0500535 {
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400536 if (b[0]->flags & VLIB_BUFFER_IS_TRACED)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700537 {
538 ipsec_if_input_trace_t *tr =
Kingwel Xie00bff192019-03-07 01:25:32 -0500539 vlib_add_trace (vm, node, b[0], sizeof (*tr));
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700540 tr->spi = clib_host_to_net_u32 (esp0->spi);
541 tr->seq = clib_host_to_net_u32 (esp0->seq);
542 }
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700543 }
Kingwel Xie00bff192019-03-07 01:25:32 -0500544
545 /* next */
546 b += 1;
547 next += 1;
548 n_left_from -= 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700549 }
550
Kingwel Xie00bff192019-03-07 01:25:32 -0500551 if (n_packets)
Matthew Smith01034be2017-05-16 11:51:18 -0500552 {
Matthew Smith831fd642018-05-15 22:03:05 -0500553 vlib_increment_combined_counter (rx_counter,
Matthew Smith01034be2017-05-16 11:51:18 -0500554 thread_index,
555 last_sw_if_index, n_packets, n_bytes);
556 }
557
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400558 vlib_node_increment_counter (vm, node->node_index,
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700559 IPSEC_IF_INPUT_ERROR_RX,
Neale Rannse524d452019-02-19 15:22:46 +0000560 from_frame->n_vectors - (n_disabled +
561 n_no_tunnel));
Kingwel Xie00bff192019-03-07 01:25:32 -0500562
563 vlib_buffer_enqueue_to_next (vm, node, from, nexts, from_frame->n_vectors);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700564
565 return from_frame->n_vectors;
566}
567
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400568VLIB_NODE_FN (ipsec4_if_input_node) (vlib_main_t * vm,
569 vlib_node_runtime_t * node,
570 vlib_frame_t * from_frame)
Kingwel Xie00bff192019-03-07 01:25:32 -0500571{
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400572 return ipsec_if_input_inline (vm, node, from_frame, 0 /* is_ip6 */ );
Kingwel Xie00bff192019-03-07 01:25:32 -0500573}
574
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700575/* *INDENT-OFF* */
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400576VLIB_REGISTER_NODE (ipsec4_if_input_node) = {
577 .name = "ipsec4-if-input",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700578 .vector_size = sizeof (u32),
579 .format_trace = format_ipsec_if_input_trace,
580 .type = VLIB_NODE_TYPE_INTERNAL,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700581 .n_errors = ARRAY_LEN(ipsec_if_input_error_strings),
582 .error_strings = ipsec_if_input_error_strings,
Pierre Pfister057b3562018-12-10 17:01:01 +0100583 .sibling_of = "ipsec4-input-feature",
Damjan Marion1c80e832016-05-11 23:07:18 +0200584};
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700585/* *INDENT-ON* */
Damjan Marion1c80e832016-05-11 23:07:18 +0200586
Kingwel Xie1ba5bc82019-03-20 07:21:58 -0400587VLIB_NODE_FN (ipsec6_if_input_node) (vlib_main_t * vm,
588 vlib_node_runtime_t * node,
589 vlib_frame_t * from_frame)
590{
591 return ipsec_if_input_inline (vm, node, from_frame, 1 /* is_ip6 */ );
592}
593
594/* *INDENT-OFF* */
595VLIB_REGISTER_NODE (ipsec6_if_input_node) = {
596 .name = "ipsec6-if-input",
597 .vector_size = sizeof (u32),
598 .format_trace = format_ipsec_if_input_trace,
599 .type = VLIB_NODE_TYPE_INTERNAL,
600 .n_errors = ARRAY_LEN(ipsec_if_input_error_strings),
601 .error_strings = ipsec_if_input_error_strings,
602 .sibling_of = "ipsec6-input-feature",
603};
604/* *INDENT-ON* */
605
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700606/*
607 * fd.io coding-style-patch-verification: ON
608 *
609 * Local Variables:
610 * eval: (c-set-style "gnu")
611 * End:
612 */