Trivial: Clean up some typos.
[vpp.git] / src / vnet / lisp-cp / lisp_msg_serdes.c
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 <vnet/lisp-cp/lisp_msg_serdes.h>
17 #include <vnet/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 lisp_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
41 static void
42 lisp_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);
50   MAP_REC_TTL (p) = clib_host_to_net_u32 (MAP_REGISTER_DEFAULT_TTL);
51   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
58 static void
59 lisp_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
66 void *
67 lisp_msg_put_gid (vlib_buffer_t * b, gid_address_t * gid)
68 {
69   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     }
81   return p;
82 }
83
84 static void *
85 lisp_msg_put_itr_rlocs (lisp_cp_main_t * lcm, vlib_buffer_t * b,
86                         gid_address_t * rlocs, u8 * locs_put)
87 {
88   u8 *bp, count = 0;
89   u32 i;
90
91   bp = vlib_buffer_get_current (b);
92   for (i = 0; i < vec_len (rlocs); i++)
93     {
94       lisp_msg_put_gid (b, &rlocs[i]);
95       count++;
96     }
97
98   *locs_put = count - 1;
99   return bp;
100 }
101
102 void *
103 lisp_msg_put_eid_rec (vlib_buffer_t * b, gid_address_t * eid)
104 {
105   eid_record_hdr_t *h = vlib_buffer_put_uninit (b, sizeof (*h));
106
107   memset (h, 0, sizeof (*h));
108   EID_REC_MLEN (h) = gid_address_len (eid);
109   lisp_msg_put_gid (b, eid);
110   return h;
111 }
112
113 u64
114 nonce_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 second clock in the upper 32-bits. */
123   syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts);
124   nonce_lower = ts.tv_nsec;
125   nonce_upper = ts.tv_sec ^ clib_host_to_net_u32 (nonce_lower);
126
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
136 void *
137 lisp_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
152 void *
153 lisp_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
179 void *
180 lisp_msg_put_mreq (lisp_cp_main_t * lcm, vlib_buffer_t * b,
181                    gid_address_t * seid, gid_address_t * deid,
182                    gid_address_t * rlocs, u8 is_smr_invoked,
183                    u8 rloc_probe_set, u64 * nonce)
184 {
185   u8 loc_count = 0;
186
187   /* Basic header init */
188   map_request_hdr_t *h = vlib_buffer_put_uninit (b, sizeof (h[0]));
189
190   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;
194   MREQ_RLOC_PROBE (h) = rloc_probe_set ? 1 : 0;
195
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 */
203   lisp_msg_put_itr_rlocs (lcm, b, rlocs, &loc_count);
204   MREQ_ITR_RLOC_COUNT (h) = loc_count;
205
206   /* Put eid record */
207   lisp_msg_put_eid_rec (b, deid);
208
209   nonce[0] = MREQ_NONCE (h);
210   return h;
211 }
212
213 void *
214 lisp_msg_push_ecm (vlib_main_t * vm, vlib_buffer_t * b, int lp, int rp,
215                    gid_address_t * la, gid_address_t * ra)
216 {
217   ecm_hdr_t *h;
218   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)
220     {
221       /* empty ip4 */
222       memset (src_ip, 0, sizeof (src_ip[0]));
223       memset (dst_ip, 0, sizeof (dst_ip[0]));
224     }
225   else
226     {
227       src_ip = &gid_address_ip (la);
228       dst_ip = &gid_address_ip (ra);
229     }
230
231   /* Push inner ip and udp */
232   pkt_push_udp_and_ip (vm, b, lp, rp, src_ip, dst_ip, 0);
233
234   /* Push lisp ecm hdr */
235   h = pkt_push_ecm_hdr (b);
236
237   return h;
238 }
239
240 static u32
241 msg_type_to_hdr_len (lisp_msg_type_e type)
242 {
243   switch (type)
244     {
245     case LISP_MAP_REQUEST:
246       return (sizeof (map_request_hdr_t));
247     case LISP_MAP_REPLY:
248       return (sizeof (map_reply_hdr_t));
249     default:
250       return (0);
251     }
252 }
253
254 void *
255 lisp_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
260 u32
261 lisp_msg_parse_addr (vlib_buffer_t * b, gid_address_t * eid)
262 {
263   u32 len;
264   memset (eid, 0, sizeof (*eid));
265   len = gid_address_parse (vlib_buffer_get_current (b), eid);
266   if (len != ~0)
267     vlib_buffer_pull (b, len);
268   return len;
269 }
270
271 u32
272 lisp_msg_parse_eid_rec (vlib_buffer_t * b, gid_address_t * eid)
273 {
274   eid_record_hdr_t *h = vlib_buffer_get_current (b);
275   u32 len;
276   memset (eid, 0, sizeof (*eid));
277   len = gid_address_parse (EID_REC_ADDR (h), eid);
278   if (len == ~0)
279     return len;
280
281   gid_address_ippref_len (eid) = EID_REC_MLEN (h);
282   vlib_buffer_pull (b, len + sizeof (eid_record_hdr_t));
283
284   return len + sizeof (eid_record_hdr_t);
285 }
286
287 u32
288 lisp_msg_parse_itr_rlocs (vlib_buffer_t * b, gid_address_t ** rlocs,
289                           u8 rloc_count)
290 {
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)
299         return len;
300       vec_add1 (*rlocs, tloc);
301       tlen += len;
302     }
303   return tlen;
304 }
305
306 u32
307 lisp_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)
313     return ~0;
314
315   if (!vlib_buffer_has_space (b, sizeof (len)))
316     return ~0;
317   vlib_buffer_pull (b, len);
318
319   return len;
320 }
321
322 u32
323 lisp_msg_parse_mapping_record (vlib_buffer_t * b, gid_address_t * eid,
324                                locator_t ** locs, locator_t * probed_)
325 {
326   void *h = 0, *loc_hdr = 0;
327   locator_t loc, *probed = 0;
328   int i = 0, len = 0, llen = 0;
329
330   h = vlib_buffer_get_current (b);
331   if (!vlib_buffer_has_space (b, sizeof (mapping_record_hdr_t)))
332     return ~0;
333
334   vlib_buffer_pull (b, sizeof (mapping_record_hdr_t));
335
336   memset (eid, 0, sizeof (*eid));
337   len = gid_address_parse (vlib_buffer_get_current (b), eid);
338   if (len == ~0)
339     return len;
340
341   if (!vlib_buffer_has_space (b, sizeof (len)))
342     return ~0;
343
344   vlib_buffer_pull (b, len);
345   if (GID_ADDR_IP_PREFIX == gid_address_type (eid))
346     gid_address_ippref_len (eid) = MAP_REC_EID_PLEN (h);
347
348   for (i = 0; i < MAP_REC_LOC_COUNT (h); i++)
349     {
350       loc_hdr = vlib_buffer_get_current (b);
351
352       llen = lisp_msg_parse_loc (b, &loc);
353       if (llen == ~0)
354         return llen;
355       vec_add1 (*locs, loc);
356       len += llen;
357
358       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         }
366     }
367   /* XXX */
368   if (probed_ != 0 && probed)
369     *probed_ = *probed;
370
371   return len + sizeof (map_reply_hdr_t);
372 }
373
374 /*
375  * fd.io coding-style-patch-verification: ON
376  *
377  * Local Variables:
378  * eval: (c-set-style "gnu")
379  * End:
380  */