diff options
-rw-r--r-- | vnet/vnet/ethernet/arp_packet.h | 3 | ||||
-rw-r--r-- | vnet/vnet/ip/ip4.h | 5 | ||||
-rw-r--r-- | vnet/vnet/ip/ip4_forward.c | 8 | ||||
-rw-r--r-- | vnet/vnet/ip/ip6.h | 5 | ||||
-rw-r--r-- | vnet/vnet/ip/ip6_forward.c | 12 | ||||
-rw-r--r-- | vnet/vnet/ip/lookup.h | 2 |
6 files changed, 28 insertions, 7 deletions
diff --git a/vnet/vnet/ethernet/arp_packet.h b/vnet/vnet/ethernet/arp_packet.h index c2214949d89..b3447c5e1c1 100644 --- a/vnet/vnet/ethernet/arp_packet.h +++ b/vnet/vnet/ethernet/arp_packet.h @@ -109,7 +109,8 @@ typedef enum { IP4_ARP_ERROR_REQUEST_SENT, IP4_ARP_ERROR_NON_ARP_ADJ, IP4_ARP_ERROR_REPLICATE_DROP, - IP4_ARP_ERROR_REPLICATE_FAIL + IP4_ARP_ERROR_REPLICATE_FAIL, + IP4_ARP_ERROR_NO_SOURCE_ADDRESS, } ip4_arp_error_t; typedef CLIB_PACKED (struct { diff --git a/vnet/vnet/ip/ip4.h b/vnet/vnet/ip/ip4.h index c01006ea590..f005522bb7a 100644 --- a/vnet/vnet/ip/ip4.h +++ b/vnet/vnet/ip/ip4.h @@ -237,13 +237,16 @@ ip4_unaligned_destination_matches_route (ip4_main_t * im, uword dest_length) { return 0 == ((clib_mem_unaligned (&key->data_u32, u32) ^ dest->data_u32) & im->fib_masks[dest_length]); } -always_inline void +always_inline int ip4_src_address_for_packet (ip4_main_t * im, vlib_buffer_t * p, ip4_address_t * src, u32 sw_if_index) { ip_lookup_main_t * lm = &im->lookup_main; ip_interface_address_t * ia = ip_interface_address_for_packet (lm, p, sw_if_index); + if (ia == NULL) + return -1; ip4_address_t * a = ip_interface_address_get_address (lm, ia); *src = a[0]; + return 0; } /* Find interface address which matches destination. */ diff --git a/vnet/vnet/ip/ip4_forward.c b/vnet/vnet/ip/ip4_forward.c index 3075e0c3f73..08a1785aaa5 100644 --- a/vnet/vnet/ip/ip4_forward.c +++ b/vnet/vnet/ip/ip4_forward.c @@ -2373,7 +2373,12 @@ ip4_arp (vlib_main_t * vm, clib_memcpy (h0->ip4_over_ethernet[0].ethernet, hw_if0->hw_address, sizeof (h0->ip4_over_ethernet[0].ethernet)); - ip4_src_address_for_packet (im, p0, &h0->ip4_over_ethernet[0].ip4, sw_if_index0); + if (ip4_src_address_for_packet (im, p0, &h0->ip4_over_ethernet[0].ip4, sw_if_index0)) { + //No source address available + p0->error = node->errors[IP4_ARP_ERROR_NO_SOURCE_ADDRESS]; + vlib_buffer_free(vm, &bi0, 1); + continue; + } /* Copy in destination address we are requesting. */ h0->ip4_over_ethernet[1].ip4.data_u32 = ip0->dst_address.data_u32; @@ -2400,6 +2405,7 @@ static char * ip4_arp_error_strings[] = { [IP4_ARP_ERROR_NON_ARP_ADJ] = "ARPs to non-ARP adjacencies", [IP4_ARP_ERROR_REPLICATE_DROP] = "ARP replication completed", [IP4_ARP_ERROR_REPLICATE_FAIL] = "ARP replication failed", + [IP4_ARP_ERROR_NO_SOURCE_ADDRESS] = "no source address for ARP request", }; VLIB_REGISTER_NODE (ip4_arp_node) = { diff --git a/vnet/vnet/ip/ip6.h b/vnet/vnet/ip/ip6.h index 312e39845b4..70e32672530 100644 --- a/vnet/vnet/ip/ip6.h +++ b/vnet/vnet/ip/ip6.h @@ -289,13 +289,16 @@ ip6_unaligned_destination_matches_route (ip6_main_t * im, return 1; } -always_inline void +always_inline int ip6_src_address_for_packet (ip6_main_t * im, vlib_buffer_t * p, ip6_address_t * src, u32 sw_if_index) { ip_lookup_main_t * lm = &im->lookup_main; ip_interface_address_t * ia = ip_interface_address_for_packet (lm, p, sw_if_index); + if (ia == NULL) + return -1; ip6_address_t * a = ip_interface_address_get_address (lm, ia); *src = a[0]; + return 0; } always_inline u32 diff --git a/vnet/vnet/ip/ip6_forward.c b/vnet/vnet/ip/ip6_forward.c index 86ee8d5ba2b..b558787c45c 100644 --- a/vnet/vnet/ip/ip6_forward.c +++ b/vnet/vnet/ip/ip6_forward.c @@ -1993,6 +1993,7 @@ typedef enum { typedef enum { IP6_DISCOVER_NEIGHBOR_ERROR_DROP, IP6_DISCOVER_NEIGHBOR_ERROR_REQUEST_SENT, + IP6_DISCOVER_NEIGHBOR_ERROR_NO_SOURCE_ADDRESS, } ip6_discover_neighbor_error_t; static uword @@ -2123,8 +2124,13 @@ ip6_discover_neighbor (vlib_main_t * vm, * Choose source address based on destination lookup * adjacency. */ - ip6_src_address_for_packet (im, p0, &h0->ip.src_address, - sw_if_index0); + if (ip6_src_address_for_packet (im, p0, &h0->ip.src_address, + sw_if_index0)) { + //There is no address on the interface + p0->error = node->errors[IP6_DISCOVER_NEIGHBOR_ERROR_NO_SOURCE_ADDRESS]; + vlib_buffer_free(vm, &bi0, 1); + continue; + } /* * Destination address is a solicited node multicast address. @@ -2175,6 +2181,8 @@ static char * ip6_discover_neighbor_error_strings[] = { [IP6_DISCOVER_NEIGHBOR_ERROR_DROP] = "address overflow drops", [IP6_DISCOVER_NEIGHBOR_ERROR_REQUEST_SENT] = "neighbor solicitations sent", + [IP6_DISCOVER_NEIGHBOR_ERROR_NO_SOURCE_ADDRESS] + = "no source address for ND solicitation", }; VLIB_REGISTER_NODE (ip6_discover_neighbor_node) = { diff --git a/vnet/vnet/ip/lookup.h b/vnet/vnet/ip/lookup.h index 35c19a77327..c22c5003fd3 100644 --- a/vnet/vnet/ip/lookup.h +++ b/vnet/vnet/ip/lookup.h @@ -531,7 +531,7 @@ ip_interface_address_for_packet (ip_lookup_main_t * lm, vlib_buffer_t * b, u32 s vec_elt (lm->if_address_pool_index_by_sw_if_index, sw_if_index) : if_address_index); - return pool_elt_at_index (lm->if_address_pool, if_address_index); + return (if_address_index != ~0)?pool_elt_at_index (lm->if_address_pool, if_address_index):NULL; } #define foreach_ip_interface_address(lm,a,sw_if_index,loop,body) \ |