FD.io VPP  v20.01-48-g3e0dafb74
Vector Packet Processing
ip6_neighbor.c
Go to the documentation of this file.
1 /*
2  * ip/ip6_neighbor.c: IP6 neighbor handling
3  *
4  * Copyright (c) 2010 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 
19 
20 void
22 {
25 
27  (&ip6_main, dst, adj->rewrite_header.sw_if_index, &ia);
28 
29  if (!src)
30  return;
31 
32  ip6_neighbor_probe (vlib_get_main (), vnet_get_main (), adj, src, dst);
33 }
34 
35 void
37  vnet_main_t * vnm,
39 {
40  vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
41  ip6_main_t *i6m = &ip6_main;
42  u8 *rewrite, rewrite_len;
43  u8 dst_address[6];
44 
45  if (NULL == addr)
46  addr = ip6_interface_first_address (i6m, sw_if_index);
47 
48  if (addr)
49  {
51  ("Sending unsolicitated NA IP6 address %U on sw_if_idex %d",
52  format_ip6_address, addr, sw_if_index);
53 
54  /* Form unsolicited neighbor advertisement packet from NS pkt template */
55  int bogus_length;
56  u32 bi = 0;
57  icmp6_neighbor_solicitation_header_t *h =
59  &ip6_neighbor_packet_template,
60  &bi);
61  if (!h)
62  return;
63 
64  ip6_set_reserved_multicast_address (&h->ip.dst_address,
65  IP6_MULTICAST_SCOPE_link_local,
66  IP6_MULTICAST_GROUP_ID_all_hosts);
67  h->ip.src_address = addr[0];
68  h->neighbor.icmp.type = ICMP6_neighbor_advertisement;
69  h->neighbor.target_address = addr[0];
70  h->neighbor.advertisement_flags = clib_host_to_net_u32
72  h->link_layer_option.header.type =
73  ICMP6_NEIGHBOR_DISCOVERY_OPTION_target_link_layer_address;
74  clib_memcpy (h->link_layer_option.ethernet_address,
75  hi->hw_address, vec_len (hi->hw_address));
76  h->neighbor.icmp.checksum =
77  ip6_tcp_udp_icmp_compute_checksum (vm, 0, &h->ip, &bogus_length);
78  ASSERT (bogus_length == 0);
79 
80  /* Setup MAC header with IP6 Etype and mcast DMAC */
81  vlib_buffer_t *b = vlib_get_buffer (vm, bi);
82  ip6_multicast_ethernet_address (dst_address,
83  IP6_MULTICAST_GROUP_ID_all_hosts);
84  rewrite =
85  ethernet_build_rewrite (vnm, sw_if_index, VNET_LINK_IP6, dst_address);
86  rewrite_len = vec_len (rewrite);
87  vlib_buffer_advance (b, -rewrite_len);
89  clib_memcpy (e->dst_address, rewrite, rewrite_len);
90  vec_free (rewrite);
91 
92  /* Send unsolicited ND advertisement packet out the specified interface */
93  vnet_buffer (b)->sw_if_index[VLIB_RX] =
94  vnet_buffer (b)->sw_if_index[VLIB_TX] = sw_if_index;
96  u32 *to_next = vlib_frame_vector_args (f);
97  to_next[0] = bi;
98  f->n_vectors = 1;
100  }
101 }
102 
103 typedef enum
104 {
109 
110 typedef enum
111 {
117 
118 static uword
121  vlib_frame_t * frame, int is_glean)
122 {
123  vnet_main_t *vnm = vnet_get_main ();
124  ip6_main_t *im = &ip6_main;
125  u32 *from, *to_next_drop;
126  uword n_left_from, n_left_to_next_drop;
127  u64 seed;
128  u32 thread_index = vm->thread_index;
129 
130  if (node->flags & VLIB_NODE_FLAG_TRACE)
131  ip6_forward_next_trace (vm, node, frame, VLIB_TX);
132 
133  seed = throttle_seed (&im->nd_throttle, thread_index, vlib_time_now (vm));
134 
135  from = vlib_frame_vector_args (frame);
136  n_left_from = frame->n_vectors;
137 
138  while (n_left_from > 0)
139  {
141  to_next_drop, n_left_to_next_drop);
142 
143  while (n_left_from > 0 && n_left_to_next_drop > 0)
144  {
145  u32 pi0, adj_index0, sw_if_index0, drop0, r0;
146  vnet_hw_interface_t *hw_if0;
147  vlib_buffer_t *p0, *b0;
148  ip_adjacency_t *adj0;
150  ip6_header_t *ip0;
151 
152  pi0 = from[0];
153 
154  p0 = vlib_get_buffer (vm, pi0);
155 
156  adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
157 
158  ip0 = vlib_buffer_get_current (p0);
159 
160  adj0 = adj_get (adj_index0);
161 
162  if (!is_glean)
163  {
164  ip0->dst_address.as_u64[0] =
165  adj0->sub_type.nbr.next_hop.ip6.as_u64[0];
166  ip0->dst_address.as_u64[1] =
167  adj0->sub_type.nbr.next_hop.ip6.as_u64[1];
168  }
169 
170  sw_if_index0 = adj0->rewrite_header.sw_if_index;
171  vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
172 
173  /* combine the address and interface for a hash */
174  r0 = ip6_address_hash_to_u64 (&ip0->dst_address) ^ sw_if_index0;
175 
176  drop0 = throttle_check (&im->nd_throttle, thread_index, r0, seed);
177 
178  from += 1;
179  n_left_from -= 1;
180  to_next_drop[0] = pi0;
181  to_next_drop += 1;
182  n_left_to_next_drop -= 1;
183 
184  hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
185 
186  /* If the interface is link-down, drop the pkt */
187  if (!(hw_if0->flags & VNET_HW_INTERFACE_FLAG_LINK_UP))
188  drop0 = 1;
189 
190  if (!ip6_link_is_enabled (sw_if_index0))
191  drop0 = 1;
192 
193  /*
194  * the adj has been updated to a rewrite but the node the DPO that got
195  * us here hasn't - yet. no big deal. we'll drop while we wait.
196  */
198  drop0 = 1;
199 
200  if (drop0)
201  {
202  p0->error = node->errors[IP6_NBR_ERROR_DROP];
203  continue;
204  }
205 
206  /*
207  * Choose source address based on destination lookup
208  * adjacency.
209  */
210  if (!ip6_src_address_for_packet (sw_if_index0,
211  &ip0->dst_address, &src))
212  {
213  /* There is no address on the interface */
215  continue;
216  }
217 
218  b0 = ip6_neighbor_probe (vm, vnm, adj0, &src, &ip0->dst_address);
219 
220  if (PREDICT_TRUE (NULL != b0))
221  {
222  clib_memcpy_fast (b0->opaque2, p0->opaque2,
223  sizeof (p0->opaque2));
224  b0->flags |= p0->flags & VLIB_BUFFER_IS_TRACED;
225  b0->trace_handle = p0->trace_handle;
227  }
228  else
229  {
230  /* There is no address on the interface */
232  continue;
233  }
234  }
235 
236  vlib_put_next_frame (vm, node, IP6_NBR_NEXT_DROP, n_left_to_next_drop);
237  }
238 
239  return frame->n_vectors;
240 }
241 
242 static uword
245 {
246  return (ip6_discover_neighbor_inline (vm, node, frame, 0));
247 }
248 
249 static uword
251 {
252  return (ip6_discover_neighbor_inline (vm, node, frame, 1));
253 }
254 
256  [IP6_NBR_ERROR_DROP] = "address overflow drops",
257  [IP6_NBR_ERROR_REQUEST_SENT] = "neighbor solicitations sent",
258  [IP6_NBR_ERROR_NO_SOURCE_ADDRESS] = "no source address for ND solicitation",
259  [IP6_NBR_ERROR_NO_BUFFERS] = "no buffers",
260 };
261 
262 /* *INDENT-OFF* */
264 {
265  .function = ip6_glean,
266  .name = "ip6-glean",
267  .vector_size = sizeof (u32),
268  .format_trace = format_ip6_forward_next_trace,
270  .error_strings = ip6_discover_neighbor_error_strings,
271  .n_next_nodes = IP6_NBR_N_NEXT,
272  .next_nodes =
273  {
274  [IP6_NBR_NEXT_DROP] = "ip6-drop",
275  [IP6_NBR_NEXT_REPLY_TX] = "ip6-rewrite-mcast",
276  },
277 };
279 {
280  .function = ip6_discover_neighbor,
281  .name = "ip6-discover-neighbor",
282  .vector_size = sizeof (u32),
283  .format_trace = format_ip6_forward_next_trace,
285  .error_strings = ip6_discover_neighbor_error_strings,
286  .n_next_nodes = IP6_NBR_N_NEXT,
287  .next_nodes =
288  {
289  [IP6_NBR_NEXT_DROP] = "ip6-drop",
290  [IP6_NBR_NEXT_REPLY_TX] = "ip6-rewrite-mcast",
291  },
292 };
293 /* *INDENT-ON* */
294 
295 /* Template used to generate IP6 neighbor solicitation packets. */
297 
298 static clib_error_t *
300 {
301  icmp6_neighbor_solicitation_header_t p;
302 
303  clib_memset (&p, 0, sizeof (p));
304 
305  p.ip.ip_version_traffic_class_and_flow_label =
306  clib_host_to_net_u32 (0x6 << 28);
307  p.ip.payload_length =
308  clib_host_to_net_u16 (sizeof (p) -
310  (icmp6_neighbor_solicitation_header_t, neighbor));
311  p.ip.protocol = IP_PROTOCOL_ICMP6;
312  p.ip.hop_limit = 255;
313  ip6_set_solicited_node_multicast_address (&p.ip.dst_address, 0);
314 
315  p.neighbor.icmp.type = ICMP6_neighbor_solicitation;
316 
317  p.link_layer_option.header.type =
318  ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address;
319  p.link_layer_option.header.n_data_u64s =
320  sizeof (p.link_layer_option) / sizeof (u64);
321 
323  &ip6_neighbor_packet_template, &p, sizeof (p),
324  /* alloc chunk size */ 8,
325  "ip6 neighbor discovery");
326 
327  return NULL;
328 }
329 
331 
332 /*
333  * fd.io coding-style-patch-verification: ON
334  *
335  * Local Variables:
336  * eval: (c-set-style "gnu")
337  * End:
338  */
u32 opaque2[14]
Definition: buffer.h:170
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
static vlib_buffer_t * ip6_neighbor_probe(vlib_main_t *vm, vnet_main_t *vnm, const ip_adjacency_t *adj, const ip6_address_t *src, const ip6_address_t *dst)
Definition: ip6_neighbor.h:41
ip6_discover_neighbor_next_t
Definition: ip6_neighbor.c:103
static clib_error_t * ip6_neighbor_init(vlib_main_t *vm)
Definition: ip6_neighbor.c:299
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
#define PREDICT_TRUE(x)
Definition: clib.h:112
u64 as_u64[2]
Definition: ip6_packet.h:51
unsigned long u64
Definition: types.h:89
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
#define NULL
Definition: clib.h:58
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:279
IP unicast adjacency.
Definition: adj.h:221
u32 thread_index
Definition: main.h:218
static uword ip6_discover_neighbor_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_glean)
Definition: ip6_neighbor.c:119
This packet is to be rewritten and forwarded to the next processing node.
Definition: adj.h:73
ip6_address_t * ip6_interface_first_address(ip6_main_t *im, u32 sw_if_index)
get first IPv6 interface address
Definition: ip6_forward.c:271
vl_api_address_t src
Definition: gre.api:60
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:65
vlib_packet_template_t ip6_neighbor_packet_template
Definition: ip6_neighbor.c:296
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:470
vhost_vring_addr_t addr
Definition: vhost_user.h:147
unsigned char u8
Definition: types.h:56
#define clib_memcpy(d, s, n)
Definition: string.h:180
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:431
static u64 ip6_address_hash_to_u64(const ip6_address_t *a)
Definition: ip6_packet.h:286
void * vlib_packet_template_get_packet(vlib_main_t *vm, vlib_packet_template_t *t, u32 *bi_result)
Definition: buffer.c:400
vl_api_interface_index_t sw_if_index
Definition: gre.api:59
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
static uword ip6_glean(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip6_neighbor.c:250
#define ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_OVERRIDE
u8 dst_address[6]
Definition: packet.h:55
struct ip_adjacency_t_::@119::@120 nbr
IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE.
vnet_hw_interface_flags_t flags
Definition: interface.h:523
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:185
union ip_adjacency_t_::@119 sub_type
unsigned int u32
Definition: types.h:88
void ip6_neighbor_advertise(vlib_main_t *vm, vnet_main_t *vnm, u32 sw_if_index, const ip6_address_t *addr)
Definition: ip6_neighbor.c:36
throttle_t nd_throttle
ND throttling.
Definition: ip6.h:240
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
void vlib_packet_template_init(vlib_main_t *vm, vlib_packet_template_t *t, void *packet_data, uword n_packet_data_bytes, uword min_n_buffers_each_alloc, char *fmt,...)
Definition: buffer.c:378
static char * ip6_discover_neighbor_error_strings[]
Definition: ip6_neighbor.c:255
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:194
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
u32 trace_handle
Specifies trace buffer handle if VLIB_PACKET_IS_TRACED flag is set.
Definition: buffer.h:163
static u64 throttle_seed(throttle_t *t, u32 thread_index, f64 time_now)
Definition: throttle.h:41
ip6_discover_neighbor_error_t
Definition: ip6_neighbor.c:110
ip6_main_t ip6_main
Definition: ip6_forward.c:2703
vl_api_address_t dst
Definition: gre.api:61
#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:338
vlib_main_t * vm
Definition: in2out_ed.c:1810
static uword ip6_discover_neighbor(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip6_neighbor.c:243
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:397
format_function_t format_ip6_address
Definition: format.h:91
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:342
#define clib_warning(format, args...)
Definition: error.h:59
#define ARRAY_LEN(x)
Definition: clib.h:62
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:456
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1810
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:1021
#define ASSERT(truth)
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:248
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
vl_api_ip4_address_t hi
Definition: arp.api:37
Definition: defs.h:47
static void ip6_set_solicited_node_multicast_address(ip6_address_t *a, u32 id)
Definition: ip6_packet.h:141
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
ip_lookup_next_t lookup_next_index
Next hop after ip4-lookup.
Definition: adj.h:236
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
void ip6_neighbor_probe_dst(const ip_adjacency_t *adj, const ip6_address_t *dst)
Definition: ip6_neighbor.c:21
u8 * ethernet_build_rewrite(vnet_main_t *vnm, u32 sw_if_index, vnet_link_t link_type, const void *dst_address)
build a rewrite string to use for sending packets of type &#39;link_type&#39; to &#39;dst_address&#39; ...
Definition: interface.c:83
vlib_node_registration_t ip6_glean_node
(constructor) VLIB_REGISTER_NODE (ip6_glean_node)
Definition: ip6_neighbor.c:263
#define vnet_buffer(b)
Definition: buffer.h:408
vlib_node_registration_t ip6_discover_neighbor_node
(constructor) VLIB_REGISTER_NODE (ip6_discover_neighbor_node)
Definition: ip6_neighbor.c:278
void ip6_forward_next_trace(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, vlib_rx_or_tx_t which_adj_index)
Definition: ip6_forward.c:929
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1811
u16 flags
Copy of main node flags.
Definition: node.h:509
static void ip6_multicast_ethernet_address(u8 *ethernet_address, u32 group_id)
Definition: ip6_packet.h:153
static ip6_address_t * ip6_interface_address_matching_destination(ip6_main_t *im, const ip6_address_t *dst, u32 sw_if_index, ip_interface_address_t **result_ia)
Definition: ip6.h:305
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:302
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
Definition: defs.h:46
ip6_address_t dst_address
Definition: ip6_packet.h:307
static void ip6_set_reserved_multicast_address(ip6_address_t *a, ip6_multicast_address_scope_t scope, u16 id)
Definition: ip6_packet.h:131
static int throttle_check(throttle_t *t, u32 thread_index, u64 hash, u64 seed)
Definition: throttle.h:54
u8 * format_ip6_forward_next_trace(u8 *s, va_list *args)
Definition: ip6_forward.c:877