62d78b7b176c43f226f4560bec464bc100cb62ff
[dpdk.git] / lib / librte_ipsec / iph.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Intel Corporation
3  */
4
5 #ifndef _IPH_H_
6 #define _IPH_H_
7
8 #include <rte_ip.h>
9
10 /**
11  * @file iph.h
12  * Contains functions/structures/macros to manipulate IPv4/IPv6 headers
13  * used internally by ipsec library.
14  */
15
16 /*
17  * Move preceding (L3) headers down to remove ESP header and IV.
18  */
19 static inline void
20 remove_esph(char *np, char *op, uint32_t hlen)
21 {
22         uint32_t i;
23
24         for (i = hlen; i-- != 0; np[i] = op[i])
25                 ;
26 }
27
28 /*
29  * Move preceding (L3) headers up to free space for ESP header and IV.
30  */
31 static inline void
32 insert_esph(char *np, char *op, uint32_t hlen)
33 {
34         uint32_t i;
35
36         for (i = 0; i != hlen; i++)
37                 np[i] = op[i];
38 }
39
40 /* update original ip header fields for transport case */
41 static inline int
42 update_trs_l3hdr(const struct rte_ipsec_sa *sa, void *p, uint32_t plen,
43                 uint32_t l2len, uint32_t l3len, uint8_t proto)
44 {
45         int32_t rc;
46
47         /* IPv4 */
48         if ((sa->type & RTE_IPSEC_SATP_IPV_MASK) == RTE_IPSEC_SATP_IPV4) {
49                 struct rte_ipv4_hdr *v4h;
50
51                 v4h = p;
52                 rc = v4h->next_proto_id;
53                 v4h->next_proto_id = proto;
54                 v4h->total_length = rte_cpu_to_be_16(plen - l2len);
55         /* IPv6 */
56         } else {
57                 struct rte_ipv6_hdr *v6h;
58                 uint8_t *p_nh;
59
60                 v6h = p;
61
62                 /* basic IPv6 header with no extensions */
63                 if (l3len == sizeof(struct rte_ipv6_hdr))
64                         p_nh = &v6h->proto;
65
66                 /* IPv6 with extensions */
67                 else {
68                         size_t ext_len;
69                         int nh;
70                         uint8_t *pd, *plimit;
71
72                         /* locate last extension within l3len bytes */
73                         pd = (uint8_t *)p;
74                         plimit = pd + l3len;
75                         ext_len = sizeof(struct rte_ipv6_hdr);
76                         nh = v6h->proto;
77                         while (pd + ext_len < plimit) {
78                                 pd += ext_len;
79                                 nh = rte_ipv6_get_next_ext(pd, nh, &ext_len);
80                                 if (unlikely(nh < 0))
81                                         return -EINVAL;
82                         }
83
84                         /* invalid l3len - extension exceeds header length */
85                         if (unlikely(pd + ext_len != plimit))
86                                 return -EINVAL;
87
88                         /* save last extension offset */
89                         p_nh = pd;
90                 }
91
92                 /* update header type; return original value */
93                 rc = *p_nh;
94                 *p_nh = proto;
95
96                 /* fix packet length */
97                 v6h->payload_len = rte_cpu_to_be_16(plen - l2len -
98                                 sizeof(*v6h));
99         }
100
101         return rc;
102 }
103
104 /* update original and new ip header fields for tunnel case */
105 static inline void
106 update_tun_l3hdr(const struct rte_ipsec_sa *sa, void *p, uint32_t plen,
107                 uint32_t l2len, rte_be16_t pid)
108 {
109         struct rte_ipv4_hdr *v4h;
110         struct rte_ipv6_hdr *v6h;
111
112         if (sa->type & RTE_IPSEC_SATP_MODE_TUNLV4) {
113                 v4h = p;
114                 v4h->packet_id = pid;
115                 v4h->total_length = rte_cpu_to_be_16(plen - l2len);
116         } else {
117                 v6h = p;
118                 v6h->payload_len = rte_cpu_to_be_16(plen - l2len -
119                                 sizeof(*v6h));
120         }
121 }
122
123 #endif /* _IPH_H_ */