Fix ip4 udp encap length type
[vpp.git] / vnet / vnet / ip / udp.h
1 /*
2  * ip/udp.h: udp protocol
3  *
4  * Copyright (c) 2013 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #ifndef included_udp_h
19 #define included_udp_h
20
21 #include <vnet/vnet.h>
22 #include <vnet/ip/udp_packet.h>
23 #include <vnet/ip/ip.h>
24 #include <vnet/ip/ip4.h>
25 #include <vnet/ip/ip4_packet.h>
26 #include <vnet/pg/pg.h>
27 #include <vnet/ip/format.h>
28
29 typedef enum {
30 #define udp_error(n,s) UDP_ERROR_##n,
31 #include <vnet/ip/udp_error.def>
32 #undef udp_error
33   UDP_N_ERROR,
34 } udp_error_t;
35
36 #define foreach_udp4_dst_port                   \
37 _ (67, dhcp_to_server)                          \
38 _ (68, dhcp_to_client)                          \
39 _ (500, ikev2)                                  \
40 _ (4341, lisp_gpe)                              \
41 _ (4342, lisp_cp)                               \
42 _ (4739, ipfix)                                 \
43 _ (4789, vxlan)                                 \
44 _ (4790, vxlan_gpe)                             \
45 _ (6633, vpath_3)
46
47
48 #define foreach_udp6_dst_port                   \
49 _ (547, dhcpv6_to_server)                       \
50 _ (546, dhcpv6_to_client)                       \
51 _ (4342, lisp_cp6)                              \
52 _ (6633, vpath6_3)
53
54 typedef enum {
55 #define _(n,f) UDP_DST_PORT_##f = n,
56   foreach_udp4_dst_port
57   foreach_udp6_dst_port
58 #undef _
59 } udp_dst_port_t;
60
61 typedef enum {
62 #define _(n,f) UDP6_DST_PORT_##f = n,
63   foreach_udp6_dst_port
64 #undef _
65 } udp6_dst_port_t;
66
67 typedef struct {
68   /* Name (a c string). */
69   char * name;
70
71   /* GRE protocol type in host byte order. */
72   udp_dst_port_t dst_port;
73
74   /* Node which handles this type. */
75   u32 node_index;
76
77   /* Next index for this type. */
78   u32 next_index;
79 } udp_dst_port_info_t;
80
81 typedef enum {
82   UDP_IP6 = 0,
83   UDP_IP4,                      /* the code is full of is_ip4... */
84   N_UDP_AF,
85 } udp_af_t;
86
87 typedef struct {
88   udp_dst_port_info_t * dst_port_infos [N_UDP_AF];
89
90   /* Hash tables mapping name/protocol to protocol info index. */
91   uword * dst_port_info_by_name[N_UDP_AF];
92   uword * dst_port_info_by_dst_port[N_UDP_AF];
93
94   /* convenience */
95   vlib_main_t * vlib_main;
96 } udp_main_t;
97
98 always_inline udp_dst_port_info_t *
99 udp_get_dst_port_info (udp_main_t * um, udp_dst_port_t dst_port, u8 is_ip4)
100 {
101   uword * p = hash_get (um->dst_port_info_by_dst_port[is_ip4], dst_port);
102   return p ? vec_elt_at_index (um->dst_port_infos[is_ip4], p[0]) : 0;
103 }
104
105 format_function_t format_udp_header;
106 format_function_t format_udp_rx_trace;
107
108 unformat_function_t unformat_udp_header;
109
110 void udp_register_dst_port (vlib_main_t * vm,
111                             udp_dst_port_t dst_port,
112                             u32 node_index, u8 is_ip4);
113
114 always_inline void
115 ip4_udp_encap_one (vlib_main_t * vm, vlib_buffer_t * b0, u8 * ec0, word ec_len)
116 {
117   ip4_header_t * ip0;
118   ip_csum_t sum0;
119   u16 old_l0 = 0;
120   u16 new_l0;
121   udp_header_t * udp0;
122
123   vlib_buffer_advance (b0, - ec_len);
124   ip0 = vlib_buffer_get_current(b0);
125
126   /* Apply the encap string. */
127 #if DPDK > 0
128   rte_memcpy(ip0, ec0, ec_len);
129 #else
130   memcpy(ip0, ec0, ec_len);
131 #endif
132
133   /* fix the <bleep>ing outer-IP checksum */
134   sum0 = ip0->checksum;
135   /* old_l0 always 0, see the rewrite setup */
136   new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0));
137
138   sum0 = ip_csum_update(sum0, old_l0, new_l0, ip4_header_t,
139                         length /* changed member */);
140   ip0->checksum = ip_csum_fold (sum0);
141   ip0->length = new_l0;
142
143   /* Fix UDP length */
144   udp0 = (udp_header_t *)(ip0+1);
145   new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)
146                                  - sizeof (*ip0));
147
148   udp0->length = new_l0;
149 }
150
151 always_inline void
152 ip4_udp_encap_two (vlib_main_t * vm, vlib_buffer_t * b0, vlib_buffer_t * b1,
153                    u8 * ec0, u8 * ec1, word ec_len)
154 {
155   ip4_header_t * ip0, *ip1;
156   ip_csum_t sum0, sum1;
157   u16 old_l0 = 0, old_l1 = 0;
158   u16 new_l0, new_l1;
159   udp_header_t * udp0, *udp1;
160
161   ASSERT(_vec_len(ec0) == _vec_len(ec1));
162
163   vlib_buffer_advance (b0, -ec_len);
164   vlib_buffer_advance (b1, -ec_len);
165
166   ip0 = vlib_buffer_get_current (b0);
167   ip1 = vlib_buffer_get_current (b1);
168
169   /* Apply the encap string */
170 #if DPDK > 0
171   rte_memcpy (ip0, ec0, ec_len);
172   rte_memcpy (ip1, ec1, ec_len);
173 #else
174   memcpy (ip0, ec0, ec_len);
175   memcpy (ip1, ec1, ec_len);
176 #endif
177
178   /* fix the <bleep>ing outer-IP checksum */
179   sum0 = ip0->checksum;
180   sum1 = ip1->checksum;
181
182   /* old_l0 always 0, see the rewrite setup */
183   new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0));
184   new_l1 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b1));
185
186   sum0 = ip_csum_update(sum0, old_l0, new_l0, ip4_header_t,
187                         length /* changed member */);
188   sum1 = ip_csum_update(sum1, old_l1, new_l1, ip4_header_t,
189                         length /* changed member */);
190
191   ip0->checksum = ip_csum_fold (sum0);
192   ip1->checksum = ip_csum_fold (sum1);
193
194   ip0->length = new_l0;
195   ip1->length = new_l1;
196
197   /* Fix UDP length */
198   udp0 = (udp_header_t *) (ip0 + 1);
199   udp1 = (udp_header_t *) (ip1 + 1);
200
201   new_l0 = clib_host_to_net_u16 (
202       vlib_buffer_length_in_chain (vm, b0) - sizeof(*ip0));
203   new_l1 = clib_host_to_net_u16 (
204       vlib_buffer_length_in_chain (vm, b1) - sizeof(*ip1));
205   udp0->length = new_l0;
206   udp1->length = new_l1;
207   return;
208 }
209
210 #endif /* included_udp_h */