FD.io VPP  v17.04-9-g99c0734
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);
33  else
34  mfib_table_lock(fib_index, proto);
35 }
36 
37 static void
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 
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];
172  fib_table_unlock (server->server_fib_index, proto);
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),
232  };
233 
234  vec_add1(proxy->dhcp_servers, server);
235 
236  return (new);
237 }
238 
240 {
242  void *opaque;
245 
246 static int
248  void *arg)
249 {
250  dhcp_proxy_dump_walk_cxt_t *ctx = arg;
251 
253  ctx->opaque,
254  ctx->context,
255  proxy);
256 
257  return (1);
258 }
259 
260 void
262  void *opaque,
263  u32 context)
264 {
266  .proto = proto,
267  .opaque = opaque,
268  .context = context,
269  };
271 }
272 
273 int
275  u32 rx_table_id,
276  void *ctx)
277 {
278  vlib_main_t * vm = ctx;
279 
280  vlib_cli_output (vm, "%=6d%=6d%=12d",
281  rx_table_id,
282  vss->oui,
283  vss->fib_id);
284 
285  return (1);
286 }
287 
289  u32 tbl_id,
290  u32 oui,
291  u32 fib_id,
292  int is_del)
293 {
295  dhcp_vss_t *v = NULL;
296  u32 rx_fib_index;
297  int rc = 0;
298 
299  if (proto == FIB_PROTOCOL_IP4)
300  rx_fib_index = fib_table_find_or_create_and_lock(proto, tbl_id);
301  else
302  rx_fib_index = mfib_table_find_or_create_and_lock(proto, tbl_id);
303  v = dhcp_get_vss_info(dm, rx_fib_index, proto);
304 
305  if (NULL != v)
306  {
307  if (is_del)
308  {
309  /* release the lock held on the table when the VSS
310  * info was created */
311  dhcp_proxy_rx_table_unlock (proto, rx_fib_index);
312 
313  pool_put (dm->vss[proto], v);
314  dm->vss_index_by_rx_fib_index[proto][rx_fib_index] = ~0;
315  }
316  else
317  {
318  /* this is a modify */
319  v->fib_id = fib_id;
320  v->oui = oui;
321  }
322  }
323  else
324  {
325  if (is_del)
326  rc = VNET_API_ERROR_NO_SUCH_ENTRY;
327  else
328  {
329  /* create a new entry */
331  rx_fib_index, ~0);
332 
333  /* hold a lock on the table whilst the VSS info exist */
334  pool_get (dm->vss[proto], v);
335  v->fib_id = fib_id;
336  v->oui = oui;
337 
338  dm->vss_index_by_rx_fib_index[proto][rx_fib_index] =
339  v - dm->vss[proto];
340  dhcp_proxy_rx_table_lock (proto, rx_fib_index);
341  }
342  }
343 
344  /* Release the lock taken during the create_or_lock at the start */
345  dhcp_proxy_rx_table_unlock (proto, rx_fib_index);
346 
347  return (rc);
348 }
#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:343
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
void fib_table_lock(u32 fib_index, fib_protocol_t proto)
Release a reference counting lock on the table.
Definition: fib_table.c:1072
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
void mfib_table_unlock(u32 fib_index, fib_protocol_t proto)
Take a reference counting lock on the table.
Definition: mfib_table.c:468
#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:274
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:522
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:247
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:200
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:261
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:938
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
void fib_table_unlock(u32 fib_index, fib_protocol_t proto)
Take a reference counting lock on the table.
Definition: fib_table.c:1058
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:397
struct dhcp4_proxy_dump_walk_ctx_t_ dhcp_proxy_dump_walk_cxt_t
#define v
Definition: acl.c:246
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:241
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:805
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:56
vlib_main_t * vm
Definition: buffer.c:276
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
A representation of a single DHCP Server within a given VRF config.
Definition: dhcp_proxy.h:63
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
u32 fib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:954
u32 mft_table_id
Table ID (hash key) for this FIB.
Definition: mfib_table.h:55
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:288
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
u32 mfib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: mfib_table.c:420
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)
void mfib_table_lock(u32 fib_index, fib_protocol_t proto)
Release a reference counting lock on the table.
Definition: mfib_table.c:483
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:29
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:84
#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:485
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:577
A protocol Independent FIB table.
Definition: fib_table.h:29