blob: 8e31c3dbecc670ed2b302ec2071b0d95867c222f [file] [log] [blame]
Neale Ranns2dd68522017-02-16 03:38:59 -08001/*
2 * proxy_node.c: common dhcp v4 and v6 proxy node processing
3 *
4 * Copyright (c) 2013 Cisco and/or its affiliates.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include <vnet/dhcp/dhcp_proxy.h>
19#include <vnet/fib/fib_table.h>
Neale Ranns358425b2017-02-20 09:42:36 -080020#include <vnet/mfib/mfib_table.h>
Neale Ranns2dd68522017-02-16 03:38:59 -080021
22/**
23 * @brief Shard 4/6 instance of DHCP main
24 */
25dhcp_proxy_main_t dhcp_proxy_main;
26
Neale Ranns358425b2017-02-20 09:42:36 -080027static void
28dhcp_proxy_rx_table_lock (fib_protocol_t proto,
29 u32 fib_index)
30{
31 if (FIB_PROTOCOL_IP4 == proto)
32 fib_table_lock(fib_index, proto);
33 else
34 mfib_table_lock(fib_index, proto);
35}
36
37static void
38dhcp_proxy_rx_table_unlock (fib_protocol_t proto,
39 u32 fib_index)
40{
41 if (FIB_PROTOCOL_IP4 == proto)
42 fib_table_unlock(fib_index, proto);
43 else
44 mfib_table_unlock(fib_index, proto);
45}
46
47static u32
48dhcp_proxy_rx_table_get_table_id (fib_protocol_t proto,
49 u32 fib_index)
50{
51 if (FIB_PROTOCOL_IP4 == proto)
52 {
53 fib_table_t *fib;
54
55 fib = fib_table_get(fib_index, proto);
56
57 return (fib->ft_table_id);
58 }
59 else
60 {
61 mfib_table_t *mfib;
62
63 mfib = mfib_table_get(fib_index, proto);
64
65 return (mfib->mft_table_id);
66 }
67}
68
Neale Ranns2dd68522017-02-16 03:38:59 -080069void
70dhcp_proxy_walk (fib_protocol_t proto,
71 dhcp_proxy_walk_fn_t fn,
72 void *ctx)
73{
74 dhcp_proxy_main_t * dpm = &dhcp_proxy_main;
75 dhcp_server_t * server;
76 u32 server_index, i;
77
78 vec_foreach_index (i, dpm->dhcp_server_index_by_rx_fib_index[proto])
79 {
80 server_index = dpm->dhcp_server_index_by_rx_fib_index[proto][i];
81 if (~0 == server_index)
82 continue;
83
84 server = pool_elt_at_index (dpm->dhcp_servers[proto], server_index);
85
86 if (!fn(server, ctx))
87 break;
88 }
89}
90
91void
92dhcp_vss_walk (fib_protocol_t proto,
93 dhcp_vss_walk_fn_t fn,
94 void *ctx)
95{
96 dhcp_proxy_main_t * dpm = &dhcp_proxy_main;
Neale Ranns358425b2017-02-20 09:42:36 -080097 mfib_table_t *mfib;
Neale Ranns2dd68522017-02-16 03:38:59 -080098 dhcp_vss_t * vss;
99 u32 vss_index, i;
100 fib_table_t *fib;
101
Neale Ranns2dd68522017-02-16 03:38:59 -0800102 vec_foreach_index (i, dpm->vss_index_by_rx_fib_index[proto])
103 {
104 vss_index = dpm->vss_index_by_rx_fib_index[proto][i];
105 if (~0 == vss_index)
106 continue;
107
108 vss = pool_elt_at_index (dpm->vss[proto], vss_index);
109
Neale Ranns358425b2017-02-20 09:42:36 -0800110 if (FIB_PROTOCOL_IP4 == proto)
111 {
112 fib = fib_table_get(i, proto);
Neale Ranns2dd68522017-02-16 03:38:59 -0800113
Neale Ranns358425b2017-02-20 09:42:36 -0800114 if (!fn(vss, fib->ft_table_id, ctx))
115 break;
116 }
117 else
118 {
119 mfib = mfib_table_get(i, proto);
120
121 if (!fn(vss, mfib->mft_table_id, ctx))
122 break;
123 }
Neale Ranns2dd68522017-02-16 03:38:59 -0800124 }
125}
126
127int
128dhcp_proxy_server_del (fib_protocol_t proto,
129 u32 rx_fib_index)
130{
131 dhcp_proxy_main_t * dpm = &dhcp_proxy_main;
132 dhcp_server_t * server = 0;
133 int rc = 0;
134
135 server = dhcp_get_server(dpm, rx_fib_index, proto);
136
137 if (NULL == server)
138 {
139 rc = VNET_API_ERROR_NO_SUCH_ENTRY;
140 }
141 else
142 {
143 /* Use the default server again. */
144 dpm->dhcp_server_index_by_rx_fib_index[proto][rx_fib_index] = ~0;
145
146 fib_table_unlock (server->server_fib_index, proto);
147
148 pool_put (dpm->dhcp_servers[proto], server);
149 }
150
151 return (rc);
152}
153
154int
155dhcp_proxy_server_add (fib_protocol_t proto,
156 ip46_address_t *addr,
157 ip46_address_t *src_address,
158 u32 rx_fib_index,
159 u32 server_table_id)
160{
161 dhcp_proxy_main_t * dpm = &dhcp_proxy_main;
162 dhcp_server_t * server = 0;
163 int new = 0;
164
165 server = dhcp_get_server(dpm, rx_fib_index, proto);
166
167 if (NULL == server)
168 {
169 vec_validate_init_empty(dpm->dhcp_server_index_by_rx_fib_index[proto],
170 rx_fib_index,
171 ~0);
172
173 pool_get (dpm->dhcp_servers[proto], server);
174 memset (server, 0, sizeof (*server));
175 new = 1;
176
177 dpm->dhcp_server_index_by_rx_fib_index[proto][rx_fib_index] =
178 server - dpm->dhcp_servers[proto];
179
180 server->rx_fib_index = rx_fib_index;
181 server->server_fib_index =
182 fib_table_find_or_create_and_lock(proto, server_table_id);
183 }
184 else
185 {
186 /* modify, may need to swap server FIBs */
187 u32 tmp_index;
188
189 tmp_index = fib_table_find(proto, server_table_id);
190
191 if (tmp_index != server->server_fib_index)
192 {
193 tmp_index = server->server_fib_index;
194
195 /* certainly swapping if the fib doesn't exist */
196 server->server_fib_index =
197 fib_table_find_or_create_and_lock(proto, server_table_id);
198 fib_table_unlock (tmp_index, proto);
199 }
200 }
201
202 server->dhcp_server = *addr;
203 server->dhcp_src_address = *src_address;
204
205 return (new);
206}
207
208typedef struct dhcp4_proxy_dump_walk_ctx_t_
209{
210 fib_protocol_t proto;
211 void *opaque;
212 u32 context;
213} dhcp_proxy_dump_walk_cxt_t;
214
215static int
216dhcp_proxy_dump_walk (dhcp_server_t *server,
217 void *arg)
218{
219 dhcp_proxy_dump_walk_cxt_t *ctx = arg;
Neale Ranns358425b2017-02-20 09:42:36 -0800220 fib_table_t *s_fib;
221 u32 rx_table_id;
Neale Ranns2dd68522017-02-16 03:38:59 -0800222 dhcp_vss_t *v;
223
224 v = dhcp_get_vss_info(&dhcp_proxy_main,
225 server->rx_fib_index,
226 ctx->proto);
227
228 s_fib = fib_table_get(server->server_fib_index, ctx->proto);
Neale Ranns358425b2017-02-20 09:42:36 -0800229 rx_table_id = dhcp_proxy_rx_table_get_table_id(server->rx_fib_index,
230 ctx->proto);
Neale Ranns2dd68522017-02-16 03:38:59 -0800231
232 dhcp_send_details(ctx->proto,
233 ctx->opaque,
234 ctx->context,
235 &server->dhcp_server,
236 &server->dhcp_src_address,
237 s_fib->ft_table_id,
Neale Ranns358425b2017-02-20 09:42:36 -0800238 rx_table_id,
Neale Ranns2dd68522017-02-16 03:38:59 -0800239 (v ? v->fib_id : 0),
240 (v ? v->oui : 0));
241
242 return (1);
243}
244
245void
246dhcp_proxy_dump (fib_protocol_t proto,
247 void *opaque,
248 u32 context)
249{
250 dhcp_proxy_dump_walk_cxt_t ctx = {
251 .proto = proto,
252 .opaque = opaque,
253 .context = context,
254 };
255 dhcp_proxy_walk(proto, dhcp_proxy_dump_walk, &ctx);
256}
257
258int
259dhcp_vss_show_walk (dhcp_vss_t *vss,
260 u32 rx_table_id,
261 void *ctx)
262{
263 vlib_main_t * vm = ctx;
264
265 vlib_cli_output (vm, "%=6d%=6d%=12d",
266 rx_table_id,
267 vss->oui,
268 vss->fib_id);
269
270 return (1);
271}
272
273int dhcp_proxy_set_vss (fib_protocol_t proto,
274 u32 tbl_id,
275 u32 oui,
276 u32 fib_id,
277 int is_del)
278{
279 dhcp_proxy_main_t *dm = &dhcp_proxy_main;
280 dhcp_vss_t *v = NULL;
281 u32 rx_fib_index;
282 int rc = 0;
283
Neale Ranns358425b2017-02-20 09:42:36 -0800284 if (proto == FIB_PROTOCOL_IP4)
285 rx_fib_index = fib_table_find_or_create_and_lock(proto, tbl_id);
286 else
287 rx_fib_index = mfib_table_find_or_create_and_lock(proto, tbl_id);
Neale Ranns2dd68522017-02-16 03:38:59 -0800288 v = dhcp_get_vss_info(dm, rx_fib_index, proto);
289
290 if (NULL != v)
291 {
292 if (is_del)
293 {
294 /* release the lock held on the table when the VSS
295 * info was created */
Neale Ranns358425b2017-02-20 09:42:36 -0800296 dhcp_proxy_rx_table_unlock (proto, rx_fib_index);
Neale Ranns2dd68522017-02-16 03:38:59 -0800297
298 pool_put (dm->vss[proto], v);
299 dm->vss_index_by_rx_fib_index[proto][rx_fib_index] = ~0;
300 }
301 else
302 {
303 /* this is a modify */
304 v->fib_id = fib_id;
305 v->oui = oui;
306 }
307 }
308 else
309 {
310 if (is_del)
311 rc = VNET_API_ERROR_NO_SUCH_ENTRY;
312 else
313 {
314 /* create a new entry */
315 vec_validate_init_empty(dm->vss_index_by_rx_fib_index[proto],
316 rx_fib_index, ~0);
317
318 /* hold a lock on the table whilst the VSS info exist */
Neale Ranns2dd68522017-02-16 03:38:59 -0800319 pool_get (dm->vss[proto], v);
320 v->fib_id = fib_id;
321 v->oui = oui;
Neale Ranns358425b2017-02-20 09:42:36 -0800322
Neale Ranns2dd68522017-02-16 03:38:59 -0800323 dm->vss_index_by_rx_fib_index[proto][rx_fib_index] =
324 v - dm->vss[proto];
Neale Ranns358425b2017-02-20 09:42:36 -0800325 dhcp_proxy_rx_table_lock (proto, rx_fib_index);
Neale Ranns2dd68522017-02-16 03:38:59 -0800326 }
327 }
328
329 /* Release the lock taken during the create_or_lock at the start */
Neale Ranns358425b2017-02-20 09:42:36 -0800330 dhcp_proxy_rx_table_unlock (proto, rx_fib_index);
331
Neale Ranns2dd68522017-02-16 03:38:59 -0800332 return (rc);
333}