FD.io VPP  v16.09
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 
22 static char * dhcpv6_proxy_error_strings[] = {
23 #define dhcpv6_proxy_error(n,s) s,
24 #include "proxy_error.def"
25 #undef dhcpv6_proxy_error
26 };
27 
28 #define foreach_dhcpv6_proxy_to_server_input_next \
29  _ (DROP, "error-drop") \
30  _ (LOOKUP, "ip6-lookup") \
31  _ (SEND_TO_CLIENT, "dhcpv6-proxy-to-client")
32 
33 
34 typedef enum {
35 #define _(s,n) DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_##s,
37 #undef _
40 
41 typedef struct {
42  /* 0 => to server, 1 => to client */
43  int which;
44  u8 packet_data[64];
49 
52 
53 
54 u8 * format_dhcpv6_proxy_trace (u8 * s, va_list * args)
55 {
56  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
57  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
58  dhcpv6_proxy_trace_t * t = va_arg (*args, dhcpv6_proxy_trace_t *);
59 
60  if (t->which == 0)
61  s = format (s, "DHCPV6 proxy: sent to server %U",
63  else
64  s = format (s, "DHCPV6 proxy: sent to client from %U",
66  if (t->error != (u32)~0)
67  s = format (s, " error: %s\n", dhcpv6_proxy_error_strings[t->error]);
68 
69  s = format (s, " original_sw_if_index: %d, sw_if_index: %d\n",
71 
72  return s;
73 }
74 
76 {
77  dhcpv6_header_t * h = va_arg (*args, dhcpv6_header_t *);
78  u32 max_header_bytes = va_arg (*args, u32);
79  u32 header_bytes;
80 
81  header_bytes = sizeof (h[0]);
82  if (max_header_bytes != 0 && header_bytes > max_header_bytes)
83  return format (s, "dhcpv6 header truncated");
84 
85  s = format (s, "DHCPV6 Proxy");
86 
87  return s;
88 }
89 /* get first interface address */
90 static ip6_address_t *
92 {
93  ip_lookup_main_t * lm = &im->lookup_main;
94  ip_interface_address_t * ia = 0;
95  ip6_address_t * result = 0;
96 
97  foreach_ip_interface_address (lm, ia, sw_if_index,
98  1 /* honor unnumbered */,
99  ({
101  if ((a->as_u8[0] & 0xe0) == 0x20 ||
102  (a->as_u8[0] & 0xfe) == 0xfc) {
103  result = a;
104  break;
105  }
106  }));
107  return result;
108 }
109 
110 /* get first interface address */
111 static ip6_address_t *
113 {
114  ip_lookup_main_t * lm = &im->lookup_main;
115  ip_interface_address_t * ia = 0;
116  ip6_address_t * result = 0;
117 
118  foreach_ip_interface_address (lm, ia, sw_if_index,
119  1 /* honor unnumbered */,
120  ({
122  result = a;
123  break;
124  }));
125  return result;
126 }
127 
128 static inline void copy_ip6_address (ip6_address_t *dst, ip6_address_t *src)
129 {
130 
131  dst->as_u64[0] = src->as_u64[0];
132  dst->as_u64[1] = src->as_u64[1];
133 }
134 
135 static uword
137  vlib_node_runtime_t * node,
138  vlib_frame_t * from_frame)
139 {
140  u32 n_left_from, next_index, * from, * to_next;
142  from = vlib_frame_vector_args (from_frame);
143  n_left_from = from_frame->n_vectors;
144  u32 pkts_to_server=0, pkts_to_client=0;
145  u32 pkts_no_interface_address=0, pkts_no_exceeding_max_hop=0;
146  u32 pkts_no_src_address=0;
147  u32 pkts_wrong_msg_type=0;
148  u32 pkts_too_big=0;
149  ip6_main_t * im = &ip6_main;
150  u32 fib_index=0, fib_id=0;
151  ip6_fib_t * fib;
152  ip6_address_t * src;
153  int bogus_length;
154 
155  next_index = node->cached_next_index;
156 
157  while (n_left_from > 0)
158  {
159  u32 n_left_to_next;
160 
161  vlib_get_next_frame (vm, node, next_index,
162  to_next, n_left_to_next);
163 
164  while (n_left_from > 0 && n_left_to_next > 0)
165  {
166  vnet_main_t *vnm = vnet_get_main();
167  u32 sw_if_index = 0;
168  u32 original_sw_if_index = 0;
169  vnet_sw_interface_t *swif;
170  u32 bi0;
171  vlib_buffer_t * b0;
172  udp_header_t * u0, *u1;
173  dhcpv6_header_t * h0; // client msg hdr
174  ip6_header_t * ip0, *ip1;
175  ip6_address_t _ia0, *ia0=&_ia0;
176  u32 next0;
177  u32 error0 = (u32) ~0;
178  dhcpv6_option_t *fwd_opt;
179  dhcpv6_relay_hdr_t *r1;
180  u16 len;
181  dhcpv6_int_id_t *id1;
182  dhcpv6_vss_t *vss1;
183  dhcpv6_client_mac_t *cmac; // client mac
184  ethernet_header_t * e_h0;
185  u8 client_src_mac[6];
187 
188  uword *p_vss;
189  u32 oui1=0;
190  u32 fib_id1;
191  dhcpv6_vss_info *vss;
192 
193  fib_id1 = 0;
194  bi0 = from[0];
195  to_next[0] = bi0;
196  from += 1;
197  to_next += 1;
198  n_left_from -= 1;
199  n_left_to_next -= 1;
200 
201  b0 = vlib_get_buffer (vm, bi0);
202 
203  h0 = vlib_buffer_get_current (b0);
204 
205  /* Send to DHCPV6 server via the configured FIB */
206  vnet_buffer(b0)->sw_if_index[VLIB_TX] =
207  dpm->server_fib_index;
208 
209  /*
210  * udp_local hands us the DHCPV6 header.
211  */
212  u0 = (void *)h0 -(sizeof(*u0));
213  ip0 = (void *)u0 -(sizeof(*ip0));
214  e_h0 = (void *)ip0 - ethernet_buffer_header_size(b0);
215 
216  clib_memcpy(client_src_mac, e_h0->src_address, 6);
217 
218  switch (h0->u.msg_type) {
219  case DHCPV6_MSG_SOLICIT:
220  case DHCPV6_MSG_REQUEST:
221  case DHCPV6_MSG_CONFIRM:
222  case DHCPV6_MSG_RENEW:
223  case DHCPV6_MSG_REBIND:
224  case DHCPV6_MSG_RELEASE:
225  case DHCPV6_MSG_DECLINE:
228  /* send to server */
229  break;
231  /* send to client */
232  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_SEND_TO_CLIENT;
233  error0 = 0;
234  pkts_to_client++;
235  goto do_enqueue;
236  default:
237  /* drop the packet */
238  pkts_wrong_msg_type++;
239  error0 = DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE;
240  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
241  goto do_trace;
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  original_sw_if_index = sw_if_index =
293  vnet_buffer(b0)->sw_if_index[VLIB_RX];
294  swif = vnet_get_sw_interface (vnm, sw_if_index);
296  sw_if_index = swif->unnumbered_sw_if_index;
297 
299  if (ia0 == 0)
300  {
301  error0 = DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS;
302  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
303  pkts_no_interface_address++;
304  goto do_trace;
305  }
306 
307  copy_ip6_address(&r1->link_addr, ia0);
308 
309  link_address_set:
311 
312  if ((b0->current_length+sizeof(*id1)+sizeof(*vss1)+sizeof(*cmac))
313  > fl->n_data_bytes)
314  {
315  error0 = DHCPV6_PROXY_ERROR_PKT_TOO_BIG;
316  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
317  pkts_too_big++;
318  goto do_trace;
319  }
320 
321  id1 = (dhcpv6_int_id_t *) (((uword) ip1) + b0->current_length);
322  b0->current_length += (sizeof (*id1));
323 
324  fib_index = im->fib_index_by_sw_if_index
325  [vnet_buffer(b0)->sw_if_index[VLIB_RX]];
326  fib = vec_elt_at_index (im->fibs, fib_index);
327  fib_id = fib->table_id;
328 
329  p_vss = hash_get (dpm->vss_index_by_vrf_id,
330  fib_id);
331  if (p_vss)
332  {
333  vss = pool_elt_at_index (dpm->vss, p_vss[0]);
334  oui1 = vss->vpn_id.oui;
335  fib_id1 = vss->vpn_id.fib_id;
336  }
337 
338  id1->opt.option = clib_host_to_net_u16(DHCPV6_OPTION_INTERFACE_ID);
339  id1->opt.length = clib_host_to_net_u16(sizeof(original_sw_if_index));
340  id1->int_idx = clib_host_to_net_u32(original_sw_if_index);
341 
342  u1->length =0;
343  if (h0->u.msg_type != DHCPV6_MSG_RELAY_FORW)
344  {
345  cmac = (dhcpv6_client_mac_t *) (((uword) ip1) + b0->current_length);
346  b0->current_length += (sizeof (*cmac));
347  cmac->opt.length =clib_host_to_net_u16(sizeof(*cmac) -
348  sizeof(cmac->opt));
349  cmac->opt.option = clib_host_to_net_u16(DHCPV6_OPTION_CLIENT_LINK_LAYER_ADDRESS);
350  cmac->link_type = clib_host_to_net_u16(1); // ethernet
351  clib_memcpy(cmac->data, client_src_mac, 6);
352  u1->length += sizeof(*cmac);
353  }
354  if (oui1 || fib_id1) {
355  vss1 = (dhcpv6_vss_t *) (((uword) ip1) + b0->current_length);
356  b0->current_length += (sizeof (*vss1));
357  vss1->opt.length =clib_host_to_net_u16(sizeof(*vss1) -
358  sizeof(vss1->opt));
359  vss1->opt.option = clib_host_to_net_u16(DHCPV6_OPTION_VSS);
360  vss1->data[0] = 1; // type
361  vss1->data[1] = oui1>>16 & 0xff;
362  vss1->data[2] = oui1>>8 & 0xff;
363  vss1->data[3] = oui1 & 0xff;
364  vss1->data[4] = fib_id1>>24 & 0xff;
365  vss1->data[5] = fib_id1>>16 & 0xff;
366  vss1->data[6] = fib_id1>>8 & 0xff;
367  vss1->data[7] = fib_id1 & 0xff;
368  u1->length += sizeof(*vss1);
369  }
370 
371  pkts_to_server++;
372  u1->checksum = 0;
373  u1->src_port = clib_host_to_net_u16(UDP_DST_PORT_dhcpv6_to_client);
374  u1->dst_port = clib_host_to_net_u16(UDP_DST_PORT_dhcpv6_to_server);
375 
376  u1->length =
377  clib_host_to_net_u16( clib_net_to_host_u16(fwd_opt->length) +
378  sizeof(*r1) + sizeof(*fwd_opt) +
379  sizeof(*u1) + sizeof(*id1) + u1->length);
380 
381  memset(ip1, 0, sizeof(*ip1));
382  ip1->ip_version_traffic_class_and_flow_label = 0x60;
383  ip1->payload_length = u1->length;
384  ip1->protocol = PROTO_UDP;
385  ip1->hop_limit = HOP_COUNT_LIMIT;
386  src = (dpm->dhcpv6_server.as_u64[0] || dpm->dhcpv6_server.as_u64[1]) ?
388  copy_ip6_address(&ip1->dst_address, src);
389 
390 
392  (&ip6_main, vnet_buffer(b0)->sw_if_index[VLIB_RX]);
393 
394  src = (dpm->dhcpv6_src_address.as_u64[0] || dpm->dhcpv6_src_address.as_u64[1]) ?
395  &dpm->dhcpv6_src_address : ia0;
396  if (ia0 == 0)
397  {
398  error0 = DHCPV6_PROXY_ERROR_NO_SRC_ADDRESS;
399  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
400  pkts_no_src_address++;
401  goto do_trace;
402  }
403 
404  copy_ip6_address (&ip1->src_address, src);
405 
406 
407  u1->checksum = ip6_tcp_udp_icmp_compute_checksum(vm, b0, ip1,
408  &bogus_length);
409  ASSERT(bogus_length == 0);
410 
411  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP;
412 
413  do_trace:
415  {
416  dhcpv6_proxy_trace_t *tr = vlib_add_trace (vm, node,
417  b0, sizeof (*tr));
418  tr->which = 0; /* to server */
419  tr->error = error0;
420  tr->original_sw_if_index = original_sw_if_index;
421  tr->sw_if_index = sw_if_index;
422  if (DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP == next0)
424  }
425 
426  do_enqueue:
427  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
428  to_next, n_left_to_next,
429  bi0, next0);
430  }
431 
432  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
433  }
434 
436  DHCPV6_PROXY_ERROR_RELAY_TO_CLIENT,
437  pkts_to_client);
439  DHCPV6_PROXY_ERROR_RELAY_TO_SERVER,
440  pkts_to_server);
442  DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS,
443  pkts_no_interface_address);
445  DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE,
446  pkts_wrong_msg_type);
448  DHCPV6_PROXY_ERROR_NO_SRC_ADDRESS,
449  pkts_no_src_address);
451  DHCPV6_PROXY_ERROR_PKT_TOO_BIG,
452  pkts_too_big);
453  return from_frame->n_vectors;
454 }
455 
457  .function = dhcpv6_proxy_to_server_input,
458  .name = "dhcpv6-proxy-to-server",
459  /* Takes a vector of packets. */
460  .vector_size = sizeof (u32),
461 
462  .n_errors = DHCPV6_PROXY_N_ERROR,
463  .error_strings = dhcpv6_proxy_error_strings,
464 
465  .n_next_nodes = DHCPV6_PROXY_TO_SERVER_INPUT_N_NEXT,
466  .next_nodes = {
467 #define _(s,n) [DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_##s] = n,
469 #undef _
470  },
471 
473  .format_trace = format_dhcpv6_proxy_trace,
474 #if 0
475  .unformat_buffer = unformat_dhcpv6_proxy_header,
476 #endif
477 };
478 
479 static uword
481  vlib_node_runtime_t * node,
482  vlib_frame_t * from_frame)
483 {
484 
485  u32 n_left_from, * from;
488  vnet_main_t * vnm = vnet_get_main();
489  int bogus_length;
490 
491  from = vlib_frame_vector_args (from_frame);
492  n_left_from = from_frame->n_vectors;
493 
494  while (n_left_from > 0)
495  {
496  u32 bi0;
497  vlib_buffer_t * b0;
498  udp_header_t * u0, *u1=0;
499  dhcpv6_relay_hdr_t * h0;
500  ip6_header_t * ip1 = 0, *ip0;
501  ip6_address_t _ia0, * ia0 = &_ia0;
502  ip6_address_t client_address;
504  ethernet_header_t *mac0;
505  vnet_hw_interface_t *hi0;
506  vlib_frame_t *f0;
507  u32 * to_next0;
508  u32 sw_if_index = ~0;
509  u32 original_sw_if_index = ~0;
510  vnet_sw_interface_t *si0;
511  u32 error0 = (u32)~0;
512  vnet_sw_interface_t *swif;
513  dhcpv6_option_t *r0, *o;
514  u16 len = 0;
515  u32 svr_fib_index, svr_fib_id;
516  ip6_fib_t * svr_fib;
517  ip6_main_t * im = &ip6_main;
518 
519  bi0 = from[0];
520  from += 1;
521  n_left_from -= 1;
522 
523  b0 = vlib_get_buffer (vm, bi0);
524  h0 = vlib_buffer_get_current (b0);
525 
526  if (DHCPV6_MSG_RELAY_REPL != h0->msg_type)
527  {
528  error0 = DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE;
529 
530  drop_packet:
532  error0, 1);
533 
535  to_next0 = vlib_frame_vector_args (f0);
536  to_next0[0] = bi0;
537  f0->n_vectors = 1;
539  goto do_trace;
540  }
541  /* hop count seems not need to be checked */
542  if (HOP_COUNT_LIMIT < h0->hop_count)
543  {
545  goto drop_packet;
546  }
547  u0 = (void *)h0 -(sizeof(*u0));
548  ip0 = (void *)u0 -(sizeof(*ip0));
549 
550  vlib_buffer_advance (b0, sizeof(*h0));
551  o = r0 = vlib_buffer_get_current (b0);
552 
553  /* Parse through TLVs looking for option 9 (DHCPV6_OPTION_INTERFACE_ID).
554  The interface-ID is the FIB number we need
555  to track down the client-facing interface */
556 
557  while ((u8 *) o < (b0->data + b0->current_data + b0->current_length))
558  {
559  if (DHCPV6_OPTION_INTERFACE_ID == clib_net_to_host_u16(o->option))
560  {
561  if (clib_net_to_host_u16(o->length) == sizeof(sw_if_index))
562  sw_if_index = clib_net_to_host_u32(((dhcpv6_int_id_t*)o)->int_idx);
563  break;
564  }
565  o = (dhcpv6_option_t *) (((uword) o) + clib_net_to_host_u16(o->length) + sizeof(*o));
566  }
567 
568  if ((u32)~0 == sw_if_index)
569  {
570  error0 = DHCPV6_PROXY_ERROR_NO_CIRCUIT_ID_OPTION;
571  goto drop_packet;
572  }
573 
574  svr_fib_index = im->fib_index_by_sw_if_index
575  [vnet_buffer(b0)->sw_if_index[VLIB_RX]];
576  svr_fib = vec_elt_at_index (im->fibs, svr_fib_index);
577  svr_fib_id = svr_fib->table_id;
578 
579  if (svr_fib_id != dpm->server_fib_index ||
580  ip0->src_address.as_u64[0] != dpm->dhcpv6_server.as_u64[0] ||
581  ip0->src_address.as_u64[1] != dpm->dhcpv6_server.as_u64[1])
582  {
583  //drop packet if not from server with configured address or FIB
584  error0 = DHCPV6_PROXY_ERROR_BAD_SVR_FIB_OR_ADDRESS;
585  goto drop_packet;
586  }
587 
588  vnet_buffer (b0)->sw_if_index[VLIB_TX] = original_sw_if_index
589  = sw_if_index;
590 
591  swif = vnet_get_sw_interface (vnm, original_sw_if_index);
593  sw_if_index = swif->unnumbered_sw_if_index;
594 
595  vlib_buffer_advance (b0, sizeof(*r0));
596  /*
597  * udp_local hands us the DHCPV6 header, need udp hdr,
598  * ip hdr to relay to client
599  */
600  vlib_buffer_advance (b0, -(sizeof(*u1)));
601  u1 = vlib_buffer_get_current (b0);
602 
603  vlib_buffer_advance (b0, -(sizeof(*ip1)));
604  ip1 = vlib_buffer_get_current (b0);
605 
606  copy_ip6_address(&client_address, &h0->peer_addr);
607 
608  ia0 = ip6_interface_first_address (&ip6_main, sw_if_index);
609  if (ia0 == 0)
610  {
611  error0 = DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS;
612  goto drop_packet;
613  }
614 
615  len = clib_net_to_host_u16(r0->length);
616  memset(ip1, 0, sizeof(*ip1));
617  copy_ip6_address(&ip1->dst_address, &client_address);
618  u1->checksum = 0;
619  u1->src_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcpv6_to_server);
620  u1->dst_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcpv6_to_client);
621  u1->length = clib_host_to_net_u16 (len + sizeof(udp_header_t));
622 
624  ip0->ip_version_traffic_class_and_flow_label &
625  0x00000fff;
626  ip1->payload_length = u1->length;
627  ip1->protocol = PROTO_UDP;
628  ip1->hop_limit = HOP_COUNT_LIMIT;
629  copy_ip6_address(&ip1->src_address, ia0);
630 
631  u1->checksum = ip6_tcp_udp_icmp_compute_checksum(vm, b0, ip1,
632  &bogus_length);
633  ASSERT(bogus_length == 0);
634 
635  vlib_buffer_advance (b0, -(sizeof(ethernet_header_t)));
636  si0 = vnet_get_sw_interface (vnm, original_sw_if_index);
637  if (si0->type == VNET_SW_INTERFACE_TYPE_SUB)
638  vlib_buffer_advance (b0, -4 /* space for VLAN tag */);
639 
640  mac0 = vlib_buffer_get_current (b0);
641 
642  hi0 = vnet_get_sup_hw_interface (vnm, original_sw_if_index);
643  ei0 = pool_elt_at_index (em->interfaces, hi0->hw_instance);
644  clib_memcpy (mac0->src_address, ei0->address, sizeof (ei0->address));
645  memset (&mac0->dst_address, 0xff, sizeof (mac0->dst_address));
646  mac0->type = (si0->type == VNET_SW_INTERFACE_TYPE_SUB) ?
647  clib_net_to_host_u16(0x8100) : clib_net_to_host_u16 (0x86dd);
648 
649  if (si0->type == VNET_SW_INTERFACE_TYPE_SUB)
650  {
651  u32 * vlan_tag = (u32 *)(mac0+1);
652  u32 tmp;
653  tmp = (si0->sub.id << 16) | 0x0800;
654  *vlan_tag = clib_host_to_net_u32 (tmp);
655  }
656 
657  /* $$$ consider adding a dynamic next to the graph node, for performance */
659  to_next0 = vlib_frame_vector_args (f0);
660  to_next0[0] = bi0;
661  f0->n_vectors = 1;
663 
664  do_trace:
666  {
667  dhcpv6_proxy_trace_t *tr = vlib_add_trace (vm, node,
668  b0, sizeof (*tr));
669  tr->which = 1; /* to client */
670  if (ia0)
672  tr->error = error0;
673  tr->original_sw_if_index = original_sw_if_index;
674  tr->sw_if_index = sw_if_index;
675  }
676  }
677  return from_frame->n_vectors;
678 
679 }
680 
682  .function = dhcpv6_proxy_to_client_input,
683  .name = "dhcpv6-proxy-to-client",
684  /* Takes a vector of packets. */
685  .vector_size = sizeof (u32),
686 
687  .n_errors = DHCPV6_PROXY_N_ERROR,
688  .error_strings = dhcpv6_proxy_error_strings,
690  .format_trace = format_dhcpv6_proxy_trace,
691 #if 0
692  .unformat_buffer = unformat_dhcpv6_proxy_header,
693 #endif
694 };
695 
697 {
699  vlib_node_t * error_drop_node;
700 
701  dm->vlib_main = vm;
702  dm->vnet_main = vnet_get_main();
703  error_drop_node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
704  dm->error_drop_node_index = error_drop_node->index;
705 
706  /* RFC says this is the dhcpv6 server address */
707  dm->all_dhcpv6_server_address.as_u64[0] = clib_host_to_net_u64 (0xFF05000000000000);
708  dm->all_dhcpv6_server_address.as_u64[1] = clib_host_to_net_u64 (0x00010003);
709 
710  /* RFC says this is the server and agent address */
711  dm->all_dhcpv6_server_relay_agent_address.as_u64[0] = clib_host_to_net_u64 (0xFF02000000000000);
712  dm->all_dhcpv6_server_relay_agent_address.as_u64[1] = clib_host_to_net_u64 (0x00010002);
713 
714  udp_register_dst_port (vm, UDP_DST_PORT_dhcpv6_to_client,
715  dhcpv6_proxy_to_client_node.index, 0 /* is_ip4 */);
716 
717  udp_register_dst_port (vm, UDP_DST_PORT_dhcpv6_to_server,
718  dhcpv6_proxy_to_server_node.index, 0 /* is_ip6 */);
719  return 0;
720 }
721 
723 
725  u32 fib_id, int insert_vss, int is_del)
726 {
728  ip6_main_t * im = &ip6_main;
729  uword * p;
730 
731 
732  if (is_del)
733  {
734  dm->dhcpv6_server.as_u64[0] = 0;
735  dm->dhcpv6_server.as_u64[1] = 0;
736  dm->server_fib_index = 0;
737  dm->dhcpv6_src_address.as_u64[0] = 0;
738  dm->dhcpv6_src_address.as_u64[1] = 0;
739  dm->insert_option = 0;
740  return 0;
741  }
742 
743  if (addr->as_u64[0] == 0 &&
744  addr->as_u64[1] == 0 )
745  return VNET_API_ERROR_INVALID_DST_ADDRESS;
746 
747  if (src_address->as_u64[0] == 0 &&
748  src_address->as_u64[1] == 0)
749  return VNET_API_ERROR_INVALID_SRC_ADDRESS;
750 
751  p = hash_get (im->fib_index_by_table_id, fib_id);
752  if (p == 0)
753  return VNET_API_ERROR_NO_SUCH_FIB;
754 
755  copy_ip6_address(&dm->dhcpv6_server, addr);
756  dm->server_fib_index = p[0];
757  copy_ip6_address(&dm->dhcpv6_src_address, src_address);
758  dm->insert_option = insert_vss;
759  return 0;
760 }
761 
762 static clib_error_t *
764  unformat_input_t * input,
765  vlib_cli_command_t * cmd)
766 {
767  ip6_address_t addr, src_addr;
768  int set_server = 0, set_src_address = 0, add_opt = 0;
769  u32 fib_id = 0;
770  int is_del = 0;
771 
773  {
774  if (unformat (input, "server %U",
775  unformat_ip6_address, &addr))
776  set_server = 1;
777  else if (unformat(input, "src-address %U",
778  unformat_ip6_address, &src_addr))
779  set_src_address =1;
780  else if (unformat (input, "fib-id %d", &fib_id))
781  ;
782  else if (unformat (input, "add-option")
783  || unformat (input, "insert-option"))
784  add_opt = 1;
785  else if (unformat (input, "delete") ||
786  unformat (input, "del"))
787  is_del = 1;
788  else
789  break;
790  }
791 
792  if (is_del || (set_server && set_src_address))
793  {
794  int rv;
795 
796  rv = dhcpv6_proxy_set_server (&addr, &src_addr, fib_id,
797  add_opt, is_del);
798  switch (rv)
799  {
800  case 0:
801  return 0;
802 
803  case -1:
804  return clib_error_return (0, "FIB id %d does not exist", fib_id);
805 
806  default:
807  return clib_error_return (0, "BUG: rv %d", rv);
808  }
809  }
810  else
811  return clib_error_return (0, "parse error`%U'",
812  format_unformat_error, input);
813 }
814 
815 VLIB_CLI_COMMAND (dhcpv6_proxy_set_command, static) = {
816  .path = "set dhcpv6 proxy",
817  .short_help = "set dhcpv6 proxy server <ipv6-addr> fib-id <fib-id> src-address <ipv6-addr>",
818  .function = dhcpv6_proxy_set_command_fn,
819 };
820 
821 u8 * format_dhcpv6_proxy_server (u8 * s, va_list * args)
822 {
823  dhcpv6_proxy_main_t * dm = va_arg (*args, dhcpv6_proxy_main_t *);
824  ip6_fib_t * f;
825  u32 fib_id = (u32)~0;
826 
827  if (dm == 0)
828  {
829  s = format (s, "%=40s%=40s%=14s", "Server Address", "Source Address",
830  "Server FIB");
831  return s;
832  }
833 
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:622
#define VNET_SW_INTERFACE_FLAG_UNNUMBERED
Definition: interface.h:422
#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:724
#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
format_function_t format_ip6_address
Definition: format.h:87
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:96
u32 free_list_index
Buffer free list that this buffer was allocated from and will be freed to.
Definition: buffer.h:105
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:358
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:298
format_function_t format_vnet_sw_if_index_name
u32 oui
Definition: proxy.h:39
union dhcpv6_hdr_::@116 u
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
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:112
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:187
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:407
ip6_fib_t * find_ip6_fib_by_table_index_or_id(ip6_main_t *im, u32 table_index_or_id, u32 flags)
Get or create an IPv6 fib.
Definition: ip6_forward.c:185
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
ip6_fib_t * fibs
Definition: ip6.h:118
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:447
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:50
#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:130
#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:348
u8 * format_dhcpv6_proxy_server(u8 *s, va_list *args)
Definition: proxy_node.c:821
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:136
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1111
unformat_function_t unformat_ip6_address
Definition: format.h:86
u8 * format_dhcpv6_proxy_header_with_length(u8 *s, va_list *args)
Definition: proxy_node.c:75
uword * fib_index_by_table_id
Definition: ip6.h:127
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:64
dhcpv6_vss_id vpn_id
Definition: proxy.h:45
clib_error_t * dhcpv6_proxy_init(vlib_main_t *vm)
Definition: proxy_node.c:696
#define clib_memcpy(a, b, c)
Definition: string.h:63
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:200
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:1666
dhcpv6_proxy_to_server_input_next_t
Definition: proxy_node.c:34
u16 cached_next_index
Definition: node.h:462
#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:335
ip6_main_t ip6_main
Definition: ip6_forward.c:2955
ip_lookup_main_t lookup_main
Definition: ip6.h:110
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
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:763
vlib_node_registration_t dhcpv6_proxy_to_client_node
(constructor) VLIB_REGISTER_NODE (dhcpv6_proxy_to_client_node)
Definition: proxy_node.c:51
u8 * format_dhcpv6_proxy_trace(u8 *s, va_list *args)
Definition: proxy_node.c:54
u8 msg_type
Definition: packet.h:103
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:93
#define IP6_ROUTE_FLAG_FIB_INDEX
Definition: ip6.h:354
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:285
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:289
VLIB_CLI_COMMAND(set_interface_ip_source_and_port_range_check_command, static)
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:251
static void copy_ip6_address(ip6_address_t *dst, ip6_address_t *src)
Definition: proxy_node.c:128
ip6_address_t all_dhcpv6_server_address
Definition: proxy.h:59
#define foreach_dhcpv6_proxy_to_server_input_next
Definition: proxy_node.c:28
static char * dhcpv6_proxy_error_strings[]
Definition: proxy_node.c:22
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:410
u8 data[0]
Packet data.
Definition: buffer.h:151
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:66
vhost_vring_addr_t addr
Definition: vhost-user.h:82
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:461
#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:601
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:216
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:123
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:298
static ip6_address_t * ip6_interface_first_global_or_site_address(ip6_main_t *im, u32 sw_if_index)
Definition: proxy_node.c:91
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:480