Currently, when the interface has no address assigned to it,
VPP crashes as ip_interface_address_for_packet assumes there
always is at least one address.
This patch checks if an address is available at all.
The only part of VPP using it is ARP or NDP.
When a neighbor discovery message has to be sent while
there is no address assigned on the interace, no
solicitation is sent and an error counter is incremented.
Change-Id: Ia9fdaf8e84050a1ceeb47f5370819d3df95714f0
Signed-off-by: Pierre Pfister <ppfister@cisco.com>
IP4_ARP_ERROR_REQUEST_SENT,
IP4_ARP_ERROR_NON_ARP_ADJ,
IP4_ARP_ERROR_REPLICATE_DROP,
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 {
} ip4_arp_error_t;
typedef CLIB_PACKED (struct {
uword dest_length)
{ return 0 == ((clib_mem_unaligned (&key->data_u32, u32) ^ dest->data_u32) & im->fib_masks[dest_length]); }
uword dest_length)
{ return 0 == ((clib_mem_unaligned (&key->data_u32, u32) ^ dest->data_u32) & im->fib_masks[dest_length]); }
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);
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];
ip4_address_t * a = ip_interface_address_get_address (lm, ia);
*src = a[0];
}
/* Find interface address which matches destination. */
}
/* Find interface address which matches destination. */
clib_memcpy (h0->ip4_over_ethernet[0].ethernet, hw_if0->hw_address,
sizeof (h0->ip4_over_ethernet[0].ethernet));
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;
/* Copy in destination address we are requesting. */
h0->ip4_over_ethernet[1].ip4.data_u32 = ip0->dst_address.data_u32;
[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_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) = {
};
VLIB_REGISTER_NODE (ip4_arp_node) = {
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);
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];
ip6_address_t * a = ip_interface_address_get_address (lm, ia);
*src = a[0];
typedef enum {
IP6_DISCOVER_NEIGHBOR_ERROR_DROP,
IP6_DISCOVER_NEIGHBOR_ERROR_REQUEST_SENT,
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
} ip6_discover_neighbor_error_t;
static uword
* Choose source address based on destination lookup
* adjacency.
*/
* 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.
/*
* Destination address is a solicited node multicast address.
[IP6_DISCOVER_NEIGHBOR_ERROR_DROP] = "address overflow drops",
[IP6_DISCOVER_NEIGHBOR_ERROR_REQUEST_SENT]
= "neighbor solicitations sent",
[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) = {
};
VLIB_REGISTER_NODE (ip6_discover_neighbor_node) = {
vec_elt (lm->if_address_pool_index_by_sw_if_index, sw_if_index)
: if_address_index);
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) \
}
#define foreach_ip_interface_address(lm,a,sw_if_index,loop,body) \