+ static const u8 pad_data[ESP_MAX_BLOCK_SIZE] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x00, 0x00,
+ };
+
+ u16 min_length = b->current_length + sizeof (esp_footer_t);
+ u16 new_length = round_pow2 (min_length, block_size);
+ u8 pad_bytes = new_length - min_length;
+ esp_footer_t *f = (esp_footer_t *) (vlib_buffer_get_current (b) +
+ new_length - sizeof (esp_footer_t));
+
+ if (pad_bytes)
+ clib_memcpy_fast ((u8 *) f - pad_bytes, pad_data, ESP_MAX_BLOCK_SIZE);
+
+ f->pad_length = pad_bytes;
+ b->current_length = new_length + icv_sz;
+ return &f->next_header;
+}
+
+static_always_inline void
+esp_update_ip4_hdr (ip4_header_t * ip4, u16 len, int is_transport, int is_udp)
+{
+ ip_csum_t sum = ip4->checksum;
+ u16 old_len = 0;
+
+ if (is_transport)
+ {
+ u8 prot = is_udp ? IP_PROTOCOL_UDP : IP_PROTOCOL_IPSEC_ESP;
+ old_len = ip4->length;
+ sum = ip_csum_update (sum, ip4->protocol, prot, ip4_header_t, protocol);
+ ip4->protocol = prot;
+ }
+
+ ip4->length = len = clib_net_to_host_u16 (len);
+ sum = ip_csum_update (ip4->checksum, old_len, len, ip4_header_t, length);
+ ip4->checksum = ip_csum_fold (sum);
+}
+
+static_always_inline void
+esp_fill_udp_hdr (ipsec_sa_t * sa, udp_header_t * udp, u16 len)
+{
+ clib_memcpy_fast (udp, &sa->udp_hdr, sizeof (udp_header_t));
+ udp->length = clib_net_to_host_u16 (len);
+}
+
+static_always_inline u8
+ext_hdr_is_pre_esp (u8 nexthdr)
+{
+#ifdef CLIB_HAVE_VEC128
+ static const u8x16 ext_hdr_types = {
+ IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS,
+ IP_PROTOCOL_IPV6_ROUTE,
+ IP_PROTOCOL_IPV6_FRAGMENTATION,
+ };
+
+ return !u8x16_is_all_zero (ext_hdr_types == u8x16_splat (nexthdr));