FD.io VPP  v17.10-9-gd594711
Vector Packet Processing
dhcp_proxy.c
Go to the documentation of this file.
1 /*
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>
20 #include <vnet/mfib/mfib_table.h>
21 
22 /**
23  * @brief Shard 4/6 instance of DHCP main
24  */
26 
27 static void
29  u32 fib_index)
30 {
31  if (FIB_PROTOCOL_IP4 == proto)
32  fib_table_lock(fib_index, proto, FIB_SOURCE_DHCP);
33  else
34  mfib_table_lock(fib_index, proto, MFIB_SOURCE_DHCP);
35 }
36 
37 static void
39  u32 fib_index)
40 {
41  if (FIB_PROTOCOL_IP4 == proto)
42  fib_table_unlock(fib_index, proto, FIB_SOURCE_DHCP);
43  else
44  mfib_table_unlock(fib_index, proto, MFIB_SOURCE_DHCP);
45 }
46 
47  u32
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 
69 void
72  void *ctx)
73 {
75  dhcp_proxy_t * server;
76  u32 server_index, i;
77 
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 
91 void
94  void *ctx)
95 {
97  mfib_table_t *mfib;
98  dhcp_vss_t * vss;
99  u32 vss_index, i;
100  fib_table_t *fib;
101 
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 
110  if (FIB_PROTOCOL_IP4 == proto)
111  {
112  fib = fib_table_get(i, proto);
113 
114  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  }
124  }
125 }
126 
127 static u32
129  fib_protocol_t proto,
130  ip46_address_t *addr,
131  u32 server_table_id)
132 {
133  dhcp_server_t *server;
134  u32 ii, fib_index;
135 
136  vec_foreach_index(ii, proxy->dhcp_servers)
137  {
138  server = &proxy->dhcp_servers[ii];
139  fib_index = fib_table_find(proto, server_table_id);
140 
141  if (ip46_address_is_equal(&server->dhcp_server,
142  addr) &&
143  (server->server_fib_index == fib_index))
144  {
145  return (ii);
146  }
147  }
148  return (~0);
149 }
150 
151 int
153  u32 rx_fib_index,
154  ip46_address_t *addr,
155  u32 server_table_id)
156 {
158  dhcp_proxy_t *proxy = 0;
159 
160  proxy = dhcp_get_proxy(dpm, rx_fib_index, proto);
161 
162  if (NULL != proxy)
163  {
164  dhcp_server_t *server;
165  u32 index;
166 
167  index = dhcp_proxy_server_find(proxy, proto, addr, server_table_id);
168 
169  if (~0 != index)
170  {
171  server = &proxy->dhcp_servers[index];
173 
174  vec_del1(proxy->dhcp_servers, index);
175 
176  if (0 == vec_len(proxy->dhcp_servers))
177  {
178  /* no servers left, delete the proxy config */
179  dpm->dhcp_server_index_by_rx_fib_index[proto][rx_fib_index] = ~0;
180  vec_free(proxy->dhcp_servers);
181  pool_put (dpm->dhcp_servers[proto], proxy);
182  return (1);
183  }
184  }
185  }
186 
187  /* the proxy still exists */
188  return (0);
189 }
190 
191 int
193  ip46_address_t *addr,
194  ip46_address_t *src_address,
195  u32 rx_fib_index,
196  u32 server_table_id)
197 {
199  dhcp_proxy_t * proxy = 0;
200  int new = 0;
201 
202  proxy = dhcp_get_proxy(dpm, rx_fib_index, proto);
203 
204  if (NULL == proxy)
205  {
207  rx_fib_index,
208  ~0);
209 
210  pool_get (dpm->dhcp_servers[proto], proxy);
211  memset (proxy, 0, sizeof (*proxy));
212  new = 1;
213 
214  dpm->dhcp_server_index_by_rx_fib_index[proto][rx_fib_index] =
215  proxy - dpm->dhcp_servers[proto];
216 
217  proxy->dhcp_src_address = *src_address;
218  proxy->rx_fib_index = rx_fib_index;
219  }
220  else
221  {
222  if (~0 != dhcp_proxy_server_find(proxy, proto, addr, server_table_id))
223  {
224  return (new);
225  }
226  }
227 
228  dhcp_server_t server = {
229  .dhcp_server = *addr,
230  .server_fib_index = fib_table_find_or_create_and_lock(proto,
231  server_table_id,
233  };
234 
235  vec_add1(proxy->dhcp_servers, server);
236 
237  return (new);
238 }
239 
241 {
243  void *opaque;
246 
247 static int
249  void *arg)
250 {
252 
254  ctx->opaque,
255  ctx->context,
256  proxy);
257 
258  return (1);
259 }
260 
261 void
263  void *opaque,
264  u32 context)
265 {
267  .proto = proto,
268  .opaque = opaque,
269  .context = context,
270  };
272 }
273 
274 int
276  u32 rx_table_id,
277  void *ctx)
278 {
279  vlib_main_t * vm = ctx;
280 
281  vlib_cli_output (vm, "%=6d%=6d%=12d",
282  rx_table_id,
283  vss->oui,
284  vss->fib_id);
285 
286  return (1);
287 }
288 
290  u32 tbl_id,
291  u32 oui,
292  u32 fib_id,
293  int is_del)
294 {
296  dhcp_vss_t *v = NULL;
297  u32 rx_fib_index;
298  int rc = 0;
299 
300  if (proto == FIB_PROTOCOL_IP4)
301  rx_fib_index = fib_table_find_or_create_and_lock(proto, tbl_id,
303  else
304  rx_fib_index = mfib_table_find_or_create_and_lock(proto, tbl_id,
306  v = dhcp_get_vss_info(dm, rx_fib_index, proto);
307 
308  if (NULL != v)
309  {
310  if (is_del)
311  {
312  /* release the lock held on the table when the VSS
313  * info was created */
314  dhcp_proxy_rx_table_unlock (proto, rx_fib_index);
315 
316  pool_put (dm->vss[proto], v);
317  dm->vss_index_by_rx_fib_index[proto][rx_fib_index] = ~0;
318  }
319  else
320  {
321  /* this is a modify */
322  v->fib_id = fib_id;
323  v->oui = oui;
324  }
325  }
326  else
327  {
328  if (is_del)
329  rc = VNET_API_ERROR_NO_SUCH_ENTRY;
330  else
331  {
332  /* create a new entry */
334  rx_fib_index, ~0);
335 
336  /* hold a lock on the table whilst the VSS info exist */
337  pool_get (dm->vss[proto], v);
338  v->fib_id = fib_id;
339  v->oui = oui;
340 
341  dm->vss_index_by_rx_fib_index[proto][rx_fib_index] =
342  v - dm->vss[proto];
343  dhcp_proxy_rx_table_lock (proto, rx_fib_index);
344  }
345  }
346 
347  /* Release the lock taken during the create_or_lock at the start */
348  dhcp_proxy_rx_table_unlock (proto, rx_fib_index);
349 
350  return (rc);
351 }
u32 mfib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id, mfib_source_t src)
Get the index of the FIB for a Table-ID.
Definition: mfib_table.c:467
#define vec_foreach_index(var, v)
Iterate over vector indices.
static dhcp_vss_t * dhcp_get_vss_info(dhcp_proxy_main_t *dm, u32 rx_fib_index, fib_protocol_t proto)
Get the VSS data for the FIB index.
Definition: dhcp_proxy.h:237
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
void dhcp_vss_walk(fib_protocol_t proto, dhcp_vss_walk_fn_t fn, void *ctx)
Walk/Visit each DHCP proxy VSS.
Definition: dhcp_proxy.c:92
dhcp_server_t * dhcp_servers
The set of DHCP servers to which messages are relayed.
Definition: dhcp_proxy.h:90
void dhcp_proxy_walk(fib_protocol_t proto, dhcp_proxy_walk_fn_t fn, void *ctx)
Walk/Visit each DHCP proxy server.
Definition: dhcp_proxy.c:70
#define NULL
Definition: clib.h:55
dhcp_proxy_main_t dhcp_proxy_main
Shard 4/6 instance of DHCP main.
Definition: dhcp_proxy.c:25
int dhcp_vss_show_walk(dhcp_vss_t *vss, u32 rx_table_id, void *ctx)
Show (on CLI) a VSS config during a show walk.
Definition: dhcp_proxy.c:275
ip46_address_t dhcp_src_address
The source address to use in relayed messaes.
Definition: dhcp_proxy.h:105
The Virtual Sub-net Selection information for a given RX FIB.
Definition: dhcp_proxy.h:49
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:518
u32 * dhcp_server_index_by_rx_fib_index[DHCP_N_PROTOS]
Definition: dhcp_proxy.h:124
void dhcp_send_details(fib_protocol_t proto, void *opaque, u32 context, dhcp_proxy_t *proxy)
Send the details of a proxy session to the API client during a dump.
Definition: dhcp_api.c:122
u32 rx_fib_index
The FIB index (not the external Table-ID) in which the client is resides.
Definition: dhcp_proxy.h:111
static int dhcp_proxy_dump_walk(dhcp_proxy_t *proxy, void *arg)
Definition: dhcp_proxy.c:248
u32 oui
?? RFC doesn&#39;t say
Definition: dhcp_proxy.h:53
static void dhcp_proxy_rx_table_unlock(fib_protocol_t proto, u32 fib_index)
Definition: dhcp_proxy.c:38
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:225
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
void dhcp_proxy_dump(fib_protocol_t proto, void *opaque, u32 context)
Dump the proxy configs to the API.
Definition: dhcp_proxy.c:262
static dhcp_proxy_t * dhcp_get_proxy(dhcp_proxy_main_t *dm, u32 rx_fib_index, fib_protocol_t proto)
Get the DHCP proxy server data for the FIB index.
Definition: dhcp_proxy.h:258
u32 * vss_index_by_rx_fib_index[DHCP_N_PROTOS]
Definition: dhcp_proxy.h:132
int dhcp_proxy_server_add(fib_protocol_t proto, ip46_address_t *addr, ip46_address_t *src_address, u32 rx_fib_index, u32 server_table_id)
Add a new DHCP proxy server configuration.
Definition: dhcp_proxy.c:192
u32 fib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1025
dhcp_proxy_t * dhcp_servers[DHCP_N_PROTOS]
Definition: dhcp_proxy.h:121
u32 server_fib_index
The FIB index (not the external Table-ID) in which the server is reachable.
Definition: dhcp_proxy.h:75
Collection of global DHCP proxy data.
Definition: dhcp_proxy.h:119
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:458
struct dhcp4_proxy_dump_walk_ctx_t_ dhcp_proxy_dump_walk_cxt_t
void mfib_table_unlock(u32 fib_index, fib_protocol_t proto, mfib_source_t source)
Take a reference counting lock on the table.
Definition: mfib_table.c:558
#define v
Definition: acl.c:323
int(* dhcp_vss_walk_fn_t)(dhcp_vss_t *server, u32 rx_table_id, void *ctx)
Callback function invoked for each DHCP VSS entry return 0 to break the walk, non-zero otherwise...
Definition: dhcp_proxy.h:210
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:270
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:801
void mfib_table_lock(u32 fib_index, fib_protocol_t proto, mfib_source_t source)
Release a reference counting lock on the table.
Definition: mfib_table.c:587
void fib_table_unlock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Take a reference counting lock on the table.
Definition: fib_table.c:1177
u32 fib_id
VPN-ID.
Definition: dhcp_proxy.h:57
u32 ft_table_id
Table ID (hash key) for this FIB.
Definition: fib_table.h:50
vlib_main_t * vm
Definition: buffer.c:283
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:336
A representation of a single DHCP Server within a given VRF config.
Definition: dhcp_proxy.h:63
void fib_table_lock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Release a reference counting lock on the table.
Definition: fib_table.c:1206
int(* dhcp_proxy_walk_fn_t)(dhcp_proxy_t *server, void *ctx)
Callback function invoked for each DHCP proxy entry return 0 to break the walk, non-zero otherwise...
Definition: dhcp_proxy.h:196
ip46_address_t dhcp_server
The address of the DHCP server to which to relay the client&#39;s messages.
Definition: dhcp_proxy.h:69
unsigned int u32
Definition: types.h:88
long ctx[MAX_CONNS]
Definition: main.c:95
u32 fib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id, fib_source_t src)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1084
u32 mft_table_id
Table ID (hash key) for this FIB.
Definition: mfib_table.h:61
static void dhcp_proxy_rx_table_lock(fib_protocol_t proto, u32 fib_index)
Definition: dhcp_proxy.c:28
int dhcp_proxy_set_vss(fib_protocol_t proto, u32 tbl_id, u32 oui, u32 fib_id, int is_del)
Configure/set a new VSS info.
Definition: dhcp_proxy.c:289
static u32 dhcp_proxy_server_find(dhcp_proxy_t *proxy, fib_protocol_t proto, ip46_address_t *addr, u32 server_table_id)
Definition: dhcp_proxy.c:128
A DHCP proxy represenation fpr per-client VRF config.
Definition: dhcp_proxy.h:81
int dhcp_proxy_server_del(fib_protocol_t proto, u32 rx_fib_index, ip46_address_t *addr, u32 server_table_id)
Delete a DHCP proxy config.
Definition: dhcp_proxy.c:152
mfib_table_t * mfib_table_get(fib_node_index_t index, fib_protocol_t proto)
Get a pointer to a FIB table.
Definition: mfib_table.c:26
#define ip46_address_is_equal(a1, a2)
Definition: ip6_packet.h:82
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
DHCP.
Definition: fib_entry.h:82
dhcp_vss_t * vss[DHCP_N_PROTOS]
Definition: dhcp_proxy.h:129
fib_table_t * fib_table_get(fib_node_index_t index, fib_protocol_t proto)
Get a pointer to a FIB table.
Definition: fib_table.c:27
A protocol Independent IP multicast FIB table.
Definition: mfib_table.h:35
u32 dhcp_proxy_rx_table_get_table_id(fib_protocol_t proto, u32 fib_index)
Definition: dhcp_proxy.c:48
vhost_vring_addr_t addr
Definition: vhost-user.h:83
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:481
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:680
A protocol Independent FIB table.
Definition: fib_table.h:35