FD.io VPP  v16.12-rc0-308-g931be3a
Vector Packet Processing
proxy_node.c
Go to the documentation of this file.
1 /*
2  * 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/dhcpv6/proxy.h>
21 #include <vnet/fib/ip6_fib.h>
22 
23 static char * dhcpv6_proxy_error_strings[] = {
24 #define dhcpv6_proxy_error(n,s) s,
25 #include "proxy_error.def"
26 #undef dhcpv6_proxy_error
27 };
28 
29 #define foreach_dhcpv6_proxy_to_server_input_next \
30  _ (DROP, "error-drop") \
31  _ (LOOKUP, "ip6-lookup") \
32  _ (SEND_TO_CLIENT, "dhcpv6-proxy-to-client")
33 
34 
35 typedef enum {
36 #define _(s,n) DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_##s,
38 #undef _
41 
42 typedef struct {
43  /* 0 => to server, 1 => to client */
44  int which;
45  u8 packet_data[64];
50 
53 
54 
55 u8 * format_dhcpv6_proxy_trace (u8 * s, va_list * args)
56 {
57  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
58  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
59  dhcpv6_proxy_trace_t * t = va_arg (*args, dhcpv6_proxy_trace_t *);
60 
61  if (t->which == 0)
62  s = format (s, "DHCPV6 proxy: sent to server %U",
64  else
65  s = format (s, "DHCPV6 proxy: sent to client from %U",
67  if (t->error != (u32)~0)
68  s = format (s, " error: %s\n", dhcpv6_proxy_error_strings[t->error]);
69 
70  s = format (s, " original_sw_if_index: %d, sw_if_index: %d\n",
72 
73  return s;
74 }
75 
77 {
78  dhcpv6_header_t * h = va_arg (*args, dhcpv6_header_t *);
79  u32 max_header_bytes = va_arg (*args, u32);
80  u32 header_bytes;
81 
82  header_bytes = sizeof (h[0]);
83  if (max_header_bytes != 0 && header_bytes > max_header_bytes)
84  return format (s, "dhcpv6 header truncated");
85 
86  s = format (s, "DHCPV6 Proxy");
87 
88  return s;
89 }
90 /* get first interface address */
91 static ip6_address_t *
93 {
94  ip_lookup_main_t * lm = &im->lookup_main;
95  ip_interface_address_t * ia = 0;
96  ip6_address_t * result = 0;
97 
98  foreach_ip_interface_address (lm, ia, sw_if_index,
99  1 /* honor unnumbered */,
100  ({
102  if ((a->as_u8[0] & 0xe0) == 0x20 ||
103  (a->as_u8[0] & 0xfe) == 0xfc) {
104  result = a;
105  break;
106  }
107  }));
108  return result;
109 }
110 
111 /* get first interface address */
112 static ip6_address_t *
114 {
115  ip_lookup_main_t * lm = &im->lookup_main;
116  ip_interface_address_t * ia = 0;
117  ip6_address_t * result = 0;
118 
119  foreach_ip_interface_address (lm, ia, sw_if_index,
120  1 /* honor unnumbered */,
121  ({
123  result = a;
124  break;
125  }));
126  return result;
127 }
128 
129 static inline void copy_ip6_address (ip6_address_t *dst, ip6_address_t *src)
130 {
131 
132  dst->as_u64[0] = src->as_u64[0];
133  dst->as_u64[1] = src->as_u64[1];
134 }
135 
136 static uword
138  vlib_node_runtime_t * node,
139  vlib_frame_t * from_frame)
140 {
141  u32 n_left_from, next_index, * from, * to_next;
143  from = vlib_frame_vector_args (from_frame);
144  n_left_from = from_frame->n_vectors;
145  u32 pkts_to_server=0, pkts_to_client=0;
146  u32 pkts_no_interface_address=0, pkts_no_exceeding_max_hop=0;
147  u32 pkts_no_src_address=0;
148  u32 pkts_wrong_msg_type=0;
149  u32 pkts_too_big=0;
150  ip6_main_t * im = &ip6_main;
151  u32 fib_index=0, fib_id=0;
152  ip6_fib_t * fib;
153  ip6_address_t * src;
154  int bogus_length;
155 
156  next_index = node->cached_next_index;
157 
158  while (n_left_from > 0)
159  {
160  u32 n_left_to_next;
161 
162  vlib_get_next_frame (vm, node, next_index,
163  to_next, n_left_to_next);
164 
165  while (n_left_from > 0 && n_left_to_next > 0)
166  {
167  vnet_main_t *vnm = vnet_get_main();
168  u32 sw_if_index = 0;
169  u32 original_sw_if_index = 0;
170  vnet_sw_interface_t *swif;
171  u32 bi0;
172  vlib_buffer_t * b0;
173  udp_header_t * u0, *u1;
174  dhcpv6_header_t * h0; // client msg hdr
175  ip6_header_t * ip0, *ip1;
176  ip6_address_t _ia0, *ia0=&_ia0;
177  u32 next0;
178  u32 error0 = (u32) ~0;
179  dhcpv6_option_t *fwd_opt;
180  dhcpv6_relay_hdr_t *r1;
181  u16 len;
182  dhcpv6_int_id_t *id1;
183  dhcpv6_vss_t *vss1;
184  dhcpv6_client_mac_t *cmac; // client mac
185  ethernet_header_t * e_h0;
186  u8 client_src_mac[6];
188 
189  uword *p_vss;
190  u32 oui1=0;
191  u32 fib_id1;
192  dhcpv6_vss_info *vss;
193 
194  fib_id1 = 0;
195  bi0 = from[0];
196  to_next[0] = bi0;
197  from += 1;
198  to_next += 1;
199  n_left_from -= 1;
200  n_left_to_next -= 1;
201 
202  b0 = vlib_get_buffer (vm, bi0);
203 
204  h0 = vlib_buffer_get_current (b0);
205 
206  /* Send to DHCPV6 server via the configured FIB */
207  vnet_buffer(b0)->sw_if_index[VLIB_TX] =
208  dpm->server_fib_index;
209 
210  /*
211  * udp_local hands us the DHCPV6 header.
212  */
213  u0 = (void *)h0 -(sizeof(*u0));
214  ip0 = (void *)u0 -(sizeof(*ip0));
215  e_h0 = (void *)ip0 - ethernet_buffer_header_size(b0);
216 
217  clib_memcpy(client_src_mac, e_h0->src_address, 6);
218 
219  switch (h0->u.msg_type) {
220  case DHCPV6_MSG_SOLICIT:
221  case DHCPV6_MSG_REQUEST:
222  case DHCPV6_MSG_CONFIRM:
223  case DHCPV6_MSG_RENEW:
224  case DHCPV6_MSG_REBIND:
225  case DHCPV6_MSG_RELEASE:
226  case DHCPV6_MSG_DECLINE:
229  /* send to server */
230  break;
232  /* send to client */
233  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_SEND_TO_CLIENT;
234  error0 = 0;
235  pkts_to_client++;
236  goto do_enqueue;
237  default:
238  /* drop the packet */
239  pkts_wrong_msg_type++;
240  error0 = DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE;
241  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
242  goto do_trace;
243 
244  }
245  /* relay-option header pointer */
246  vlib_buffer_advance(b0, -(sizeof(*fwd_opt)));
247  fwd_opt = vlib_buffer_get_current(b0);
248  /* relay message header pointer */
249  vlib_buffer_advance(b0, -(sizeof(*r1)));
250  r1 = vlib_buffer_get_current(b0);
251 
252  vlib_buffer_advance(b0, -(sizeof(*u1)));
253  u1 = vlib_buffer_get_current(b0);
254 
255  vlib_buffer_advance(b0, -(sizeof(*ip1)));
256  ip1 = vlib_buffer_get_current(b0);
257 
258  /* fill in all that rubbish... */
259  len = clib_net_to_host_u16(u0->length) - sizeof(udp_header_t);
260  copy_ip6_address(&r1->peer_addr, &ip0->src_address);
261 
262  r1->msg_type = DHCPV6_MSG_RELAY_FORW;
263  fwd_opt->length = clib_host_to_net_u16(len);
264  fwd_opt->option = clib_host_to_net_u16(DHCPV6_OPTION_RELAY_MSG);
265 
266  r1->hop_count++;
267  r1->hop_count = (h0->u.msg_type != DHCPV6_MSG_RELAY_FORW) ? 0 : r1->hop_count;
268 
269  if (PREDICT_FALSE(r1->hop_count >= HOP_COUNT_LIMIT))
270  {
272  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
273  pkts_no_exceeding_max_hop++;
274  goto do_trace;
275  }
276 
277 
278  /* If relay-fwd and src address is site or global unicast address */
279  if (h0->u.msg_type == DHCPV6_MSG_RELAY_FORW &&
280  ((ip0->src_address.as_u8[0] & 0xe0) == 0x20 ||
281  (ip0->src_address.as_u8[0] & 0xfe) == 0xfc))
282  {
283  /* Set link address to zero */
284  r1->link_addr.as_u64[0] = 0;
285  r1->link_addr.as_u64[1] = 0;
286  goto link_address_set;
287  }
288 
289  /* if receiving interface is unnumbered, use receiving interface
290  * IP address as link address, otherwise use the loopback interface
291  * IP address as link address.
292  */
293  original_sw_if_index = sw_if_index =
294  vnet_buffer(b0)->sw_if_index[VLIB_RX];
295  swif = vnet_get_sw_interface (vnm, sw_if_index);
297  sw_if_index = swif->unnumbered_sw_if_index;
298 
300  if (ia0 == 0)
301  {
302  error0 = DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS;
303  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
304  pkts_no_interface_address++;
305  goto do_trace;
306  }
307 
308  copy_ip6_address(&r1->link_addr, ia0);
309 
310  link_address_set:
312 
313  if ((b0->current_length+sizeof(*id1)+sizeof(*vss1)+sizeof(*cmac))
314  > fl->n_data_bytes)
315  {
316  error0 = DHCPV6_PROXY_ERROR_PKT_TOO_BIG;
317  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
318  pkts_too_big++;
319  goto do_trace;
320  }
321 
322  id1 = (dhcpv6_int_id_t *) (((uword) ip1) + b0->current_length);
323  b0->current_length += (sizeof (*id1));
324 
325  fib_index = im->fib_index_by_sw_if_index
326  [vnet_buffer(b0)->sw_if_index[VLIB_RX]];
327  fib = ip6_fib_get (fib_index);
328  fib_id = fib->table_id;
329 
330  p_vss = hash_get (dpm->vss_index_by_vrf_id,
331  fib_id);
332  if (p_vss)
333  {
334  vss = pool_elt_at_index (dpm->vss, p_vss[0]);
335  oui1 = vss->vpn_id.oui;
336  fib_id1 = vss->vpn_id.fib_id;
337  }
338 
339  id1->opt.option = clib_host_to_net_u16(DHCPV6_OPTION_INTERFACE_ID);
340  id1->opt.length = clib_host_to_net_u16(sizeof(original_sw_if_index));
341  id1->int_idx = clib_host_to_net_u32(original_sw_if_index);
342 
343  u1->length =0;
344  if (h0->u.msg_type != DHCPV6_MSG_RELAY_FORW)
345  {
346  cmac = (dhcpv6_client_mac_t *) (((uword) ip1) + b0->current_length);
347  b0->current_length += (sizeof (*cmac));
348  cmac->opt.length =clib_host_to_net_u16(sizeof(*cmac) -
349  sizeof(cmac->opt));
350  cmac->opt.option = clib_host_to_net_u16(DHCPV6_OPTION_CLIENT_LINK_LAYER_ADDRESS);
351  cmac->link_type = clib_host_to_net_u16(1); // ethernet
352  clib_memcpy(cmac->data, client_src_mac, 6);
353  u1->length += sizeof(*cmac);
354  }
355  if (oui1 || fib_id1) {
356  vss1 = (dhcpv6_vss_t *) (((uword) ip1) + b0->current_length);
357  b0->current_length += (sizeof (*vss1));
358  vss1->opt.length =clib_host_to_net_u16(sizeof(*vss1) -
359  sizeof(vss1->opt));
360  vss1->opt.option = clib_host_to_net_u16(DHCPV6_OPTION_VSS);
361  vss1->data[0] = 1; // type
362  vss1->data[1] = oui1>>16 & 0xff;
363  vss1->data[2] = oui1>>8 & 0xff;
364  vss1->data[3] = oui1 & 0xff;
365  vss1->data[4] = fib_id1>>24 & 0xff;
366  vss1->data[5] = fib_id1>>16 & 0xff;
367  vss1->data[6] = fib_id1>>8 & 0xff;
368  vss1->data[7] = fib_id1 & 0xff;
369  u1->length += sizeof(*vss1);
370  }
371 
372  pkts_to_server++;
373  u1->checksum = 0;
374  u1->src_port = clib_host_to_net_u16(UDP_DST_PORT_dhcpv6_to_client);
375  u1->dst_port = clib_host_to_net_u16(UDP_DST_PORT_dhcpv6_to_server);
376 
377  u1->length =
378  clib_host_to_net_u16( clib_net_to_host_u16(fwd_opt->length) +
379  sizeof(*r1) + sizeof(*fwd_opt) +
380  sizeof(*u1) + sizeof(*id1) + u1->length);
381 
382  memset(ip1, 0, sizeof(*ip1));
383  ip1->ip_version_traffic_class_and_flow_label = 0x60;
384  ip1->payload_length = u1->length;
385  ip1->protocol = PROTO_UDP;
386  ip1->hop_limit = HOP_COUNT_LIMIT;
387  src = (dpm->dhcpv6_server.as_u64[0] || dpm->dhcpv6_server.as_u64[1]) ?
389  copy_ip6_address(&ip1->dst_address, src);
390 
391 
393  (&ip6_main, vnet_buffer(b0)->sw_if_index[VLIB_RX]);
394 
395  src = (dpm->dhcpv6_src_address.as_u64[0] || dpm->dhcpv6_src_address.as_u64[1]) ?
396  &dpm->dhcpv6_src_address : ia0;
397  if (ia0 == 0)
398  {
399  error0 = DHCPV6_PROXY_ERROR_NO_SRC_ADDRESS;
400  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
401  pkts_no_src_address++;
402  goto do_trace;
403  }
404 
405  copy_ip6_address (&ip1->src_address, src);
406 
407 
408  u1->checksum = ip6_tcp_udp_icmp_compute_checksum(vm, b0, ip1,
409  &bogus_length);
410  ASSERT(bogus_length == 0);
411 
412  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP;
413 
414  do_trace:
416  {
417  dhcpv6_proxy_trace_t *tr = vlib_add_trace (vm, node,
418  b0, sizeof (*tr));
419  tr->which = 0; /* to server */
420  tr->error = error0;
421  tr->original_sw_if_index = original_sw_if_index;
422  tr->sw_if_index = sw_if_index;
423  if (DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP == next0)
425  }
426 
427  do_enqueue:
428  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
429  to_next, n_left_to_next,
430  bi0, next0);
431  }
432 
433  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
434  }
435 
437  DHCPV6_PROXY_ERROR_RELAY_TO_CLIENT,
438  pkts_to_client);
440  DHCPV6_PROXY_ERROR_RELAY_TO_SERVER,
441  pkts_to_server);
443  DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS,
444  pkts_no_interface_address);
446  DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE,
447  pkts_wrong_msg_type);
449  DHCPV6_PROXY_ERROR_NO_SRC_ADDRESS,
450  pkts_no_src_address);
452  DHCPV6_PROXY_ERROR_PKT_TOO_BIG,
453  pkts_too_big);
454  return from_frame->n_vectors;
455 }
456 
458  .function = dhcpv6_proxy_to_server_input,
459  .name = "dhcpv6-proxy-to-server",
460  /* Takes a vector of packets. */
461  .vector_size = sizeof (u32),
462 
463  .n_errors = DHCPV6_PROXY_N_ERROR,
464  .error_strings = dhcpv6_proxy_error_strings,
465 
466  .n_next_nodes = DHCPV6_PROXY_TO_SERVER_INPUT_N_NEXT,
467  .next_nodes = {
468 #define _(s,n) [DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_##s] = n,
470 #undef _
471  },
472 
474  .format_trace = format_dhcpv6_proxy_trace,
475 #if 0
476  .unformat_buffer = unformat_dhcpv6_proxy_header,
477 #endif
478 };
479 
480 static uword
482  vlib_node_runtime_t * node,
483  vlib_frame_t * from_frame)
484 {
485 
486  u32 n_left_from, * from;
489  vnet_main_t * vnm = vnet_get_main();
490  int bogus_length;
491 
492  from = vlib_frame_vector_args (from_frame);
493  n_left_from = from_frame->n_vectors;
494 
495  while (n_left_from > 0)
496  {
497  u32 bi0;
498  vlib_buffer_t * b0;
499  udp_header_t * u0, *u1=0;
500  dhcpv6_relay_hdr_t * h0;
501  ip6_header_t * ip1 = 0, *ip0;
502  ip6_address_t _ia0, * ia0 = &_ia0;
503  ip6_address_t client_address;
505  ethernet_header_t *mac0;
506  vnet_hw_interface_t *hi0;
507  vlib_frame_t *f0;
508  u32 * to_next0;
509  u32 sw_if_index = ~0;
510  u32 original_sw_if_index = ~0;
511  vnet_sw_interface_t *si0;
512  u32 error0 = (u32)~0;
513  vnet_sw_interface_t *swif;
514  dhcpv6_option_t *r0, *o;
515  u16 len = 0;
516  u32 svr_fib_index, svr_fib_id;
517  ip6_fib_t * svr_fib;
518  ip6_main_t * im = &ip6_main;
519 
520  bi0 = from[0];
521  from += 1;
522  n_left_from -= 1;
523 
524  b0 = vlib_get_buffer (vm, bi0);
525  h0 = vlib_buffer_get_current (b0);
526 
527  if (DHCPV6_MSG_RELAY_REPL != h0->msg_type)
528  {
529  error0 = DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE;
530 
531  drop_packet:
533  error0, 1);
534 
536  to_next0 = vlib_frame_vector_args (f0);
537  to_next0[0] = bi0;
538  f0->n_vectors = 1;
540  goto do_trace;
541  }
542  /* hop count seems not need to be checked */
543  if (HOP_COUNT_LIMIT < h0->hop_count)
544  {
546  goto drop_packet;
547  }
548  u0 = (void *)h0 -(sizeof(*u0));
549  ip0 = (void *)u0 -(sizeof(*ip0));
550 
551  vlib_buffer_advance (b0, sizeof(*h0));
552  o = r0 = vlib_buffer_get_current (b0);
553 
554  /* Parse through TLVs looking for option 9 (DHCPV6_OPTION_INTERFACE_ID).
555  The interface-ID is the FIB number we need
556  to track down the client-facing interface */
557 
558  while ((u8 *) o < (b0->data + b0->current_data + b0->current_length))
559  {
560  if (DHCPV6_OPTION_INTERFACE_ID == clib_net_to_host_u16(o->option))
561  {
562  if (clib_net_to_host_u16(o->length) == sizeof(sw_if_index))
563  sw_if_index = clib_net_to_host_u32(((dhcpv6_int_id_t*)o)->int_idx);
564  break;
565  }
566  o = (dhcpv6_option_t *) (((uword) o) + clib_net_to_host_u16(o->length) + sizeof(*o));
567  }
568 
569  if ((u32)~0 == sw_if_index)
570  {
571  error0 = DHCPV6_PROXY_ERROR_NO_CIRCUIT_ID_OPTION;
572  goto drop_packet;
573  }
574 
575  svr_fib_index = im->fib_index_by_sw_if_index
576  [vnet_buffer(b0)->sw_if_index[VLIB_RX]];
577  svr_fib = ip6_fib_get (svr_fib_index);
578  svr_fib_id = svr_fib->table_id;
579 
580  if (svr_fib_id != dpm->server_fib_index ||
581  ip0->src_address.as_u64[0] != dpm->dhcpv6_server.as_u64[0] ||
582  ip0->src_address.as_u64[1] != dpm->dhcpv6_server.as_u64[1])
583  {
584  //drop packet if not from server with configured address or FIB
585  error0 = DHCPV6_PROXY_ERROR_BAD_SVR_FIB_OR_ADDRESS;
586  goto drop_packet;
587  }
588 
589  vnet_buffer (b0)->sw_if_index[VLIB_TX] = original_sw_if_index
590  = sw_if_index;
591 
592  swif = vnet_get_sw_interface (vnm, original_sw_if_index);
594  sw_if_index = swif->unnumbered_sw_if_index;
595 
596  vlib_buffer_advance (b0, sizeof(*r0));
597  /*
598  * udp_local hands us the DHCPV6 header, need udp hdr,
599  * ip hdr to relay to client
600  */
601  vlib_buffer_advance (b0, -(sizeof(*u1)));
602  u1 = vlib_buffer_get_current (b0);
603 
604  vlib_buffer_advance (b0, -(sizeof(*ip1)));
605  ip1 = vlib_buffer_get_current (b0);
606 
607  copy_ip6_address(&client_address, &h0->peer_addr);
608 
609  ia0 = ip6_interface_first_address (&ip6_main, sw_if_index);
610  if (ia0 == 0)
611  {
612  error0 = DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS;
613  goto drop_packet;
614  }
615 
616  len = clib_net_to_host_u16(r0->length);
617  memset(ip1, 0, sizeof(*ip1));
618  copy_ip6_address(&ip1->dst_address, &client_address);
619  u1->checksum = 0;
620  u1->src_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcpv6_to_server);
621  u1->dst_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcpv6_to_client);
622  u1->length = clib_host_to_net_u16 (len + sizeof(udp_header_t));
623 
625  ip0->ip_version_traffic_class_and_flow_label &
626  0x00000fff;
627  ip1->payload_length = u1->length;
628  ip1->protocol = PROTO_UDP;
629  ip1->hop_limit = HOP_COUNT_LIMIT;
630  copy_ip6_address(&ip1->src_address, ia0);
631 
632  u1->checksum = ip6_tcp_udp_icmp_compute_checksum(vm, b0, ip1,
633  &bogus_length);
634  ASSERT(bogus_length == 0);
635 
636  vlib_buffer_advance (b0, -(sizeof(ethernet_header_t)));
637  si0 = vnet_get_sw_interface (vnm, original_sw_if_index);
638  if (si0->type == VNET_SW_INTERFACE_TYPE_SUB)
639  vlib_buffer_advance (b0, -4 /* space for VLAN tag */);
640 
641  mac0 = vlib_buffer_get_current (b0);
642 
643  hi0 = vnet_get_sup_hw_interface (vnm, original_sw_if_index);
644  ei0 = pool_elt_at_index (em->interfaces, hi0->hw_instance);
645  clib_memcpy (mac0->src_address, ei0->address, sizeof (ei0->address));
646  memset (&mac0->dst_address, 0xff, sizeof (mac0->dst_address));
647  mac0->type = (si0->type == VNET_SW_INTERFACE_TYPE_SUB) ?
648  clib_net_to_host_u16(0x8100) : clib_net_to_host_u16 (0x86dd);
649 
650  if (si0->type == VNET_SW_INTERFACE_TYPE_SUB)
651  {
652  u32 * vlan_tag = (u32 *)(mac0+1);
653  u32 tmp;
654  tmp = (si0->sub.id << 16) | 0x0800;
655  *vlan_tag = clib_host_to_net_u32 (tmp);
656  }
657 
658  /* $$$ consider adding a dynamic next to the graph node, for performance */
660  to_next0 = vlib_frame_vector_args (f0);
661  to_next0[0] = bi0;
662  f0->n_vectors = 1;
664 
665  do_trace:
667  {
668  dhcpv6_proxy_trace_t *tr = vlib_add_trace (vm, node,
669  b0, sizeof (*tr));
670  tr->which = 1; /* to client */
671  if (ia0)
673  tr->error = error0;
674  tr->original_sw_if_index = original_sw_if_index;
675  tr->sw_if_index = sw_if_index;
676  }
677  }
678  return from_frame->n_vectors;
679 
680 }
681 
683  .function = dhcpv6_proxy_to_client_input,
684  .name = "dhcpv6-proxy-to-client",
685  /* Takes a vector of packets. */
686  .vector_size = sizeof (u32),
687 
688  .n_errors = DHCPV6_PROXY_N_ERROR,
689  .error_strings = dhcpv6_proxy_error_strings,
691  .format_trace = format_dhcpv6_proxy_trace,
692 #if 0
693  .unformat_buffer = unformat_dhcpv6_proxy_header,
694 #endif
695 };
696 
698 {
700  vlib_node_t * error_drop_node;
701 
702  dm->vlib_main = vm;
703  dm->vnet_main = vnet_get_main();
704  error_drop_node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
705  dm->error_drop_node_index = error_drop_node->index;
706 
707  /* RFC says this is the dhcpv6 server address */
708  dm->all_dhcpv6_server_address.as_u64[0] = clib_host_to_net_u64 (0xFF05000000000000);
709  dm->all_dhcpv6_server_address.as_u64[1] = clib_host_to_net_u64 (0x00010003);
710 
711  /* RFC says this is the server and agent address */
712  dm->all_dhcpv6_server_relay_agent_address.as_u64[0] = clib_host_to_net_u64 (0xFF02000000000000);
713  dm->all_dhcpv6_server_relay_agent_address.as_u64[1] = clib_host_to_net_u64 (0x00010002);
714 
715  udp_register_dst_port (vm, UDP_DST_PORT_dhcpv6_to_client,
716  dhcpv6_proxy_to_client_node.index, 0 /* is_ip4 */);
717 
718  udp_register_dst_port (vm, UDP_DST_PORT_dhcpv6_to_server,
719  dhcpv6_proxy_to_server_node.index, 0 /* is_ip6 */);
720  return 0;
721 }
722 
724 
726  u32 fib_id, int insert_vss, int is_del)
727 {
729  ip6_main_t * im = &ip6_main;
730  uword * p;
731 
732 
733  if (is_del)
734  {
735  dm->dhcpv6_server.as_u64[0] = 0;
736  dm->dhcpv6_server.as_u64[1] = 0;
737  dm->server_fib_index = 0;
738  dm->dhcpv6_src_address.as_u64[0] = 0;
739  dm->dhcpv6_src_address.as_u64[1] = 0;
740  dm->insert_option = 0;
741  return 0;
742  }
743 
744  if (addr->as_u64[0] == 0 &&
745  addr->as_u64[1] == 0 )
746  return VNET_API_ERROR_INVALID_DST_ADDRESS;
747 
748  if (src_address->as_u64[0] == 0 &&
749  src_address->as_u64[1] == 0)
750  return VNET_API_ERROR_INVALID_SRC_ADDRESS;
751 
752  p = hash_get (im->fib_index_by_table_id, fib_id);
753  if (p == 0)
754  return VNET_API_ERROR_NO_SUCH_FIB;
755 
756  copy_ip6_address(&dm->dhcpv6_server, addr);
757  dm->server_fib_index = p[0];
758  copy_ip6_address(&dm->dhcpv6_src_address, src_address);
759  dm->insert_option = insert_vss;
760  return 0;
761 }
762 
763 static clib_error_t *
765  unformat_input_t * input,
766  vlib_cli_command_t * cmd)
767 {
768  ip6_address_t addr, src_addr;
769  int set_server = 0, set_src_address = 0, add_opt = 0;
770  u32 fib_id = 0;
771  int is_del = 0;
772 
774  {
775  if (unformat (input, "server %U",
776  unformat_ip6_address, &addr))
777  set_server = 1;
778  else if (unformat(input, "src-address %U",
779  unformat_ip6_address, &src_addr))
780  set_src_address =1;
781  else if (unformat (input, "fib-id %d", &fib_id))
782  ;
783  else if (unformat (input, "add-option")
784  || unformat (input, "insert-option"))
785  add_opt = 1;
786  else if (unformat (input, "delete") ||
787  unformat (input, "del"))
788  is_del = 1;
789  else
790  break;
791  }
792 
793  if (is_del || (set_server && set_src_address))
794  {
795  int rv;
796 
797  rv = dhcpv6_proxy_set_server (&addr, &src_addr, fib_id,
798  add_opt, is_del);
799  switch (rv)
800  {
801  case 0:
802  return 0;
803 
804  case -1:
805  return clib_error_return (0, "FIB id %d does not exist", fib_id);
806 
807  default:
808  return clib_error_return (0, "BUG: rv %d", rv);
809  }
810  }
811  else
812  return clib_error_return (0, "parse error`%U'",
813  format_unformat_error, input);
814 }
815 
816 VLIB_CLI_COMMAND (dhcpv6_proxy_set_command, static) = {
817  .path = "set dhcpv6 proxy",
818  .short_help = "set dhcpv6 proxy server <ipv6-addr> fib-id <fib-id> src-address <ipv6-addr>",
819  .function = dhcpv6_proxy_set_command_fn,
820 };
821 
822 u8 * format_dhcpv6_proxy_server (u8 * s, va_list * args)
823 {
824  dhcpv6_proxy_main_t * dm = va_arg (*args, dhcpv6_proxy_main_t *);
825  ip6_fib_t * f;
826  u32 fib_id = (u32)~0;
827 
828  if (dm == 0)
829  {
830  s = format (s, "%=40s%=40s%=14s", "Server Address", "Source Address",
831  "Server FIB");
832  return s;
833  }
834 
835  f = ip6_fib_get (dm->server_fib_index);
836  if (f)
837  fib_id = f->table_id;
838 
839 
840  s = format (s, "%=40U%=40U%=14u",
843  fib_id);
844  return s;
845 }
846 
847 static clib_error_t *
849  unformat_input_t * input,
850  vlib_cli_command_t * cmd)
851 {
853 
854  vlib_cli_output (vm, "%U", format_dhcpv6_proxy_server, 0 /* header line */);
856  return 0;
857 }
858 
859 VLIB_CLI_COMMAND (dhcpv6_proxy_show_command, static) = {
860  .path = "show dhcpv6 proxy",
861  .short_help = "Display dhcpv6 proxy info",
862  .function = dhcpv6_proxy_show_command_fn,
863 };
864 
866  u32 oui,
867  u32 fib_id,
868  int is_del)
869 {
871  u32 old_oui, old_fib_id;
872  uword *p;
873  dhcpv6_vss_info *v;
874 
875  p = hash_get (dm->vss_index_by_vrf_id, tbl_id);
876 
877  if (p) {
878  v = pool_elt_at_index (dm->vss, p[0]);
879  if (!v)
880  return VNET_API_ERROR_NO_SUCH_FIB;
881 
882  old_oui = v->vpn_id.oui;
883  old_fib_id = v->vpn_id.fib_id;
884 
885  if (is_del)
886  {
887  if (old_oui == oui &&
888  old_fib_id == fib_id )
889  {
890  pool_put(dm->vss, v);
891  hash_unset (dm->vss_index_by_vrf_id, tbl_id);
892  return 0;
893  }
894  else
895  return VNET_API_ERROR_NO_SUCH_ENTRY;
896  }
897 
898  pool_put(dm->vss, v);
899  hash_unset (dm->vss_index_by_vrf_id, tbl_id);
900  } else if (is_del)
901  return VNET_API_ERROR_NO_SUCH_ENTRY;
902 
903  pool_get (dm->vss, v);
904  memset (v, ~0, sizeof (*v));
905  v->vpn_id.fib_id = fib_id;
906  v->vpn_id.oui = oui;
907  hash_set (dm->vss_index_by_vrf_id, tbl_id, v - dm->vss);
908 
909  return 0;
910 }
911 
912 
913 static clib_error_t *
915  unformat_input_t * input,
916  vlib_cli_command_t * cmd)
917 {
918  int is_del = 0, got_new_vss=0;
919  u32 oui=0;
920  u32 fib_id=0, tbl_id=~0;
921 
923  {
924  if (unformat (input, "oui %d", &oui))
925  got_new_vss = 1;
926  else if (unformat (input, "vpn-id %d", &fib_id))
927  got_new_vss = 1;
928  else if (unformat (input, "table %d", &tbl_id))
929  got_new_vss = 1;
930  else if (unformat(input, "delete") || unformat(input, "del"))
931  is_del = 1;
932  else
933  break;
934  }
935 
936  if (tbl_id ==~0)
937  return clib_error_return (0, "no table ID specified.");
938 
939  if (is_del || got_new_vss)
940  {
941  int rv;
942 
943  rv = dhcpv6_proxy_set_vss(tbl_id, oui, fib_id, is_del);
944  switch (rv)
945  {
946  case 0:
947  return 0;
948 
949  case VNET_API_ERROR_NO_SUCH_FIB:
950  return clib_error_return (0, "vss info (oui:%d, vpn-id:%d) not found in table %d.",
951  oui, fib_id, tbl_id);
952 
953  case VNET_API_ERROR_NO_SUCH_ENTRY:
954  return clib_error_return (0, "vss for table %d not found in pool.",
955  tbl_id);
956 
957  default:
958  return clib_error_return (0, "BUG: rv %d", rv);
959  }
960  }
961  else
962  return clib_error_return (0, "parse error`%U'",
963  format_unformat_error, input);
964 
965 }
966 
967 VLIB_CLI_COMMAND (dhcpv6_proxy_vss_command, static) = {
968  .path = "set dhcpv6 vss",
969  .short_help = "set dhcpv6 vss table <table-id> oui <oui> vpn-idx <vpn-idx>",
970  .function = dhcpv6_vss_command_fn,
971 };
972 
973 static clib_error_t *
975  unformat_input_t * input,
976  vlib_cli_command_t * cmd)
977 
978 {
980  dhcpv6_vss_info *v;
981  u32 oui;
982  u32 fib_id;
983  u32 tbl_id;
984  uword index;
985 
986  vlib_cli_output (vm, "%=6s%=6s%=12s","Table", "OUI", "VPN ID");
987  hash_foreach (tbl_id, index, dm->vss_index_by_vrf_id,
988  ({
989  v = pool_elt_at_index (dm->vss, index);
990  oui = v->vpn_id.oui;
991  fib_id = v->vpn_id.fib_id;
992  vlib_cli_output (vm, "%=6d%=6d%=12d",
993  tbl_id, oui, fib_id);
994  }));
995 
996  return 0;
997 }
998 
999 VLIB_CLI_COMMAND (dhcpv6_proxy_vss_show_command, static) = {
1000  .path = "show dhcpv6 vss",
1001  .short_help = "show dhcpv6 VSS",
1002  .function = dhcpv6_vss_show_command_fn,
1003 };
1004 
1005 static clib_error_t *
1007  unformat_input_t * input,
1008  vlib_cli_command_t * cmd)
1009 
1010 {
1012  vnet_main_t *vnm = vnet_get_main();
1013  u32 sw_if_index0=0, sw_if_index;
1014  ip6_address_t *ia0;
1015  vnet_sw_interface_t *swif;
1016 
1017  while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT)
1018  {
1019 
1020  if (unformat(input, "%U",
1021  unformat_vnet_sw_interface, dm->vnet_main, &sw_if_index0))
1022  {
1023  swif = vnet_get_sw_interface (vnm, sw_if_index0);
1024  sw_if_index = (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED) ?
1025  swif->unnumbered_sw_if_index : sw_if_index0;
1026  ia0 = ip6_interface_first_address(&ip6_main, sw_if_index);
1027  if (ia0)
1028  {
1029  vlib_cli_output (vm, "%=20s%=48s", "interface", "link-address");
1030 
1031  vlib_cli_output (vm, "%=20U%=48U",
1032  format_vnet_sw_if_index_name, dm->vnet_main, sw_if_index0,
1033  format_ip6_address, ia0);
1034  } else
1035  vlib_cli_output (vm, "%=34s%=20U", "No IPv6 address configured on",
1036  format_vnet_sw_if_index_name, dm->vnet_main, sw_if_index);
1037  } else
1038  break;
1039  }
1040 
1041  return 0;
1042 }
1043 
1044 VLIB_CLI_COMMAND (dhcpv6_proxy_address_show_command, static) = {
1045  .path = "show dhcpv6 link-address interface",
1046  .short_help = "show dhcpv6 link-address interface <interface>",
1048 };
static clib_error_t * dhcpv6_vss_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: proxy_node.c:914
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:457
#define foreach_ip_interface_address(lm, a, sw_if_index, loop, body)
Definition: lookup.h:434
#define VNET_SW_INTERFACE_FLAG_UNNUMBERED
Definition: interface.h:497
#define hash_set(h, key, value)
Definition: hash.h:254
int dhcpv6_proxy_set_server(ip6_address_t *addr, ip6_address_t *src_address, u32 fib_id, int insert_vss, int is_del)
Definition: proxy_node.c:725
#define CLIB_UNUSED(x)
Definition: clib.h:79
dhcpv6_proxy_main_t dhcpv6_proxy_main
Definition: proxy.h:78
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
#define hash_unset(h, key)
Definition: hash.h:260
a
Definition: bitmap.h:516
static ip6_fib_t * ip6_fib_get(fib_node_index_t index)
Definition: ip6_fib.h:108
format_function_t format_ip6_address
Definition: format.h:94
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:126
u32 free_list_index
Buffer free list that this buffer was allocated from and will be freed to.
Definition: buffer.h:108
u8 as_u8[16]
Definition: ip6_packet.h:47
u64 as_u64[2]
Definition: ip6_packet.h:50
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
u32 index
Definition: node.h:237
#define ethernet_buffer_header_size(b)
Determine the size of the Ethernet headers of the current frame in the buffer.
Definition: ethernet.h:409
u8 src_address[6]
Definition: packet.h:54
struct _vlib_node_registration vlib_node_registration_t
ip6_address_t all_dhcpv6_server_relay_agent_address
Definition: proxy.h:60
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
unformat_function_t unformat_vnet_sw_interface
#define HOP_COUNT_LIMIT
Definition: packet.h:28
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
ip6_address_t src_address
Definition: ip6_packet.h:300
format_function_t format_vnet_sw_if_index_name
u32 oui
Definition: proxy.h:39
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:78
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
static ip6_address_t * ip6_interface_first_address(ip6_main_t *im, u32 sw_if_index)
Definition: proxy_node.c:113
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:190
vnet_main_t * vnet_main
Definition: proxy.h:75
u32 server_fib_index
Definition: proxy.h:53
u8 dst_address[6]
Definition: packet.h:53
#define hash_foreach(key_var, value_var, h, body)
Definition: hash.h:418
ip6_address_t dhcpv6_server
Definition: proxy.h:50
u32 fib_id
Definition: proxy.h:40
#define hash_get(h, key)
Definition: hash.h:248
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
vnet_sub_interface_t sub
Definition: interface.h:522
static clib_error_t * dhcpv6_link_address_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: proxy_node.c:1006
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:82
vlib_node_registration_t dhcpv6_proxy_to_server_node
(constructor) VLIB_REGISTER_NODE (dhcpv6_proxy_to_server_node)
Definition: proxy_node.c:51
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
uword * vss_index_by_vrf_id
Definition: proxy.h:71
#define PREDICT_FALSE(x)
Definition: clib.h:97
int dhcpv6_proxy_set_vss(u32 tbl_id, u32 oui, u32 fib_id, int is_del)
Definition: proxy_node.c:865
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:194
#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
u8 * format_dhcpv6_proxy_server(u8 *s, va_list *args)
Definition: proxy_node.c:822
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:575
static uword dhcpv6_proxy_to_server_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: proxy_node.c:137
union dhcpv6_hdr_::@113 u
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1113
unformat_function_t unformat_ip6_address
Definition: format.h:93
u8 * format_dhcpv6_proxy_header_with_length(u8 *s, va_list *args)
Definition: proxy_node.c:76
uword * fib_index_by_table_id
Definition: ip6.h:148
u16 n_vectors
Definition: node.h:344
static clib_error_t * dhcpv6_proxy_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: proxy_node.c:848
Definition: ip6.h:66
dhcpv6_vss_id vpn_id
Definition: proxy.h:45
clib_error_t * dhcpv6_proxy_init(vlib_main_t *vm)
Definition: proxy_node.c:697
#define clib_memcpy(a, b, c)
Definition: string.h:64
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:203
#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:1105
dhcpv6_proxy_to_server_input_next_t
Definition: proxy_node.c:35
u16 cached_next_index
Definition: node.h:463
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
#define vnet_buffer(b)
Definition: buffer.h:333
ip6_main_t ip6_main
Definition: ip6_forward.c:2655
ip_lookup_main_t lookup_main
Definition: ip6.h:132
static clib_error_t * dhcpv6_proxy_set_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: proxy_node.c:764
vlib_node_registration_t dhcpv6_proxy_to_client_node
(constructor) VLIB_REGISTER_NODE (dhcpv6_proxy_to_client_node)
Definition: proxy_node.c:52
u8 * format_dhcpv6_proxy_trace(u8 *s, va_list *args)
Definition: proxy_node.c:55
u8 msg_type
Definition: packet.h:103
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:95
u64 uword
Definition: types.h:112
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
u32 ip_version_traffic_class_and_flow_label
Definition: ip6_packet.h:287
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
Definition: defs.h:47
unsigned short u16
Definition: types.h:57
dhcpv6_vss_info * vss
Definition: proxy.h:68
u16 payload_length
Definition: ip6_packet.h:291
unsigned char u8
Definition: types.h:56
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:253
static void copy_ip6_address(ip6_address_t *dst, ip6_address_t *src)
Definition: proxy_node.c:129
ip6_address_t all_dhcpv6_server_address
Definition: proxy.h:59
#define foreach_dhcpv6_proxy_to_server_input_next
Definition: proxy_node.c:29
static char * dhcpv6_proxy_error_strings[]
Definition: proxy_node.c:23
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
vnet_sw_interface_type_t type
Definition: interface.h:485
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
u8 data[0]
Packet data.
Definition: buffer.h:154
static clib_error_t * dhcpv6_vss_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: proxy_node.c:974
u32 table_id
Definition: ip6.h:68
vhost_vring_addr_t addr
Definition: vhost-user.h:81
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:458
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
static vlib_buffer_free_list_t * vlib_buffer_get_free_list(vlib_main_t *vm, u32 free_list_index)
Definition: buffer_funcs.h:337
static void * ip_interface_address_get_address(ip_lookup_main_t *lm, ip_interface_address_t *a)
Definition: lookup.h:431
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:185
ethernet_interface_t * interfaces
Definition: ethernet.h:243
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:85
ip6_address_t dhcpv6_src_address
Definition: proxy.h:56
vlib_main_t * vlib_main
Definition: proxy.h:74
u32 * fib_index_by_sw_if_index
Definition: ip6.h:141
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
#define PROTO_UDP
Definition: packet.h:25
Definition: defs.h:46
ip6_address_t dst_address
Definition: ip6_packet.h:300
static ip6_address_t * ip6_interface_first_global_or_site_address(ip6_main_t *im, u32 sw_if_index)
Definition: proxy_node.c:92
u32 error_drop_node_index
Definition: proxy.h:66
static uword dhcpv6_proxy_to_client_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: proxy_node.c:481