de9a4f5b121e02198e3d9f9a1b415bcd158c2b2b
[vpp.git] / vnet / 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 *
21 lisp_msg_put_gid (vlib_buffer_t * b, gid_address_t * gid)
22 {
23   u8 *p = vlib_buffer_put_uninit (b, gid_address_size_to_put (gid));
24   gid_address_put (p, gid);
25   return p;
26 }
27
28 static void *
29 lisp_msg_put_itr_rlocs (lisp_cp_main_t * lcm, vlib_buffer_t * b,
30                         gid_address_t * rlocs, u8 * locs_put)
31 {
32   u8 *bp, count = 0;
33   u32 i;
34
35   bp = vlib_buffer_get_current (b);
36   for (i = 0; i < vec_len (rlocs); i++)
37     {
38       lisp_msg_put_gid (b, &rlocs[i]);
39       count++;
40     }
41
42   *locs_put = count - 1;
43   return bp;
44 }
45
46 void *
47 lisp_msg_put_eid_rec (vlib_buffer_t * b, gid_address_t * eid)
48 {
49   eid_record_hdr_t *h = vlib_buffer_put_uninit (b, sizeof (*h));
50
51   memset (h, 0, sizeof (*h));
52   EID_REC_MLEN (h) = gid_address_len (eid);
53   lisp_msg_put_gid (b, eid);
54   return h;
55 }
56
57 u64
58 nonce_build (u32 seed)
59 {
60   u64 nonce;
61   u32 nonce_lower;
62   u32 nonce_upper;
63   struct timespec ts;
64
65   /* Put nanosecond clock in lower 32-bits and put an XOR of the nanosecond
66    * clock with the seond clock in the upper 32-bits. */
67   syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts);
68   nonce_lower = ts.tv_nsec;
69   nonce_upper = ts.tv_sec ^ clib_host_to_net_u32 (nonce_lower);
70
71   /* OR in a caller provided seed to the low-order 32-bits. */
72   nonce_lower |= seed;
73
74   /* Return 64-bit nonce. */
75   nonce = nonce_upper;
76   nonce = (nonce << 32) | nonce_lower;
77   return nonce;
78 }
79
80 void *
81 lisp_msg_put_mreq (lisp_cp_main_t * lcm, vlib_buffer_t * b,
82                    gid_address_t * seid, gid_address_t * deid,
83                    gid_address_t * rlocs, u8 is_smr_invoked, u64 * nonce)
84 {
85   u8 loc_count = 0;
86
87   /* Basic header init */
88   map_request_hdr_t *h = vlib_buffer_put_uninit (b, sizeof (h[0]));
89
90   memset (h, 0, sizeof (h[0]));
91   MREQ_TYPE (h) = LISP_MAP_REQUEST;
92   MREQ_NONCE (h) = nonce_build (0);
93   MREQ_SMR_INVOKED (h) = is_smr_invoked ? 1 : 0;
94
95   /* We're adding one eid record */
96   increment_record_count (h);
97
98   /* Fill source eid */
99   lisp_msg_put_gid (b, seid);
100
101   /* Put itr rlocs */
102   lisp_msg_put_itr_rlocs (lcm, b, rlocs, &loc_count);
103   MREQ_ITR_RLOC_COUNT (h) = loc_count;
104
105   /* Put eid record */
106   lisp_msg_put_eid_rec (b, deid);
107
108   nonce[0] = MREQ_NONCE (h);
109   return h;
110 }
111
112 void *
113 lisp_msg_push_ecm (vlib_main_t * vm, vlib_buffer_t * b, int lp, int rp,
114                    gid_address_t * la, gid_address_t * ra)
115 {
116   ecm_hdr_t *h;
117   ip_address_t _src_ip, *src_ip = &_src_ip, _dst_ip, *dst_ip = &_dst_ip;
118   if (gid_address_type (la) != GID_ADDR_IP_PREFIX)
119     {
120       /* empty ip4 */
121       memset (src_ip, 0, sizeof (src_ip[0]));
122       memset (dst_ip, 0, sizeof (dst_ip[0]));
123     }
124   else
125     {
126       src_ip = &gid_address_ip (la);
127       dst_ip = &gid_address_ip (ra);
128     }
129
130   /* Push inner ip and udp */
131   pkt_push_udp_and_ip (vm, b, lp, rp, src_ip, dst_ip);
132
133   /* Push lisp ecm hdr */
134   h = pkt_push_ecm_hdr (b);
135
136   return h;
137 }
138
139 static u32
140 msg_type_to_hdr_len (lisp_msg_type_e type)
141 {
142   switch (type)
143     {
144     case LISP_MAP_REQUEST:
145       return (sizeof (map_request_hdr_t));
146     case LISP_MAP_REPLY:
147       return (sizeof (map_reply_hdr_t));
148     default:
149       return (0);
150     }
151 }
152
153 void *
154 lisp_msg_pull_hdr (vlib_buffer_t * b, lisp_msg_type_e type)
155 {
156   return vlib_buffer_pull (b, msg_type_to_hdr_len (type));
157 }
158
159 u32
160 lisp_msg_parse_addr (vlib_buffer_t * b, gid_address_t * eid)
161 {
162   u32 len;
163   memset (eid, 0, sizeof (*eid));
164   len = gid_address_parse (vlib_buffer_get_current (b), eid);
165   if (len != ~0)
166     vlib_buffer_pull (b, len);
167   return len;
168 }
169
170 u32
171 lisp_msg_parse_eid_rec (vlib_buffer_t * b, gid_address_t * eid)
172 {
173   eid_record_hdr_t *h = vlib_buffer_get_current (b);
174   u32 len;
175   memset (eid, 0, sizeof (*eid));
176   len = gid_address_parse (EID_REC_ADDR (h), eid);
177   if (len == ~0)
178     return len;
179
180   gid_address_ippref_len (eid) = EID_REC_MLEN (h);
181   vlib_buffer_pull (b, len + sizeof (eid_record_hdr_t));
182
183   return len + sizeof (eid_record_hdr_t);
184 }
185
186 u32
187 lisp_msg_parse_itr_rlocs (vlib_buffer_t * b, gid_address_t ** rlocs,
188                           u8 rloc_count)
189 {
190   gid_address_t tloc;
191   u32 i, len = 0, tlen = 0;
192
193   //MREQ_ITR_RLOC_COUNT(mreq_hdr) + 1
194   for (i = 0; i < rloc_count; i++)
195     {
196       len = lisp_msg_parse_addr (b, &tloc);
197       if (len == ~0)
198         return len;
199       vec_add1 (*rlocs, tloc);
200       tlen += len;
201     }
202   return tlen;
203 }
204
205 u32
206 lisp_msg_parse_loc (vlib_buffer_t * b, locator_t * loc)
207 {
208   int len;
209
210   len = locator_parse (vlib_buffer_get_current (b), loc);
211   if (len == ~0)
212     return ~0;
213
214   vlib_buffer_pull (b, len);
215
216   return len;
217 }
218
219 u32
220 lisp_msg_parse_mapping_record (vlib_buffer_t * b, gid_address_t * eid,
221                                locator_t ** locs, locator_t * probed_)
222 {
223   void *h = 0, *loc_hdr = 0;
224   locator_t loc, *probed = 0;
225   int i = 0, len = 0, llen = 0;
226
227   h = vlib_buffer_get_current (b);
228   vlib_buffer_pull (b, sizeof (mapping_record_hdr_t));
229
230   memset (eid, 0, sizeof (*eid));
231   len = gid_address_parse (vlib_buffer_get_current (b), eid);
232   if (len == ~0)
233     return len;
234
235   vlib_buffer_pull (b, len);
236   if (GID_ADDR_IP_PREFIX == gid_address_type (eid))
237     gid_address_ippref_len (eid) = MAP_REC_EID_PLEN (h);
238
239   for (i = 0; i < MAP_REC_LOC_COUNT (h); i++)
240     {
241       loc_hdr = vlib_buffer_get_current (b);
242
243       llen = lisp_msg_parse_loc (b, &loc);
244       if (llen == ~0)
245         return llen;
246       vec_add1 (*locs, loc);
247       len += llen;
248
249       if (LOC_PROBED (loc_hdr))
250         {
251           if (probed != 0)
252             clib_warning
253               ("Multiple locators probed! Probing only the first!");
254           else
255             probed = &loc;
256         }
257     }
258   /* XXX */
259   if (probed_ != 0 && probed)
260     *probed_ = *probed;
261
262   return len + sizeof (map_reply_hdr_t);
263 }
264
265 /*
266  * fd.io coding-style-patch-verification: ON
267  *
268  * Local Variables:
269  * eval: (c-set-style "gnu")
270  * End:
271  */