2 * Copyright (c) 2015 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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
15 #include <vnet/lisp-gpe/lisp_gpe.h>
17 lisp_gpe_main_t lisp_gpe_main;
19 static u8 * format_decap_next (u8 * s, va_list * args)
21 u32 next_index = va_arg (*args, u32);
25 case LISP_GPE_INPUT_NEXT_DROP:
26 return format (s, "drop");
27 case LISP_GPE_INPUT_NEXT_IP4_INPUT:
28 return format (s, "ip4");
29 case LISP_GPE_INPUT_NEXT_IP6_INPUT:
30 return format (s, "ip6");
31 case LISP_GPE_INPUT_NEXT_LISP_GPE_ENCAP:
32 return format (s, "nsh-lisp-gpe");
34 return format (s, "unknown %d", next_index);
39 u8 * format_lisp_gpe_tunnel (u8 * s, va_list * args)
41 lisp_gpe_tunnel_t * t = va_arg (*args, lisp_gpe_tunnel_t *);
42 lisp_gpe_main_t * ngm = &lisp_gpe_main;
45 "[%d] %U (src) %U (dst) fibs: encap %d, decap %d",
47 format_ip4_address, &t->src,
48 format_ip4_address, &t->dst,
52 s = format (s, " decap next %U\n", format_decap_next, t->decap_next_index);
53 s = format (s, "lisp ver %d ", (t->ver_res>>6));
55 #define _(n,v) if (t->flags & v) s = format (s, "%s-bit ", #n);
56 foreach_lisp_gpe_flag_bit;
59 s = format (s, "next_protocol %d ver_res %x res %x\n",
60 t->next_protocol, t->ver_res, t->res);
62 s = format (s, "iid %d (0x%x)\n", t->iid, t->iid);
66 static u8 * format_lisp_gpe_name (u8 * s, va_list * args)
68 u32 dev_instance = va_arg (*args, u32);
69 return format (s, "lisp_gpe_tunnel%d", dev_instance);
72 static uword dummy_interface_tx (vlib_main_t * vm,
73 vlib_node_runtime_t * node,
76 clib_warning ("you shouldn't be here, leaking buffers...");
77 return frame->n_vectors;
80 VNET_DEVICE_CLASS (lisp_gpe_device_class,static) = {
82 .format_device_name = format_lisp_gpe_name,
83 .format_tx_trace = format_lisp_gpe_encap_trace,
84 .tx_function = dummy_interface_tx,
87 static uword dummy_set_rewrite (vnet_main_t * vnm,
92 uword max_rewrite_bytes)
97 u8 * format_lisp_gpe_header_with_length (u8 * s, va_list * args)
99 lisp_gpe_header_t * h = va_arg (*args, lisp_gpe_header_t *);
100 u32 max_header_bytes = va_arg (*args, u32);
103 header_bytes = sizeof (h[0]);
104 if (max_header_bytes != 0 && header_bytes > max_header_bytes)
105 return format (s, "gre-nsh header truncated");
107 s = format (s, "flags: ");
108 #define _(n,v) if (h->flags & v) s = format (s, "%s ", #n);
109 foreach_lisp_gpe_flag_bit;
112 s = format (s, "\n ver_res %d res %d next_protocol %d iid %d(%x)",
113 h->ver_res, h->res, h->next_protocol,
114 clib_net_to_host_u32 (h->iid),
115 clib_net_to_host_u32 (h->iid));
119 VNET_HW_INTERFACE_CLASS (lisp_gpe_hw_class) = {
121 .format_header = format_lisp_gpe_header_with_length,
122 .set_rewrite = dummy_set_rewrite,
125 #define foreach_copy_field \
130 _(decap_next_index) \
137 static int lisp_gpe_rewrite (lisp_gpe_tunnel_t * t)
141 lisp_gpe_header_t * lisp0;
142 ip4_udp_lisp_gpe_header_t * h0;
147 vec_validate_aligned (rw, len-1, CLIB_CACHE_LINE_BYTES);
149 h0 = (ip4_udp_lisp_gpe_header_t *) rw;
151 /* Fixed portion of the (outer) ip4 header */
153 ip0->ip_version_and_header_length = 0x45;
155 ip0->protocol = IP_PROTOCOL_UDP;
157 /* we fix up the ip4 header length and checksum after-the-fact */
158 ip0->src_address.as_u32 = t->src.as_u32;
159 ip0->dst_address.as_u32 = t->dst.as_u32;
160 ip0->checksum = ip4_header_checksum (ip0);
162 /* UDP header, randomize src port on something, maybe? */
163 h0->udp.src_port = clib_host_to_net_u16 (4341);
164 h0->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_lisp_gpe);
166 /* LISP-gpe header */
169 lisp0->flags = t->flags;
170 lisp0->ver_res = t->ver_res;
172 lisp0->next_protocol = t->next_protocol;
173 lisp0->iid = clib_host_to_net_u32 (t->iid);
179 int vnet_lisp_gpe_add_del_tunnel
180 (vnet_lisp_gpe_add_del_tunnel_args_t *a, u32 * sw_if_indexp)
182 lisp_gpe_main_t * ngm = &lisp_gpe_main;
183 lisp_gpe_tunnel_t *t = 0;
184 vnet_main_t * vnm = ngm->vnet_main;
185 vnet_hw_interface_t * hi;
187 u32 hw_if_index = ~0;
188 u32 sw_if_index = ~0;
190 lisp_gpe_tunnel_key_t key, *key_copy;
193 key.src = a->src.as_u32;
194 key.iid = clib_host_to_net_u32(a->iid);
196 p = hash_get_mem (ngm->lisp_gpe_tunnel_by_key, &key);
200 /* adding a tunnel: tunnel must not already exist */
202 return VNET_API_ERROR_INVALID_VALUE;
204 if (a->decap_next_index >= LISP_GPE_INPUT_N_NEXT)
205 return VNET_API_ERROR_INVALID_DECAP_NEXT;
207 pool_get_aligned (ngm->tunnels, t, CLIB_CACHE_LINE_BYTES);
208 memset (t, 0, sizeof (*t));
210 /* copy from arg structure */
211 #define _(x) t->x = a->x;
215 rv = lisp_gpe_rewrite (t);
219 pool_put (ngm->tunnels, t);
223 key_copy = clib_mem_alloc (sizeof (*key_copy));
224 memcpy (key_copy, &key, sizeof (*key_copy));
226 hash_set_mem (ngm->lisp_gpe_tunnel_by_key, key_copy,
229 if (vec_len (ngm->free_lisp_gpe_tunnel_hw_if_indices) > 0)
231 hw_if_index = ngm->free_lisp_gpe_tunnel_hw_if_indices
232 [vec_len (ngm->free_lisp_gpe_tunnel_hw_if_indices)-1];
233 _vec_len (ngm->free_lisp_gpe_tunnel_hw_if_indices) -= 1;
235 hi = vnet_get_hw_interface (vnm, hw_if_index);
236 hi->dev_instance = t - ngm->tunnels;
237 hi->hw_instance = hi->dev_instance;
241 hw_if_index = vnet_register_interface
242 (vnm, lisp_gpe_device_class.index, t - ngm->tunnels,
243 lisp_gpe_hw_class.index, t - ngm->tunnels);
244 hi = vnet_get_hw_interface (vnm, hw_if_index);
245 hi->output_node_index = lisp_gpe_encap_node.index;
248 t->hw_if_index = hw_if_index;
249 t->sw_if_index = sw_if_index = hi->sw_if_index;
251 vnet_sw_interface_set_flags (vnm, hi->sw_if_index,
252 VNET_SW_INTERFACE_FLAG_ADMIN_UP);
256 /* deleting a tunnel: tunnel must exist */
258 return VNET_API_ERROR_NO_SUCH_ENTRY;
260 t = pool_elt_at_index (ngm->tunnels, p[0]);
262 vnet_sw_interface_set_flags (vnm, t->sw_if_index, 0 /* down */);
263 vec_add1 (ngm->free_lisp_gpe_tunnel_hw_if_indices, t->hw_if_index);
265 hp = hash_get_pair (ngm->lisp_gpe_tunnel_by_key, &key);
266 key_copy = (void *)(hp->key);
267 hash_unset_mem (ngm->lisp_gpe_tunnel_by_key, &key);
268 clib_mem_free (key_copy);
270 vec_free (t->rewrite);
271 pool_put (ngm->tunnels, t);
275 *sw_if_indexp = sw_if_index;
280 static u32 fib_index_from_fib_id (u32 fib_id)
282 ip4_main_t * im = &ip4_main;
285 p = hash_get (im->fib_index_by_table_id, fib_id);
292 static uword unformat_decap_next (unformat_input_t * input, va_list * args)
294 u32 * result = va_arg (*args, u32 *);
297 if (unformat (input, "drop"))
298 *result = LISP_GPE_INPUT_NEXT_DROP;
299 else if (unformat (input, "ip4"))
300 *result = LISP_GPE_INPUT_NEXT_IP4_INPUT;
301 else if (unformat (input, "ip6"))
302 *result = LISP_GPE_INPUT_NEXT_IP6_INPUT;
303 else if (unformat (input, "ethernet"))
304 *result = LISP_GPE_INPUT_NEXT_IP6_INPUT;
305 else if (unformat (input, "lisp-gpe"))
306 *result = LISP_GPE_INPUT_NEXT_LISP_GPE_ENCAP;
307 else if (unformat (input, "%d", &tmp))
314 static clib_error_t *
315 lisp_gpe_add_del_tunnel_command_fn (vlib_main_t * vm,
316 unformat_input_t * input,
317 vlib_cli_command_t * cmd)
319 unformat_input_t _line_input, * line_input = &_line_input;
320 ip4_address_t src, dst;
324 u32 encap_fib_index = 0;
325 u32 decap_fib_index = 0;
326 u8 next_protocol = LISP_GPE_NEXT_PROTOCOL_IP4;
327 u32 decap_next_index = LISP_GPE_INPUT_NEXT_IP4_INPUT;
328 u8 flags = LISP_GPE_FLAGS_P;
335 vnet_lisp_gpe_add_del_tunnel_args_t _a, * a = &_a;
337 /* Get a line of input. */
338 if (! unformat_user (input, unformat_line_input, line_input))
341 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
342 if (unformat (line_input, "del"))
344 else if (unformat (line_input, "src %U",
345 unformat_ip4_address, &src))
347 else if (unformat (line_input, "dst %U",
348 unformat_ip4_address, &dst))
350 else if (unformat (line_input, "encap-vrf-id %d", &tmp))
352 encap_fib_index = fib_index_from_fib_id (tmp);
353 if (encap_fib_index == ~0)
354 return clib_error_return (0, "nonexistent encap fib id %d", tmp);
356 else if (unformat (line_input, "decap-vrf-id %d", &tmp))
358 decap_fib_index = fib_index_from_fib_id (tmp);
359 if (decap_fib_index == ~0)
360 return clib_error_return (0, "nonexistent decap fib id %d", tmp);
362 else if (unformat (line_input, "decap-next %U", unformat_decap_next,
365 else if (unformat(line_input, "next-ip4"))
367 else if (unformat(line_input, "next-ip6"))
369 else if (unformat(line_input, "next-ethernet"))
371 else if (unformat(line_input, "next-nsh"))
373 /* Allow the user to specify anything they want in the LISP hdr */
374 else if (unformat (line_input, "ver_res %x", &tmp))
376 else if (unformat (line_input, "res %x", &tmp))
378 else if (unformat (line_input, "flags %x", &tmp))
380 else if (unformat (line_input, "n-bit"))
381 flags |= LISP_GPE_FLAGS_N;
382 else if (unformat (line_input, "l-bit"))
383 flags |= LISP_GPE_FLAGS_L;
384 else if (unformat (line_input, "e-bit"))
385 flags |= LISP_GPE_FLAGS_E;
386 else if (unformat (line_input, "v-bit"))
387 flags |= LISP_GPE_FLAGS_V;
388 else if (unformat (line_input, "i-bit"))
389 flags |= LISP_GPE_FLAGS_V;
390 else if (unformat (line_input, "not-p-bit"))
391 flags &= ~LISP_GPE_FLAGS_P;
392 else if (unformat (line_input, "p-bit"))
393 flags |= LISP_GPE_FLAGS_P;
394 else if (unformat (line_input, "o-bit"))
395 flags |= LISP_GPE_FLAGS_O;
396 else if (unformat (line_input, "iidx %x", &iid))
398 else if (unformat (line_input, "iid %d", &iid))
401 return clib_error_return (0, "parse error: '%U'",
402 format_unformat_error, line_input);
405 unformat_free (line_input);
408 return clib_error_return (0, "tunnel src address not specified");
411 return clib_error_return (0, "tunnel dst address not specified");
414 return clib_error_return (0, "iid not specified");
416 memset (a, 0, sizeof (*a));
420 #define _(x) a->x = x;
424 rv = vnet_lisp_gpe_add_del_tunnel (a, 0 /* hw_if_indexp */);
430 case VNET_API_ERROR_INVALID_DECAP_NEXT:
431 return clib_error_return (0, "invalid decap-next...");
433 case VNET_API_ERROR_TUNNEL_EXIST:
434 return clib_error_return (0, "tunnel already exists...");
436 case VNET_API_ERROR_NO_SUCH_ENTRY:
437 return clib_error_return (0, "tunnel does not exist...");
440 return clib_error_return
441 (0, "vnet_lisp_gpe_add_del_tunnel returned %d", rv);
447 VLIB_CLI_COMMAND (create_lisp_gpe_tunnel_command, static) = {
448 .path = "lisp gpe tunnel",
450 "lisp gpe tunnel src <ip4-addr> dst <ip4-addr> iidx <0xnn> | iid <nn>\n"
451 " [encap-fib-id <nn>] [decap-fib-id <nn>]\n"
452 " [n-bit][l-bit][e-bit][v-bit][i-bit][p-bit][not-p-bit][o-bit]\n"
453 " [next-ip4][next-ip6][next-ethernet][next-nsh]\n"
454 " [decap-next [ip4|ip6|ethernet|nsh-encap|<nn>]][del]\n",
455 .function = lisp_gpe_add_del_tunnel_command_fn,
458 static clib_error_t *
459 show_lisp_gpe_tunnel_command_fn (vlib_main_t * vm,
460 unformat_input_t * input,
461 vlib_cli_command_t * cmd)
463 lisp_gpe_main_t * ngm = &lisp_gpe_main;
464 lisp_gpe_tunnel_t * t;
466 if (pool_elts (ngm->tunnels) == 0)
467 vlib_cli_output (vm, "No lisp-gpe tunnels configured...");
469 pool_foreach (t, ngm->tunnels,
471 vlib_cli_output (vm, "%U", format_lisp_gpe_tunnel, t);
477 VLIB_CLI_COMMAND (show_lisp_gpe_tunnel_command, static) = {
478 .path = "show lisp gpe tunnel",
479 .function = show_lisp_gpe_tunnel_command_fn,
482 clib_error_t *lisp_gpe_init (vlib_main_t *vm)
484 lisp_gpe_main_t *ngm = &lisp_gpe_main;
486 ngm->vnet_main = vnet_get_main();
489 ngm->lisp_gpe_tunnel_by_key
490 = hash_create_mem (0, sizeof(lisp_gpe_tunnel_key_t), sizeof (uword));
492 udp_register_dst_port (vm, UDP_DST_PORT_lisp_gpe,
493 lisp_gpe_input_node.index, 1 /* is_ip4 */);
497 VLIB_INIT_FUNCTION(lisp_gpe_init);