Line data Source code
1 : /* 2 : * ip/ip6_neighbor.h: IP6 NS transmit 3 : * 4 : * Copyright (c) 2019 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 : #ifndef __IP6_NEIGHBOR_H__ 19 : #define __IP6_NEIGHBOR_H__ 20 : 21 : #include <vlib/vlib.h> 22 : #include <vnet/ip/format.h> 23 : #include <vnet/ip/ip6.h> 24 : #include <vnet/ip/ip6_link.h> 25 : #include <vnet/ip/icmp46_packet.h> 26 : #include <vnet/ethernet/ethernet.h> 27 : #include <vnet/adj/adj_internal.h> 28 : #include <vnet/ip-neighbor/ip_neighbor_types.h> 29 : 30 : /* Template used to generate IP6 neighbor solicitation packets. */ 31 : extern vlib_packet_template_t ip6_neighbor_packet_template; 32 : 33 : extern void ip6_neighbor_advertise (vlib_main_t *vm, vnet_main_t *vnm, 34 : u32 sw_if_index, u32 thread_index, 35 : const ip6_address_t *addr); 36 : 37 : extern void ip6_neighbor_probe_dst (u32 sw_if_index, u32 thread_index, 38 : const ip6_address_t *dst); 39 : 40 : always_inline vlib_buffer_t * 41 89 : ip6_neighbor_probe (vlib_main_t *vm, vnet_main_t *vnm, u32 sw_if_index, 42 : u32 thread_index, const ip6_address_t *src, 43 : const ip6_address_t *dst) 44 : { 45 : icmp6_neighbor_solicitation_header_t *h0; 46 : vnet_hw_interface_t *hw_if0; 47 : const ip_adjacency_t *adj; 48 : vlib_buffer_t *b0; 49 : int bogus_length; 50 89 : u32 bi0 = 0; 51 : 52 89 : h0 = vlib_packet_template_get_packet 53 : (vm, &ip6_neighbor_packet_template, &bi0); 54 89 : if (!h0) 55 0 : return NULL; 56 : 57 : /* if the interface has been disabled for ip6, later steps to retrieve 58 : * an adjacency will result in a segv. 59 : */ 60 89 : if (!ip6_link_is_enabled (sw_if_index)) 61 4 : return NULL; 62 : 63 85 : b0 = vlib_get_buffer (vm, bi0); 64 : 65 85 : hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index); 66 : 67 : /* 68 : * Destination address is a solicited node multicast address. 69 : * We need to fill in 70 : * the low 24 bits with low 24 bits of target's address. 71 : */ 72 85 : h0->ip.src_address = *src; 73 85 : h0->ip.dst_address.as_u8[13] = dst->as_u8[13]; 74 85 : h0->ip.dst_address.as_u8[14] = dst->as_u8[14]; 75 85 : h0->ip.dst_address.as_u8[15] = dst->as_u8[15]; 76 : 77 85 : h0->neighbor.target_address = *dst; 78 : 79 85 : clib_memcpy (h0->link_layer_option.ethernet_address, 80 : hw_if0->hw_address, vec_len (hw_if0->hw_address)); 81 : 82 : /* $$$$ appears we need this; why is the checksum non-zero? */ 83 85 : h0->neighbor.icmp.checksum = 0; 84 85 : h0->neighbor.icmp.checksum = 85 85 : ip6_tcp_udp_icmp_compute_checksum (vm, 0, &h0->ip, &bogus_length); 86 : 87 85 : ASSERT (bogus_length == 0); 88 : 89 85 : vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index; 90 : 91 : /* Use the link's mcast adj to ship the packet */ 92 170 : vnet_buffer (b0)->ip.adj_index[VLIB_TX] = 93 85 : ip6_link_get_mcast_adj (sw_if_index); 94 85 : adj = adj_get (vnet_buffer (b0)->ip.adj_index[VLIB_TX]); 95 : 96 85 : b0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; 97 : 98 : { 99 85 : vlib_frame_t *f = vlib_get_frame_to_node (vm, adj->ia_node_index); 100 85 : u32 *to_next = vlib_frame_vector_args (f); 101 85 : to_next[0] = bi0; 102 85 : f->n_vectors = 1; 103 85 : vlib_put_frame_to_node (vm, adj->ia_node_index, f); 104 : } 105 : 106 85 : vlib_increment_simple_counter ( 107 : &ip_neighbor_counters[AF_IP6].ipnc[VLIB_TX][IP_NEIGHBOR_CTR_REQUEST], 108 : thread_index, sw_if_index, 1); 109 : 110 85 : return b0; 111 : } 112 : 113 : #endif 114 : 115 : /* 116 : * fd.io coding-style-patch-verification: ON 117 : * 118 : * Local Variables: 119 : * eval: (c-set-style "gnu") 120 : * End: 121 : */