Line data Source code
1 : /* 2 : * 3 : * ip6_nd_inline.h: ip6 neighbor discovery inline 4 : * 5 : * Copyright (c) 2021 Cisco and/or its affiliates. 6 : * Licensed under the Apache License, Version 2.0 (the "License"); 7 : * you may not use this file except in compliance with the License. 8 : * You may obtain a copy of the License at: 9 : * 10 : * http://www.apache.org/licenses/LICENSE-2.0 11 : * 12 : * Unless required by applicable law or agreed to in writing, software 13 : * distributed under the License is distributed on an "AS IS" BASIS, 14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 : * See the License for the specific language governing permissions and 16 : * limitations under the License. 17 : */ 18 : 19 : #ifndef __IP6_ND_INLINE_H__ 20 : #define __IP6_ND_INLINE_H__ 21 : 22 : #include <vnet/ethernet/ethernet.h> 23 : #include <vnet/ip/icmp46_packet.h> 24 : #include <vnet/ip/ip6.h> 25 : #include <vnet/ip-neighbor/ip_neighbor_types.h> 26 : #include <vnet/ip6-nd/ip6_ra.h> 27 : 28 : typedef enum 29 : { 30 : ICMP6_NEIGHBOR_SOLICITATION_NEXT_DROP, 31 : ICMP6_NEIGHBOR_SOLICITATION_NEXT_REPLY, 32 : ICMP6_NEIGHBOR_SOLICITATION_N_NEXT, 33 : } icmp6_neighbor_solicitation_or_advertisement_next_t; 34 : 35 : static_always_inline void 36 1638 : icmp6_send_neighbor_advertisement ( 37 : vlib_main_t *vm, vlib_buffer_t *b, ip6_header_t *ip6_h, 38 : icmp6_neighbor_solicitation_or_advertisement_header_t *icmp6_nsa, 39 : icmp6_neighbor_discovery_ethernet_link_layer_address_option_t 40 : *icmp6_nd_ell_addr, 41 : u32 sw_if_index0) 42 : { 43 1638 : vnet_main_t *vnm = vnet_get_main (); 44 : vnet_sw_interface_t *sw_if; 45 : ethernet_interface_t *eth_if; 46 : ethernet_header_t *eth; 47 : int bogus_length; 48 : 49 : /* dst address is either source address or the all-nodes mcast addr */ 50 1638 : if (!ip6_address_is_unspecified (&ip6_h->src_address)) 51 1638 : ip6_h->dst_address = ip6_h->src_address; 52 : else 53 0 : ip6_set_reserved_multicast_address (&ip6_h->dst_address, 54 : IP6_MULTICAST_SCOPE_link_local, 55 : IP6_MULTICAST_GROUP_ID_all_hosts); 56 : 57 1638 : ip6_h->src_address = icmp6_nsa->target_address; 58 1638 : ip6_h->hop_limit = 255; 59 1638 : icmp6_nsa->icmp.type = ICMP6_neighbor_advertisement; 60 : 61 1638 : sw_if = vnet_get_sup_sw_interface (vnm, sw_if_index0); 62 1638 : ASSERT (sw_if->type == VNET_SW_INTERFACE_TYPE_HARDWARE); 63 1638 : eth_if = ethernet_get_interface (ðernet_main, sw_if->hw_if_index); 64 1638 : if (eth_if && icmp6_nd_ell_addr) 65 : { 66 1638 : clib_memcpy (icmp6_nd_ell_addr->ethernet_address, ð_if->address, 6); 67 1638 : icmp6_nd_ell_addr->header.type = 68 : ICMP6_NEIGHBOR_DISCOVERY_OPTION_target_link_layer_address; 69 : } 70 : 71 1638 : icmp6_nsa->advertisement_flags = 72 1638 : clib_host_to_net_u32 (ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_SOLICITED | 73 : ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_OVERRIDE); 74 : 75 : /* if sending RAs is enabled, the "router" flag should be set, 76 : * otherwise, neighbors may believe we have changed from a router 77 : * to a host - RFC 4861 section 4.4 */ 78 1638 : if (ip6_ra_adv_enabled (sw_if_index0)) 79 0 : icmp6_nsa->advertisement_flags |= 80 0 : clib_host_to_net_u32 (ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_ROUTER); 81 : 82 1638 : icmp6_nsa->icmp.checksum = 0; 83 1638 : icmp6_nsa->icmp.checksum = 84 1638 : ip6_tcp_udp_icmp_compute_checksum (vm, b, ip6_h, &bogus_length); 85 1638 : ASSERT (bogus_length == 0); 86 : 87 : /* Reuse current MAC header, copy SMAC to DMAC and 88 : * interface MAC to SMAC */ 89 1638 : vlib_buffer_advance (b, -ethernet_buffer_header_size (b)); 90 1638 : eth = vlib_buffer_get_current (b); 91 1638 : clib_memcpy (eth->dst_address, eth->src_address, 6); 92 1638 : if (eth_if) 93 1638 : clib_memcpy (eth->src_address, ð_if->address, 6); 94 : 95 : /* Setup input and output sw_if_index for packet */ 96 1638 : ASSERT (vnet_buffer (b)->sw_if_index[VLIB_RX] == sw_if_index0); 97 1638 : vnet_buffer (b)->sw_if_index[VLIB_TX] = sw_if_index0; 98 1638 : vnet_buffer (b)->sw_if_index[VLIB_RX] = 99 1638 : vnet_main.local_interface_sw_if_index; 100 : 101 1638 : vlib_increment_simple_counter ( 102 : &ip_neighbor_counters[AF_IP6].ipnc[VLIB_TX][IP_NEIGHBOR_CTR_REPLY], 103 : vm->thread_index, sw_if_index0, 1); 104 1638 : } 105 : 106 : #endif /* included_ip6_nd_inline_h */ 107 : 108 : /* 109 : * fd.io coding-style-patch-verification: ON 110 : * 111 : * Local Variables: 112 : * eval: (c-set-style "gnu") 113 : * End: 114 : */