X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fipsec%2Fipsec_if_in.c;h=974227f7a0eac68b38f326c092f4a26ac4c46d6c;hb=f1653e62fe41e3df429aadaaab22d0cc8aaa227a;hp=b8610f4864fcd5b630b9219ec644b980b80bbeca;hpb=7ba8fe20970b501f06a6c5a6e3632913e2492acb;p=vpp.git diff --git a/src/vnet/ipsec/ipsec_if_in.c b/src/vnet/ipsec/ipsec_if_in.c index b8610f4864f..974227f7a0e 100644 --- a/src/vnet/ipsec/ipsec_if_in.c +++ b/src/vnet/ipsec/ipsec_if_in.c @@ -21,12 +21,17 @@ #include #include +#include +#include /* Statistics (not really errors) */ #define foreach_ipsec_if_input_error \ _(RX, "good packets received") \ _(DISABLED, "ipsec packets received on disabled interface") \ -_(NO_TUNNEL, "no matching tunnel") +_(NO_TUNNEL, "no matching tunnel") \ +_(NAT_KEEPALIVE, "NAT Keepalive") \ +_(TOO_SHORT, "Too Short") \ +_(SPI_0, "SPI 0") static char *ipsec_if_input_error_strings[] = { #define _(sym,string) string, @@ -45,7 +50,12 @@ typedef enum typedef struct { - u32 spi; + union + { + ipsec4_tunnel_key_t key4; + ipsec6_tunnel_key_t key6; + }; + u8 is_ip6; u32 seq; } ipsec_if_input_trace_t; @@ -56,191 +66,652 @@ format_ipsec_if_input_trace (u8 * s, va_list * args) CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); ipsec_if_input_trace_t *t = va_arg (*args, ipsec_if_input_trace_t *); - s = format (s, "IPSec: spi %u seq %u", t->spi, t->seq); + if (t->is_ip6) + s = format (s, "IPSec: %U seq %u", + format_ipsec6_tunnel_key, &t->key6, t->seq); + else + s = format (s, "IPSec: %U seq %u", + format_ipsec4_tunnel_key, &t->key4, t->seq); return s; } -VLIB_NODE_FN (ipsec_if_input_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * from_frame) +always_inline u16 +ipsec_ip4_if_no_tunnel (vlib_node_runtime_t * node, + vlib_buffer_t * b, + const esp_header_t * esp, + const ip4_header_t * ip4, u16 offset) +{ + if (PREDICT_FALSE (0 == esp->spi)) + { + b->error = node->errors[IPSEC_IF_INPUT_ERROR_SPI_0]; + b->punt_reason = + ipsec_punt_reason[(ip4->protocol == IP_PROTOCOL_UDP ? + IPSEC_PUNT_IP4_SPI_UDP_0 : + IPSEC_PUNT_IP4_NO_SUCH_TUNNEL)]; + } + else + { + b->error = node->errors[IPSEC_IF_INPUT_ERROR_NO_TUNNEL]; + b->punt_reason = ipsec_punt_reason[IPSEC_PUNT_IP4_NO_SUCH_TUNNEL]; + } + vlib_buffer_advance (b, -offset); + return IPSEC_INPUT_NEXT_PUNT; +} + +always_inline u16 +ipsec_ip6_if_no_tunnel (vlib_node_runtime_t * node, + vlib_buffer_t * b, + const esp_header_t * esp, u16 offset) +{ + b->error = node->errors[IPSEC_IF_INPUT_ERROR_NO_TUNNEL]; + b->punt_reason = ipsec_punt_reason[IPSEC_PUNT_IP6_NO_SUCH_TUNNEL]; + + vlib_buffer_advance (b, -offset); + return (IPSEC_INPUT_NEXT_PUNT); +} + +always_inline uword +ipsec_if_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * from_frame, int is_ip6) { ipsec_main_t *im = &ipsec_main; vnet_main_t *vnm = im->vnet_main; vnet_interface_main_t *vim = &vnm->interface_main; - ipsec_proto_main_t *em = &ipsec_proto_main; - u32 *from, *to_next = 0, next_index; - u32 n_left_from, last_sw_if_index = ~0; + + int is_trace = node->flags & VLIB_NODE_FLAG_TRACE; u32 thread_index = vm->thread_index; + + u32 n_left_from, *from; + u16 nexts[VLIB_FRAME_SIZE], *next; + vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b; + + from = vlib_frame_vector_args (from_frame); + n_left_from = from_frame->n_vectors; + + vlib_get_buffers (vm, from, bufs, n_left_from); + b = bufs; + next = nexts; + + clib_memset_u16 (nexts, im->esp4_decrypt_next_index, n_left_from); + u64 n_bytes = 0, n_packets = 0; - u8 icv_len; - ipsec_tunnel_if_t *last_t = NULL; - ipsec_sa_t *sa0; + u32 n_disabled = 0, n_no_tunnel = 0; + + u32 last_sw_if_index = ~0; + u32 last_tunnel_id = ~0; + ipsec4_tunnel_key_t last_key4; + ipsec6_tunnel_key_t last_key6; + vlib_combined_counter_main_t *rx_counter; vlib_combined_counter_main_t *drop_counter; - u32 n_disabled = 0, n_no_tunnel = 0; + + if (is_ip6) + clib_memset (&last_key6, 0xff, sizeof (last_key6)); + else + last_key4.as_u64 = ~0; rx_counter = vim->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX; drop_counter = vim->combined_sw_if_counters + VNET_INTERFACE_COUNTER_DROP; - from = vlib_frame_vector_args (from_frame); - n_left_from = from_frame->n_vectors; - next_index = node->cached_next_index; - - while (n_left_from > 0) + while (n_left_from >= 2) { - u32 n_left_to_next; + u32 sw_if_index0, sw_if_index1; + ip4_header_t *ip40, *ip41; + ip6_header_t *ip60, *ip61; + esp_header_t *esp0, *esp1; + u32 len0, len1; + u16 buf_adv0, buf_adv1; + u16 buf_rewind0, buf_rewind1; + u32 tid0, tid1; + ipsec_tunnel_if_t *t0, *t1; + ipsec4_tunnel_key_t key40, key41; + ipsec6_tunnel_key_t key60, key61; + + if (n_left_from >= 4) + { + CLIB_PREFETCH (b[2], CLIB_CACHE_LINE_BYTES, STORE); + CLIB_PREFETCH (b[2]->data, CLIB_CACHE_LINE_BYTES, LOAD); + CLIB_PREFETCH (b[3], CLIB_CACHE_LINE_BYTES, STORE); + CLIB_PREFETCH (b[3]->data, CLIB_CACHE_LINE_BYTES, LOAD); + } - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + ip40 = + (ip4_header_t *) (b[0]->data + vnet_buffer (b[0])->l3_hdr_offset); + ip41 = + (ip4_header_t *) (b[1]->data + vnet_buffer (b[1])->l3_hdr_offset); - while (n_left_from > 0 && n_left_to_next > 0) + if (is_ip6) + { + ip60 = (ip6_header_t *) ip40; + ip61 = (ip6_header_t *) ip41; + esp0 = (esp_header_t *) ((u8 *) ip60 + sizeof (ip6_header_t)); + esp1 = (esp_header_t *) ((u8 *) ip61 + sizeof (ip6_header_t)); + buf_adv0 = sizeof (ip6_header_t); + buf_adv1 = sizeof (ip6_header_t); + } + else { - u32 bi0, next0, sw_if_index0; - vlib_buffer_t *b0; - ip4_header_t *ip0; - esp_header_t *esp0; - uword *p; - u32 len0; + /* NAT UDP port 4500 case, don't advance any more */ + if (ip40->protocol == IP_PROTOCOL_UDP) + { + esp0 = + (esp_header_t *) ((u8 *) ip40 + ip4_header_bytes (ip40) + + sizeof (udp_header_t)); + buf_adv0 = 0; + buf_rewind0 = ip4_header_bytes (ip40) + sizeof (udp_header_t); + } + else + { + esp0 = (esp_header_t *) ((u8 *) ip40 + ip4_header_bytes (ip40)); + buf_rewind0 = buf_adv0 = ip4_header_bytes (ip40); + } + /* NAT UDP port 4500 case, don't advance any more */ + if (ip41->protocol == IP_PROTOCOL_UDP) + { + esp1 = + (esp_header_t *) ((u8 *) ip41 + ip4_header_bytes (ip41) + + sizeof (udp_header_t)); + buf_adv1 = 0; + buf_rewind1 = ip4_header_bytes (ip41) + sizeof (udp_header_t); + } + else + { + esp1 = (esp_header_t *) ((u8 *) ip41 + ip4_header_bytes (ip41)); + buf_rewind1 = buf_adv1 = ip4_header_bytes (ip41); + } + } - bi0 = to_next[0] = from[0]; - from += 1; - n_left_from -= 1; - to_next += 1; - n_left_to_next -= 1; - b0 = vlib_get_buffer (vm, bi0); - ip0 = vlib_buffer_get_current (b0); - esp0 = (esp_header_t *) ((u8 *) ip0 + ip4_header_bytes (ip0)); + vlib_buffer_advance (b[0], buf_adv0); + vlib_buffer_advance (b[1], buf_adv1); - next0 = IPSEC_INPUT_NEXT_DROP; + len0 = vlib_buffer_length_in_chain (vm, b[0]); + len1 = vlib_buffer_length_in_chain (vm, b[1]); - u64 key = (u64) ip0->src_address.as_u32 << 32 | (u64) esp0->spi; + /* If the packet is too short to contain an SPI, then maybe + * it's a keep alive */ + if (len0 < sizeof (esp_header_t)) + { + if (esp0->spi_bytes[0] == 0xff) + b[0]->error = node->errors[IPSEC_IF_INPUT_ERROR_NAT_KEEPALIVE]; + else + b[0]->error = node->errors[IPSEC_IF_INPUT_ERROR_TOO_SHORT]; - p = hash_get (im->ipsec_if_pool_index_by_key, key); + next[0] = IPSEC_INPUT_NEXT_DROP; + goto pkt1; + } - len0 = vlib_buffer_length_in_chain (vm, b0); + if (is_ip6) + { + key60.remote_ip = ip60->src_address; + key60.spi = esp0->spi; + + if (memcmp (&key60, &last_key6, sizeof (last_key6)) == 0) + { + tid0 = last_tunnel_id; + } + else + { + uword *p = + hash_get_mem (im->ipsec6_if_pool_index_by_key, &key60); + if (p) + { + tid0 = p[0]; + last_tunnel_id = tid0; + clib_memcpy_fast (&last_key6, &key60, sizeof (key60)); + } + else + { + next[0] = + ipsec_ip6_if_no_tunnel (node, b[0], esp0, buf_adv0); + n_no_tunnel++; + goto pkt1; + } + } + } + else /* !is_ip6 */ + { + key40.remote_ip = ip40->src_address; + key40.spi = esp0->spi; + + if (key40.as_u64 == last_key4.as_u64) + { + tid0 = last_tunnel_id; + } + else + { + uword *p = + hash_get (im->ipsec4_if_pool_index_by_key, key40.as_u64); + if (p) + { + tid0 = p[0]; + last_tunnel_id = tid0; + last_key4.as_u64 = key40.as_u64; + } + else + { + next[0] = + ipsec_ip4_if_no_tunnel (node, b[0], esp0, ip40, + buf_rewind0); + n_no_tunnel++; + goto pkt1; + } + } + } + + t0 = pool_elt_at_index (im->tunnel_interfaces, tid0); + vnet_buffer (b[0])->ipsec.sad_index = t0->input_sa_index; + + if (PREDICT_TRUE (t0->hw_if_index != ~0)) + { + sw_if_index0 = t0->sw_if_index; + vnet_buffer (b[0])->sw_if_index[VLIB_RX] = sw_if_index0; + + if (PREDICT_FALSE (!(t0->flags & VNET_HW_INTERFACE_FLAG_LINK_UP))) + { + vlib_increment_combined_counter + (drop_counter, thread_index, sw_if_index0, 1, len0); + n_disabled++; + b[0]->error = node->errors[IPSEC_IF_INPUT_ERROR_DISABLED]; + next[0] = IPSEC_INPUT_NEXT_DROP; + goto pkt1; + } + + if (PREDICT_TRUE (sw_if_index0 == last_sw_if_index)) + { + n_packets++; + n_bytes += len0; + } + else + { + if (n_packets) + { + vlib_increment_combined_counter + (rx_counter, thread_index, last_sw_if_index, + n_packets, n_bytes); + } + + last_sw_if_index = sw_if_index0; + n_packets = 1; + n_bytes = len0; + } + } + + pkt1: + + if (len1 < sizeof (esp_header_t)) + { + if (esp0->spi_bytes[0] == 0xff) + b[1]->error = node->errors[IPSEC_IF_INPUT_ERROR_NAT_KEEPALIVE]; + else + b[1]->error = node->errors[IPSEC_IF_INPUT_ERROR_TOO_SHORT]; + + next[1] = IPSEC_INPUT_NEXT_DROP; + goto trace1; + } + + if (is_ip6) + { + key61.remote_ip = ip61->src_address; + key61.spi = esp1->spi; + + if (memcmp (&key61, &last_key6, sizeof (last_key6)) == 0) + { + tid1 = last_tunnel_id; + } + else + { + uword *p = + hash_get_mem (im->ipsec6_if_pool_index_by_key, &key61); + if (p) + { + tid1 = p[0]; + last_tunnel_id = tid1; + clib_memcpy_fast (&last_key6, &key61, sizeof (key61)); + } + else + { + next[1] = + ipsec_ip6_if_no_tunnel (node, b[1], esp1, buf_adv1); + n_no_tunnel++; + goto trace1; + } + } + } + else /* !is_ip6 */ + { + key41.remote_ip = ip41->src_address; + key41.spi = esp1->spi; - if (p) + if (key41.as_u64 == last_key4.as_u64) { - ipsec_tunnel_if_t *t; - t = pool_elt_at_index (im->tunnel_interfaces, p[0]); - vnet_buffer (b0)->ipsec.sad_index = t->input_sa_index; - if (t->hw_if_index != ~0) + tid1 = last_tunnel_id; + } + else + { + uword *p = + hash_get (im->ipsec4_if_pool_index_by_key, key41.as_u64); + if (p) { - vnet_hw_interface_t *hi; - - vnet_buffer (b0)->ipsec.flags = 0; - hi = vnet_get_hw_interface (vnm, t->hw_if_index); - sw_if_index0 = hi->sw_if_index; - vnet_buffer (b0)->sw_if_index[VLIB_RX] = sw_if_index0; - - if (PREDICT_FALSE - (!(hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP))) - { - vlib_increment_combined_counter - (drop_counter, thread_index, sw_if_index0, 1, len0); - b0->error = node->errors[IPSEC_IF_INPUT_ERROR_DISABLED]; - n_disabled++; - goto trace; - } - - if (PREDICT_TRUE (sw_if_index0 == last_sw_if_index)) - { - n_packets++; - n_bytes += len0; - } - else - { - sa0 = pool_elt_at_index (im->sad, t->input_sa_index); - icv_len = - em->ipsec_proto_main_integ_algs[sa0-> - integ_alg].trunc_size; - - /* length = packet length - ESP/tunnel overhead */ - n_bytes -= n_packets * (sizeof (ip4_header_t) + - sizeof (esp_header_t) + - sizeof (esp_footer_t) + - 16 /* aes-cbc IV */ + icv_len); - - if (last_t) - { - vlib_increment_combined_counter - (rx_counter, thread_index, sw_if_index0, - n_packets, n_bytes); - } - - last_sw_if_index = sw_if_index0; - last_t = t; - n_packets = 1; - n_bytes = len0; - } + tid1 = p[0]; + last_tunnel_id = tid1; + last_key4.as_u64 = key41.as_u64; } else { - vnet_buffer (b0)->ipsec.flags = IPSEC_FLAG_IPSEC_GRE_TUNNEL; + next[1] = + ipsec_ip4_if_no_tunnel (node, b[1], esp1, ip41, + buf_rewind1); + n_no_tunnel++; + goto trace1; } + } + } + + t1 = pool_elt_at_index (im->tunnel_interfaces, tid1); + vnet_buffer (b[1])->ipsec.sad_index = t1->input_sa_index; + + if (PREDICT_TRUE (t1->hw_if_index != ~0)) + { + sw_if_index1 = t1->sw_if_index; + vnet_buffer (b[1])->sw_if_index[VLIB_RX] = sw_if_index1; - vlib_buffer_advance (b0, ip4_header_bytes (ip0)); - next0 = im->esp4_decrypt_next_index; + if (PREDICT_FALSE (!(t1->flags & VNET_HW_INTERFACE_FLAG_LINK_UP))) + { + vlib_increment_combined_counter + (drop_counter, thread_index, sw_if_index1, 1, len1); + n_disabled++; + b[1]->error = node->errors[IPSEC_IF_INPUT_ERROR_DISABLED]; + next[1] = IPSEC_INPUT_NEXT_DROP; + goto trace1; + } + + if (PREDICT_TRUE (sw_if_index1 == last_sw_if_index)) + { + n_packets++; + n_bytes += len1; } else { - b0->error = node->errors[IPSEC_IF_INPUT_ERROR_NO_TUNNEL]; - n_no_tunnel++; + if (n_packets) + { + vlib_increment_combined_counter + (rx_counter, thread_index, last_sw_if_index, + n_packets, n_bytes); + } + + last_sw_if_index = sw_if_index1; + n_packets = 1; + n_bytes = len1; } + } - trace: - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) + trace1: + if (PREDICT_FALSE (is_trace)) + { + if (b[0]->flags & VLIB_BUFFER_IS_TRACED) + { + ipsec_if_input_trace_t *tr = + vlib_add_trace (vm, node, b[0], sizeof (*tr)); + if (is_ip6) + clib_memcpy (&tr->key6, &key60, sizeof (tr->key6)); + else + clib_memcpy (&tr->key4, &key40, sizeof (tr->key4)); + tr->is_ip6 = is_ip6; + tr->seq = + len0 >= + sizeof (*esp0) ? clib_host_to_net_u32 (esp0->seq) : ~0; + } + if (b[1]->flags & VLIB_BUFFER_IS_TRACED) { ipsec_if_input_trace_t *tr = - vlib_add_trace (vm, node, b0, sizeof (*tr)); - tr->spi = clib_host_to_net_u32 (esp0->spi); - tr->seq = clib_host_to_net_u32 (esp0->seq); + vlib_add_trace (vm, node, b[1], sizeof (*tr)); + if (is_ip6) + clib_memcpy (&tr->key6, &key61, sizeof (tr->key6)); + else + clib_memcpy (&tr->key4, &key41, sizeof (tr->key4)); + tr->is_ip6 = is_ip6; + tr->seq = + len1 >= + sizeof (*esp1) ? clib_host_to_net_u32 (esp1->seq) : ~0; } + } - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, - n_left_to_next, bi0, next0); + /* next */ + b += 2; + next += 2; + n_left_from -= 2; + } + while (n_left_from > 0) + { + u32 sw_if_index0; + ip4_header_t *ip40; + ip6_header_t *ip60; + esp_header_t *esp0; + u32 len0; + u16 buf_adv0, buf_rewind0; + u32 tid0; + ipsec_tunnel_if_t *t0; + ipsec4_tunnel_key_t key40; + ipsec6_tunnel_key_t key60; + + ip40 = + (ip4_header_t *) (b[0]->data + vnet_buffer (b[0])->l3_hdr_offset); + + if (is_ip6) + { + ip60 = (ip6_header_t *) ip40; + esp0 = (esp_header_t *) ((u8 *) ip60 + sizeof (ip6_header_t)); + buf_adv0 = sizeof (ip6_header_t); } - vlib_put_next_frame (vm, node, next_index, n_left_to_next); + else + { + /* NAT UDP port 4500 case, don't advance any more */ + if (ip40->protocol == IP_PROTOCOL_UDP) + { + esp0 = + (esp_header_t *) ((u8 *) ip40 + ip4_header_bytes (ip40) + + sizeof (udp_header_t)); + buf_adv0 = 0; + buf_rewind0 = ip4_header_bytes (ip40) + sizeof (udp_header_t); + } + else + { + esp0 = (esp_header_t *) ((u8 *) ip40 + ip4_header_bytes (ip40)); + buf_rewind0 = buf_adv0 = ip4_header_bytes (ip40); + } + } + + /* stats for the tunnel include all the data after the IP header + just like a norml IP-IP tunnel */ + vlib_buffer_advance (b[0], buf_adv0); + len0 = vlib_buffer_length_in_chain (vm, b[0]); + + if (len0 < sizeof (esp_header_t)) + { + if (esp0->spi_bytes[0] == 0xff) + b[0]->error = node->errors[IPSEC_IF_INPUT_ERROR_NAT_KEEPALIVE]; + else + b[0]->error = node->errors[IPSEC_IF_INPUT_ERROR_TOO_SHORT]; + + next[0] = IPSEC_INPUT_NEXT_DROP; + goto trace00; + } + + if (is_ip6) + { + key60.remote_ip = ip60->src_address; + key60.spi = esp0->spi; + + if (memcmp (&key60, &last_key6, sizeof (last_key6)) == 0) + { + tid0 = last_tunnel_id; + } + else + { + uword *p = + hash_get_mem (im->ipsec6_if_pool_index_by_key, &key60); + if (p) + { + tid0 = p[0]; + last_tunnel_id = tid0; + clib_memcpy_fast (&last_key6, &key60, sizeof (key60)); + } + else + { + next[0] = + ipsec_ip6_if_no_tunnel (node, b[0], esp0, buf_adv0); + n_no_tunnel++; + goto trace00; + } + } + } + else /* !is_ip6 */ + { + key40.remote_ip = ip40->src_address; + key40.spi = esp0->spi; + + if (key40.as_u64 == last_key4.as_u64) + { + tid0 = last_tunnel_id; + } + else + { + uword *p = + hash_get (im->ipsec4_if_pool_index_by_key, key40.as_u64); + if (p) + { + tid0 = p[0]; + last_tunnel_id = tid0; + last_key4.as_u64 = key40.as_u64; + } + else + { + next[0] = + ipsec_ip4_if_no_tunnel (node, b[0], esp0, ip40, + buf_rewind0); + n_no_tunnel++; + goto trace00; + } + } + } + + t0 = pool_elt_at_index (im->tunnel_interfaces, tid0); + vnet_buffer (b[0])->ipsec.sad_index = t0->input_sa_index; + + if (PREDICT_TRUE (t0->hw_if_index != ~0)) + { + sw_if_index0 = t0->sw_if_index; + vnet_buffer (b[0])->sw_if_index[VLIB_RX] = sw_if_index0; + + if (PREDICT_FALSE (!(t0->flags & VNET_HW_INTERFACE_FLAG_LINK_UP))) + { + vlib_increment_combined_counter + (drop_counter, thread_index, sw_if_index0, 1, len0); + n_disabled++; + b[0]->error = node->errors[IPSEC_IF_INPUT_ERROR_DISABLED]; + next[0] = IPSEC_INPUT_NEXT_DROP; + goto trace00; + } + + if (PREDICT_TRUE (sw_if_index0 == last_sw_if_index)) + { + n_packets++; + n_bytes += len0; + } + else + { + if (n_packets) + { + vlib_increment_combined_counter + (rx_counter, thread_index, last_sw_if_index, + n_packets, n_bytes); + } + + last_sw_if_index = sw_if_index0; + n_packets = 1; + n_bytes = len0; + } + } + + trace00: + if (PREDICT_FALSE (is_trace)) + { + if (b[0]->flags & VLIB_BUFFER_IS_TRACED) + { + ipsec_if_input_trace_t *tr = + vlib_add_trace (vm, node, b[0], sizeof (*tr)); + if (is_ip6) + clib_memcpy (&tr->key6, &key60, sizeof (tr->key6)); + else + clib_memcpy (&tr->key4, &key40, sizeof (tr->key4)); + tr->is_ip6 = is_ip6; + tr->seq = + len0 >= + sizeof (*esp0) ? clib_host_to_net_u32 (esp0->seq) : ~0; + } + } + + /* next */ + b += 1; + next += 1; + n_left_from -= 1; } - if (last_t) + if (n_packets) { - sa0 = pool_elt_at_index (im->sad, last_t->input_sa_index); - icv_len = em->ipsec_proto_main_integ_algs[sa0->integ_alg].trunc_size; - - n_bytes -= n_packets * (sizeof (ip4_header_t) + sizeof (esp_header_t) + - sizeof (esp_footer_t) + 16 /* aes-cbc IV */ + - icv_len); vlib_increment_combined_counter (rx_counter, thread_index, last_sw_if_index, n_packets, n_bytes); } - vlib_node_increment_counter (vm, ipsec_if_input_node.index, + vlib_node_increment_counter (vm, node->node_index, IPSEC_IF_INPUT_ERROR_RX, - from_frame->n_vectors - n_disabled); + from_frame->n_vectors - (n_disabled + + n_no_tunnel)); - vlib_node_increment_counter (vm, ipsec_if_input_node.index, - IPSEC_IF_INPUT_ERROR_DISABLED, n_disabled); - vlib_node_increment_counter (vm, ipsec_if_input_node.index, - IPSEC_IF_INPUT_ERROR_DISABLED, n_no_tunnel); + vlib_buffer_enqueue_to_next (vm, node, from, nexts, from_frame->n_vectors); return from_frame->n_vectors; } +VLIB_NODE_FN (ipsec4_if_input_node) (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + return ipsec_if_input_inline (vm, node, from_frame, 0 /* is_ip6 */ ); +} + /* *INDENT-OFF* */ -VLIB_REGISTER_NODE (ipsec_if_input_node) = { - .name = "ipsec-if-input", +VLIB_REGISTER_NODE (ipsec4_if_input_node) = { + .name = "ipsec4-if-input", .vector_size = sizeof (u32), .format_trace = format_ipsec_if_input_trace, .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN(ipsec_if_input_error_strings), .error_strings = ipsec_if_input_error_strings, - .sibling_of = "ipsec4-input-feature", }; /* *INDENT-ON* */ +VLIB_NODE_FN (ipsec6_if_input_node) (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + return ipsec_if_input_inline (vm, node, from_frame, 1 /* is_ip6 */ ); +} + +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (ipsec6_if_input_node) = { + .name = "ipsec6-if-input", + .vector_size = sizeof (u32), + .format_trace = format_ipsec_if_input_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN(ipsec_if_input_error_strings), + .error_strings = ipsec_if_input_error_strings, + .sibling_of = "ipsec6-input-feature", +}; +/* *INDENT-ON* */ + /* * fd.io coding-style-patch-verification: ON *