blob: e4e59707e8fd2ad4545da4a11a321b9acc694ffb [file] [log] [blame]
Neale Ranns0bfe5d82016-08-25 15:29:12 +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 * @file
17 * @brief Common utility functions for IPv4, IPv6 and L2 LISP-GPE tunnels.
18 *
19 */
20#include <vnet/lisp-gpe/lisp_gpe.h>
21#include <vnet/lisp-gpe/lisp_gpe_tunnel.h>
22#include <vnet/lisp-gpe/lisp_gpe_adjacency.h>
23
24#include <vnet/fib/fib_table.h>
25
26/**
27 * @brief Pool of all LISP tunnels
28 */
Neale Ranns5e575b12016-10-03 09:40:25 +010029static lisp_gpe_tunnel_t *lisp_gpe_tunnel_pool;
Neale Ranns0bfe5d82016-08-25 15:29:12 +010030
31/**
32 * @brief a DB of all tunnels
33 */
34static uword *lisp_gpe_tunnel_db;
35
36/**
37 * @brief Compute IP-UDP-GPE sub-tunnel encap/rewrite header.
38 *
39 * @param[in] t Parent of the sub-tunnel.
40 * @param[in] st Sub-tunnel.
41 * @param[in] lp Local and remote locators used in the encap header.
42 *
43 * @return 0 on success.
44 */
45u8 *
Neale Ranns5e575b12016-10-03 09:40:25 +010046lisp_gpe_tunnel_build_rewrite (const lisp_gpe_tunnel_t * lgt,
Neale Ranns0bfe5d82016-08-25 15:29:12 +010047 const lisp_gpe_adjacency_t * ladj,
48 lisp_gpe_next_protocol_e payload_proto)
49{
50 lisp_gpe_header_t *lisp0;
51 u8 *rw = 0;
52 int len;
53
54 if (IP4 == ip_addr_version (&lgt->key->lcl))
55 {
56 ip4_udp_lisp_gpe_header_t *h0;
57 ip4_header_t *ip0;
58
59 len = sizeof (*h0);
60
61 vec_validate_aligned (rw, len - 1, CLIB_CACHE_LINE_BYTES);
62
63 h0 = (ip4_udp_lisp_gpe_header_t *) rw;
64
65 /* Fixed portion of the (outer) ip4 header */
66 ip0 = &h0->ip4;
67 ip0->ip_version_and_header_length = 0x45;
68 ip0->ttl = 254;
69 ip0->protocol = IP_PROTOCOL_UDP;
70
71 /* we fix up the ip4 header length and checksum after-the-fact */
72 ip_address_copy_addr (&ip0->src_address, &lgt->key->lcl);
73 ip_address_copy_addr (&ip0->dst_address, &lgt->key->rmt);
74 ip0->checksum = ip4_header_checksum (ip0);
75
76 /* UDP header, randomize src port on something, maybe? */
77 h0->udp.src_port = clib_host_to_net_u16 (4341);
78 h0->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_lisp_gpe);
79
80 /* LISP-gpe header */
81 lisp0 = &h0->lisp;
82 }
83 else
84 {
85 ip6_udp_lisp_gpe_header_t *h0;
86 ip6_header_t *ip0;
87
88 len = sizeof (*h0);
89
90 vec_validate_aligned (rw, len - 1, CLIB_CACHE_LINE_BYTES);
91
92 h0 = (ip6_udp_lisp_gpe_header_t *) rw;
93
94 /* Fixed portion of the (outer) ip6 header */
95 ip0 = &h0->ip6;
96 ip0->ip_version_traffic_class_and_flow_label =
97 clib_host_to_net_u32 (0x6 << 28);
98 ip0->hop_limit = 254;
99 ip0->protocol = IP_PROTOCOL_UDP;
100
101 /* we fix up the ip6 header length after-the-fact */
102 ip_address_copy_addr (&ip0->src_address, &lgt->key->lcl);
103 ip_address_copy_addr (&ip0->dst_address, &lgt->key->rmt);
104
105 /* UDP header, randomize src port on something, maybe? */
106 h0->udp.src_port = clib_host_to_net_u16 (4341);
107 h0->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_lisp_gpe);
108
109 /* LISP-gpe header */
110 lisp0 = &h0->lisp;
111 }
112
113 lisp0->flags = ladj->flags;
114 lisp0->ver_res = 0;
115 lisp0->res = 0;
116 lisp0->next_protocol = payload_proto;
Florin Corasf1950192016-10-25 16:47:52 +0200117 lisp0->iid = clib_host_to_net_u32 (ladj->vni) >> 8; /* first 24 bits only */
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100118
119 return (rw);
120}
121
Neale Ranns5e575b12016-10-03 09:40:25 +0100122static lisp_gpe_tunnel_t *
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100123lisp_gpe_tunnel_db_find (const lisp_gpe_tunnel_key_t * key)
124{
125 uword *p;
126
127 p = hash_get_mem (lisp_gpe_tunnel_db, (void *) key);
128
129 if (NULL != p)
130 {
131 return (pool_elt_at_index (lisp_gpe_tunnel_pool, p[0]));
132 }
133 return (NULL);
134}
135
Neale Ranns5e575b12016-10-03 09:40:25 +0100136lisp_gpe_tunnel_t *
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100137lisp_gpe_tunnel_get_i (index_t lgti)
138{
139 return (pool_elt_at_index (lisp_gpe_tunnel_pool, lgti));
140}
141
142index_t
143lisp_gpe_tunnel_find_or_create_and_lock (const locator_pair_t * pair,
144 u32 rloc_fib_index)
145{
146 lisp_gpe_tunnel_key_t key = {
147 .lcl = pair->lcl_loc,
148 .rmt = pair->rmt_loc,
149 .fib_index = rloc_fib_index,
150 };
Neale Ranns5e575b12016-10-03 09:40:25 +0100151 lisp_gpe_tunnel_t *lgt;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100152 fib_prefix_t pfx;
153
154 lgt = lisp_gpe_tunnel_db_find (&key);
155
156 if (NULL == lgt)
157 {
158 pool_get (lisp_gpe_tunnel_pool, lgt);
159 memset (lgt, 0, sizeof (*lgt));
160
161 lgt->key = clib_mem_alloc (sizeof (*lgt->key));
162 memset (lgt->key, 0, sizeof (*lgt->key));
163
164 lgt->key->rmt = pair->rmt_loc;
165 lgt->key->lcl = pair->lcl_loc;
166 lgt->key->fib_index = rloc_fib_index;
167
168 /*
169 * source the FIB entry for the RLOC so we can track its forwarding
170 * chain
171 */
172 ip_address_to_fib_prefix (&lgt->key->rmt, &pfx);
173
174 lgt->fib_entry_index = fib_table_entry_special_add (rloc_fib_index,
175 &pfx,
176 FIB_SOURCE_RR,
177 FIB_ENTRY_FLAG_NONE,
178 ADJ_INDEX_INVALID);
179
180 hash_set_mem (lisp_gpe_tunnel_db, &lgt->key,
181 (lgt - lisp_gpe_tunnel_pool));
182 }
183
184 lgt->locks++;
185
186 return (lgt - lisp_gpe_tunnel_pool);
187}
188
189void
190lisp_gpe_tunnel_unlock (index_t lgti)
191{
Neale Ranns5e575b12016-10-03 09:40:25 +0100192 lisp_gpe_tunnel_t *lgt;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100193
194 lgt = lisp_gpe_tunnel_get_i (lgti);
195 lgt->locks--;
196
197 if (0 == lgt->locks)
198 {
199 hash_unset_mem (lisp_gpe_tunnel_db, &lgt->key);
200 clib_mem_free (lgt->key);
201 pool_put (lisp_gpe_tunnel_pool, lgt);
202 }
203}
204
Neale Ranns5e575b12016-10-03 09:40:25 +0100205const lisp_gpe_tunnel_t *
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100206lisp_gpe_tunnel_get (index_t lgti)
207{
208 return (lisp_gpe_tunnel_get_i (lgti));
209}
210
211/** Format LISP-GPE tunnel. */
212u8 *
213format_lisp_gpe_tunnel (u8 * s, va_list * args)
214{
Neale Ranns5e575b12016-10-03 09:40:25 +0100215 lisp_gpe_tunnel_t *lgt = va_arg (*args, lisp_gpe_tunnel_t *);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100216
217 s = format (s, "tunnel %d\n", lgt - lisp_gpe_tunnel_pool);
218 s = format (s, " fib-index: %d, locks:%d \n",
219 lgt->key->fib_index, lgt->locks);
220 s = format (s, " lisp ver 0\n");
221
222 s = format (s, " locator-pair:\n");
223 s = format (s, " local: %U remote: %U\n",
224 format_ip_address, &lgt->key->lcl,
225 format_ip_address, &lgt->key->rmt);
226 s = format (s, " RLOC FIB entry: %d\n", lgt->fib_entry_index);
227
228 return s;
229}
230
231/**
232 * CLI command to show LISP-GPE tunnels.
233 */
234static clib_error_t *
235show_lisp_gpe_tunnel_command_fn (vlib_main_t * vm,
236 unformat_input_t * input,
237 vlib_cli_command_t * cmd)
238{
Neale Ranns5e575b12016-10-03 09:40:25 +0100239 lisp_gpe_tunnel_t *lgt;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100240 index_t index;
241
242 if (pool_elts (lisp_gpe_tunnel_pool) == 0)
243 vlib_cli_output (vm, "No lisp-gpe tunnels configured...");
244
245 if (unformat (input, "%d", &index))
246 {
247 lgt = lisp_gpe_tunnel_get_i (index);
248 vlib_cli_output (vm, "%U", format_lisp_gpe_tunnel, lgt);
249 }
250 else
251 {
252 /* *INDENT-OFF* */
253 pool_foreach (lgt, lisp_gpe_tunnel_pool,
254 ({
255 vlib_cli_output (vm, "%U", format_lisp_gpe_tunnel, lgt);
256 }));
257 /* *INDENT-ON* */
258 }
259
260 return 0;
261}
262
263/* *INDENT-OFF* */
264VLIB_CLI_COMMAND (show_lisp_gpe_tunnel_command, static) =
265{
266 .path = "show lisp gpe tunnel",
267 .function = show_lisp_gpe_tunnel_command_fn,
268};
269/* *INDENT-ON* */
270
271static clib_error_t *
272lisp_gpe_tunnel_module_init (vlib_main_t * vm)
273{
274 lisp_gpe_tunnel_db = hash_create_mem (0,
Neale Ranns5e575b12016-10-03 09:40:25 +0100275 sizeof (lisp_gpe_tunnel_key_t),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100276 sizeof (uword));
277
278 return (NULL);
279}
280
281VLIB_INIT_FUNCTION (lisp_gpe_tunnel_module_init);
282
283/*
284 * fd.io coding-style-patch-verification: ON
285 *
286 * Local Variables:
287 * eval: (c-set-style "gnu")
288 * End:
289 */