Line data Source code
1 : /*
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 <lisp/lisp-cp/lisp_msg_serdes.h>
17 : #include <lisp/lisp-cp/packets.h>
18 : #include <vppinfra/time.h>
19 :
20 : void *lisp_msg_put_gid (vlib_buffer_t * b, gid_address_t * gid);
21 :
22 : static void
23 0 : lisp_msg_put_locators (vlib_buffer_t * b, locator_t * locators)
24 : {
25 : locator_t *loc;
26 :
27 0 : vec_foreach (loc, locators)
28 : {
29 0 : u8 *p = vlib_buffer_put_uninit (b, sizeof (locator_hdr_t));
30 0 : clib_memset (p, 0, sizeof (locator_hdr_t));
31 0 : LOC_PRIORITY (p) = loc->priority;
32 0 : LOC_MPRIORITY (p) = loc->mpriority;
33 0 : LOC_WEIGHT (p) = loc->weight;
34 0 : LOC_MWEIGHT (p) = loc->mweight;
35 0 : LOC_LOCAL (p) = loc->local;
36 0 : LOC_PROBED (p) = loc->probed ? 1 : 0;
37 0 : LOC_REACHABLE (p) = loc->state ? 1 : 0;
38 0 : lisp_msg_put_gid (b, &loc->address);
39 : }
40 0 : }
41 :
42 : static void
43 0 : lisp_msg_put_mapping_record (vlib_buffer_t * b, mapping_t * record)
44 : {
45 : mapping_record_hdr_t *p =
46 0 : vlib_buffer_put_uninit (b, sizeof (mapping_record_hdr_t));
47 0 : gid_address_t *eid = &record->eid;
48 :
49 0 : clib_memset (p, 0, sizeof (*p));
50 0 : MAP_REC_EID_PLEN (p) = gid_address_len (eid);
51 0 : MAP_REC_TTL (p) = clib_host_to_net_u32 (MAP_REGISTER_DEFAULT_TTL);
52 0 : MAP_REC_AUTH (p) = record->authoritative ? 1 : 0;
53 0 : MAP_REC_LOC_COUNT (p) = vec_len (record->locators);
54 :
55 0 : lisp_msg_put_gid (b, eid);
56 0 : lisp_msg_put_locators (b, record->locators);
57 0 : }
58 :
59 : static void
60 0 : lisp_msg_put_mreg_records (vlib_buffer_t * b, mapping_t * records)
61 : {
62 : u32 i;
63 0 : for (i = 0; i < vec_len (records); i++)
64 0 : lisp_msg_put_mapping_record (b, &records[i]);
65 0 : }
66 :
67 : void *
68 0 : lisp_msg_put_gid (vlib_buffer_t * b, gid_address_t * gid)
69 : {
70 0 : u8 *p = 0;
71 0 : if (!gid)
72 : {
73 : /* insert only src-eid-afi field set to 0 */
74 0 : p = vlib_buffer_put_uninit (b, sizeof (u16));
75 0 : *(u16 *) p = 0;
76 : }
77 : else
78 : {
79 0 : p = vlib_buffer_put_uninit (b, gid_address_size_to_put (gid));
80 0 : gid_address_put (p, gid);
81 : }
82 0 : return p;
83 : }
84 :
85 : static void *
86 0 : lisp_msg_put_itr_rlocs (lisp_cp_main_t * lcm, vlib_buffer_t * b,
87 : gid_address_t * rlocs, u8 * locs_put)
88 : {
89 0 : u8 *bp, count = 0;
90 : u32 i;
91 :
92 0 : bp = vlib_buffer_get_current (b);
93 0 : for (i = 0; i < vec_len (rlocs); i++)
94 : {
95 0 : lisp_msg_put_gid (b, &rlocs[i]);
96 0 : count++;
97 : }
98 :
99 0 : *locs_put = count - 1;
100 0 : return bp;
101 : }
102 :
103 : void *
104 0 : lisp_msg_put_eid_rec (vlib_buffer_t * b, gid_address_t * eid)
105 : {
106 0 : eid_record_hdr_t *h = vlib_buffer_put_uninit (b, sizeof (*h));
107 :
108 0 : clib_memset (h, 0, sizeof (*h));
109 0 : EID_REC_MLEN (h) = gid_address_len (eid);
110 0 : lisp_msg_put_gid (b, eid);
111 0 : return h;
112 : }
113 :
114 : u64
115 0 : nonce_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
123 : * clock with the second clock in the upper 32-bits. */
124 0 : syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts);
125 0 : nonce_lower = ts.tv_nsec;
126 0 : nonce_upper = ts.tv_sec ^ clib_host_to_net_u32 (nonce_lower);
127 :
128 : /* OR in a caller provided seed to the low-order 32-bits. */
129 0 : nonce_lower |= seed;
130 :
131 : /* Return 64-bit nonce. */
132 0 : nonce = nonce_upper;
133 0 : nonce = (nonce << 32) | nonce_lower;
134 0 : return nonce;
135 : }
136 :
137 : void *
138 0 : lisp_msg_put_map_reply (vlib_buffer_t * b, mapping_t * records, u64 nonce,
139 : u8 probe_bit)
140 : {
141 0 : map_reply_hdr_t *h = vlib_buffer_put_uninit (b, sizeof (h[0]));
142 :
143 0 : clib_memset (h, 0, sizeof (h[0]));
144 0 : MREP_TYPE (h) = LISP_MAP_REPLY;
145 0 : MREP_NONCE (h) = nonce;
146 0 : MREP_REC_COUNT (h) = 1;
147 0 : MREP_RLOC_PROBE (h) = probe_bit;
148 :
149 0 : lisp_msg_put_mreg_records (b, records);
150 0 : return h;
151 : }
152 :
153 : void *
154 0 : lisp_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 0 : u8 *auth_data = 0;
159 :
160 : /* Basic header init */
161 0 : map_register_hdr_t *h = vlib_buffer_put_uninit (b, sizeof (h[0]));
162 :
163 0 : clib_memset (h, 0, sizeof (h[0]));
164 0 : MREG_TYPE (h) = LISP_MAP_REGISTER;
165 0 : MREG_NONCE (h) = nonce_build (0);
166 0 : MREG_WANT_MAP_NOTIFY (h) = want_map_notify ? 1 : 0;
167 0 : MREG_REC_COUNT (h) = vec_len (records);
168 :
169 0 : auth_data = vlib_buffer_put_uninit (b, auth_data_len);
170 0 : clib_memset (auth_data, 0, auth_data_len);
171 :
172 : /* Put map register records */
173 0 : lisp_msg_put_mreg_records (b, records);
174 :
175 0 : nonce[0] = MREG_NONCE (h);
176 0 : msg_len[0] = vlib_buffer_get_tail (b) - (u8 *) h;
177 0 : return h;
178 : }
179 :
180 : void *
181 0 : lisp_msg_put_mreq (lisp_cp_main_t * lcm, vlib_buffer_t * b,
182 : gid_address_t * seid, gid_address_t * deid,
183 : gid_address_t * rlocs, u8 is_smr_invoked,
184 : u8 rloc_probe_set, u64 * nonce)
185 : {
186 0 : u8 loc_count = 0;
187 :
188 : /* Basic header init */
189 0 : map_request_hdr_t *h = vlib_buffer_put_uninit (b, sizeof (h[0]));
190 :
191 0 : clib_memset (h, 0, sizeof (h[0]));
192 0 : MREQ_TYPE (h) = LISP_MAP_REQUEST;
193 0 : MREQ_NONCE (h) = nonce_build (0);
194 0 : MREQ_SMR_INVOKED (h) = is_smr_invoked ? 1 : 0;
195 0 : MREQ_RLOC_PROBE (h) = rloc_probe_set ? 1 : 0;
196 :
197 : /* We're adding one eid record */
198 0 : increment_record_count (h);
199 :
200 : /* Fill source eid */
201 0 : lisp_msg_put_gid (b, seid);
202 :
203 : /* Put itr rlocs */
204 0 : lisp_msg_put_itr_rlocs (lcm, b, rlocs, &loc_count);
205 0 : MREQ_ITR_RLOC_COUNT (h) = loc_count;
206 :
207 : /* Put eid record */
208 0 : lisp_msg_put_eid_rec (b, deid);
209 :
210 0 : nonce[0] = MREQ_NONCE (h);
211 0 : return h;
212 : }
213 :
214 : void *
215 0 : lisp_msg_push_ecm (vlib_main_t * vm, vlib_buffer_t * b, int lp, int rp,
216 : gid_address_t * la, gid_address_t * ra)
217 : {
218 : ecm_hdr_t *h;
219 0 : ip_address_t _src_ip, *src_ip = &_src_ip, _dst_ip, *dst_ip = &_dst_ip;
220 0 : if (gid_address_type (la) != GID_ADDR_IP_PREFIX)
221 : {
222 : /* empty ip4 */
223 0 : clib_memset (src_ip, 0, sizeof (src_ip[0]));
224 0 : clib_memset (dst_ip, 0, sizeof (dst_ip[0]));
225 : }
226 : else
227 : {
228 0 : src_ip = &gid_address_ip (la);
229 0 : dst_ip = &gid_address_ip (ra);
230 : }
231 :
232 : /* Push inner ip and udp */
233 0 : pkt_push_udp_and_ip (vm, b, lp, rp, src_ip, dst_ip, 0);
234 :
235 : /* Push lisp ecm hdr */
236 0 : h = pkt_push_ecm_hdr (b);
237 :
238 0 : return h;
239 : }
240 :
241 : static u32
242 0 : msg_type_to_hdr_len (lisp_msg_type_e type)
243 : {
244 0 : switch (type)
245 : {
246 0 : case LISP_MAP_REQUEST:
247 0 : return (sizeof (map_request_hdr_t));
248 0 : case LISP_MAP_REPLY:
249 0 : return (sizeof (map_reply_hdr_t));
250 0 : default:
251 0 : return (0);
252 : }
253 : }
254 :
255 : void *
256 0 : lisp_msg_pull_hdr (vlib_buffer_t * b, lisp_msg_type_e type)
257 : {
258 0 : return vlib_buffer_pull (b, msg_type_to_hdr_len (type));
259 : }
260 :
261 : u32
262 0 : lisp_msg_parse_addr (vlib_buffer_t * b, gid_address_t * eid)
263 : {
264 : u32 len;
265 0 : clib_memset (eid, 0, sizeof (*eid));
266 0 : len = gid_address_parse (vlib_buffer_get_current (b), eid);
267 0 : if ((len != ~0) && vlib_buffer_pull (b, len))
268 : {
269 0 : return len;
270 : }
271 : else
272 : {
273 0 : return ~0;
274 : }
275 : }
276 :
277 : u32
278 0 : lisp_msg_parse_eid_rec (vlib_buffer_t * b, gid_address_t * eid)
279 : {
280 0 : eid_record_hdr_t *h = vlib_buffer_get_current (b);
281 : u32 len;
282 0 : clib_memset (eid, 0, sizeof (*eid));
283 0 : len = gid_address_parse (EID_REC_ADDR (h), eid);
284 0 : if (len == ~0)
285 0 : return len;
286 :
287 0 : gid_address_ippref_len (eid) = EID_REC_MLEN (h);
288 0 : if (!vlib_buffer_pull (b, len + sizeof (eid_record_hdr_t)))
289 : {
290 0 : return ~0;
291 : }
292 :
293 0 : return len + sizeof (eid_record_hdr_t);
294 : }
295 :
296 : u32
297 0 : lisp_msg_parse_itr_rlocs (vlib_buffer_t * b, gid_address_t ** rlocs,
298 : u8 rloc_count)
299 : {
300 : gid_address_t tloc;
301 0 : u32 i, len = 0, tlen = 0;
302 :
303 : //MREQ_ITR_RLOC_COUNT(mreq_hdr) + 1
304 0 : for (i = 0; i < rloc_count; i++)
305 : {
306 0 : len = lisp_msg_parse_addr (b, &tloc);
307 0 : if (len == ~0)
308 0 : return len;
309 0 : vec_add1 (*rlocs, tloc);
310 0 : tlen += len;
311 : }
312 0 : return tlen;
313 : }
314 :
315 : u32
316 0 : lisp_msg_parse_loc (vlib_buffer_t * b, locator_t * loc)
317 : {
318 : int len;
319 :
320 0 : len = locator_parse (vlib_buffer_get_current (b), loc);
321 0 : if (len == ~0)
322 0 : return ~0;
323 :
324 0 : if (!vlib_buffer_has_space (b, sizeof (len)))
325 0 : return ~0;
326 0 : vlib_buffer_pull (b, len);
327 :
328 0 : return len;
329 : }
330 :
331 : u32
332 0 : lisp_msg_parse_mapping_record (vlib_buffer_t * b, gid_address_t * eid,
333 : locator_t ** locs, locator_t * probed_)
334 : {
335 0 : void *h = 0, *loc_hdr = 0;
336 0 : locator_t loc, *probed = 0;
337 0 : int i = 0, len = 0, llen = 0;
338 :
339 0 : h = vlib_buffer_get_current (b);
340 0 : if (!vlib_buffer_has_space (b, sizeof (mapping_record_hdr_t)))
341 0 : return ~0;
342 :
343 0 : vlib_buffer_pull (b, sizeof (mapping_record_hdr_t));
344 :
345 0 : clib_memset (eid, 0, sizeof (*eid));
346 0 : len = gid_address_parse (vlib_buffer_get_current (b), eid);
347 0 : if (len == ~0)
348 0 : return len;
349 :
350 0 : if (!vlib_buffer_has_space (b, sizeof (len)))
351 0 : return ~0;
352 :
353 0 : vlib_buffer_pull (b, len);
354 0 : if (GID_ADDR_IP_PREFIX == gid_address_type (eid))
355 0 : gid_address_ippref_len (eid) = MAP_REC_EID_PLEN (h);
356 :
357 0 : for (i = 0; i < MAP_REC_LOC_COUNT (h); i++)
358 : {
359 0 : loc_hdr = vlib_buffer_get_current (b);
360 :
361 0 : llen = lisp_msg_parse_loc (b, &loc);
362 0 : if (llen == ~0)
363 0 : return llen;
364 0 : vec_add1 (*locs, loc);
365 0 : len += llen;
366 :
367 0 : if (LOC_PROBED (loc_hdr))
368 : {
369 0 : if (probed != 0)
370 0 : clib_warning
371 : ("Multiple locators probed! Probing only the first!");
372 : else
373 0 : probed = &loc;
374 : }
375 : }
376 : /* XXX */
377 0 : if (probed_ != 0 && probed)
378 0 : *probed_ = *probed;
379 :
380 0 : return len + sizeof (map_reply_hdr_t);
381 : }
382 :
383 : /*
384 : * fd.io coding-style-patch-verification: ON
385 : *
386 : * Local Variables:
387 : * eval: (c-set-style "gnu")
388 : * End:
389 : */
|