FD.io VPP  v17.01-9-ge7dcee4
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, pkts_no_server=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  ip6_fib_t * fib;
152  ip6_address_t * src;
153  int bogus_length;
154  dhcpv6_server_t * server;
155  u32 rx_fib_idx = 0, server_fib_idx = 0;
156  u32 server_idx;
157  u32 fib_id1 = 0;
158 
159  next_index = node->cached_next_index;
160 
161  while (n_left_from > 0)
162  {
163  u32 n_left_to_next;
164 
165  vlib_get_next_frame (vm, node, next_index,
166  to_next, n_left_to_next);
167 
168  while (n_left_from > 0 && n_left_to_next > 0)
169  {
170  vnet_main_t *vnm = vnet_get_main();
171  u32 sw_if_index = 0;
172  u32 rx_sw_if_index = 0;
173  vnet_sw_interface_t *swif;
174  u32 bi0;
175  vlib_buffer_t * b0;
176  udp_header_t * u0, *u1;
177  dhcpv6_header_t * h0; // client msg hdr
178  ip6_header_t * ip0, *ip1;
179  ip6_address_t _ia0, *ia0=&_ia0;
180  u32 next0;
181  u32 error0 = (u32) ~0;
182  dhcpv6_option_t *fwd_opt;
183  dhcpv6_relay_hdr_t *r1;
184  u16 len;
185  dhcpv6_int_id_t *id1;
186  dhcpv6_vss_t *vss1;
187  dhcpv6_client_mac_t *cmac; // client mac
188  ethernet_header_t * e_h0;
189  u8 client_src_mac[6];
191 
192  uword *p_vss;
193  u32 oui1=0;
194  dhcpv6_vss_info *vss;
195 
196 
197  bi0 = from[0];
198  to_next[0] = bi0;
199  from += 1;
200  to_next += 1;
201  n_left_from -= 1;
202  n_left_to_next -= 1;
203 
204  b0 = vlib_get_buffer (vm, bi0);
205 
206  h0 = vlib_buffer_get_current (b0);
207 
208  /*
209  * udp_local hands us the DHCPV6 header.
210  */
211  u0 = (void *)h0 -(sizeof(*u0));
212  ip0 = (void *)u0 -(sizeof(*ip0));
213  e_h0 = (void *)ip0 - ethernet_buffer_header_size(b0);
214 
215  clib_memcpy(client_src_mac, e_h0->src_address, 6);
216 
217  switch (h0->u.msg_type) {
218  case DHCPV6_MSG_SOLICIT:
219  case DHCPV6_MSG_REQUEST:
220  case DHCPV6_MSG_CONFIRM:
221  case DHCPV6_MSG_RENEW:
222  case DHCPV6_MSG_REBIND:
223  case DHCPV6_MSG_RELEASE:
224  case DHCPV6_MSG_DECLINE:
227  /* send to server */
228  break;
230  /* send to client */
231  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_SEND_TO_CLIENT;
232  error0 = 0;
233  pkts_to_client++;
234  goto do_enqueue;
235  default:
236  /* drop the packet */
237  pkts_wrong_msg_type++;
238  error0 = DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE;
239  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
240  goto do_trace;
241 
242  }
243 
244  /* Send to DHCPV6 server via the configured FIB */
245  rx_sw_if_index = sw_if_index = vnet_buffer(b0)->sw_if_index[VLIB_RX];
246  rx_fib_idx = im->fib_index_by_sw_if_index [rx_sw_if_index];
247 
248  if (vec_len(dpm->dhcp6_server_index_by_rx_fib_index) <= rx_fib_idx)
249  goto no_server;
250 
251  server_idx = dpm->dhcp6_server_index_by_rx_fib_index[rx_fib_idx];
252 
254  server_idx)))
255  {
256  no_server:
257  error0 = DHCPV6_PROXY_ERROR_NO_SERVER;
258  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
259  pkts_no_server++;
260  goto do_trace;
261  }
262 
263  server = pool_elt_at_index(dpm->dhcp6_servers, server_idx);
264  if (server->valid == 0)
265  goto no_server;
266 
267  server_fib_idx = server->server_fib6_index;
268  vnet_buffer(b0)->sw_if_index[VLIB_TX] = server_fib_idx;
269 
270 
271  /* relay-option header pointer */
272  vlib_buffer_advance(b0, -(sizeof(*fwd_opt)));
273  fwd_opt = vlib_buffer_get_current(b0);
274  /* relay message header pointer */
275  vlib_buffer_advance(b0, -(sizeof(*r1)));
276  r1 = vlib_buffer_get_current(b0);
277 
278  vlib_buffer_advance(b0, -(sizeof(*u1)));
279  u1 = vlib_buffer_get_current(b0);
280 
281  vlib_buffer_advance(b0, -(sizeof(*ip1)));
282  ip1 = vlib_buffer_get_current(b0);
283 
284  /* fill in all that rubbish... */
285  len = clib_net_to_host_u16(u0->length) - sizeof(udp_header_t);
286  copy_ip6_address(&r1->peer_addr, &ip0->src_address);
287 
288  r1->msg_type = DHCPV6_MSG_RELAY_FORW;
289  fwd_opt->length = clib_host_to_net_u16(len);
290  fwd_opt->option = clib_host_to_net_u16(DHCPV6_OPTION_RELAY_MSG);
291 
292  r1->hop_count++;
293  r1->hop_count = (h0->u.msg_type != DHCPV6_MSG_RELAY_FORW) ? 0 : r1->hop_count;
294 
295  if (PREDICT_FALSE(r1->hop_count >= HOP_COUNT_LIMIT))
296  {
298  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
299  pkts_no_exceeding_max_hop++;
300  goto do_trace;
301  }
302 
303 
304  /* If relay-fwd and src address is site or global unicast address */
305  if (h0->u.msg_type == DHCPV6_MSG_RELAY_FORW &&
306  ((ip0->src_address.as_u8[0] & 0xe0) == 0x20 ||
307  (ip0->src_address.as_u8[0] & 0xfe) == 0xfc))
308  {
309  /* Set link address to zero */
310  r1->link_addr.as_u64[0] = 0;
311  r1->link_addr.as_u64[1] = 0;
312  goto link_address_set;
313  }
314 
315  /* if receiving interface is unnumbered, use receiving interface
316  * IP address as link address, otherwise use the loopback interface
317  * IP address as link address.
318  */
319 
320  swif = vnet_get_sw_interface (vnm, rx_sw_if_index);
322  sw_if_index = swif->unnumbered_sw_if_index;
323 
325  if (ia0 == 0)
326  {
327  error0 = DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS;
328  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
329  pkts_no_interface_address++;
330  goto do_trace;
331  }
332 
333  copy_ip6_address(&r1->link_addr, ia0);
334 
335  link_address_set:
337 
338  if ((b0->current_length+sizeof(*id1)+sizeof(*vss1)+sizeof(*cmac))
339  > fl->n_data_bytes)
340  {
341  error0 = DHCPV6_PROXY_ERROR_PKT_TOO_BIG;
342  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
343  pkts_too_big++;
344  goto do_trace;
345  }
346 
347  id1 = (dhcpv6_int_id_t *) (((uword) ip1) + b0->current_length);
348  b0->current_length += (sizeof (*id1));
349 
350 
351  fib = ip6_fib_get (rx_fib_idx);
352 
353  //TODO: Revisit if hash makes sense here
354  p_vss = hash_get (dpm->vss_index_by_vrf_id,
355  fib->table_id);
356  if (p_vss)
357  {
358  vss = pool_elt_at_index (dpm->vss, p_vss[0]);
359  oui1 = vss->vpn_id.oui;
360  fib_id1 = vss->vpn_id.fib_id;
361  }
362 
363  id1->opt.option = clib_host_to_net_u16(DHCPV6_OPTION_INTERFACE_ID);
364  id1->opt.length = clib_host_to_net_u16(sizeof(rx_sw_if_index));
365  id1->int_idx = clib_host_to_net_u32(rx_sw_if_index);
366 
367  u1->length =0;
368  if (h0->u.msg_type != DHCPV6_MSG_RELAY_FORW)
369  {
370  cmac = (dhcpv6_client_mac_t *) (((uword) ip1) + b0->current_length);
371  b0->current_length += (sizeof (*cmac));
372  cmac->opt.length =clib_host_to_net_u16(sizeof(*cmac) -
373  sizeof(cmac->opt));
374  cmac->opt.option = clib_host_to_net_u16(DHCPV6_OPTION_CLIENT_LINK_LAYER_ADDRESS);
375  cmac->link_type = clib_host_to_net_u16(1); // ethernet
376  clib_memcpy(cmac->data, client_src_mac, 6);
377  u1->length += sizeof(*cmac);
378  }
379  if (server->insert_vss !=0 ) {
380  vss1 = (dhcpv6_vss_t *) (((uword) ip1) + b0->current_length);
381  b0->current_length += (sizeof (*vss1));
382  vss1->opt.length =clib_host_to_net_u16(sizeof(*vss1) -
383  sizeof(vss1->opt));
384  vss1->opt.option = clib_host_to_net_u16(DHCPV6_OPTION_VSS);
385  vss1->data[0] = 1; // type
386  vss1->data[1] = oui1>>16 & 0xff;
387  vss1->data[2] = oui1>>8 & 0xff;
388  vss1->data[3] = oui1 & 0xff;
389  vss1->data[4] = fib_id1>>24 & 0xff;
390  vss1->data[5] = fib_id1>>16 & 0xff;
391  vss1->data[6] = fib_id1>>8 & 0xff;
392  vss1->data[7] = fib_id1 & 0xff;
393  u1->length += sizeof(*vss1);
394  }
395 
396  pkts_to_server++;
397  u1->checksum = 0;
398  u1->src_port = clib_host_to_net_u16(UDP_DST_PORT_dhcpv6_to_client);
399  u1->dst_port = clib_host_to_net_u16(UDP_DST_PORT_dhcpv6_to_server);
400 
401  u1->length =
402  clib_host_to_net_u16( clib_net_to_host_u16(fwd_opt->length) +
403  sizeof(*r1) + sizeof(*fwd_opt) +
404  sizeof(*u1) + sizeof(*id1) + u1->length);
405 
406  memset(ip1, 0, sizeof(*ip1));
407  ip1->ip_version_traffic_class_and_flow_label = 0x60;
408  ip1->payload_length = u1->length;
409  ip1->protocol = PROTO_UDP;
410  ip1->hop_limit = HOP_COUNT_LIMIT;
411  src = (server->dhcp6_server.as_u64[0] || server->dhcp6_server.as_u64[1]) ?
412  &server->dhcp6_server : &dpm->all_dhcpv6_server_address;
413  copy_ip6_address(&ip1->dst_address, src);
414 
415 
417  (&ip6_main, vnet_buffer(b0)->sw_if_index[VLIB_RX]);
418 
419  src = (server->dhcp6_src_address.as_u64[0] || server->dhcp6_src_address.as_u64[1]) ?
420  &server->dhcp6_src_address : ia0;
421  if (ia0 == 0)
422  {
423  error0 = DHCPV6_PROXY_ERROR_NO_SRC_ADDRESS;
424  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
425  pkts_no_src_address++;
426  goto do_trace;
427  }
428 
429  copy_ip6_address (&ip1->src_address, src);
430 
431 
433  &bogus_length);
434  ASSERT(bogus_length == 0);
435 
436  next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP;
437 
438  do_trace:
440  {
441  dhcpv6_proxy_trace_t *tr = vlib_add_trace (vm, node,
442  b0, sizeof (*tr));
443  tr->which = 0; /* to server */
444  tr->error = error0;
445  tr->original_sw_if_index = rx_sw_if_index;
446  tr->sw_if_index = sw_if_index;
447  if (DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP == next0)
449  }
450 
451  do_enqueue:
452  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
453  to_next, n_left_to_next,
454  bi0, next0);
455  }
456 
457  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
458  }
459 
461  DHCPV6_PROXY_ERROR_RELAY_TO_CLIENT,
462  pkts_to_client);
464  DHCPV6_PROXY_ERROR_RELAY_TO_SERVER,
465  pkts_to_server);
467  DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS,
468  pkts_no_interface_address);
470  DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE,
471  pkts_wrong_msg_type);
473  DHCPV6_PROXY_ERROR_NO_SRC_ADDRESS,
474  pkts_no_src_address);
476  DHCPV6_PROXY_ERROR_PKT_TOO_BIG,
477  pkts_too_big);
478  return from_frame->n_vectors;
479 }
480 
482  .function = dhcpv6_proxy_to_server_input,
483  .name = "dhcpv6-proxy-to-server",
484  /* Takes a vector of packets. */
485  .vector_size = sizeof (u32),
486 
487  .n_errors = DHCPV6_PROXY_N_ERROR,
488  .error_strings = dhcpv6_proxy_error_strings,
489 
490  .n_next_nodes = DHCPV6_PROXY_TO_SERVER_INPUT_N_NEXT,
491  .next_nodes = {
492 #define _(s,n) [DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_##s] = n,
494 #undef _
495  },
496 
498  .format_trace = format_dhcpv6_proxy_trace,
499 #if 0
500  .unformat_buffer = unformat_dhcpv6_proxy_header,
501 #endif
502 };
503 
504 static uword
506  vlib_node_runtime_t * node,
507  vlib_frame_t * from_frame)
508 {
509 
510  u32 n_left_from, * from;
513  dhcpv6_server_t * server;
514  vnet_main_t * vnm = vnet_get_main();
515  int bogus_length;
516 
517  from = vlib_frame_vector_args (from_frame);
518  n_left_from = from_frame->n_vectors;
519 
520  while (n_left_from > 0)
521  {
522  u32 bi0;
523  vlib_buffer_t * b0;
524  udp_header_t * u0, *u1=0;
525  dhcpv6_relay_hdr_t * h0;
526  ip6_header_t * ip1 = 0, *ip0;
527  ip6_address_t _ia0, * ia0 = &_ia0;
528  ip6_address_t client_address;
530  ethernet_header_t *mac0;
531  vnet_hw_interface_t *hi0;
532  vlib_frame_t *f0;
533  u32 * to_next0;
534  u32 sw_if_index = ~0;
535  u32 original_sw_if_index = ~0;
536  vnet_sw_interface_t *si0;
537  u32 error0 = (u32)~0;
538  vnet_sw_interface_t *swif;
539  dhcpv6_option_t *r0 = 0, *o;
540  u16 len = 0;
541  u8 interface_opt_flag = 0;
542  u8 relay_msg_opt_flag = 0;
543  ip6_fib_t * svr_fib;
544  ip6_main_t * im = &ip6_main;
545  u32 server_fib_idx, svr_fib_id, client_fib_idx, server_idx;
546 
547  bi0 = from[0];
548  from += 1;
549  n_left_from -= 1;
550 
551  b0 = vlib_get_buffer (vm, bi0);
552  h0 = vlib_buffer_get_current (b0);
553 
554  if (DHCPV6_MSG_RELAY_REPL != h0->msg_type)
555  {
556  error0 = DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE;
557 
558  drop_packet:
560  error0, 1);
561 
563  to_next0 = vlib_frame_vector_args (f0);
564  to_next0[0] = bi0;
565  f0->n_vectors = 1;
567  goto do_trace;
568  }
569  /* hop count seems not need to be checked */
570  if (HOP_COUNT_LIMIT < h0->hop_count)
571  {
573  goto drop_packet;
574  }
575  u0 = (void *)h0 -(sizeof(*u0));
576  ip0 = (void *)u0 -(sizeof(*ip0));
577 
578  vlib_buffer_advance (b0, sizeof(*h0));
579  o = vlib_buffer_get_current (b0);
580 
581  /* Parse through TLVs looking for option 18 (DHCPV6_OPTION_INTERFACE_ID)
582  _and_ option 9 (DHCPV6_OPTION_RELAY_MSG) option which must be there.
583  Currently assuming no other options need to be processed
584  The interface-ID is the FIB number we need
585  to track down the client-facing interface */
586 
587  while ((u8 *) o < (b0->data + b0->current_data + b0->current_length))
588  {
589  if (DHCPV6_OPTION_INTERFACE_ID == clib_net_to_host_u16(o->option))
590  {
591  interface_opt_flag = 1;
592  if (clib_net_to_host_u16(o->length) == sizeof(sw_if_index))
593  sw_if_index = clib_net_to_host_u32(((dhcpv6_int_id_t*)o)->int_idx);
594  if (sw_if_index >= vec_len (im->fib_index_by_sw_if_index))
595  {
596  error0 = DHCPV6_PROXY_ERROR_WRONG_INTERFACE_ID_OPTION;
597  goto drop_packet;
598  }
599  }
600  if (DHCPV6_OPTION_RELAY_MSG == clib_net_to_host_u16(o->option))
601  {
602  relay_msg_opt_flag = 1;
603  r0 = vlib_buffer_get_current (b0);
604  }
605  if ((relay_msg_opt_flag == 1) && (interface_opt_flag == 1))
606  break;
607  vlib_buffer_advance (b0, sizeof(*o) + clib_net_to_host_u16(o->length));
608  o = (dhcpv6_option_t *) (((uword) o) + clib_net_to_host_u16(o->length) + sizeof(*o));
609  }
610 
611  if ((relay_msg_opt_flag == 0) || (r0 == 0))
612  {
613  error0 = DHCPV6_PROXY_ERROR_NO_RELAY_MESSAGE_OPTION;
614  goto drop_packet;
615  }
616 
617  if ((u32)~0 == sw_if_index)
618  {
619  error0 = DHCPV6_PROXY_ERROR_NO_CIRCUIT_ID_OPTION;
620  goto drop_packet;
621  }
622 
623  //Advance buffer to start of encapsulated DHCPv6 message
624  vlib_buffer_advance (b0, sizeof(*r0));
625 
626  client_fib_idx = im->fib_index_by_sw_if_index[sw_if_index];
627  if (client_fib_idx < vec_len(dm->dhcp6_server_index_by_rx_fib_index))
628  server_idx = dm->dhcp6_server_index_by_rx_fib_index[client_fib_idx];
629  else
630  server_idx = 0;
631 
632  if (PREDICT_FALSE (pool_is_free_index (dm->dhcp6_servers, server_idx)))
633  {
634  error0 = DHCPV6_PROXY_ERROR_WRONG_INTERFACE_ID_OPTION;
635  goto drop_packet;
636  }
637 
638  server = pool_elt_at_index (dm->dhcp6_servers, server_idx);
639  if (server->valid == 0)
640  {
641  error0 = DHCPV6_PROXY_ERROR_NO_SERVER;
642  goto drop_packet;
643  }
644 
645 
646  server_fib_idx = im->fib_index_by_sw_if_index
647  [vnet_buffer(b0)->sw_if_index[VLIB_RX]];
648  svr_fib = ip6_fib_get (server_fib_idx);
649  svr_fib_id = svr_fib->table_id;
650 
651  if (svr_fib_id != server->server_fib6_index ||
652  ip0->src_address.as_u64[0] != server->dhcp6_server.as_u64[0] ||
653  ip0->src_address.as_u64[1] != server->dhcp6_server.as_u64[1])
654  {
655  //drop packet if not from server with configured address or FIB
656  error0 = DHCPV6_PROXY_ERROR_BAD_SVR_FIB_OR_ADDRESS;
657  goto drop_packet;
658  }
659 
660  vnet_buffer (b0)->sw_if_index[VLIB_TX] = original_sw_if_index
661  = sw_if_index;
662 
663  swif = vnet_get_sw_interface (vnm, original_sw_if_index);
665  sw_if_index = swif->unnumbered_sw_if_index;
666 
667 
668  /*
669  * udp_local hands us the DHCPV6 header, need udp hdr,
670  * ip hdr to relay to client
671  */
672  vlib_buffer_advance (b0, -(sizeof(*u1)));
673  u1 = vlib_buffer_get_current (b0);
674 
675  vlib_buffer_advance (b0, -(sizeof(*ip1)));
676  ip1 = vlib_buffer_get_current (b0);
677 
678  copy_ip6_address(&client_address, &h0->peer_addr);
679 
680  ia0 = ip6_interface_first_address (&ip6_main, sw_if_index);
681  if (ia0 == 0)
682  {
683  error0 = DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS;
684  goto drop_packet;
685  }
686 
687  len = clib_net_to_host_u16(r0->length);
688  memset(ip1, 0, sizeof(*ip1));
689  copy_ip6_address(&ip1->dst_address, &client_address);
690  u1->checksum = 0;
691  u1->src_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcpv6_to_server);
692  u1->dst_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcpv6_to_client);
693  u1->length = clib_host_to_net_u16 (len + sizeof(udp_header_t));
694 
696  ip0->ip_version_traffic_class_and_flow_label &
697  0x00000fff;
698  ip1->payload_length = u1->length;
699  ip1->protocol = PROTO_UDP;
700  ip1->hop_limit = HOP_COUNT_LIMIT;
701  copy_ip6_address(&ip1->src_address, ia0);
702 
704  &bogus_length);
705  ASSERT(bogus_length == 0);
706 
707  vlib_buffer_advance (b0, -(sizeof(ethernet_header_t)));
708  si0 = vnet_get_sw_interface (vnm, original_sw_if_index);
709  if (si0->type == VNET_SW_INTERFACE_TYPE_SUB)
710  vlib_buffer_advance (b0, -4 /* space for VLAN tag */);
711 
712  mac0 = vlib_buffer_get_current (b0);
713 
714  hi0 = vnet_get_sup_hw_interface (vnm, original_sw_if_index);
715  ei0 = pool_elt_at_index (em->interfaces, hi0->hw_instance);
716  clib_memcpy (mac0->src_address, ei0->address, sizeof (ei0->address));
717  memset (&mac0->dst_address, 0xff, sizeof (mac0->dst_address));
718  mac0->type = (si0->type == VNET_SW_INTERFACE_TYPE_SUB) ?
719  clib_net_to_host_u16(0x8100) : clib_net_to_host_u16 (0x86dd);
720 
721  if (si0->type == VNET_SW_INTERFACE_TYPE_SUB)
722  {
723  u32 * vlan_tag = (u32 *)(mac0+1);
724  u32 tmp;
725  tmp = (si0->sub.id << 16) | 0x0800;
726  *vlan_tag = clib_host_to_net_u32 (tmp);
727  }
728 
729  /* $$$ consider adding a dynamic next to the graph node, for performance */
731  to_next0 = vlib_frame_vector_args (f0);
732  to_next0[0] = bi0;
733  f0->n_vectors = 1;
735 
736  do_trace:
738  {
739  dhcpv6_proxy_trace_t *tr = vlib_add_trace (vm, node,
740  b0, sizeof (*tr));
741  tr->which = 1; /* to client */
742  if (ia0)
744  tr->error = error0;
745  tr->original_sw_if_index = original_sw_if_index;
746  tr->sw_if_index = sw_if_index;
747  }
748  }
749  return from_frame->n_vectors;
750 
751 }
752 
754  .function = dhcpv6_proxy_to_client_input,
755  .name = "dhcpv6-proxy-to-client",
756  /* Takes a vector of packets. */
757  .vector_size = sizeof (u32),
758 
759  .n_errors = DHCPV6_PROXY_N_ERROR,
760  .error_strings = dhcpv6_proxy_error_strings,
762  .format_trace = format_dhcpv6_proxy_trace,
763 #if 0
764  .unformat_buffer = unformat_dhcpv6_proxy_header,
765 #endif
766 };
767 
769 {
771  vlib_node_t * error_drop_node;
772  dhcpv6_server_t * server;
773 
774  dm->vlib_main = vm;
775  dm->vnet_main = vnet_get_main();
776  error_drop_node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
777  dm->error_drop_node_index = error_drop_node->index;
778 
779  dm->vss_index_by_vrf_id = hash_create (0, sizeof (uword));
780 
781  /* RFC says this is the dhcpv6 server address */
782  dm->all_dhcpv6_server_address.as_u64[0] = clib_host_to_net_u64 (0xFF05000000000000);
783  dm->all_dhcpv6_server_address.as_u64[1] = clib_host_to_net_u64 (0x00010003);
784 
785  /* RFC says this is the server and agent address */
786  dm->all_dhcpv6_server_relay_agent_address.as_u64[0] = clib_host_to_net_u64 (0xFF02000000000000);
787  dm->all_dhcpv6_server_relay_agent_address.as_u64[1] = clib_host_to_net_u64 (0x00010002);
788 
789  udp_register_dst_port (vm, UDP_DST_PORT_dhcpv6_to_client,
790  dhcpv6_proxy_to_client_node.index, 0 /* is_ip6 */);
791 
792  udp_register_dst_port (vm, UDP_DST_PORT_dhcpv6_to_server,
793  dhcpv6_proxy_to_server_node.index, 0 /* is_ip6 */);
794 
795  /* Create the default server, don't mark it valid */
796  pool_get (dm->dhcp6_servers, server);
797  memset (server, 0, sizeof (*server));
798 
799  return 0;
800 }
801 
803 
804 /* Old API, manipulates a single server (only) shared by all Rx VRFs */
806  u32 fib_id, int insert_vss, int is_del)
807 {
808  return dhcpv6_proxy_set_server_2 (addr, src_address,
809  0, fib_id,
810  insert_vss, is_del);
811 }
812 
814  u32 rx_fib_id, u32 server_fib_id,
815  int insert_vss, int is_del)
816 {
818  dhcpv6_server_t * server = 0;
819  u32 server_fib_index = 0;
820  u32 rx_fib_index = 0;
821 
822  rx_fib_index = ip6_fib_table_find_or_create_and_lock(rx_fib_id);
823  server_fib_index = ip6_fib_table_find_or_create_and_lock(server_fib_id);
824 
825  if (is_del)
826  {
827 
828  if (rx_fib_index >= vec_len(dm->dhcp6_server_index_by_rx_fib_index))
829  return VNET_API_ERROR_NO_SUCH_ENTRY;
830 
831  server_fib_index = dm->dhcp6_server_index_by_rx_fib_index[rx_fib_index];
832 
833  dm->dhcp6_server_index_by_rx_fib_index[rx_fib_index] = 0;
834  server = pool_elt_at_index (dm->dhcp6_servers, server_fib_index);
835  memset (server, 0, sizeof (*server));
836  pool_put (dm->dhcp6_servers, server);
837  return 0;
838  }
839 
840  if (addr->as_u64[0] == 0 &&
841  addr->as_u64[1] == 0 )
842  return VNET_API_ERROR_INVALID_DST_ADDRESS;
843 
844  if (src_address->as_u64[0] == 0 &&
845  src_address->as_u64[1] == 0)
846  return VNET_API_ERROR_INVALID_SRC_ADDRESS;
847 
848  if (rx_fib_id == 0)
849  {
850  server = pool_elt_at_index (dm->dhcp6_servers, 0);
851 
852  goto initialize_it;
853  }
854 
855  if (rx_fib_index < vec_len(dm->dhcp6_server_index_by_rx_fib_index))
856  {
857  server_fib_index = dm->dhcp6_server_index_by_rx_fib_index[rx_fib_index];
858  if (server_fib_index != 0)
859  {
860  server = pool_elt_at_index (dm->dhcp6_servers, server_fib_index);
861  goto initialize_it;
862  }
863  }
864 
865  /*Allocate a new server*/
866  pool_get (dm->dhcp6_servers, server);
867 
868  initialize_it:
869 
870  copy_ip6_address(&server->dhcp6_server, addr);
871  copy_ip6_address(&server->dhcp6_src_address, src_address);
872  server->server_fib6_index = server_fib_index;
873  server->valid = 1;
874  server->insert_vss = insert_vss;
875 
877  dm->dhcp6_server_index_by_rx_fib_index[rx_fib_index] =
878  server - dm->dhcp6_servers;
879 
880  return 0;
881 }
882 
883 static clib_error_t *
885  unformat_input_t * input,
886  vlib_cli_command_t * cmd)
887 {
888  ip6_address_t addr, src_addr;
889  int set_server = 0, set_src_address = 0;
890  u32 rx_fib_id = 0, server_fib_id = 0;
891  int is_del = 0, add_vss = 0;
892 
894  {
895  if (unformat (input, "server %U",
896  unformat_ip6_address, &addr))
897  set_server = 1;
898  else if (unformat(input, "src-address %U",
899  unformat_ip6_address, &src_addr))
900  set_src_address =1;
901  else if (unformat (input, "server-fib-id %d", &server_fib_id))
902  ;
903  else if (unformat (input, "rx-fib-id %d", &rx_fib_id))
904  ;
905  else if (unformat (input, "add-vss-option")
906  || unformat (input, "insert-option"))
907  add_vss = 1;
908  else if (unformat (input, "delete") ||
909  unformat (input, "del"))
910  is_del = 1;
911  else
912  break;
913  }
914 
915  if (is_del || (set_server && set_src_address))
916  {
917  int rv;
918 
919  rv = dhcpv6_proxy_set_server_2 (&addr, &src_addr, rx_fib_id,
920  server_fib_id, add_vss, is_del);
921 
922  //TODO: Complete the errors
923  switch (rv)
924  {
925  case 0:
926  return 0;
927 
928  case -1:
929  return clib_error_return (0, "FIB id %d does not exist", server_fib_id);
930 
931  default:
932  return clib_error_return (0, "BUG: rv %d", rv);
933  }
934  }
935  else
936  return clib_error_return (0, "parse error`%U'",
937  format_unformat_error, input);
938 }
939 
940 VLIB_CLI_COMMAND (dhcpv6_proxy_set_command, static) = {
941  .path = "set dhcpv6 proxy",
942  .short_help = "set dhcpv6 proxy [del] server <ipv6-addr> src-address <ipv6-addr> "
943  "[add-vss-option] [server-fib-id <fib-id>] [rx-fib-id <fib-id>] ",
944  .function = dhcpv6_proxy_set_command_fn,
945 };
946 
947 u8 * format_dhcpv6_proxy_server (u8 * s, va_list * args)
948 {
949  dhcpv6_proxy_main_t * dm = va_arg (*args, dhcpv6_proxy_main_t *);
950  dhcpv6_server_t * server = va_arg (*args, dhcpv6_server_t *);
951  u32 rx_fib_index = va_arg (*args, u32);
952  ip6_fib_t * rx_fib, * server_fib;
953  u32 server_fib_id = (u32)~0, rx_fib_id = ~0;
954 
955  if (dm == 0)
956  {
957  s = format (s, "%=40s%=40s%=14s%=14s%=20s", "Server Address", "Source Address",
958  "Server FIB", "RX FIB", "Insert VSS Option");
959  return s;
960  }
961 
962  server_fib = ip6_fib_get(server->server_fib6_index);
963  if (server_fib)
964  server_fib_id= server_fib->table_id;
965 
966  rx_fib= ip6_fib_get(rx_fib_index);
967 
968  if (rx_fib)
969  rx_fib_id = rx_fib->table_id;
970 
971  s = format (s, "%=40U%=40U%=14u%=14u%=20s",
974  server_fib_id, rx_fib_id,
975  server->insert_vss ? "yes" : "no");
976  return s;
977 }
978 
979 static clib_error_t *
981  unformat_input_t * input,
982  vlib_cli_command_t * cmd)
983 {
985  ip6_main_t * im = &ip6_main;
986  int i;
987  u32 server_index;
988  dhcpv6_server_t * server;
989 
990  vlib_cli_output (vm, "%U", format_dhcpv6_proxy_server, 0 /* header line */,
991  0, 0);
992  for (i = 0; i < vec_len (im->fibs); i++)
993  {
995  server_index = dm->dhcp6_server_index_by_rx_fib_index[i];
996  else
997  server_index = 0;
998  server = pool_elt_at_index (dm->dhcp6_servers, server_index);
999  if (server->valid)
1001  server, i);
1002  }
1003  return 0;
1004 }
1005 
1006 VLIB_CLI_COMMAND (dhcpv6_proxy_show_command, static) = {
1007  .path = "show dhcpv6 proxy",
1008  .short_help = "Display dhcpv6 proxy info",
1009  .function = dhcpv6_proxy_show_command_fn,
1010 };
1011 
1013  u32 oui,
1014  u32 fib_id,
1015  int is_del)
1016 {
1018  u32 old_oui, old_fib_id;
1019  uword *p;
1020  dhcpv6_vss_info *v;
1021 
1022  p = hash_get (dm->vss_index_by_vrf_id, tbl_id);
1023 
1024  if (p) {
1025  v = pool_elt_at_index (dm->vss, p[0]);
1026  if (!v)
1027  return VNET_API_ERROR_NO_SUCH_FIB;
1028 
1029  old_oui = v->vpn_id.oui;
1030  old_fib_id = v->vpn_id.fib_id;
1031 
1032  if (is_del)
1033  {
1034  if (old_oui == oui &&
1035  old_fib_id == fib_id )
1036  {
1037  pool_put(dm->vss, v);
1038  hash_unset (dm->vss_index_by_vrf_id, tbl_id);
1039  return 0;
1040  }
1041  else
1042  return VNET_API_ERROR_NO_SUCH_ENTRY;
1043  }
1044 
1045  pool_put(dm->vss, v);
1046  hash_unset (dm->vss_index_by_vrf_id, tbl_id);
1047  } else if (is_del)
1048  return VNET_API_ERROR_NO_SUCH_ENTRY;
1049 
1050  pool_get (dm->vss, v);
1051  memset (v, ~0, sizeof (*v));
1052  v->vpn_id.fib_id = fib_id;
1053  v->vpn_id.oui = oui;
1054  hash_set (dm->vss_index_by_vrf_id, tbl_id, v - dm->vss);
1055 
1056  return 0;
1057 }
1058 
1059 
1060 static clib_error_t *
1062  unformat_input_t * input,
1063  vlib_cli_command_t * cmd)
1064 {
1065  int is_del = 0, got_new_vss=0;
1066  u32 oui=0;
1067  u32 fib_id=0, tbl_id=~0;
1068 
1070  {
1071  if (unformat (input, "oui %d", &oui))
1072  got_new_vss = 1;
1073  else if (unformat (input, "vpn-id %d", &fib_id))
1074  got_new_vss = 1;
1075  else if (unformat (input, "table %d", &tbl_id))
1076  got_new_vss = 1;
1077  else if (unformat(input, "delete") || unformat(input, "del"))
1078  is_del = 1;
1079  else
1080  break;
1081  }
1082 
1083  if (tbl_id ==~0)
1084  return clib_error_return (0, "no table ID specified.");
1085 
1086  if (is_del || got_new_vss)
1087  {
1088  int rv;
1089 
1090  rv = dhcpv6_proxy_set_vss(tbl_id, oui, fib_id, is_del);
1091  switch (rv)
1092  {
1093  case 0:
1094  return 0;
1095 
1096  case VNET_API_ERROR_NO_SUCH_FIB:
1097  return clib_error_return (0, "vss info (oui:%d, vpn-id:%d) not found in table %d.",
1098  oui, fib_id, tbl_id);
1099 
1100  case VNET_API_ERROR_NO_SUCH_ENTRY:
1101  return clib_error_return (0, "vss for table %d not found in pool.",
1102  tbl_id);
1103 
1104  default:
1105  return clib_error_return (0, "BUG: rv %d", rv);
1106  }
1107  }
1108  else
1109  return clib_error_return (0, "parse error`%U'",
1110  format_unformat_error, input);
1111 
1112 }
1113 
1114 VLIB_CLI_COMMAND (dhcpv6_proxy_vss_command, static) = {
1115  .path = "set dhcpv6 vss",
1116  .short_help = "set dhcpv6 vss table <table-id> oui <oui> vpn-idx <vpn-idx>",
1117  .function = dhcpv6_vss_command_fn,
1118 };
1119 
1120 static clib_error_t *
1122  unformat_input_t * input,
1123  vlib_cli_command_t * cmd)
1124 
1125 {
1127  dhcpv6_vss_info *v;
1128  u32 oui;
1129  u32 fib_id;
1130  u32 tbl_id;
1131  uword index;
1132 
1133  vlib_cli_output (vm, "%=6s%=6s%=12s","Table", "OUI", "VPN ID");
1134  hash_foreach (tbl_id, index, dm->vss_index_by_vrf_id,
1135  ({
1136  v = pool_elt_at_index (dm->vss, index);
1137  oui = v->vpn_id.oui;
1138  fib_id = v->vpn_id.fib_id;
1139  vlib_cli_output (vm, "%=6d%=6d%=12d",
1140  tbl_id, oui, fib_id);
1141  }));
1142 
1143  return 0;
1144 }
1145 
1146 VLIB_CLI_COMMAND (dhcpv6_proxy_vss_show_command, static) = {
1147  .path = "show dhcpv6 vss",
1148  .short_help = "show dhcpv6 VSS",
1149  .function = dhcpv6_vss_show_command_fn,
1150 };
1151 
1152 static clib_error_t *
1154  unformat_input_t * input,
1155  vlib_cli_command_t * cmd)
1156 
1157 {
1159  vnet_main_t *vnm = vnet_get_main();
1160  u32 sw_if_index0=0, sw_if_index;
1161  ip6_address_t *ia0;
1162  vnet_sw_interface_t *swif;
1163 
1165  {
1166 
1167  if (unformat(input, "%U",
1168  unformat_vnet_sw_interface, dm->vnet_main, &sw_if_index0))
1169  {
1170  swif = vnet_get_sw_interface (vnm, sw_if_index0);
1171  sw_if_index = (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED) ?
1172  swif->unnumbered_sw_if_index : sw_if_index0;
1173  ia0 = ip6_interface_first_address(&ip6_main, sw_if_index);
1174  if (ia0)
1175  {
1176  vlib_cli_output (vm, "%=20s%=48s", "interface", "link-address");
1177 
1178  vlib_cli_output (vm, "%=20U%=48U",
1179  format_vnet_sw_if_index_name, dm->vnet_main, sw_if_index0,
1180  format_ip6_address, ia0);
1181  } else
1182  vlib_cli_output (vm, "%=34s%=20U", "No IPv6 address configured on",
1183  format_vnet_sw_if_index_name, dm->vnet_main, sw_if_index);
1184  } else
1185  break;
1186  }
1187 
1188  return 0;
1189 }
1190 
1191 VLIB_CLI_COMMAND (dhcpv6_proxy_address_show_command, static) = {
1192  .path = "show dhcpv6 link-address interface",
1193  .short_help = "show dhcpv6 link-address interface <interface>",
1195 };
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:1061
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:396
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
#define foreach_ip_interface_address(lm, a, sw_if_index, loop, body)
Definition: lookup.h:460
#define VNET_SW_INTERFACE_FLAG_UNNUMBERED
Definition: interface.h:535
#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:805
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
#define CLIB_UNUSED(x)
Definition: clib.h:79
dhcpv6_proxy_main_t dhcpv6_proxy_main
Definition: proxy.h:80
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:106
format_function_t format_ip6_address
Definition: format.h:95
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
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:48
u64 as_u64[2]
Definition: ip6_packet.h:51
#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:387
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:65
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:337
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:194
vnet_main_t * vnet_main
Definition: proxy.h:77
u8 dst_address[6]
Definition: packet.h:53
#define hash_foreach(key_var, value_var, h, body)
Definition: hash.h:418
ip6_address_t dhcp6_server
Definition: proxy.h:49
u32 insert_vss
Definition: proxy.h:51
dhcpv6_server_t * dhcp6_servers
Definition: proxy.h:58
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:558
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:1153
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 v
Definition: acl.c:314
#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:73
#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:1012
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:196
#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:947
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:576
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
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:94
u8 * format_dhcpv6_proxy_header_with_length(u8 *s, va_list *args)
Definition: proxy_node.c:76
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:980
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:768
#define clib_memcpy(a, b, c)
Definition: string.h:69
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:207
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:211
#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:1141
#define hash_create(elts, value_bytes)
Definition: hash.h:658
dhcpv6_proxy_to_server_input_next_t
Definition: proxy_node.c:35
u16 cached_next_index
Definition: node.h:463
u32 server_fib6_index
Definition: proxy.h:52
#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:361
ip6_main_t ip6_main
Definition: ip6_forward.c:2828
ip_lookup_main_t lookup_main
Definition: ip6.h:135
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:884
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:324
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:70
u16 payload_length
Definition: ip6_packet.h:328
u32 ip6_fib_table_find_or_create_and_lock(u32 table_id)
Get or create an IPv6 fib.
Definition: ip6_fib.c:134
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
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:64
#define foreach_dhcpv6_proxy_to_server_input_next
Definition: proxy_node.c:29
union dhcpv6_hdr_::@119 u
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:523
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
u8 data[0]
Packet data.
Definition: buffer.h:158
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:1121
u32 table_id
Definition: ip6.h:69
ip6_address_t dhcp6_src_address
Definition: proxy.h:50
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:495
#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:317
static void * ip_interface_address_get_address(ip_lookup_main_t *lm, ip_interface_address_t *a)
Definition: lookup.h:453
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:187
ethernet_interface_t * interfaces
Definition: ethernet.h:243
int dhcpv6_proxy_set_server_2(ip6_address_t *addr, ip6_address_t *src_address, u32 rx_fib_id, u32 server_fib_id, int insert_vss, int is_del)
Definition: proxy_node.c:813
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:85
vlib_main_t * vlib_main
Definition: proxy.h:76
struct fib_table_t_ * fibs
Definition: ip6.h:138
u32 * fib_index_by_sw_if_index
Definition: ip6.h:144
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
#define PROTO_UDP
Definition: packet.h:25
Definition: defs.h:46
u32 * dhcp6_server_index_by_rx_fib_index
Definition: proxy.h:61
ip6_address_t dst_address
Definition: ip6_packet.h:337
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:68
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:505