FD.io VPP  v17.04-9-g99c0734
Vector Packet Processing
dhcp6_proxy_node.c
Go to the documentation of this file.
1 /*
2  * dhcp6_proxy_node.c: dhcpv6 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 <vlib/vlib.h>
19 #include <vnet/pg/pg.h>
20 #include <vnet/dhcp/dhcp_proxy.h>
21 #include <vnet/dhcp/dhcp6_packet.h>
22 #include <vnet/fib/ip6_fib.h>
23 #include <vnet/mfib/mfib_table.h>
24 #include <vnet/mfib/ip6_mfib.h>
25 
26 static char * dhcpv6_proxy_error_strings[] = {
27 #define dhcpv6_proxy_error(n,s) s,
29 #undef dhcpv6_proxy_error
30 };
31 
32 #define foreach_dhcpv6_proxy_to_server_input_next \
33  _ (DROP, "error-drop") \
34  _ (LOOKUP, "ip6-lookup") \
35  _ (SEND_TO_CLIENT, "dhcpv6-proxy-to-client")
36 
37 
38 typedef enum {
39 #define _(s,n) DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_##s,
41 #undef _
44 
45 typedef struct {
46  /* 0 => to server, 1 => to client */
47  int which;
48  u8 packet_data[64];
53 
56 
57 /* all DHCP servers address */
60 
61 static u8 *
62 format_dhcpv6_proxy_trace (u8 * s, va_list * args)
63 {
64  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
65  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
66  dhcpv6_proxy_trace_t * t = va_arg (*args, dhcpv6_proxy_trace_t *);
67 
68  if (t->which == 0)
69  s = format (s, "DHCPV6 proxy: sent to server %U",
71  else
72  s = format (s, "DHCPV6 proxy: sent to client from %U",
74  if (t->error != (u32)~0)
75  s = format (s, " error: %s\n", dhcpv6_proxy_error_strings[t->error]);
76 
77  s = format (s, " original_sw_if_index: %d, sw_if_index: %d\n",
79 
80  return s;
81 }
82 
83 static u8 *
85 {
86  dhcpv6_header_t * h = va_arg (*args, dhcpv6_header_t *);
87  u32 max_header_bytes = va_arg (*args, u32);
88  u32 header_bytes;
89 
90  header_bytes = sizeof (h[0]);
91  if (max_header_bytes != 0 && header_bytes > max_header_bytes)
92  return format (s, "dhcpv6 header truncated");
93 
94  s = format (s, "DHCPV6 Proxy");
95 
96  return s;
97 }
98 /* get first interface address */
99 static ip6_address_t *
101 {
102  ip_lookup_main_t * lm = &im->lookup_main;
103  ip_interface_address_t * ia = 0;
104  ip6_address_t * result = 0;
105 
106  foreach_ip_interface_address (lm, ia, sw_if_index,
107  1 /* honor unnumbered */,
108  ({
110  if ((a->as_u8[0] & 0xe0) == 0x20 ||
111  (a->as_u8[0] & 0xfe) == 0xfc) {
112  result = a;
113  break;
114  }
115  }));
116  return result;
117 }
118 
119 static inline void copy_ip6_address (ip6_address_t *dst,
120  ip6_address_t *src)
121 {
122  dst->as_u64[0] = src->as_u64[0];
123  dst->as_u64[1] = src->as_u64[1];
124 }
125 
126 static uword
128  vlib_node_runtime_t * node,
129  vlib_frame_t * from_frame)
130 {
131  u32 n_left_from, next_index, * from, * to_next;
133  from = vlib_frame_vector_args (from_frame);
134  n_left_from = from_frame->n_vectors;
135  u32 pkts_to_server=0, pkts_to_client=0, pkts_no_server=0;
136  u32 pkts_no_interface_address=0, pkts_no_exceeding_max_hop=0;
137  u32 pkts_no_src_address=0;
138  u32 pkts_wrong_msg_type=0;
139  u32 pkts_too_big=0;
140  ip6_main_t * im = &ip6_main;
141  ip6_address_t * src;
142  int bogus_length;
143  dhcp_proxy_t *proxy;
144  dhcp_server_t *server;
145  u32 rx_fib_idx = 0, server_fib_idx = 0;
146 
147  next_index = node->cached_next_index;
148 
149  while (n_left_from > 0)
150  {
151  u32 n_left_to_next;
152 
153  vlib_get_next_frame (vm, node, next_index,
154  to_next, n_left_to_next);
155 
156  while (n_left_from > 0 && n_left_to_next > 0)
157  {
158  vnet_main_t *vnm = vnet_get_main();
159  u32 sw_if_index = 0;
160  u32 rx_sw_if_index = 0;
161  vnet_sw_interface_t *swif;
162  u32 bi0;
163  vlib_buffer_t * b0;
164  udp_header_t * u0, *u1;
165  dhcpv6_header_t * h0; // client msg hdr
166  ip6_header_t * ip0, *ip1;
167  ip6_address_t _ia0, *ia0=&_ia0;
168  u32 next0;
169  u32 error0 = (u32) ~0;
170  dhcpv6_option_t *fwd_opt;
171  dhcpv6_relay_hdr_t *r1;
172  u16 len;
173  dhcpv6_int_id_t *id1;
174  dhcpv6_vss_t *vss1;
175  dhcpv6_client_mac_t *cmac; // client mac
176  ethernet_header_t * e_h0;
177  u8 client_src_mac[6];
179  dhcp_vss_t *vss;
180  u8 is_solicit = 0;
181 
182  bi0 = from[0];
183  from += 1;
184  n_left_from -= 1;
185 
186  b0 = vlib_get_buffer (vm, bi0);
187 
188  h0 = vlib_buffer_get_current (b0);
189 
190  /*
191  * udp_local hands us the DHCPV6 header.
192  */
193  u0 = (void *)h0 -(sizeof(*u0));
194  ip0 = (void *)u0 -(sizeof(*ip0));
195  e_h0 = (void *)ip0 - ethernet_buffer_header_size(b0);
196 
197  clib_memcpy(client_src_mac, e_h0->src_address, 6);
198 
199  switch (h0->u.msg_type) {
200  case DHCPV6_MSG_SOLICIT:
201  case DHCPV6_MSG_REQUEST:
202  case DHCPV6_MSG_CONFIRM:
203  case DHCPV6_MSG_RENEW:
204  case DHCPV6_MSG_REBIND:
205  case DHCPV6_MSG_RELEASE:
206  case DHCPV6_MSG_DECLINE:
209  /* send to server */
210  break;
212  /* send to client */
213  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_SEND_TO_CLIENT;
214  error0 = 0;
215  pkts_to_client++;
216  goto do_enqueue;
217  default:
218  /* drop the packet */
219  pkts_wrong_msg_type++;
220  error0 = DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE;
221  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
222  goto do_trace;
223 
224  }
225 
226  /* Send to DHCPV6 server via the configured FIB */
227  rx_sw_if_index = sw_if_index = vnet_buffer(b0)->sw_if_index[VLIB_RX];
228  rx_fib_idx = im->mfib_index_by_sw_if_index [rx_sw_if_index];
229  proxy = dhcp_get_proxy(dpm, rx_fib_idx, FIB_PROTOCOL_IP6);
230 
231  if (PREDICT_FALSE (NULL == proxy))
232  {
233  error0 = DHCPV6_PROXY_ERROR_NO_SERVER;
234  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
235  pkts_no_server++;
236  goto do_trace;
237  }
238 
239  server = &proxy->dhcp_servers[0];
240  server_fib_idx = server->server_fib_index;
241  vnet_buffer(b0)->sw_if_index[VLIB_TX] = server_fib_idx;
242 
243 
244  /* relay-option header pointer */
245  vlib_buffer_advance(b0, -(sizeof(*fwd_opt)));
246  fwd_opt = vlib_buffer_get_current(b0);
247  /* relay message header pointer */
248  vlib_buffer_advance(b0, -(sizeof(*r1)));
249  r1 = vlib_buffer_get_current(b0);
250 
251  vlib_buffer_advance(b0, -(sizeof(*u1)));
252  u1 = vlib_buffer_get_current(b0);
253 
254  vlib_buffer_advance(b0, -(sizeof(*ip1)));
255  ip1 = vlib_buffer_get_current(b0);
256 
257  /* fill in all that rubbish... */
258  len = clib_net_to_host_u16(u0->length) - sizeof(udp_header_t);
259  copy_ip6_address(&r1->peer_addr, &ip0->src_address);
260 
261  r1->msg_type = DHCPV6_MSG_RELAY_FORW;
262  fwd_opt->length = clib_host_to_net_u16(len);
263  fwd_opt->option = clib_host_to_net_u16(DHCPV6_OPTION_RELAY_MSG);
264 
265  r1->hop_count++;
266  r1->hop_count = (h0->u.msg_type != DHCPV6_MSG_RELAY_FORW) ? 0 : r1->hop_count;
267 
268  if (PREDICT_FALSE(r1->hop_count >= HOP_COUNT_LIMIT))
269  {
271  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
272  pkts_no_exceeding_max_hop++;
273  goto do_trace;
274  }
275 
276 
277  /* If relay-fwd and src address is site or global unicast address */
278  if (h0->u.msg_type == DHCPV6_MSG_RELAY_FORW &&
279  ((ip0->src_address.as_u8[0] & 0xe0) == 0x20 ||
280  (ip0->src_address.as_u8[0] & 0xfe) == 0xfc))
281  {
282  /* Set link address to zero */
283  r1->link_addr.as_u64[0] = 0;
284  r1->link_addr.as_u64[1] = 0;
285  goto link_address_set;
286  }
287 
288  /* if receiving interface is unnumbered, use receiving interface
289  * IP address as link address, otherwise use the loopback interface
290  * IP address as link address.
291  */
292 
293  swif = vnet_get_sw_interface (vnm, rx_sw_if_index);
295  sw_if_index = swif->unnumbered_sw_if_index;
296 
298  if (ia0 == 0)
299  {
300  error0 = DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS;
301  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
302  pkts_no_interface_address++;
303  goto do_trace;
304  }
305 
306  copy_ip6_address(&r1->link_addr, ia0);
307 
308  link_address_set:
310 
311  if ((b0->current_length+sizeof(*id1)+sizeof(*vss1)+sizeof(*cmac))
312  > fl->n_data_bytes)
313  {
314  error0 = DHCPV6_PROXY_ERROR_PKT_TOO_BIG;
315  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
316  pkts_too_big++;
317  goto do_trace;
318  }
319 
320  id1 = (dhcpv6_int_id_t *) (((uword) ip1) + b0->current_length);
321  b0->current_length += (sizeof (*id1));
322 
323  id1->opt.option = clib_host_to_net_u16(DHCPV6_OPTION_INTERFACE_ID);
324  id1->opt.length = clib_host_to_net_u16(sizeof(rx_sw_if_index));
325  id1->int_idx = clib_host_to_net_u32(rx_sw_if_index);
326 
327  u1->length =0;
328  if (h0->u.msg_type != DHCPV6_MSG_RELAY_FORW)
329  {
330  cmac = (dhcpv6_client_mac_t *) (((uword) ip1) + b0->current_length);
331  b0->current_length += (sizeof (*cmac));
332  cmac->opt.length =clib_host_to_net_u16(sizeof(*cmac) -
333  sizeof(cmac->opt));
334  cmac->opt.option = clib_host_to_net_u16(DHCPV6_OPTION_CLIENT_LINK_LAYER_ADDRESS);
335  cmac->link_type = clib_host_to_net_u16(1); // ethernet
336  clib_memcpy(cmac->data, client_src_mac, 6);
337  u1->length += sizeof(*cmac);
338  }
339 
340  vss = dhcp_get_vss_info(dpm, rx_fib_idx, FIB_PROTOCOL_IP6);
341 
342  if (NULL != vss) {
343  vss1 = (dhcpv6_vss_t *) (((uword) ip1) + b0->current_length);
344  b0->current_length += (sizeof (*vss1));
345  vss1->opt.length =clib_host_to_net_u16(sizeof(*vss1) -
346  sizeof(vss1->opt));
347  vss1->opt.option = clib_host_to_net_u16(DHCPV6_OPTION_VSS);
348  vss1->data[0] = 1; // type
349  vss1->data[1] = vss->oui >>16 & 0xff;
350  vss1->data[2] = vss->oui >>8 & 0xff;
351  vss1->data[3] = vss->oui & 0xff;
352  vss1->data[4] = vss->fib_id >> 24 & 0xff;
353  vss1->data[5] = vss->fib_id >> 16 & 0xff;
354  vss1->data[6] = vss->fib_id >> 8 & 0xff;
355  vss1->data[7] = vss->fib_id & 0xff;
356  u1->length += sizeof(*vss1);
357  }
358 
359  pkts_to_server++;
360  u1->checksum = 0;
361  u1->src_port = clib_host_to_net_u16(UDP_DST_PORT_dhcpv6_to_client);
362  u1->dst_port = clib_host_to_net_u16(UDP_DST_PORT_dhcpv6_to_server);
363 
364  u1->length =
365  clib_host_to_net_u16( clib_net_to_host_u16(fwd_opt->length) +
366  sizeof(*r1) + sizeof(*fwd_opt) +
367  sizeof(*u1) + sizeof(*id1) + u1->length);
368 
369  memset(ip1, 0, sizeof(*ip1));
370  ip1->ip_version_traffic_class_and_flow_label = 0x60;
371  ip1->payload_length = u1->length;
372  ip1->protocol = PROTO_UDP;
373  ip1->hop_limit = HOP_COUNT_LIMIT;
374  src = ((server->dhcp_server.ip6.as_u64[0] ||
375  server->dhcp_server.ip6.as_u64[1]) ?
376  &server->dhcp_server.ip6 :
377  &all_dhcpv6_server_address);
378  copy_ip6_address(&ip1->dst_address, src);
379 
380 
382  (&ip6_main, vnet_buffer(b0)->sw_if_index[VLIB_RX]);
383 
384  src = (proxy->dhcp_src_address.ip6.as_u64[0] ||
385  proxy->dhcp_src_address.ip6.as_u64[1]) ?
386  &proxy->dhcp_src_address.ip6 : ia0;
387  if (ia0 == 0)
388  {
389  error0 = DHCPV6_PROXY_ERROR_NO_SRC_ADDRESS;
390  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
391  pkts_no_src_address++;
392  goto do_trace;
393  }
394 
395  copy_ip6_address (&ip1->src_address, src);
396 
397 
399  &bogus_length);
400  ASSERT(bogus_length == 0);
401 
402  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP;
403 
404  is_solicit = (DHCPV6_MSG_SOLICIT == h0->u.msg_type);
405 
406  /*
407  * If we have multiple servers configured and this is the
408  * client's discover message, then send copies to each of
409  * those servers
410  */
411  if (is_solicit && vec_len(proxy->dhcp_servers) > 1)
412  {
413  u32 ii;
414 
415  for (ii = 1; ii < vec_len(proxy->dhcp_servers); ii++)
416  {
417  vlib_buffer_t *c0;
418  u32 ci0;
419 
420  c0 = vlib_buffer_copy(vm, b0);
421  ci0 = vlib_get_buffer_index(vm, c0);
422  server = &proxy->dhcp_servers[ii];
423 
424  ip0 = vlib_buffer_get_current (c0);
425 
426  src = ((server->dhcp_server.ip6.as_u64[0] ||
427  server->dhcp_server.ip6.as_u64[1]) ?
428  &server->dhcp_server.ip6 :
429  &all_dhcpv6_server_address);
430  copy_ip6_address(&ip1->dst_address, src);
431 
432  to_next[0] = ci0;
433  to_next += 1;
434  n_left_to_next -= 1;
435 
436  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
437  to_next, n_left_to_next,
438  ci0, next0);
439 
441  {
443 
444  tr = vlib_add_trace (vm, node, c0, sizeof (*tr));
445  tr->which = 0; /* to server */
446  tr->error = error0;
447  tr->original_sw_if_index = rx_sw_if_index;
448  tr->sw_if_index = sw_if_index;
449  if (next0 == DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP)
451  &server->dhcp_server.ip6);
452  }
453 
454  if (PREDICT_FALSE(0 == n_left_to_next))
455  {
456  vlib_put_next_frame (vm, node, next_index,
457  n_left_to_next);
458  vlib_get_next_frame (vm, node, next_index,
459  to_next, n_left_to_next);
460  }
461  }
462  }
463 
464  do_trace:
466  {
467  dhcpv6_proxy_trace_t *tr = vlib_add_trace (vm, node,
468  b0, sizeof (*tr));
469  tr->which = 0; /* to server */
470  tr->error = error0;
471  tr->original_sw_if_index = rx_sw_if_index;
472  tr->sw_if_index = sw_if_index;
473  if (DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP == next0)
474  copy_ip6_address((ip6_address_t *)&tr->packet_data[0], &server->dhcp_server.ip6);
475  }
476 
477  do_enqueue:
478  to_next[0] = bi0;
479  to_next += 1;
480  n_left_to_next -= 1;
481 
482  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
483  to_next, n_left_to_next,
484  bi0, next0);
485  }
486 
487  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
488  }
489 
491  DHCPV6_PROXY_ERROR_RELAY_TO_CLIENT,
492  pkts_to_client);
494  DHCPV6_PROXY_ERROR_RELAY_TO_SERVER,
495  pkts_to_server);
497  DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS,
498  pkts_no_interface_address);
500  DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE,
501  pkts_wrong_msg_type);
503  DHCPV6_PROXY_ERROR_NO_SRC_ADDRESS,
504  pkts_no_src_address);
506  DHCPV6_PROXY_ERROR_PKT_TOO_BIG,
507  pkts_too_big);
508  return from_frame->n_vectors;
509 }
510 
512  .function = dhcpv6_proxy_to_server_input,
513  .name = "dhcpv6-proxy-to-server",
514  /* Takes a vector of packets. */
515  .vector_size = sizeof (u32),
516 
517  .n_errors = DHCPV6_PROXY_N_ERROR,
518  .error_strings = dhcpv6_proxy_error_strings,
519 
520  .n_next_nodes = DHCPV6_PROXY_TO_SERVER_INPUT_N_NEXT,
521  .next_nodes = {
522 #define _(s,n) [DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_##s] = n,
524 #undef _
525  },
526 
528  .format_trace = format_dhcpv6_proxy_trace,
529 #if 0
530  .unformat_buffer = unformat_dhcpv6_proxy_header,
531 #endif
532 };
533 
534 static uword
536  vlib_node_runtime_t * node,
537  vlib_frame_t * from_frame)
538 {
539 
540  u32 n_left_from, * from;
543  dhcp_proxy_t *proxy;
544  dhcp_server_t *server;
545  vnet_main_t * vnm = vnet_get_main();
546  int bogus_length;
547 
548  from = vlib_frame_vector_args (from_frame);
549  n_left_from = from_frame->n_vectors;
550 
551  while (n_left_from > 0)
552  {
553  u32 bi0;
554  vlib_buffer_t * b0;
555  udp_header_t * u0, *u1=0;
556  dhcpv6_relay_hdr_t * h0;
557  ip6_header_t * ip1 = 0, *ip0;
558  ip6_address_t _ia0, * ia0 = &_ia0;
559  ip6_address_t client_address;
561  ethernet_header_t *mac0;
562  vnet_hw_interface_t *hi0;
563  vlib_frame_t *f0;
564  u32 * to_next0;
565  u32 sw_if_index = ~0;
566  u32 original_sw_if_index = ~0;
567  vnet_sw_interface_t *si0;
568  u32 error0 = (u32)~0;
569  vnet_sw_interface_t *swif;
570  dhcpv6_option_t *r0 = 0, *o;
571  u16 len = 0;
572  u8 interface_opt_flag = 0;
573  u8 relay_msg_opt_flag = 0;
574  ip6_main_t * im = &ip6_main;
575  u32 server_fib_idx, client_fib_idx;
576 
577  bi0 = from[0];
578  from += 1;
579  n_left_from -= 1;
580 
581  b0 = vlib_get_buffer (vm, bi0);
582  h0 = vlib_buffer_get_current (b0);
583 
584  if (DHCPV6_MSG_RELAY_REPL != h0->msg_type)
585  {
586  error0 = DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE;
587 
588  drop_packet:
590  error0, 1);
591 
593  to_next0 = vlib_frame_vector_args (f0);
594  to_next0[0] = bi0;
595  f0->n_vectors = 1;
597  goto do_trace;
598  }
599  /* hop count seems not need to be checked */
600  if (HOP_COUNT_LIMIT < h0->hop_count)
601  {
603  goto drop_packet;
604  }
605  u0 = (void *)h0 -(sizeof(*u0));
606  ip0 = (void *)u0 -(sizeof(*ip0));
607 
608  vlib_buffer_advance (b0, sizeof(*h0));
609  o = vlib_buffer_get_current (b0);
610 
611  /* Parse through TLVs looking for option 18 (DHCPV6_OPTION_INTERFACE_ID)
612  _and_ option 9 (DHCPV6_OPTION_RELAY_MSG) option which must be there.
613  Currently assuming no other options need to be processed
614  The interface-ID is the FIB number we need
615  to track down the client-facing interface */
616 
617  while ((u8 *) o < (b0->data + b0->current_data + b0->current_length))
618  {
619  if (DHCPV6_OPTION_INTERFACE_ID == clib_net_to_host_u16(o->option))
620  {
621  interface_opt_flag = 1;
622  if (clib_net_to_host_u16(o->length) == sizeof(sw_if_index))
623  sw_if_index = clib_net_to_host_u32(((dhcpv6_int_id_t*)o)->int_idx);
624  if (sw_if_index >= vec_len (im->fib_index_by_sw_if_index))
625  {
626  error0 = DHCPV6_PROXY_ERROR_WRONG_INTERFACE_ID_OPTION;
627  goto drop_packet;
628  }
629  }
630  if (DHCPV6_OPTION_RELAY_MSG == clib_net_to_host_u16(o->option))
631  {
632  relay_msg_opt_flag = 1;
633  r0 = vlib_buffer_get_current (b0);
634  }
635  if ((relay_msg_opt_flag == 1) && (interface_opt_flag == 1))
636  break;
637  vlib_buffer_advance (b0, sizeof(*o) + clib_net_to_host_u16(o->length));
638  o = (dhcpv6_option_t *) (((uword) o) + clib_net_to_host_u16(o->length) + sizeof(*o));
639  }
640 
641  if ((relay_msg_opt_flag == 0) || (r0 == 0))
642  {
643  error0 = DHCPV6_PROXY_ERROR_NO_RELAY_MESSAGE_OPTION;
644  goto drop_packet;
645  }
646 
647  if ((u32)~0 == sw_if_index)
648  {
649  error0 = DHCPV6_PROXY_ERROR_NO_CIRCUIT_ID_OPTION;
650  goto drop_packet;
651  }
652 
653  //Advance buffer to start of encapsulated DHCPv6 message
654  vlib_buffer_advance (b0, sizeof(*r0));
655 
656  client_fib_idx = im->mfib_index_by_sw_if_index[sw_if_index];
657  proxy = dhcp_get_proxy(dm, client_fib_idx, FIB_PROTOCOL_IP6);
658 
659  if (NULL == proxy)
660  {
661  error0 = DHCPV6_PROXY_ERROR_NO_SERVER;
662  goto drop_packet;
663  }
664 
665  server_fib_idx = im->fib_index_by_sw_if_index
666  [vnet_buffer(b0)->sw_if_index[VLIB_RX]];
667 
668  vec_foreach(server, proxy->dhcp_servers)
669  {
670  if (server_fib_idx == server->server_fib_index &&
671  ip0->src_address.as_u64[0] == server->dhcp_server.ip6.as_u64[0] &&
672  ip0->src_address.as_u64[1] == server->dhcp_server.ip6.as_u64[1])
673  {
674  goto server_found;
675  }
676  }
677 
678  //drop packet if not from server with configured address or FIB
679  error0 = DHCPV6_PROXY_ERROR_BAD_SVR_FIB_OR_ADDRESS;
680  goto drop_packet;
681 
682  server_found:
683  vnet_buffer (b0)->sw_if_index[VLIB_TX] = original_sw_if_index
684  = sw_if_index;
685 
686  swif = vnet_get_sw_interface (vnm, original_sw_if_index);
688  sw_if_index = swif->unnumbered_sw_if_index;
689 
690 
691  /*
692  * udp_local hands us the DHCPV6 header, need udp hdr,
693  * ip hdr to relay to client
694  */
695  vlib_buffer_advance (b0, -(sizeof(*u1)));
696  u1 = vlib_buffer_get_current (b0);
697 
698  vlib_buffer_advance (b0, -(sizeof(*ip1)));
699  ip1 = vlib_buffer_get_current (b0);
700 
701  copy_ip6_address(&client_address, &h0->peer_addr);
702 
703  ia0 = ip6_interface_first_address (&ip6_main, sw_if_index);
704  if (ia0 == 0)
705  {
706  error0 = DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS;
707  goto drop_packet;
708  }
709 
710  len = clib_net_to_host_u16(r0->length);
711  memset(ip1, 0, sizeof(*ip1));
712  copy_ip6_address(&ip1->dst_address, &client_address);
713  u1->checksum = 0;
714  u1->src_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcpv6_to_server);
715  u1->dst_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcpv6_to_client);
716  u1->length = clib_host_to_net_u16 (len + sizeof(udp_header_t));
717 
719  ip0->ip_version_traffic_class_and_flow_label &
720  0x00000fff;
721  ip1->payload_length = u1->length;
722  ip1->protocol = PROTO_UDP;
723  ip1->hop_limit = HOP_COUNT_LIMIT;
724  copy_ip6_address(&ip1->src_address, ia0);
725 
727  &bogus_length);
728  ASSERT(bogus_length == 0);
729 
730  vlib_buffer_advance (b0, -(sizeof(ethernet_header_t)));
731  si0 = vnet_get_sw_interface (vnm, original_sw_if_index);
732  if (si0->type == VNET_SW_INTERFACE_TYPE_SUB)
733  vlib_buffer_advance (b0, -4 /* space for VLAN tag */);
734 
735  mac0 = vlib_buffer_get_current (b0);
736 
737  hi0 = vnet_get_sup_hw_interface (vnm, original_sw_if_index);
738  ei0 = pool_elt_at_index (em->interfaces, hi0->hw_instance);
739  clib_memcpy (mac0->src_address, ei0->address, sizeof (ei0->address));
740  memset (&mac0->dst_address, 0xff, sizeof (mac0->dst_address));
741  mac0->type = (si0->type == VNET_SW_INTERFACE_TYPE_SUB) ?
742  clib_net_to_host_u16(0x8100) : clib_net_to_host_u16 (0x86dd);
743 
744  if (si0->type == VNET_SW_INTERFACE_TYPE_SUB)
745  {
746  u32 * vlan_tag = (u32 *)(mac0+1);
747  u32 tmp;
748  tmp = (si0->sub.id << 16) | 0x0800;
749  *vlan_tag = clib_host_to_net_u32 (tmp);
750  }
751 
752  /* $$$ consider adding a dynamic next to the graph node, for performance */
754  to_next0 = vlib_frame_vector_args (f0);
755  to_next0[0] = bi0;
756  f0->n_vectors = 1;
758 
759  do_trace:
761  {
762  dhcpv6_proxy_trace_t *tr = vlib_add_trace (vm, node,
763  b0, sizeof (*tr));
764  tr->which = 1; /* to client */
765  if (ia0)
767  tr->error = error0;
768  tr->original_sw_if_index = original_sw_if_index;
769  tr->sw_if_index = sw_if_index;
770  }
771  }
772  return from_frame->n_vectors;
773 
774 }
775 
777  .function = dhcpv6_proxy_to_client_input,
778  .name = "dhcpv6-proxy-to-client",
779  /* Takes a vector of packets. */
780  .vector_size = sizeof (u32),
781 
782  .n_errors = DHCPV6_PROXY_N_ERROR,
783  .error_strings = dhcpv6_proxy_error_strings,
785  .format_trace = format_dhcpv6_proxy_trace,
786 #if 0
787  .unformat_buffer = unformat_dhcpv6_proxy_header,
788 #endif
789 };
790 
791 static clib_error_t *
793 {
795  vlib_node_t * error_drop_node;
796 
797  error_drop_node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
798  dm->error_drop_node_index = error_drop_node->index;
799 
800  /* RFC says this is the dhcpv6 server address */
801  all_dhcpv6_server_address.as_u64[0] = clib_host_to_net_u64 (0xFF05000000000000);
802  all_dhcpv6_server_address.as_u64[1] = clib_host_to_net_u64 (0x00010003);
803 
804  /* RFC says this is the server and agent address */
805  all_dhcpv6_server_relay_agent_address.as_u64[0] = clib_host_to_net_u64 (0xFF02000000000000);
806  all_dhcpv6_server_relay_agent_address.as_u64[1] = clib_host_to_net_u64 (0x00010002);
807 
808  udp_register_dst_port (vm, UDP_DST_PORT_dhcpv6_to_client,
809  dhcpv6_proxy_to_client_node.index, 0 /* is_ip6 */);
810 
811  udp_register_dst_port (vm, UDP_DST_PORT_dhcpv6_to_server,
812  dhcpv6_proxy_to_server_node.index, 0 /* is_ip6 */);
813 
814  return 0;
815 }
816 
818 
819 int
820 dhcp6_proxy_set_server (ip46_address_t *addr,
821  ip46_address_t *src_addr,
822  u32 rx_table_id,
823  u32 server_table_id,
824  int is_del)
825 {
826  u32 rx_fib_index = 0;
827  int rc = 0;
828 
829  const mfib_prefix_t all_dhcp_servers = {
830  .fp_len = 128,
831  .fp_proto = FIB_PROTOCOL_IP6,
832  .fp_grp_addr = {
834  }
835  };
836 
837  if (ip46_address_is_zero(addr))
838  return VNET_API_ERROR_INVALID_DST_ADDRESS;
839 
840  if (ip46_address_is_zero(src_addr))
841  return VNET_API_ERROR_INVALID_SRC_ADDRESS;
842 
844  rx_table_id);
845 
846  if (is_del)
847  {
848  if (dhcp_proxy_server_del (FIB_PROTOCOL_IP6, rx_fib_index,
849  addr, server_table_id))
850  {
851  mfib_table_entry_delete(rx_fib_index,
852  &all_dhcp_servers,
854  mfib_table_unlock(rx_fib_index, FIB_PROTOCOL_IP6);
855  }
856  }
857  else
858  {
859  const fib_route_path_t path_for_us = {
861  .frp_addr = zero_addr,
862  .frp_sw_if_index = 0xffffffff,
863  .frp_fib_index = ~0,
864  .frp_weight = 0,
865  .frp_flags = FIB_ROUTE_PATH_LOCAL,
866  };
867  if (dhcp_proxy_server_add (FIB_PROTOCOL_IP6, addr, src_addr,
868  rx_fib_index, server_table_id))
869  {
870  mfib_table_entry_path_update(rx_fib_index,
871  &all_dhcp_servers,
873  &path_for_us,
875  /*
876  * Each interface that is enabled in this table, needs to be added
877  * as an accepting interface, but this is not easily doable in VPP.
878  * So we cheat. Add a flag to the entry that indicates accept form
879  * any interface.
880  * We will still only accept on v6 enabled interfaces, since the
881  * input feature ensures this.
882  */
883  mfib_table_entry_update(rx_fib_index,
884  &all_dhcp_servers,
887  mfib_table_lock(rx_fib_index, FIB_PROTOCOL_IP6);
888  }
889  }
890 
891  mfib_table_unlock(rx_fib_index, FIB_PROTOCOL_IP6);
892 
893  return (rc);
894 }
895 
896 static clib_error_t *
898  unformat_input_t * input,
899  vlib_cli_command_t * cmd)
900 {
901  ip46_address_t addr, src_addr;
902  int set_server = 0, set_src_address = 0;
903  u32 rx_table_id = 0, server_table_id = 0;
904  int is_del = 0;
905 
907  {
908  if (unformat (input, "server %U",
909  unformat_ip6_address, &addr.ip6))
910  set_server = 1;
911  else if (unformat(input, "src-address %U",
912  unformat_ip6_address, &src_addr.ip6))
913  set_src_address =1;
914  else if (unformat (input, "server-fib-id %d", &server_table_id))
915  ;
916  else if (unformat (input, "rx-fib-id %d", &rx_table_id))
917  ;
918  else if (unformat (input, "delete") ||
919  unformat (input, "del"))
920  is_del = 1;
921  else
922  break;
923  }
924 
925  if (is_del || (set_server && set_src_address))
926  {
927  int rv;
928 
929  rv = dhcp6_proxy_set_server (&addr, &src_addr, rx_table_id,
930  server_table_id, is_del);
931 
932  //TODO: Complete the errors
933  switch (rv)
934  {
935  case 0:
936  return 0;
937 
938  case VNET_API_ERROR_INVALID_DST_ADDRESS:
939  return clib_error_return (0, "Invalid server address");
940 
941  case VNET_API_ERROR_INVALID_SRC_ADDRESS:
942  return clib_error_return (0, "Invalid src address");
943 
944  case VNET_API_ERROR_NO_SUCH_ENTRY:
945  return clib_error_return
946  (0, "Fib id %d: no per-fib DHCP server configured", rx_table_id);
947 
948  default:
949  return clib_error_return (0, "BUG: rv %d", rv);
950  }
951  }
952  else
953  return clib_error_return (0, "parse error`%U'",
954  format_unformat_error, input);
955 }
956 
957 VLIB_CLI_COMMAND (dhcpv6_proxy_set_command, static) = {
958  .path = "set dhcpv6 proxy",
959  .short_help = "set dhcpv6 proxy [del] server <ipv6-addr> src-address <ipv6-addr> "
960  "[server-fib-id <fib-id>] [rx-fib-id <fib-id>] ",
961  .function = dhcpv6_proxy_set_command_fn,
962 };
963 
964 static u8 *
965 format_dhcp6_proxy_server (u8 * s, va_list * args)
966 {
967  dhcp_proxy_t * proxy = va_arg (*args, dhcp_proxy_t *);
968  ip6_fib_t *server_fib;
969  dhcp_server_t *server;
970  ip6_mfib_t *rx_fib;
971 
972  if (proxy == 0)
973  {
974  s = format (s, "%=14s%=16s%s", "RX FIB", "Src Address",
975  "Servers FIB,Address");
976  return s;
977  }
978 
979  rx_fib = ip6_mfib_get(proxy->rx_fib_index);
980 
981  s = format (s, "%=14u%=16U",
982  rx_fib->table_id,
984 
985  vec_foreach(server, proxy->dhcp_servers)
986  {
987  server_fib = ip6_fib_get(server->server_fib_index);
988  s = format (s, "%u,%U ",
989  server_fib->table_id,
991  }
992 
993  return s;
994 }
995 
996 static int
998  void *ctx)
999 {
1000  vlib_main_t * vm = ctx;
1001 
1002  vlib_cli_output (vm, "%U", format_dhcp6_proxy_server, proxy);
1003 
1004  return (1);
1005 }
1006 
1007 static clib_error_t *
1009  unformat_input_t * input,
1010  vlib_cli_command_t * cmd)
1011 {
1012  vlib_cli_output (vm, "%U", format_dhcp6_proxy_server, NULL /* header line */);
1013 
1015 
1016  return (NULL);
1017 }
1018 
1019 VLIB_CLI_COMMAND (dhcpv6_proxy_show_command, static) = {
1020  .path = "show dhcpv6 proxy",
1021  .short_help = "Display dhcpv6 proxy info",
1022  .function = dhcpv6_proxy_show_command_fn,
1023 };
1024 
1025 static clib_error_t *
1027  unformat_input_t * input,
1028  vlib_cli_command_t * cmd)
1029 {
1030  int is_del = 0, got_new_vss=0;
1031  u32 oui=0;
1032  u32 fib_id=0, tbl_id=~0;
1033 
1035  {
1036  if (unformat (input, "oui %d", &oui))
1037  got_new_vss = 1;
1038  else if (unformat (input, "vpn-id %d", &fib_id))
1039  got_new_vss = 1;
1040  else if (unformat (input, "table %d", &tbl_id))
1041  got_new_vss = 1;
1042  else if (unformat(input, "delete") || unformat(input, "del"))
1043  is_del = 1;
1044  else
1045  break;
1046  }
1047 
1048  if (tbl_id ==~0)
1049  return clib_error_return (0, "no table ID specified.");
1050 
1051  if (is_del || got_new_vss)
1052  {
1053  int rv;
1054 
1055  rv = dhcp_proxy_set_vss(FIB_PROTOCOL_IP6, tbl_id, oui, fib_id, is_del);
1056  switch (rv)
1057  {
1058  case 0:
1059  return 0;
1060 
1061  case VNET_API_ERROR_NO_SUCH_FIB:
1062  return clib_error_return (0, "vss info (oui:%d, vpn-id:%d) not found in table %d.",
1063  oui, fib_id, tbl_id);
1064 
1065  case VNET_API_ERROR_NO_SUCH_ENTRY:
1066  return clib_error_return (0, "vss for table %d not found in pool.",
1067  tbl_id);
1068 
1069  default:
1070  return clib_error_return (0, "BUG: rv %d", rv);
1071  }
1072  }
1073  else
1074  return clib_error_return (0, "parse error`%U'",
1075  format_unformat_error, input);
1076 
1077 }
1078 
1079 VLIB_CLI_COMMAND (dhcpv6_proxy_vss_command, static) = {
1080  .path = "set dhcpv6 vss",
1081  .short_help = "set dhcpv6 vss table <table-id> oui <oui> vpn-idx <vpn-idx>",
1082  .function = dhcpv6_vss_command_fn,
1083 };
1084 
1085 static clib_error_t *
1087  unformat_input_t * input,
1088  vlib_cli_command_t * cmd)
1089 
1090 {
1092 
1093  return (NULL);
1094 }
1095 
1096 VLIB_CLI_COMMAND (dhcpv6_proxy_vss_show_command, static) = {
1097  .path = "show dhcpv6 vss",
1098  .short_help = "show dhcpv6 VSS",
1099  .function = dhcpv6_vss_show_command_fn,
1100 };
1101 
1102 static clib_error_t *
1104  unformat_input_t * input,
1105  vlib_cli_command_t * cmd)
1106 
1107 {
1108  vnet_main_t *vnm = vnet_get_main();
1109  u32 sw_if_index0=0, sw_if_index;
1110  vnet_sw_interface_t *swif;
1111  ip6_address_t *ia0;
1112 
1114  {
1115 
1116  if (unformat(input, "%U",
1117  unformat_vnet_sw_interface, vnm, &sw_if_index0))
1118  {
1119  swif = vnet_get_sw_interface (vnm, sw_if_index0);
1120  sw_if_index = (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED) ?
1121  swif->unnumbered_sw_if_index : sw_if_index0;
1122  ia0 = ip6_interface_first_address(&ip6_main, sw_if_index);
1123  if (ia0)
1124  {
1125  vlib_cli_output (vm, "%=20s%=48s", "interface", "link-address");
1126 
1127  vlib_cli_output (vm, "%=20U%=48U",
1128  format_vnet_sw_if_index_name, vnm, sw_if_index0,
1129  format_ip6_address, ia0);
1130  } else
1131  vlib_cli_output (vm, "%=34s%=20U", "No IPv6 address configured on",
1132  format_vnet_sw_if_index_name, vnm, sw_if_index);
1133  } else
1134  break;
1135  }
1136 
1137  return 0;
1138 }
1139 
1140 VLIB_CLI_COMMAND (dhcpv6_proxy_address_show_command, static) = {
1141  .path = "show dhcpv6 link-address interface",
1142  .short_help = "show dhcpv6 link-address interface <interface>",
1144 };
#define foreach_ip_interface_address(lm, a, sw_if_index, loop, body)
Definition: lookup.h:417
#define VNET_SW_INTERFACE_FLAG_UNNUMBERED
Definition: interface.h:543
void mfib_table_entry_delete(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source)
Delete a FIB entry.
Definition: mfib_table.c:350
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:187
static ip6_address_t all_dhcpv6_server_relay_agent_address
fib_protocol_t frp_proto
The protocol of the address below.
Definition: fib_types.h:313
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
#define CLIB_UNUSED(x)
Definition: clib.h:79
a
Definition: bitmap.h:516
static u8 * format_dhcpv6_proxy_trace(u8 *s, va_list *args)
u32 * mfib_index_by_sw_if_index
Table index indexed by software interface.
Definition: ip6.h:166
static ip6_fib_t * ip6_fib_get(fib_node_index_t index)
Definition: ip6_fib.h:115
A representation of a path as described by a route producer.
Definition: fib_types.h:308
static clib_error_t * dhcpv6_proxy_set_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
ethernet_main_t * ethernet_get_main(vlib_main_t *vm)
Definition: init.c:116
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
u32 free_list_index
Buffer free list that this buffer was allocated from and will be freed to.
Definition: buffer.h:99
static u8 * format_dhcpv6_proxy_header_with_length(u8 *s, va_list *args)
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
u8 as_u8[16]
Definition: ip6_packet.h:48
u64 as_u64[2]
Definition: ip6_packet.h:51
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
u32 index
Definition: node.h:237
dhcp_proxy_main_t dhcp_proxy_main
Shard 4/6 instance of DHCP main.
Definition: dhcp_proxy.c:25
static ip6_address_t all_dhcpv6_server_address
int dhcp6_proxy_set_server(ip46_address_t *addr, ip46_address_t *src_addr, u32 rx_table_id, u32 server_table_id, int is_del)
#define ethernet_buffer_header_size(b)
Determine the size of the Ethernet headers of the current frame in the buffer.
Definition: ethernet.h:390
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:459
u8 src_address[6]
Definition: packet.h:54
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
static clib_error_t * dhcpv6_vss_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
ip6_address_t * ip6_interface_first_address(ip6_main_t *im, u32 sw_if_index)
get first IPv6 interface address
Definition: ip6_forward.c:428
struct _vlib_node_registration vlib_node_registration_t
static vlib_node_registration_t dhcpv6_proxy_to_server_node
(constructor) VLIB_REGISTER_NODE (dhcpv6_proxy_to_server_node)
u32 rx_fib_index
The FIB index (not the external Table-ID) in which the client is resides.
Definition: dhcp_proxy.h:111
format_function_t format_ip46_address
Definition: format.h:61
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
unformat_function_t unformat_vnet_sw_interface
static ip6_address_t * ip6_interface_first_global_or_site_address(ip6_main_t *im, u32 sw_if_index)
u32 oui
?? RFC doesn&#39;t say
Definition: dhcp_proxy.h:53
ip6_address_t src_address
Definition: ip6_packet.h:341
format_function_t format_vnet_sw_if_index_name
static vlib_buffer_t * vlib_buffer_copy(vlib_main_t *vm, vlib_buffer_t *b)
Definition: buffer_funcs.h:475
static clib_error_t * dhcp6_proxy_init(vlib_main_t *vm)
static char * dhcpv6_proxy_error_strings[]
union dhcpv6_hdr_::@82 u
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:67
dhcpv6_proxy_to_server_input_next_t
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
u8 dst_address[6]
Definition: packet.h:53
fib_node_index_t mfib_table_entry_update(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source, mfib_entry_flags_t entry_flags)
Add a new (with no replication) or lock an existing entry.
Definition: mfib_table.c:165
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
#define clib_error_return(e, args...)
Definition: error.h:111
fib_node_index_t mfib_table_entry_path_update(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source, const fib_route_path_t *rpath, mfib_itf_flags_t itf_flags)
Add n paths to an entry (aka route) in the FIB.
Definition: mfib_table.c:216
static clib_error_t * dhcpv6_vss_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
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
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
Definition: buffer_funcs.h:70
static vlib_node_registration_t dhcpv6_proxy_to_client_node
(constructor) VLIB_REGISTER_NODE (dhcpv6_proxy_to_client_node)
#define foreach_dhcpv6_proxy_to_server_input_next
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:397
vnet_sub_interface_t sub
Definition: interface.h:569
static clib_error_t * dhcpv6_proxy_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:71
struct _unformat_input_t unformat_input_t
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:188
#define PREDICT_FALSE(x)
Definition: clib.h:97
#define HOP_COUNT_LIMIT
Definition: dhcp6_packet.h:28
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:216
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:350
Definition: ip6.h:79
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1112
u32 fib_id
VPN-ID.
Definition: dhcp_proxy.h:57
unformat_function_t unformat_ip6_address
Definition: format.h:94
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
u16 n_vectors
Definition: node.h:344
format_function_t format_ip6_address
Definition: format.h:95
vlib_main_t * vm
Definition: buffer.c:276
vec_header_t h
Definition: buffer.c:275
Definition: ip6.h:67
static clib_error_t * dhcpv6_link_address_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:85
#define clib_memcpy(a, b, c)
Definition: string.h:69
A representation of a single DHCP Server within a given VRF config.
Definition: dhcp_proxy.h:63
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
Aggregrate type for a prefix.
Definition: mfib_types.h:24
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
u16 ip6_tcp_udp_icmp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip6_header_t *ip0, int *bogus_lengthp)
Definition: ip6_forward.c:1139
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:455
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
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
ip6_main_t ip6_main
Definition: ip6_forward.c:2846
ip_lookup_main_t lookup_main
Definition: ip6.h:151
u32 table_id
Definition: ip6.h:82
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:201
u64 uword
Definition: types.h:112
static void copy_ip6_address(ip6_address_t *dst, ip6_address_t *src)
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
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
A DHCP proxy represenation fpr per-client VRF config.
Definition: dhcp_proxy.h:81
u32 ip_version_traffic_class_and_flow_label
Definition: ip6_packet.h:328
Definition: defs.h:47
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
unsigned short u16
Definition: types.h:57
u16 payload_length
Definition: ip6_packet.h:332
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
A for-us/local path.
Definition: fib_types.h:284
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
void mfib_table_lock(u32 fib_index, fib_protocol_t proto)
Release a reference counting lock on the table.
Definition: mfib_table.c:483
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:253
static ip6_mfib_t * ip6_mfib_get(u32 index)
Get the FIB at the given index.
Definition: ip6_mfib.h:65
#define vnet_buffer(b)
Definition: buffer.h:294
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
vnet_sw_interface_type_t type
Definition: interface.h:531
u8 data[0]
Packet data.
Definition: buffer.h:152
#define vec_foreach(var, vec)
Vector iterator.
u32 table_id
Definition: ip6.h:70
vhost_vring_addr_t addr
Definition: vhost-user.h:84
void udp_register_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
Definition: udp_local.c:488
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:196
static vlib_buffer_free_list_t * vlib_buffer_get_free_list(vlib_main_t *vm, u32 free_list_index)
Definition: buffer_funcs.h:385
static void * ip_interface_address_get_address(ip_lookup_main_t *lm, ip_interface_address_t *a)
Definition: lookup.h:410
u16 fp_len
The mask length.
Definition: mfib_types.h:28
ethernet_interface_t * interfaces
Definition: ethernet.h:243
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:74
static int dhcp6_proxy_show_walk(dhcp_proxy_t *proxy, void *ctx)
#define ip46_address_is_zero(ip46)
Definition: ip6_packet.h:81
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:577
u32 * fib_index_by_sw_if_index
Definition: ip6.h:163
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
static u8 * format_dhcp6_proxy_server(u8 *s, va_list *args)
const ip46_address_t zero_addr
Definition: lookup.c:354
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:971
Definition: defs.h:46
ip6_address_t dst_address
Definition: ip6_packet.h:341
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
static uword dhcpv6_proxy_to_server_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
#define PROTO_UDP
Definition: dhcp6_packet.h:25
static uword dhcpv6_proxy_to_client_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)