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