blob: aee4f25e6a615e729bbe8f6a2fd6e76263ee31b9 [file] [log] [blame]
Florin Corase127a7e2016-02-18 22:20:01 +01001/*
2 * Copyright (c) 2016 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#include <vnet/lisp-cp/lisp_msg_serdes.h>
17#include <vnet/lisp-cp/packets.h>
18#include <vppinfra/time.h>
19
Filip Tehlar397fd7d2016-10-26 14:31:24 +020020void *lisp_msg_put_gid (vlib_buffer_t * b, gid_address_t * gid);
21
22static void
23lisp_msg_put_locators (vlib_buffer_t * b, locator_t * locators)
24{
25 locator_t *loc;
26
27 vec_foreach (loc, locators)
28 {
29 u8 *p = vlib_buffer_put_uninit (b, sizeof (locator_hdr_t));
30 memset (p, 0, sizeof (locator_hdr_t));
31 LOC_PRIORITY (p) = loc->priority;
32 LOC_MPRIORITY (p) = loc->mpriority;
33 LOC_WEIGHT (p) = loc->weight;
34 LOC_MWEIGHT (p) = loc->mweight;
35 LOC_LOCAL (p) = loc->local;
36 LOC_PROBED (p) = loc->probed ? 1 : 0;
37 lisp_msg_put_gid (b, &loc->address);
38 }
39}
40
41static void
42lisp_msg_put_mapping_record (vlib_buffer_t * b, mapping_t * record)
43{
44 mapping_record_hdr_t *p =
45 vlib_buffer_put_uninit (b, sizeof (mapping_record_hdr_t));
46 gid_address_t *eid = &record->eid;
47
48 memset (p, 0, sizeof (*p));
49 MAP_REC_EID_PLEN (p) = gid_address_len (eid);
Filip Tehlarfb9931f2016-12-09 13:52:38 +010050 MAP_REC_TTL (p) = clib_host_to_net_u32 (MAP_REGISTER_DEFAULT_TTL);
Filip Tehlar397fd7d2016-10-26 14:31:24 +020051 MAP_REC_AUTH (p) = record->authoritative ? 1 : 0;
52 MAP_REC_LOC_COUNT (p) = vec_len (record->locators);
53
54 lisp_msg_put_gid (b, eid);
55 lisp_msg_put_locators (b, record->locators);
56}
57
58static void
59lisp_msg_put_mreg_records (vlib_buffer_t * b, mapping_t * records)
60{
61 u32 i;
62 for (i = 0; i < vec_len (records); i++)
63 lisp_msg_put_mapping_record (b, &records[i]);
64}
65
Florin Corase127a7e2016-02-18 22:20:01 +010066void *
67lisp_msg_put_gid (vlib_buffer_t * b, gid_address_t * gid)
68{
Filip Tehlar397fd7d2016-10-26 14:31:24 +020069 u8 *p = 0;
70 if (!gid)
71 {
72 /* insert only src-eid-afi field set to 0 */
73 p = vlib_buffer_put_uninit (b, sizeof (u16));
74 *(u16 *) p = 0;
75 }
76 else
77 {
78 p = vlib_buffer_put_uninit (b, gid_address_size_to_put (gid));
79 gid_address_put (p, gid);
80 }
Florin Corase127a7e2016-02-18 22:20:01 +010081 return p;
82}
83
Filip Tehlarbeceab92016-04-20 17:21:55 +020084static void *
Florin Corase127a7e2016-02-18 22:20:01 +010085lisp_msg_put_itr_rlocs (lisp_cp_main_t * lcm, vlib_buffer_t * b,
Florin Corasa2157cf2016-08-16 21:09:14 +020086 gid_address_t * rlocs, u8 * locs_put)
Florin Corase127a7e2016-02-18 22:20:01 +010087{
Florin Corasa2157cf2016-08-16 21:09:14 +020088 u8 *bp, count = 0;
Filip Tehlar254b0362016-04-07 10:04:34 +020089 u32 i;
Florin Corase127a7e2016-02-18 22:20:01 +010090
Filip Tehlarbeceab92016-04-20 17:21:55 +020091 bp = vlib_buffer_get_current (b);
92 for (i = 0; i < vec_len (rlocs); i++)
Florin Corase127a7e2016-02-18 22:20:01 +010093 {
Filip Tehlarbeceab92016-04-20 17:21:55 +020094 lisp_msg_put_gid (b, &rlocs[i]);
Filip Tehlar254b0362016-04-07 10:04:34 +020095 count++;
Florin Corase127a7e2016-02-18 22:20:01 +010096 }
Filip Tehlar254b0362016-04-07 10:04:34 +020097
Florin Corasa2157cf2016-08-16 21:09:14 +020098 *locs_put = count - 1;
Florin Corase127a7e2016-02-18 22:20:01 +010099 return bp;
100}
101
102void *
103lisp_msg_put_eid_rec (vlib_buffer_t * b, gid_address_t * eid)
104{
Florin Corasa2157cf2016-08-16 21:09:14 +0200105 eid_record_hdr_t *h = vlib_buffer_put_uninit (b, sizeof (*h));
Florin Corase127a7e2016-02-18 22:20:01 +0100106
Florin Corasa2157cf2016-08-16 21:09:14 +0200107 memset (h, 0, sizeof (*h));
Florin Corase127a7e2016-02-18 22:20:01 +0100108 EID_REC_MLEN (h) = gid_address_len (eid);
109 lisp_msg_put_gid (b, eid);
110 return h;
111}
112
113u64
114nonce_build (u32 seed)
115{
116 u64 nonce;
117 u32 nonce_lower;
118 u32 nonce_upper;
119 struct timespec ts;
120
121 /* Put nanosecond clock in lower 32-bits and put an XOR of the nanosecond
122 * clock with the seond clock in the upper 32-bits. */
123 syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts);
124 nonce_lower = ts.tv_nsec;
Florin Corasa2157cf2016-08-16 21:09:14 +0200125 nonce_upper = ts.tv_sec ^ clib_host_to_net_u32 (nonce_lower);
Florin Corase127a7e2016-02-18 22:20:01 +0100126
127 /* OR in a caller provided seed to the low-order 32-bits. */
128 nonce_lower |= seed;
129
130 /* Return 64-bit nonce. */
131 nonce = nonce_upper;
132 nonce = (nonce << 32) | nonce_lower;
133 return nonce;
134}
135
136void *
Filip Tehlar397fd7d2016-10-26 14:31:24 +0200137lisp_msg_put_map_reply (vlib_buffer_t * b, mapping_t * records, u64 nonce,
138 u8 probe_bit)
139{
140 map_reply_hdr_t *h = vlib_buffer_put_uninit (b, sizeof (h[0]));
141
142 memset (h, 0, sizeof (h[0]));
143 MREP_TYPE (h) = LISP_MAP_REPLY;
144 MREP_NONCE (h) = nonce;
145 MREP_REC_COUNT (h) = 1;
146 MREP_RLOC_PROBE (h) = probe_bit;
147
148 lisp_msg_put_mreg_records (b, records);
149 return h;
150}
151
152void *
153lisp_msg_put_map_register (vlib_buffer_t * b, mapping_t * records,
154 u8 want_map_notify, u16 auth_data_len, u64 * nonce,
155 u32 * msg_len)
156{
157 u8 *auth_data = 0;
158
159 /* Basic header init */
160 map_register_hdr_t *h = vlib_buffer_put_uninit (b, sizeof (h[0]));
161
162 memset (h, 0, sizeof (h[0]));
163 MREG_TYPE (h) = LISP_MAP_REGISTER;
164 MREG_NONCE (h) = nonce_build (0);
165 MREG_WANT_MAP_NOTIFY (h) = want_map_notify ? 1 : 0;
166 MREG_REC_COUNT (h) = vec_len (records);
167
168 auth_data = vlib_buffer_put_uninit (b, auth_data_len);
169 memset (auth_data, 0, auth_data_len);
170
171 /* Put map register records */
172 lisp_msg_put_mreg_records (b, records);
173
174 nonce[0] = MREG_NONCE (h);
175 msg_len[0] = vlib_buffer_get_tail (b) - (u8 *) h;
176 return h;
177}
178
179void *
Florin Corase127a7e2016-02-18 22:20:01 +0100180lisp_msg_put_mreq (lisp_cp_main_t * lcm, vlib_buffer_t * b,
Florin Corasa2157cf2016-08-16 21:09:14 +0200181 gid_address_t * seid, gid_address_t * deid,
Filip Tehlar397fd7d2016-10-26 14:31:24 +0200182 gid_address_t * rlocs, u8 is_smr_invoked,
183 u8 rloc_probe_set, u64 * nonce)
Florin Corase127a7e2016-02-18 22:20:01 +0100184{
185 u8 loc_count = 0;
186
187 /* Basic header init */
Florin Corasa2157cf2016-08-16 21:09:14 +0200188 map_request_hdr_t *h = vlib_buffer_put_uninit (b, sizeof (h[0]));
Florin Corase127a7e2016-02-18 22:20:01 +0100189
Florin Corasa2157cf2016-08-16 21:09:14 +0200190 memset (h, 0, sizeof (h[0]));
191 MREQ_TYPE (h) = LISP_MAP_REQUEST;
192 MREQ_NONCE (h) = nonce_build (0);
193 MREQ_SMR_INVOKED (h) = is_smr_invoked ? 1 : 0;
Filip Tehlar397fd7d2016-10-26 14:31:24 +0200194 MREQ_RLOC_PROBE (h) = rloc_probe_set ? 1 : 0;
Florin Corase127a7e2016-02-18 22:20:01 +0100195
196 /* We're adding one eid record */
197 increment_record_count (h);
198
199 /* Fill source eid */
200 lisp_msg_put_gid (b, seid);
201
202 /* Put itr rlocs */
Florin Corasa2157cf2016-08-16 21:09:14 +0200203 lisp_msg_put_itr_rlocs (lcm, b, rlocs, &loc_count);
204 MREQ_ITR_RLOC_COUNT (h) = loc_count;
Florin Corase127a7e2016-02-18 22:20:01 +0100205
206 /* Put eid record */
Florin Corasa2157cf2016-08-16 21:09:14 +0200207 lisp_msg_put_eid_rec (b, deid);
Florin Corase127a7e2016-02-18 22:20:01 +0100208
Florin Corasa2157cf2016-08-16 21:09:14 +0200209 nonce[0] = MREQ_NONCE (h);
Florin Corase127a7e2016-02-18 22:20:01 +0100210 return h;
211}
212
213void *
Florin Corasa2157cf2016-08-16 21:09:14 +0200214lisp_msg_push_ecm (vlib_main_t * vm, vlib_buffer_t * b, int lp, int rp,
215 gid_address_t * la, gid_address_t * ra)
Florin Corase127a7e2016-02-18 22:20:01 +0100216{
217 ecm_hdr_t *h;
Florin Corasa2157cf2016-08-16 21:09:14 +0200218 ip_address_t _src_ip, *src_ip = &_src_ip, _dst_ip, *dst_ip = &_dst_ip;
219 if (gid_address_type (la) != GID_ADDR_IP_PREFIX)
Florin Coras1a1adc72016-07-22 01:45:30 +0200220 {
221 /* empty ip4 */
Florin Corasa2157cf2016-08-16 21:09:14 +0200222 memset (src_ip, 0, sizeof (src_ip[0]));
223 memset (dst_ip, 0, sizeof (dst_ip[0]));
Florin Coras1a1adc72016-07-22 01:45:30 +0200224 }
225 else
226 {
Florin Corasa2157cf2016-08-16 21:09:14 +0200227 src_ip = &gid_address_ip (la);
228 dst_ip = &gid_address_ip (ra);
Florin Coras1a1adc72016-07-22 01:45:30 +0200229 }
Florin Corase127a7e2016-02-18 22:20:01 +0100230
231 /* Push inner ip and udp */
Florin Corasfdbc3822017-07-27 00:34:12 -0700232 pkt_push_udp_and_ip (vm, b, lp, rp, src_ip, dst_ip, 0);
Florin Corase127a7e2016-02-18 22:20:01 +0100233
234 /* Push lisp ecm hdr */
235 h = pkt_push_ecm_hdr (b);
236
237 return h;
238}
239
240static u32
241msg_type_to_hdr_len (lisp_msg_type_e type)
242{
243 switch (type)
244 {
245 case LISP_MAP_REQUEST:
Florin Corasa2157cf2016-08-16 21:09:14 +0200246 return (sizeof (map_request_hdr_t));
Florin Corase127a7e2016-02-18 22:20:01 +0100247 case LISP_MAP_REPLY:
Florin Corasa2157cf2016-08-16 21:09:14 +0200248 return (sizeof (map_reply_hdr_t));
Florin Corase127a7e2016-02-18 22:20:01 +0100249 default:
250 return (0);
251 }
252}
253
254void *
255lisp_msg_pull_hdr (vlib_buffer_t * b, lisp_msg_type_e type)
256{
257 return vlib_buffer_pull (b, msg_type_to_hdr_len (type));
258}
259
260u32
261lisp_msg_parse_addr (vlib_buffer_t * b, gid_address_t * eid)
262{
Florin Corasf727db92016-06-23 15:01:58 +0200263 u32 len;
Florin Corasa2157cf2016-08-16 21:09:14 +0200264 memset (eid, 0, sizeof (*eid));
Florin Corasf727db92016-06-23 15:01:58 +0200265 len = gid_address_parse (vlib_buffer_get_current (b), eid);
Florin Corase127a7e2016-02-18 22:20:01 +0100266 if (len != ~0)
267 vlib_buffer_pull (b, len);
268 return len;
269}
270
271u32
272lisp_msg_parse_eid_rec (vlib_buffer_t * b, gid_address_t * eid)
273{
Florin Corasa2157cf2016-08-16 21:09:14 +0200274 eid_record_hdr_t *h = vlib_buffer_get_current (b);
Florin Corasf727db92016-06-23 15:01:58 +0200275 u32 len;
Florin Corasa2157cf2016-08-16 21:09:14 +0200276 memset (eid, 0, sizeof (*eid));
277 len = gid_address_parse (EID_REC_ADDR (h), eid);
Florin Corase127a7e2016-02-18 22:20:01 +0100278 if (len == ~0)
279 return len;
280
Florin Corasa2157cf2016-08-16 21:09:14 +0200281 gid_address_ippref_len (eid) = EID_REC_MLEN (h);
282 vlib_buffer_pull (b, len + sizeof (eid_record_hdr_t));
Florin Corase127a7e2016-02-18 22:20:01 +0100283
Florin Corasa2157cf2016-08-16 21:09:14 +0200284 return len + sizeof (eid_record_hdr_t);
Florin Corase127a7e2016-02-18 22:20:01 +0100285}
286
287u32
288lisp_msg_parse_itr_rlocs (vlib_buffer_t * b, gid_address_t ** rlocs,
Florin Corasa2157cf2016-08-16 21:09:14 +0200289 u8 rloc_count)
Florin Corase127a7e2016-02-18 22:20:01 +0100290{
291 gid_address_t tloc;
292 u32 i, len = 0, tlen = 0;
293
294 //MREQ_ITR_RLOC_COUNT(mreq_hdr) + 1
295 for (i = 0; i < rloc_count; i++)
296 {
297 len = lisp_msg_parse_addr (b, &tloc);
298 if (len == ~0)
Florin Corasa2157cf2016-08-16 21:09:14 +0200299 return len;
300 vec_add1 (*rlocs, tloc);
Florin Corase127a7e2016-02-18 22:20:01 +0100301 tlen += len;
302 }
303 return tlen;
304}
305
306u32
307lisp_msg_parse_loc (vlib_buffer_t * b, locator_t * loc)
308{
309 int len;
310
311 len = locator_parse (vlib_buffer_get_current (b), loc);
312 if (len == ~0)
Florin Corasa2157cf2016-08-16 21:09:14 +0200313 return ~0;
Florin Corase127a7e2016-02-18 22:20:01 +0100314
Filip Tehlar816f4372017-04-26 16:09:06 +0200315 if (!vlib_buffer_has_space (b, sizeof (len)))
316 return ~0;
Florin Corase127a7e2016-02-18 22:20:01 +0100317 vlib_buffer_pull (b, len);
318
319 return len;
320}
321
322u32
323lisp_msg_parse_mapping_record (vlib_buffer_t * b, gid_address_t * eid,
Florin Corasa2157cf2016-08-16 21:09:14 +0200324 locator_t ** locs, locator_t * probed_)
Florin Corase127a7e2016-02-18 22:20:01 +0100325{
Florin Corasa2157cf2016-08-16 21:09:14 +0200326 void *h = 0, *loc_hdr = 0;
327 locator_t loc, *probed = 0;
Florin Corase127a7e2016-02-18 22:20:01 +0100328 int i = 0, len = 0, llen = 0;
329
330 h = vlib_buffer_get_current (b);
Filip Tehlar816f4372017-04-26 16:09:06 +0200331 if (!vlib_buffer_has_space (b, sizeof (mapping_record_hdr_t)))
332 return ~0;
333
Florin Corasa2157cf2016-08-16 21:09:14 +0200334 vlib_buffer_pull (b, sizeof (mapping_record_hdr_t));
Florin Corase127a7e2016-02-18 22:20:01 +0100335
Florin Corasa2157cf2016-08-16 21:09:14 +0200336 memset (eid, 0, sizeof (*eid));
Florin Corase127a7e2016-02-18 22:20:01 +0100337 len = gid_address_parse (vlib_buffer_get_current (b), eid);
338 if (len == ~0)
339 return len;
340
Filip Tehlar816f4372017-04-26 16:09:06 +0200341 if (!vlib_buffer_has_space (b, sizeof (len)))
342 return ~0;
343
Florin Corase127a7e2016-02-18 22:20:01 +0100344 vlib_buffer_pull (b, len);
Florin Corasdca88042016-09-14 16:01:38 +0200345 if (GID_ADDR_IP_PREFIX == gid_address_type (eid))
346 gid_address_ippref_len (eid) = MAP_REC_EID_PLEN (h);
Florin Corase127a7e2016-02-18 22:20:01 +0100347
Florin Corasa2157cf2016-08-16 21:09:14 +0200348 for (i = 0; i < MAP_REC_LOC_COUNT (h); i++)
Florin Corase127a7e2016-02-18 22:20:01 +0100349 {
350 loc_hdr = vlib_buffer_get_current (b);
351
352 llen = lisp_msg_parse_loc (b, &loc);
353 if (llen == ~0)
Florin Corasa2157cf2016-08-16 21:09:14 +0200354 return llen;
355 vec_add1 (*locs, loc);
Florin Corase127a7e2016-02-18 22:20:01 +0100356 len += llen;
357
Florin Corasa2157cf2016-08-16 21:09:14 +0200358 if (LOC_PROBED (loc_hdr))
359 {
360 if (probed != 0)
361 clib_warning
362 ("Multiple locators probed! Probing only the first!");
363 else
364 probed = &loc;
365 }
Florin Corase127a7e2016-02-18 22:20:01 +0100366 }
367 /* XXX */
368 if (probed_ != 0 && probed)
369 *probed_ = *probed;
370
Florin Corasa2157cf2016-08-16 21:09:14 +0200371 return len + sizeof (map_reply_hdr_t);
Florin Corase127a7e2016-02-18 22:20:01 +0100372}
Florin Corasa2157cf2016-08-16 21:09:14 +0200373
374/*
375 * fd.io coding-style-patch-verification: ON
376 *
377 * Local Variables:
378 * eval: (c-set-style "gnu")
379 * End:
380 */