FD.io VPP  v18.07-rc0-415-g6c78436
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 {
30  if (FIB_PROTOCOL_IP4 == proto)
31  fib_table_lock (fib_index, proto, FIB_SOURCE_DHCP);
32  else
33  mfib_table_lock (fib_index, proto, MFIB_SOURCE_DHCP);
34 }
35 
36 static void
38 {
39  if (FIB_PROTOCOL_IP4 == proto)
40  fib_table_unlock (fib_index, proto, FIB_SOURCE_DHCP);
41  else
42  mfib_table_unlock (fib_index, proto, MFIB_SOURCE_DHCP);
43 }
44 
45 u32
47 {
48  if (FIB_PROTOCOL_IP4 == proto)
49  {
50  fib_table_t *fib;
51 
52  fib = fib_table_get (fib_index, proto);
53 
54  return (fib->ft_table_id);
55  }
56  else
57  {
58  mfib_table_t *mfib;
59 
60  mfib = mfib_table_get (fib_index, proto);
61 
62  return (mfib->mft_table_id);
63  }
64 }
65 
66 void
68 {
70  dhcp_proxy_t *server;
71  u32 server_index, i;
72 
74  {
75  server_index = dpm->dhcp_server_index_by_rx_fib_index[proto][i];
76  if (~0 == server_index)
77  continue;
78 
79  server = pool_elt_at_index (dpm->dhcp_servers[proto], server_index);
80 
81  if (!fn (server, ctx))
82  break;
83  }
84 }
85 
86 void
88 {
90  mfib_table_t *mfib;
91  dhcp_vss_t *vss;
92  u32 vss_index, i;
93  fib_table_t *fib;
94 
96  {
97  vss_index = dpm->vss_index_by_rx_fib_index[proto][i];
98  if (~0 == vss_index)
99  continue;
100 
101  vss = pool_elt_at_index (dpm->vss[proto], vss_index);
102 
103  if (FIB_PROTOCOL_IP4 == proto)
104  {
105  fib = fib_table_get (i, proto);
106 
107  if (!fn (vss, fib->ft_table_id, ctx))
108  break;
109  }
110  else
111  {
112  mfib = mfib_table_get (i, proto);
113 
114  if (!fn (vss, mfib->mft_table_id, ctx))
115  break;
116  }
117  }
118 }
119 
120 static u32
122  fib_protocol_t proto,
123  ip46_address_t * addr, u32 server_table_id)
124 {
125  dhcp_server_t *server;
126  u32 ii, fib_index;
127 
128  vec_foreach_index (ii, proxy->dhcp_servers)
129  {
130  server = &proxy->dhcp_servers[ii];
131  fib_index = fib_table_find (proto, server_table_id);
132 
133  if (ip46_address_is_equal (&server->dhcp_server,
134  addr) &&
135  (server->server_fib_index == fib_index))
136  {
137  return (ii);
138  }
139  }
140  return (~0);
141 }
142 
143 int
145  u32 rx_fib_index,
146  ip46_address_t * addr, u32 server_table_id)
147 {
149  dhcp_proxy_t *proxy = 0;
150 
151  proxy = dhcp_get_proxy (dpm, rx_fib_index, proto);
152 
153  if (NULL != proxy)
154  {
155  dhcp_server_t *server;
156  u32 index;
157 
158  index = dhcp_proxy_server_find (proxy, proto, addr, server_table_id);
159 
160  if (~0 != index)
161  {
162  server = &proxy->dhcp_servers[index];
164 
165  vec_del1 (proxy->dhcp_servers, index);
166 
167  if (0 == vec_len (proxy->dhcp_servers))
168  {
169  /* no servers left, delete the proxy config */
170  dpm->dhcp_server_index_by_rx_fib_index[proto][rx_fib_index] =
171  ~0;
172  vec_free (proxy->dhcp_servers);
173  pool_put (dpm->dhcp_servers[proto], proxy);
174  return (1);
175  }
176  }
177  }
178 
179  /* the proxy still exists */
180  return (0);
181 }
182 
183 int
185  ip46_address_t * addr,
186  ip46_address_t * src_address,
187  u32 rx_fib_index, u32 server_table_id)
188 {
190  dhcp_proxy_t *proxy = 0;
191  int new = 0;
192 
193  proxy = dhcp_get_proxy (dpm, rx_fib_index, proto);
194 
195  if (NULL == proxy)
196  {
198  rx_fib_index, ~0);
199 
200  pool_get (dpm->dhcp_servers[proto], proxy);
201  memset (proxy, 0, sizeof (*proxy));
202  new = 1;
203 
204  dpm->dhcp_server_index_by_rx_fib_index[proto][rx_fib_index] =
205  proxy - dpm->dhcp_servers[proto];
206 
207  proxy->dhcp_src_address = *src_address;
208  proxy->rx_fib_index = rx_fib_index;
209  }
210  else
211  {
212  if (~0 != dhcp_proxy_server_find (proxy, proto, addr, server_table_id))
213  {
214  return (new);
215  }
216  }
217 
218  dhcp_server_t server = {
219  .dhcp_server = *addr,
220  .server_fib_index = fib_table_find_or_create_and_lock (proto,
221  server_table_id,
223  };
224 
225  vec_add1 (proxy->dhcp_servers, server);
226 
227  return (new);
228 }
229 
231 {
233  void *opaque;
236 
237 static int
238 dhcp_proxy_dump_walk (dhcp_proxy_t * proxy, void *arg)
239 {
241 
242  dhcp_send_details (ctx->proto, ctx->opaque, ctx->context, proxy);
243 
244  return (1);
245 }
246 
247 void
249 {
251  .proto = proto,
252  .opaque = opaque,
253  .context = context,
254  };
255  dhcp_proxy_walk (proto, dhcp_proxy_dump_walk, &ctx);
256 }
257 
258 int
259 dhcp_vss_show_walk (dhcp_vss_t * vss, u32 rx_table_id, void *ctx)
260 {
261  vlib_main_t *vm = ctx;
262 
263  if (vss->vss_type == VSS_TYPE_VPN_ID)
264  {
265  u32 oui = ((u32) vss->vpn_id[0] << 16) + ((u32) vss->vpn_id[1] << 8)
266  + ((u32) vss->vpn_id[2]);
267  u32 fib_id = ((u32) vss->vpn_id[3] << 24) + ((u32) vss->vpn_id[4] << 16)
268  + ((u32) vss->vpn_id[5] << 8) + ((u32) vss->vpn_id[6]);
269  vlib_cli_output (vm, " fib_table: %d oui: %d vpn_index: %d",
270  rx_table_id, oui, fib_id);
271  }
272  else if (vss->vss_type == VSS_TYPE_ASCII)
273  vlib_cli_output (vm, " fib_table: %d vpn_id: %s",
274  rx_table_id, vss->vpn_ascii_id);
275  else
276  vlib_cli_output (vm, " fib_table: %d default global vpn", rx_table_id);
277 
278  return (1);
279 }
280 
281 void
283  u8 vss_type, u8 * vpn_ascii_id, u32 oui, u32 vpn_index)
284 {
285  v->vss_type = vss_type;
286  if (v->vpn_ascii_id)
287  {
288  if (v->vpn_ascii_id == (u8 *) ~ 0)
289  v->vpn_ascii_id = 0;
290  else
291  vec_free (v->vpn_ascii_id);
292  }
293 
294  if (vss_type == VSS_TYPE_ASCII)
295  v->vpn_ascii_id = vpn_ascii_id;
296  else if (vss_type == VSS_TYPE_VPN_ID)
297  {
298  v->vpn_id[0] = (oui >> 16) & 0xff;
299  v->vpn_id[1] = (oui >> 8) & 0xff;
300  v->vpn_id[2] = (oui >> 0) & 0xff;
301  v->vpn_id[3] = (vpn_index >> 24) & 0xff;
302  v->vpn_id[4] = (vpn_index >> 16) & 0xff;
303  v->vpn_id[5] = (vpn_index >> 8) & 0xff;
304  v->vpn_id[6] = (vpn_index >> 0) & 0xff;
305  }
306 }
307 
308 int
310  u32 tbl_id,
311  u8 vss_type,
312  u8 * vpn_ascii_id, u32 oui, u32 vpn_index, u8 is_del)
313 {
315  dhcp_vss_t *v = NULL;
316  u32 rx_fib_index;
317  int rc = 0;
318 
319  if (proto == FIB_PROTOCOL_IP4)
320  rx_fib_index = fib_table_find_or_create_and_lock (proto, tbl_id,
322  else
323  rx_fib_index = mfib_table_find_or_create_and_lock (proto, tbl_id,
325  v = dhcp_get_vss_info (dm, rx_fib_index, proto);
326 
327  if (NULL != v)
328  {
329  if (is_del)
330  {
331  /* release the lock held on the table when the VSS
332  * info was created */
333  dhcp_proxy_rx_table_unlock (proto, rx_fib_index);
334 
335  vec_free (v->vpn_ascii_id);
336  pool_put (dm->vss[proto], v);
337  dm->vss_index_by_rx_fib_index[proto][rx_fib_index] = ~0;
338  }
339  else
340  {
341  update_vss (v, vss_type, vpn_ascii_id, oui, vpn_index);
342  }
343  }
344  else
345  {
346  if (is_del)
347  rc = VNET_API_ERROR_NO_SUCH_ENTRY;
348  else
349  {
350  /* create a new entry */
352  rx_fib_index, ~0);
353 
354  /* hold a lock on the table whilst the VSS info exist */
355  pool_get (dm->vss[proto], v);
356  update_vss (v, vss_type, vpn_ascii_id, oui, vpn_index);
357  dm->vss_index_by_rx_fib_index[proto][rx_fib_index] =
358  v - dm->vss[proto];
359  dhcp_proxy_rx_table_lock (proto, rx_fib_index);
360  }
361  }
362 
363  /* Release the lock taken during the create_or_lock at the start */
364  dhcp_proxy_rx_table_unlock (proto, rx_fib_index);
365 
366  return (rc);
367 }
368 
369 /*
370  * fd.io coding-style-patch-verification: ON
371  *
372  * Local Variables:
373  * eval: (c-set-style "gnu")
374  * End:
375  */
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
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:87
dhcp_server_t * dhcp_servers
The set of DHCP servers to which messages are relayed.
Definition: dhcp_proxy.h:105
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:67
#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:259
ip46_address_t dhcp_src_address
The source address to use in relayed messaes.
Definition: dhcp_proxy.h:120
The Virtual Sub-net Selection information for a given RX FIB.
Definition: dhcp_proxy.h:51
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:523
int i
u32 * dhcp_server_index_by_rx_fib_index[DHCP_N_PROTOS]
Definition: dhcp_proxy.h:140
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:134
u32 rx_fib_index
The FIB index (not the external Table-ID) in which the client is resides.
Definition: dhcp_proxy.h:126
static int dhcp_proxy_dump_walk(dhcp_proxy_t *proxy, void *arg)
Definition: dhcp_proxy.c:238
u8 vss_type
VSS type as defined in RFC 6607: 0 for NVT ASCII VPN Identifier 1 for RFC 2685 VPN-ID of 7 octects - ...
Definition: dhcp_proxy.h:59
static void dhcp_proxy_rx_table_unlock(fib_protocol_t proto, u32 fib_index)
Definition: dhcp_proxy.c:37
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:227
unsigned char u8
Definition: types.h:56
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:248
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:257
#define VSS_TYPE_ASCII
Definition: dhcp_proxy.h:60
u32 * vss_index_by_rx_fib_index[DHCP_N_PROTOS]
Definition: dhcp_proxy.h:148
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:184
unsigned int u32
Definition: types.h:88
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:1056
dhcp_proxy_t * dhcp_servers[DHCP_N_PROTOS]
Definition: dhcp_proxy.h:137
u32 server_fib_index
The FIB index (not the external Table-ID) in which the server is reachable.
Definition: dhcp_proxy.h:89
Collection of global DHCP proxy data.
Definition: dhcp_proxy.h:134
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:461
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:491
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:213
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:273
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:806
int dhcp_proxy_set_vss(fib_protocol_t proto, u32 tbl_id, u8 vss_type, u8 *vpn_ascii_id, u32 oui, u32 vpn_index, u8 is_del)
Configure/set a new VSS info.
Definition: dhcp_proxy.c:309
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:1228
u8 * vpn_ascii_id
Type 0 ASCII VPN Identifier.
Definition: dhcp_proxy.h:71
u32 ft_table_id
Table ID (hash key) for this FIB.
Definition: fib_table.h:89
vlib_main_t * vm
Definition: buffer.c:294
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:339
A representation of a single DHCP Server within a given VRF config.
Definition: dhcp_proxy.h:77
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:1257
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:201
ip46_address_t dhcp_server
The address of the DHCP server to which to relay the client&#39;s messages.
Definition: dhcp_proxy.h:83
long ctx[MAX_CONNS]
Definition: main.c:126
void update_vss(dhcp_vss_t *v, u8 vss_type, u8 *vpn_ascii_id, u32 oui, u32 vpn_index)
Definition: dhcp_proxy.c:282
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:1115
u32 mft_table_id
Table ID (hash key) for this FIB.
Definition: mfib_table.h:66
static void dhcp_proxy_rx_table_lock(fib_protocol_t proto, u32 fib_index)
Definition: dhcp_proxy.c:28
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:121
A DHCP proxy represenation fpr per-client VRF config.
Definition: dhcp_proxy.h:95
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:144
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:87
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u8 vpn_id[7]
Type 1 VPN-ID.
Definition: dhcp_proxy.h:67
DHCP.
Definition: fib_entry.h:90
dhcp_vss_t * vss[DHCP_N_PROTOS]
Definition: dhcp_proxy.h:145
#define VSS_TYPE_VPN_ID
Definition: dhcp_proxy.h:61
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:46
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:486
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:681
A protocol Independent FIB table.
Definition: fib_table.h:69