f4460202c02b012132cda5be141a2ff5f0e9d4f5
[dpdk.git] / lib / net / rte_net.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2016 6WIND S.A.
3  */
4
5 #ifndef _RTE_NET_PTYPE_H_
6 #define _RTE_NET_PTYPE_H_
7
8 #ifdef __cplusplus
9 extern "C" {
10 #endif
11
12 #include <rte_ip.h>
13 #include <rte_udp.h>
14 #include <rte_tcp.h>
15 #include <rte_sctp.h>
16
17 /**
18  * Structure containing header lengths associated to a packet, filled
19  * by rte_net_get_ptype().
20  */
21 struct rte_net_hdr_lens {
22         uint8_t l2_len;
23         uint8_t inner_l2_len;
24         uint16_t l3_len;
25         uint16_t inner_l3_len;
26         uint16_t tunnel_len;
27         uint8_t l4_len;
28         uint8_t inner_l4_len;
29 };
30
31 /**
32  * Skip IPv6 header extensions.
33  *
34  * This function skips all IPv6 extensions, returning size of
35  * complete header including options and final protocol value.
36  *
37  * @param proto
38  *   Protocol field of IPv6 header.
39  * @param m
40  *   The packet mbuf to be parsed.
41  * @param off
42  *   On input, must contain the offset to the first byte following
43  *   IPv6 header, on output, contains offset to the first byte
44  *   of next layer (after any IPv6 extension header)
45  * @param frag
46  *   Contains 1 in output if packet is an IPv6 fragment.
47  * @return
48  *   Protocol that follows IPv6 header.
49  *   -1 if an error occurs during mbuf parsing.
50  */
51 int
52 rte_net_skip_ip6_ext(uint16_t proto, const struct rte_mbuf *m, uint32_t *off,
53         int *frag);
54
55 /**
56  * Parse an Ethernet packet to get its packet type.
57  *
58  * This function parses the network headers in mbuf data and return its
59  * packet type.
60  *
61  * If it is provided by the user, it also fills a rte_net_hdr_lens
62  * structure that contains the lengths of the parsed network
63  * headers. Each length field is valid only if the associated packet
64  * type is set. For instance, hdr_lens->l2_len is valid only if
65  * (retval & RTE_PTYPE_L2_MASK) != RTE_PTYPE_UNKNOWN.
66  *
67  * Supported packet types are:
68  *   L2: Ether, Vlan, QinQ
69  *   L3: IPv4, IPv6
70  *   L4: TCP, UDP, SCTP
71  *   Tunnels: IPv4, IPv6, Gre, Nvgre
72  *
73  * @param m
74  *   The packet mbuf to be parsed.
75  * @param hdr_lens
76  *   A pointer to a structure where the header lengths will be returned,
77  *   or NULL.
78  * @param layers
79  *   List of layers to parse. The function will stop at the first
80  *   empty layer. Examples:
81  *   - To parse all known layers, use RTE_PTYPE_ALL_MASK.
82  *   - To parse only L2 and L3, use RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK
83  * @return
84  *   The packet type of the packet.
85  */
86 uint32_t rte_net_get_ptype(const struct rte_mbuf *m,
87         struct rte_net_hdr_lens *hdr_lens, uint32_t layers);
88
89 /**
90  * Prepare pseudo header checksum
91  *
92  * This function prepares pseudo header checksum for TSO and non-TSO tcp/udp in
93  * provided mbufs packet data and based on the requested offload flags.
94  *
95  * - for non-TSO tcp/udp packets full pseudo-header checksum is counted and set
96  *   in packet data,
97  * - for TSO the IP payload length is not included in pseudo header.
98  *
99  * This function expects that used headers are in the first data segment of
100  * mbuf, are not fragmented and can be safely modified.
101  *
102  * @param m
103  *   The packet mbuf to be fixed.
104  * @param ol_flags
105  *   TX offloads flags to use with this packet.
106  * @return
107  *   0 if checksum is initialized properly
108  */
109 static inline int
110 rte_net_intel_cksum_flags_prepare(struct rte_mbuf *m, uint64_t ol_flags)
111 {
112         /* Initialise ipv4_hdr to avoid false positive compiler warnings. */
113         struct rte_ipv4_hdr *ipv4_hdr = NULL;
114         struct rte_ipv6_hdr *ipv6_hdr;
115         struct rte_tcp_hdr *tcp_hdr;
116         struct rte_udp_hdr *udp_hdr;
117         uint64_t inner_l3_offset = m->l2_len;
118
119         /*
120          * Does packet set any of available offloads?
121          * Mainly it is required to avoid fragmented headers check if
122          * no offloads are requested.
123          */
124         if (!(ol_flags & (PKT_TX_IP_CKSUM | PKT_TX_L4_MASK | PKT_TX_TCP_SEG |
125                           PKT_TX_OUTER_IP_CKSUM)))
126                 return 0;
127
128         if (ol_flags & (PKT_TX_OUTER_IPV4 | PKT_TX_OUTER_IPV6)) {
129                 inner_l3_offset += m->outer_l2_len + m->outer_l3_len;
130                 /*
131                  * prepare outer IPv4 header checksum by setting it to 0,
132                  * in order to be computed by hardware NICs.
133                  */
134                 if (ol_flags & PKT_TX_OUTER_IP_CKSUM) {
135                         ipv4_hdr = rte_pktmbuf_mtod_offset(m,
136                                         struct rte_ipv4_hdr *, m->outer_l2_len);
137                         ipv4_hdr->hdr_checksum = 0;
138                 }
139         }
140
141         /*
142          * Check if headers are fragmented.
143          * The check could be less strict depending on which offloads are
144          * requested and headers to be used, but let's keep it simple.
145          */
146         if (unlikely(rte_pktmbuf_data_len(m) <
147                      inner_l3_offset + m->l3_len + m->l4_len))
148                 return -ENOTSUP;
149
150         if (ol_flags & PKT_TX_IPV4) {
151                 ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *,
152                                 inner_l3_offset);
153
154                 if (ol_flags & PKT_TX_IP_CKSUM)
155                         ipv4_hdr->hdr_checksum = 0;
156         }
157
158         if ((ol_flags & PKT_TX_L4_MASK) == PKT_TX_UDP_CKSUM) {
159                 if (ol_flags & PKT_TX_IPV4) {
160                         udp_hdr = (struct rte_udp_hdr *)((char *)ipv4_hdr +
161                                         m->l3_len);
162                         udp_hdr->dgram_cksum = rte_ipv4_phdr_cksum(ipv4_hdr,
163                                         ol_flags);
164                 } else {
165                         ipv6_hdr = rte_pktmbuf_mtod_offset(m,
166                                 struct rte_ipv6_hdr *, inner_l3_offset);
167                         /* non-TSO udp */
168                         udp_hdr = rte_pktmbuf_mtod_offset(m,
169                                         struct rte_udp_hdr *,
170                                         inner_l3_offset + m->l3_len);
171                         udp_hdr->dgram_cksum = rte_ipv6_phdr_cksum(ipv6_hdr,
172                                         ol_flags);
173                 }
174         } else if ((ol_flags & PKT_TX_L4_MASK) == PKT_TX_TCP_CKSUM ||
175                         (ol_flags & PKT_TX_TCP_SEG)) {
176                 if (ol_flags & PKT_TX_IPV4) {
177                         /* non-TSO tcp or TSO */
178                         tcp_hdr = (struct rte_tcp_hdr *)((char *)ipv4_hdr +
179                                         m->l3_len);
180                         tcp_hdr->cksum = rte_ipv4_phdr_cksum(ipv4_hdr,
181                                         ol_flags);
182                 } else {
183                         ipv6_hdr = rte_pktmbuf_mtod_offset(m,
184                                 struct rte_ipv6_hdr *, inner_l3_offset);
185                         /* non-TSO tcp or TSO */
186                         tcp_hdr = rte_pktmbuf_mtod_offset(m,
187                                         struct rte_tcp_hdr *,
188                                         inner_l3_offset + m->l3_len);
189                         tcp_hdr->cksum = rte_ipv6_phdr_cksum(ipv6_hdr,
190                                         ol_flags);
191                 }
192         }
193
194         return 0;
195 }
196
197 /**
198  * Prepare pseudo header checksum
199  *
200  * This function prepares pseudo header checksum for TSO and non-TSO tcp/udp in
201  * provided mbufs packet data.
202  *
203  * - for non-TSO tcp/udp packets full pseudo-header checksum is counted and set
204  *   in packet data,
205  * - for TSO the IP payload length is not included in pseudo header.
206  *
207  * This function expects that used headers are in the first data segment of
208  * mbuf, are not fragmented and can be safely modified.
209  *
210  * @param m
211  *   The packet mbuf to be fixed.
212  * @return
213  *   0 if checksum is initialized properly
214  */
215 static inline int
216 rte_net_intel_cksum_prepare(struct rte_mbuf *m)
217 {
218         return rte_net_intel_cksum_flags_prepare(m, m->ol_flags);
219 }
220
221 #ifdef __cplusplus
222 }
223 #endif
224
225
226 #endif /* _RTE_NET_PTYPE_H_ */