2 * proxy_node.c: common dhcp v4 and v6 proxy node processing
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <vnet/dhcp/dhcp_proxy.h>
19 #include <vnet/fib/fib_table.h>
20 #include <vnet/mfib/mfib_table.h>
23 * @brief Shard 4/6 instance of DHCP main
25 dhcp_proxy_main_t dhcp_proxy_main;
28 dhcp_proxy_rx_table_lock (fib_protocol_t proto,
31 if (FIB_PROTOCOL_IP4 == proto)
32 fib_table_lock(fib_index, proto);
34 mfib_table_lock(fib_index, proto);
38 dhcp_proxy_rx_table_unlock (fib_protocol_t proto,
41 if (FIB_PROTOCOL_IP4 == proto)
42 fib_table_unlock(fib_index, proto);
44 mfib_table_unlock(fib_index, proto);
48 dhcp_proxy_rx_table_get_table_id (fib_protocol_t proto,
51 if (FIB_PROTOCOL_IP4 == proto)
55 fib = fib_table_get(fib_index, proto);
57 return (fib->ft_table_id);
63 mfib = mfib_table_get(fib_index, proto);
65 return (mfib->mft_table_id);
70 dhcp_proxy_walk (fib_protocol_t proto,
71 dhcp_proxy_walk_fn_t fn,
74 dhcp_proxy_main_t * dpm = &dhcp_proxy_main;
75 dhcp_server_t * server;
78 vec_foreach_index (i, dpm->dhcp_server_index_by_rx_fib_index[proto])
80 server_index = dpm->dhcp_server_index_by_rx_fib_index[proto][i];
81 if (~0 == server_index)
84 server = pool_elt_at_index (dpm->dhcp_servers[proto], server_index);
92 dhcp_vss_walk (fib_protocol_t proto,
93 dhcp_vss_walk_fn_t fn,
96 dhcp_proxy_main_t * dpm = &dhcp_proxy_main;
102 vec_foreach_index (i, dpm->vss_index_by_rx_fib_index[proto])
104 vss_index = dpm->vss_index_by_rx_fib_index[proto][i];
108 vss = pool_elt_at_index (dpm->vss[proto], vss_index);
110 if (FIB_PROTOCOL_IP4 == proto)
112 fib = fib_table_get(i, proto);
114 if (!fn(vss, fib->ft_table_id, ctx))
119 mfib = mfib_table_get(i, proto);
121 if (!fn(vss, mfib->mft_table_id, ctx))
128 dhcp_proxy_server_del (fib_protocol_t proto,
131 dhcp_proxy_main_t * dpm = &dhcp_proxy_main;
132 dhcp_server_t * server = 0;
135 server = dhcp_get_server(dpm, rx_fib_index, proto);
139 rc = VNET_API_ERROR_NO_SUCH_ENTRY;
143 /* Use the default server again. */
144 dpm->dhcp_server_index_by_rx_fib_index[proto][rx_fib_index] = ~0;
146 fib_table_unlock (server->server_fib_index, proto);
148 pool_put (dpm->dhcp_servers[proto], server);
155 dhcp_proxy_server_add (fib_protocol_t proto,
156 ip46_address_t *addr,
157 ip46_address_t *src_address,
161 dhcp_proxy_main_t * dpm = &dhcp_proxy_main;
162 dhcp_server_t * server = 0;
165 server = dhcp_get_server(dpm, rx_fib_index, proto);
169 vec_validate_init_empty(dpm->dhcp_server_index_by_rx_fib_index[proto],
173 pool_get (dpm->dhcp_servers[proto], server);
174 memset (server, 0, sizeof (*server));
177 dpm->dhcp_server_index_by_rx_fib_index[proto][rx_fib_index] =
178 server - dpm->dhcp_servers[proto];
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);
186 /* modify, may need to swap server FIBs */
189 tmp_index = fib_table_find(proto, server_table_id);
191 if (tmp_index != server->server_fib_index)
193 tmp_index = server->server_fib_index;
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);
202 server->dhcp_server = *addr;
203 server->dhcp_src_address = *src_address;
208 typedef struct dhcp4_proxy_dump_walk_ctx_t_
210 fib_protocol_t proto;
213 } dhcp_proxy_dump_walk_cxt_t;
216 dhcp_proxy_dump_walk (dhcp_server_t *server,
219 dhcp_proxy_dump_walk_cxt_t *ctx = arg;
224 v = dhcp_get_vss_info(&dhcp_proxy_main,
225 server->rx_fib_index,
228 s_fib = fib_table_get(server->server_fib_index, ctx->proto);
229 rx_table_id = dhcp_proxy_rx_table_get_table_id(server->rx_fib_index,
232 dhcp_send_details(ctx->proto,
235 &server->dhcp_server,
236 &server->dhcp_src_address,
246 dhcp_proxy_dump (fib_protocol_t proto,
250 dhcp_proxy_dump_walk_cxt_t ctx = {
255 dhcp_proxy_walk(proto, dhcp_proxy_dump_walk, &ctx);
259 dhcp_vss_show_walk (dhcp_vss_t *vss,
263 vlib_main_t * vm = ctx;
265 vlib_cli_output (vm, "%=6d%=6d%=12d",
273 int dhcp_proxy_set_vss (fib_protocol_t proto,
279 dhcp_proxy_main_t *dm = &dhcp_proxy_main;
280 dhcp_vss_t *v = NULL;
284 if (proto == FIB_PROTOCOL_IP4)
285 rx_fib_index = fib_table_find_or_create_and_lock(proto, tbl_id);
287 rx_fib_index = mfib_table_find_or_create_and_lock(proto, tbl_id);
288 v = dhcp_get_vss_info(dm, rx_fib_index, proto);
294 /* release the lock held on the table when the VSS
295 * info was created */
296 dhcp_proxy_rx_table_unlock (proto, rx_fib_index);
298 pool_put (dm->vss[proto], v);
299 dm->vss_index_by_rx_fib_index[proto][rx_fib_index] = ~0;
303 /* this is a modify */
311 rc = VNET_API_ERROR_NO_SUCH_ENTRY;
314 /* create a new entry */
315 vec_validate_init_empty(dm->vss_index_by_rx_fib_index[proto],
318 /* hold a lock on the table whilst the VSS info exist */
319 pool_get (dm->vss[proto], v);
323 dm->vss_index_by_rx_fib_index[proto][rx_fib_index] =
325 dhcp_proxy_rx_table_lock (proto, rx_fib_index);
329 /* Release the lock taken during the create_or_lock at the start */
330 dhcp_proxy_rx_table_unlock (proto, rx_fib_index);