blob: 90afb10b68b50710e7f914be9759f0af6f003b90 [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));
Dave Barachb7b92992018-10-17 10:38:51 -040030 clib_memset (p, 0, sizeof (locator_hdr_t));
Filip Tehlar397fd7d2016-10-26 14:31:24 +020031 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;
Florin Coras822f5a42019-01-29 17:30:29 -080037 LOC_REACHABLE (p) = loc->state ? 1 : 0;
Filip Tehlar397fd7d2016-10-26 14:31:24 +020038 lisp_msg_put_gid (b, &loc->address);
39 }
40}
41
42static void
43lisp_msg_put_mapping_record (vlib_buffer_t * b, mapping_t * record)
44{
45 mapping_record_hdr_t *p =
46 vlib_buffer_put_uninit (b, sizeof (mapping_record_hdr_t));
47 gid_address_t *eid = &record->eid;
48
Dave Barachb7b92992018-10-17 10:38:51 -040049 clib_memset (p, 0, sizeof (*p));
Filip Tehlar397fd7d2016-10-26 14:31:24 +020050 MAP_REC_EID_PLEN (p) = gid_address_len (eid);
Filip Tehlarfb9931f2016-12-09 13:52:38 +010051 MAP_REC_TTL (p) = clib_host_to_net_u32 (MAP_REGISTER_DEFAULT_TTL);
Filip Tehlar397fd7d2016-10-26 14:31:24 +020052 MAP_REC_AUTH (p) = record->authoritative ? 1 : 0;
53 MAP_REC_LOC_COUNT (p) = vec_len (record->locators);
54
55 lisp_msg_put_gid (b, eid);
56 lisp_msg_put_locators (b, record->locators);
57}
58
59static void
60lisp_msg_put_mreg_records (vlib_buffer_t * b, mapping_t * records)
61{
62 u32 i;
63 for (i = 0; i < vec_len (records); i++)
64 lisp_msg_put_mapping_record (b, &records[i]);
65}
66
Florin Corase127a7e2016-02-18 22:20:01 +010067void *
68lisp_msg_put_gid (vlib_buffer_t * b, gid_address_t * gid)
69{
Filip Tehlar397fd7d2016-10-26 14:31:24 +020070 u8 *p = 0;
71 if (!gid)
72 {
73 /* insert only src-eid-afi field set to 0 */
74 p = vlib_buffer_put_uninit (b, sizeof (u16));
75 *(u16 *) p = 0;
76 }
77 else
78 {
79 p = vlib_buffer_put_uninit (b, gid_address_size_to_put (gid));
80 gid_address_put (p, gid);
81 }
Florin Corase127a7e2016-02-18 22:20:01 +010082 return p;
83}
84
Filip Tehlarbeceab92016-04-20 17:21:55 +020085static void *
Florin Corase127a7e2016-02-18 22:20:01 +010086lisp_msg_put_itr_rlocs (lisp_cp_main_t * lcm, vlib_buffer_t * b,
Florin Corasa2157cf2016-08-16 21:09:14 +020087 gid_address_t * rlocs, u8 * locs_put)
Florin Corase127a7e2016-02-18 22:20:01 +010088{
Florin Corasa2157cf2016-08-16 21:09:14 +020089 u8 *bp, count = 0;
Filip Tehlar254b0362016-04-07 10:04:34 +020090 u32 i;
Florin Corase127a7e2016-02-18 22:20:01 +010091
Filip Tehlarbeceab92016-04-20 17:21:55 +020092 bp = vlib_buffer_get_current (b);
93 for (i = 0; i < vec_len (rlocs); i++)
Florin Corase127a7e2016-02-18 22:20:01 +010094 {
Filip Tehlarbeceab92016-04-20 17:21:55 +020095 lisp_msg_put_gid (b, &rlocs[i]);
Filip Tehlar254b0362016-04-07 10:04:34 +020096 count++;
Florin Corase127a7e2016-02-18 22:20:01 +010097 }
Filip Tehlar254b0362016-04-07 10:04:34 +020098
Florin Corasa2157cf2016-08-16 21:09:14 +020099 *locs_put = count - 1;
Florin Corase127a7e2016-02-18 22:20:01 +0100100 return bp;
101}
102
103void *
104lisp_msg_put_eid_rec (vlib_buffer_t * b, gid_address_t * eid)
105{
Florin Corasa2157cf2016-08-16 21:09:14 +0200106 eid_record_hdr_t *h = vlib_buffer_put_uninit (b, sizeof (*h));
Florin Corase127a7e2016-02-18 22:20:01 +0100107
Dave Barachb7b92992018-10-17 10:38:51 -0400108 clib_memset (h, 0, sizeof (*h));
Florin Corase127a7e2016-02-18 22:20:01 +0100109 EID_REC_MLEN (h) = gid_address_len (eid);
110 lisp_msg_put_gid (b, eid);
111 return h;
112}
113
114u64
115nonce_build (u32 seed)
116{
117 u64 nonce;
118 u32 nonce_lower;
119 u32 nonce_upper;
120 struct timespec ts;
121
122 /* Put nanosecond clock in lower 32-bits and put an XOR of the nanosecond
Paul Vinciguerrabdc0e6b2018-09-22 05:32:50 -0700123 * clock with the second clock in the upper 32-bits. */
Florin Corase127a7e2016-02-18 22:20:01 +0100124 syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts);
125 nonce_lower = ts.tv_nsec;
Florin Corasa2157cf2016-08-16 21:09:14 +0200126 nonce_upper = ts.tv_sec ^ clib_host_to_net_u32 (nonce_lower);
Florin Corase127a7e2016-02-18 22:20:01 +0100127
128 /* OR in a caller provided seed to the low-order 32-bits. */
129 nonce_lower |= seed;
130
131 /* Return 64-bit nonce. */
132 nonce = nonce_upper;
133 nonce = (nonce << 32) | nonce_lower;
134 return nonce;
135}
136
137void *
Filip Tehlar397fd7d2016-10-26 14:31:24 +0200138lisp_msg_put_map_reply (vlib_buffer_t * b, mapping_t * records, u64 nonce,
139 u8 probe_bit)
140{
141 map_reply_hdr_t *h = vlib_buffer_put_uninit (b, sizeof (h[0]));
142
Dave Barachb7b92992018-10-17 10:38:51 -0400143 clib_memset (h, 0, sizeof (h[0]));
Filip Tehlar397fd7d2016-10-26 14:31:24 +0200144 MREP_TYPE (h) = LISP_MAP_REPLY;
145 MREP_NONCE (h) = nonce;
146 MREP_REC_COUNT (h) = 1;
147 MREP_RLOC_PROBE (h) = probe_bit;
148
149 lisp_msg_put_mreg_records (b, records);
150 return h;
151}
152
153void *
154lisp_msg_put_map_register (vlib_buffer_t * b, mapping_t * records,
155 u8 want_map_notify, u16 auth_data_len, u64 * nonce,
156 u32 * msg_len)
157{
158 u8 *auth_data = 0;
159
160 /* Basic header init */
161 map_register_hdr_t *h = vlib_buffer_put_uninit (b, sizeof (h[0]));
162
Dave Barachb7b92992018-10-17 10:38:51 -0400163 clib_memset (h, 0, sizeof (h[0]));
Filip Tehlar397fd7d2016-10-26 14:31:24 +0200164 MREG_TYPE (h) = LISP_MAP_REGISTER;
165 MREG_NONCE (h) = nonce_build (0);
166 MREG_WANT_MAP_NOTIFY (h) = want_map_notify ? 1 : 0;
167 MREG_REC_COUNT (h) = vec_len (records);
168
169 auth_data = vlib_buffer_put_uninit (b, auth_data_len);
Dave Barachb7b92992018-10-17 10:38:51 -0400170 clib_memset (auth_data, 0, auth_data_len);
Filip Tehlar397fd7d2016-10-26 14:31:24 +0200171
172 /* Put map register records */
173 lisp_msg_put_mreg_records (b, records);
174
175 nonce[0] = MREG_NONCE (h);
176 msg_len[0] = vlib_buffer_get_tail (b) - (u8 *) h;
177 return h;
178}
179
180void *
Florin Corase127a7e2016-02-18 22:20:01 +0100181lisp_msg_put_mreq (lisp_cp_main_t * lcm, vlib_buffer_t * b,
Florin Corasa2157cf2016-08-16 21:09:14 +0200182 gid_address_t * seid, gid_address_t * deid,
Filip Tehlar397fd7d2016-10-26 14:31:24 +0200183 gid_address_t * rlocs, u8 is_smr_invoked,
184 u8 rloc_probe_set, u64 * nonce)
Florin Corase127a7e2016-02-18 22:20:01 +0100185{
186 u8 loc_count = 0;
187
188 /* Basic header init */
Florin Corasa2157cf2016-08-16 21:09:14 +0200189 map_request_hdr_t *h = vlib_buffer_put_uninit (b, sizeof (h[0]));
Florin Corase127a7e2016-02-18 22:20:01 +0100190
Dave Barachb7b92992018-10-17 10:38:51 -0400191 clib_memset (h, 0, sizeof (h[0]));
Florin Corasa2157cf2016-08-16 21:09:14 +0200192 MREQ_TYPE (h) = LISP_MAP_REQUEST;
193 MREQ_NONCE (h) = nonce_build (0);
194 MREQ_SMR_INVOKED (h) = is_smr_invoked ? 1 : 0;
Filip Tehlar397fd7d2016-10-26 14:31:24 +0200195 MREQ_RLOC_PROBE (h) = rloc_probe_set ? 1 : 0;
Florin Corase127a7e2016-02-18 22:20:01 +0100196
197 /* We're adding one eid record */
198 increment_record_count (h);
199
200 /* Fill source eid */
201 lisp_msg_put_gid (b, seid);
202
203 /* Put itr rlocs */
Florin Corasa2157cf2016-08-16 21:09:14 +0200204 lisp_msg_put_itr_rlocs (lcm, b, rlocs, &loc_count);
205 MREQ_ITR_RLOC_COUNT (h) = loc_count;
Florin Corase127a7e2016-02-18 22:20:01 +0100206
207 /* Put eid record */
Florin Corasa2157cf2016-08-16 21:09:14 +0200208 lisp_msg_put_eid_rec (b, deid);
Florin Corase127a7e2016-02-18 22:20:01 +0100209
Florin Corasa2157cf2016-08-16 21:09:14 +0200210 nonce[0] = MREQ_NONCE (h);
Florin Corase127a7e2016-02-18 22:20:01 +0100211 return h;
212}
213
214void *
Florin Corasa2157cf2016-08-16 21:09:14 +0200215lisp_msg_push_ecm (vlib_main_t * vm, vlib_buffer_t * b, int lp, int rp,
216 gid_address_t * la, gid_address_t * ra)
Florin Corase127a7e2016-02-18 22:20:01 +0100217{
218 ecm_hdr_t *h;
Florin Corasa2157cf2016-08-16 21:09:14 +0200219 ip_address_t _src_ip, *src_ip = &_src_ip, _dst_ip, *dst_ip = &_dst_ip;
220 if (gid_address_type (la) != GID_ADDR_IP_PREFIX)
Florin Coras1a1adc72016-07-22 01:45:30 +0200221 {
222 /* empty ip4 */
Dave Barachb7b92992018-10-17 10:38:51 -0400223 clib_memset (src_ip, 0, sizeof (src_ip[0]));
224 clib_memset (dst_ip, 0, sizeof (dst_ip[0]));
Florin Coras1a1adc72016-07-22 01:45:30 +0200225 }
226 else
227 {
Florin Corasa2157cf2016-08-16 21:09:14 +0200228 src_ip = &gid_address_ip (la);
229 dst_ip = &gid_address_ip (ra);
Florin Coras1a1adc72016-07-22 01:45:30 +0200230 }
Florin Corase127a7e2016-02-18 22:20:01 +0100231
232 /* Push inner ip and udp */
Florin Corasfdbc3822017-07-27 00:34:12 -0700233 pkt_push_udp_and_ip (vm, b, lp, rp, src_ip, dst_ip, 0);
Florin Corase127a7e2016-02-18 22:20:01 +0100234
235 /* Push lisp ecm hdr */
236 h = pkt_push_ecm_hdr (b);
237
238 return h;
239}
240
241static u32
242msg_type_to_hdr_len (lisp_msg_type_e type)
243{
244 switch (type)
245 {
246 case LISP_MAP_REQUEST:
Florin Corasa2157cf2016-08-16 21:09:14 +0200247 return (sizeof (map_request_hdr_t));
Florin Corase127a7e2016-02-18 22:20:01 +0100248 case LISP_MAP_REPLY:
Florin Corasa2157cf2016-08-16 21:09:14 +0200249 return (sizeof (map_reply_hdr_t));
Florin Corase127a7e2016-02-18 22:20:01 +0100250 default:
251 return (0);
252 }
253}
254
255void *
256lisp_msg_pull_hdr (vlib_buffer_t * b, lisp_msg_type_e type)
257{
258 return vlib_buffer_pull (b, msg_type_to_hdr_len (type));
259}
260
261u32
262lisp_msg_parse_addr (vlib_buffer_t * b, gid_address_t * eid)
263{
Florin Corasf727db92016-06-23 15:01:58 +0200264 u32 len;
Dave Barachb7b92992018-10-17 10:38:51 -0400265 clib_memset (eid, 0, sizeof (*eid));
Florin Corasf727db92016-06-23 15:01:58 +0200266 len = gid_address_parse (vlib_buffer_get_current (b), eid);
Florin Corase127a7e2016-02-18 22:20:01 +0100267 if (len != ~0)
268 vlib_buffer_pull (b, len);
269 return len;
270}
271
272u32
273lisp_msg_parse_eid_rec (vlib_buffer_t * b, gid_address_t * eid)
274{
Florin Corasa2157cf2016-08-16 21:09:14 +0200275 eid_record_hdr_t *h = vlib_buffer_get_current (b);
Florin Corasf727db92016-06-23 15:01:58 +0200276 u32 len;
Dave Barachb7b92992018-10-17 10:38:51 -0400277 clib_memset (eid, 0, sizeof (*eid));
Florin Corasa2157cf2016-08-16 21:09:14 +0200278 len = gid_address_parse (EID_REC_ADDR (h), eid);
Florin Corase127a7e2016-02-18 22:20:01 +0100279 if (len == ~0)
280 return len;
281
Florin Corasa2157cf2016-08-16 21:09:14 +0200282 gid_address_ippref_len (eid) = EID_REC_MLEN (h);
283 vlib_buffer_pull (b, len + sizeof (eid_record_hdr_t));
Florin Corase127a7e2016-02-18 22:20:01 +0100284
Florin Corasa2157cf2016-08-16 21:09:14 +0200285 return len + sizeof (eid_record_hdr_t);
Florin Corase127a7e2016-02-18 22:20:01 +0100286}
287
288u32
289lisp_msg_parse_itr_rlocs (vlib_buffer_t * b, gid_address_t ** rlocs,
Florin Corasa2157cf2016-08-16 21:09:14 +0200290 u8 rloc_count)
Florin Corase127a7e2016-02-18 22:20:01 +0100291{
292 gid_address_t tloc;
293 u32 i, len = 0, tlen = 0;
294
295 //MREQ_ITR_RLOC_COUNT(mreq_hdr) + 1
296 for (i = 0; i < rloc_count; i++)
297 {
298 len = lisp_msg_parse_addr (b, &tloc);
299 if (len == ~0)
Florin Corasa2157cf2016-08-16 21:09:14 +0200300 return len;
301 vec_add1 (*rlocs, tloc);
Florin Corase127a7e2016-02-18 22:20:01 +0100302 tlen += len;
303 }
304 return tlen;
305}
306
307u32
308lisp_msg_parse_loc (vlib_buffer_t * b, locator_t * loc)
309{
310 int len;
311
312 len = locator_parse (vlib_buffer_get_current (b), loc);
313 if (len == ~0)
Florin Corasa2157cf2016-08-16 21:09:14 +0200314 return ~0;
Florin Corase127a7e2016-02-18 22:20:01 +0100315
Filip Tehlar816f4372017-04-26 16:09:06 +0200316 if (!vlib_buffer_has_space (b, sizeof (len)))
317 return ~0;
Florin Corase127a7e2016-02-18 22:20:01 +0100318 vlib_buffer_pull (b, len);
319
320 return len;
321}
322
323u32
324lisp_msg_parse_mapping_record (vlib_buffer_t * b, gid_address_t * eid,
Florin Corasa2157cf2016-08-16 21:09:14 +0200325 locator_t ** locs, locator_t * probed_)
Florin Corase127a7e2016-02-18 22:20:01 +0100326{
Florin Corasa2157cf2016-08-16 21:09:14 +0200327 void *h = 0, *loc_hdr = 0;
328 locator_t loc, *probed = 0;
Florin Corase127a7e2016-02-18 22:20:01 +0100329 int i = 0, len = 0, llen = 0;
330
331 h = vlib_buffer_get_current (b);
Filip Tehlar816f4372017-04-26 16:09:06 +0200332 if (!vlib_buffer_has_space (b, sizeof (mapping_record_hdr_t)))
333 return ~0;
334
Florin Corasa2157cf2016-08-16 21:09:14 +0200335 vlib_buffer_pull (b, sizeof (mapping_record_hdr_t));
Florin Corase127a7e2016-02-18 22:20:01 +0100336
Dave Barachb7b92992018-10-17 10:38:51 -0400337 clib_memset (eid, 0, sizeof (*eid));
Florin Corase127a7e2016-02-18 22:20:01 +0100338 len = gid_address_parse (vlib_buffer_get_current (b), eid);
339 if (len == ~0)
340 return len;
341
Filip Tehlar816f4372017-04-26 16:09:06 +0200342 if (!vlib_buffer_has_space (b, sizeof (len)))
343 return ~0;
344
Florin Corase127a7e2016-02-18 22:20:01 +0100345 vlib_buffer_pull (b, len);
Florin Corasdca88042016-09-14 16:01:38 +0200346 if (GID_ADDR_IP_PREFIX == gid_address_type (eid))
347 gid_address_ippref_len (eid) = MAP_REC_EID_PLEN (h);
Florin Corase127a7e2016-02-18 22:20:01 +0100348
Florin Corasa2157cf2016-08-16 21:09:14 +0200349 for (i = 0; i < MAP_REC_LOC_COUNT (h); i++)
Florin Corase127a7e2016-02-18 22:20:01 +0100350 {
351 loc_hdr = vlib_buffer_get_current (b);
352
353 llen = lisp_msg_parse_loc (b, &loc);
354 if (llen == ~0)
Florin Corasa2157cf2016-08-16 21:09:14 +0200355 return llen;
356 vec_add1 (*locs, loc);
Florin Corase127a7e2016-02-18 22:20:01 +0100357 len += llen;
358
Florin Corasa2157cf2016-08-16 21:09:14 +0200359 if (LOC_PROBED (loc_hdr))
360 {
361 if (probed != 0)
362 clib_warning
363 ("Multiple locators probed! Probing only the first!");
364 else
365 probed = &loc;
366 }
Florin Corase127a7e2016-02-18 22:20:01 +0100367 }
368 /* XXX */
369 if (probed_ != 0 && probed)
370 *probed_ = *probed;
371
Florin Corasa2157cf2016-08-16 21:09:14 +0200372 return len + sizeof (map_reply_hdr_t);
Florin Corase127a7e2016-02-18 22:20:01 +0100373}
Florin Corasa2157cf2016-08-16 21:09:14 +0200374
375/*
376 * fd.io coding-style-patch-verification: ON
377 *
378 * Local Variables:
379 * eval: (c-set-style "gnu")
380 * End:
381 */