FD.io VPP  v21.01.1
Vector Packet Processing
udp_inlines.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef SRC_VNET_UDP_UDP_INLINES_H_
17 #define SRC_VNET_UDP_UDP_INLINES_H_
18 
19 #include <vnet/vnet.h>
20 #include <vnet/ip/ip4.h>
21 #include <vnet/ip/ip6.h>
22 #include <vnet/udp/udp_packet.h>
23 
24 always_inline void *
25 vlib_buffer_push_udp (vlib_buffer_t * b, u16 sp, u16 dp, u8 offload_csum)
26 {
27  udp_header_t *uh;
28  u16 udp_len = sizeof (udp_header_t) + b->current_length;
29  if (PREDICT_FALSE (b->flags & VLIB_BUFFER_TOTAL_LENGTH_VALID))
31 
32  uh = vlib_buffer_push_uninit (b, sizeof (udp_header_t));
33  uh->src_port = sp;
34  uh->dst_port = dp;
35  uh->checksum = 0;
36  uh->length = clib_host_to_net_u16 (udp_len);
37  if (offload_csum)
38  b->flags |= VNET_BUFFER_F_OFFLOAD_UDP_CKSUM;
39  vnet_buffer (b)->l4_hdr_offset = (u8 *) uh - b->data;
40  b->flags |= VNET_BUFFER_F_L4_HDR_OFFSET_VALID;
41  return uh;
42 }
43 
44 always_inline void
46 {
47  u16 new_l0;
48  udp_header_t *udp0;
49 
50  if (is_ip4)
51  {
52  ip4_header_t *ip0;
53  ip_csum_t sum0;
54  u16 old_l0 = 0;
55 
56  ip0 = vlib_buffer_get_current (b0);
57 
58  /* fix the <bleep>ing outer-IP checksum */
59  sum0 = ip0->checksum;
60  /* old_l0 always 0, see the rewrite setup */
61  new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0));
62 
63  sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
64  length /* changed member */ );
65  ip0->checksum = ip_csum_fold (sum0);
66  ip0->length = new_l0;
67 
68  /* Fix UDP length */
69  udp0 = (udp_header_t *) (ip0 + 1);
70  new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)
71  - sizeof (*ip0));
72  udp0->length = new_l0;
73  }
74  else
75  {
76  ip6_header_t *ip0;
77  int bogus0;
78 
79  ip0 = vlib_buffer_get_current (b0);
80 
81  new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)
82  - sizeof (*ip0));
83  ip0->payload_length = new_l0;
84 
85  /* Fix UDP length */
86  udp0 = (udp_header_t *) (ip0 + 1);
87  udp0->length = new_l0;
88 
89  udp0->checksum =
90  ip6_tcp_udp_icmp_compute_checksum (vm, b0, ip0, &bogus0);
91  ASSERT (bogus0 == 0);
92 
93  if (udp0->checksum == 0)
94  udp0->checksum = 0xffff;
95  }
96 }
97 
98 always_inline void
100  u8 is_ip4)
101 {
102  vlib_buffer_advance (b0, -ec_len);
103 
104  if (is_ip4)
105  {
106  ip4_header_t *ip0;
107 
108  ip0 = vlib_buffer_get_current (b0);
109 
110  /* Apply the encap string. */
111  clib_memcpy_fast (ip0, ec0, ec_len);
112  ip_udp_fixup_one (vm, b0, 1);
113  }
114  else
115  {
116  ip6_header_t *ip0;
117 
118  ip0 = vlib_buffer_get_current (b0);
119 
120  /* Apply the encap string. */
121  clib_memcpy_fast (ip0, ec0, ec_len);
122  ip_udp_fixup_one (vm, b0, 0);
123  }
124 }
125 
126 always_inline void
128  u8 * ec0, u8 * ec1, word ec_len, u8 is_v4)
129 {
130  u16 new_l0, new_l1;
131  udp_header_t *udp0, *udp1;
132 
133  ASSERT (_vec_len (ec0) == _vec_len (ec1));
134 
135  vlib_buffer_advance (b0, -ec_len);
136  vlib_buffer_advance (b1, -ec_len);
137 
138  if (is_v4)
139  {
140  ip4_header_t *ip0, *ip1;
141  ip_csum_t sum0, sum1;
142  u16 old_l0 = 0, old_l1 = 0;
143 
144  ip0 = vlib_buffer_get_current (b0);
145  ip1 = vlib_buffer_get_current (b1);
146 
147  /* Apply the encap string */
148  clib_memcpy_fast (ip0, ec0, ec_len);
149  clib_memcpy_fast (ip1, ec1, ec_len);
150 
151  /* fix the <bleep>ing outer-IP checksum */
152  sum0 = ip0->checksum;
153  sum1 = ip1->checksum;
154 
155  /* old_l0 always 0, see the rewrite setup */
156  new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0));
157  new_l1 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b1));
158 
159  sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
160  length /* changed member */ );
161  sum1 = ip_csum_update (sum1, old_l1, new_l1, ip4_header_t,
162  length /* changed member */ );
163 
164  ip0->checksum = ip_csum_fold (sum0);
165  ip1->checksum = ip_csum_fold (sum1);
166 
167  ip0->length = new_l0;
168  ip1->length = new_l1;
169 
170  /* Fix UDP length */
171  udp0 = (udp_header_t *) (ip0 + 1);
172  udp1 = (udp_header_t *) (ip1 + 1);
173 
174  new_l0 =
175  clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0) -
176  sizeof (*ip0));
177  new_l1 =
178  clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b1) -
179  sizeof (*ip1));
180  udp0->length = new_l0;
181  udp1->length = new_l1;
182  }
183  else
184  {
185  ip6_header_t *ip0, *ip1;
186  int bogus0, bogus1;
187 
188  ip0 = vlib_buffer_get_current (b0);
189  ip1 = vlib_buffer_get_current (b1);
190 
191  /* Apply the encap string. */
192  clib_memcpy_fast (ip0, ec0, ec_len);
193  clib_memcpy_fast (ip1, ec1, ec_len);
194 
195  new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)
196  - sizeof (*ip0));
197  new_l1 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b1)
198  - sizeof (*ip1));
199  ip0->payload_length = new_l0;
200  ip1->payload_length = new_l1;
201 
202  /* Fix UDP length */
203  udp0 = (udp_header_t *) (ip0 + 1);
204  udp1 = (udp_header_t *) (ip1 + 1);
205 
206  udp0->length = new_l0;
207  udp1->length = new_l1;
208 
209  udp0->checksum =
210  ip6_tcp_udp_icmp_compute_checksum (vm, b0, ip0, &bogus0);
211  udp1->checksum =
212  ip6_tcp_udp_icmp_compute_checksum (vm, b1, ip1, &bogus1);
213  ASSERT (bogus0 == 0);
214  ASSERT (bogus1 == 0);
215 
216  if (udp0->checksum == 0)
217  udp0->checksum = 0xffff;
218  if (udp1->checksum == 0)
219  udp1->checksum = 0xffff;
220  }
221 }
222 
223 #endif /* SRC_VNET_UDP_UDP_INLINES_H_ */
224 
225 /*
226  * fd.io coding-style-patch-verification: ON
227  *
228  * Local Variables:
229  * eval: (c-set-style "gnu")
230  * End:
231  */
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
static void ip_udp_fixup_one(vlib_main_t *vm, vlib_buffer_t *b0, u8 is_ip4)
Definition: udp_inlines.h:45
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
uword ip_csum_t
Definition: ip_packet.h:246
vlib_main_t * vm
Definition: in2out_ed.c:1580
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:402
unsigned char u8
Definition: types.h:56
i64 word
Definition: types.h:111
const cJSON *const b
Definition: cJSON.h:255
unsigned short u16
Definition: types.h:57
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:233
#define PREDICT_FALSE(x)
Definition: clib.h:121
#define always_inline
Definition: ipsec.h:28
u8 data[]
Packet data.
Definition: buffer.h:181
u16 ip6_tcp_udp_icmp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip6_header_t *ip0, int *bogus_lengthp)
Definition: ip6_forward.c:1099
#define ASSERT(truth)
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:252
char const int length
Definition: cJSON.h:163
static void * vlib_buffer_push_udp(vlib_buffer_t *b, u16 sp, u16 dp, u8 offload_csum)
Definition: udp_inlines.h:25
static void * vlib_buffer_push_uninit(vlib_buffer_t *b, u8 size)
Prepend uninitialized data to buffer.
Definition: buffer.h:339
u16 payload_length
Definition: ip6_packet.h:301
VLIB buffer representation.
Definition: buffer.h:102
#define ip_csum_update(sum, old, new, type, field)
Definition: ip_packet.h:296
#define vnet_buffer(b)
Definition: buffer.h:417
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
Definition: buffer.h:167
static void ip_udp_encap_one(vlib_main_t *vm, vlib_buffer_t *b0, u8 *ec0, word ec_len, u8 is_ip4)
Definition: udp_inlines.h:99
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:302
static void ip_udp_encap_two(vlib_main_t *vm, vlib_buffer_t *b0, vlib_buffer_t *b1, u8 *ec0, u8 *ec1, word ec_len, u8 is_v4)
Definition: udp_inlines.h:127