#include <vnet/ip/ip4_packet.h>
#include <vnet/ip/ip6_link.h>
#include <vnet/ethernet/arp_packet.h>
+#include <vnet/fib/fib_sas.h>
#include <vppinfra/error.h>
#include <vrrp/vrrp.h>
#include <vrrp/vrrp_packet.h>
VRRP_INPUT_N_NEXT,
} vrrp_next_t;
-typedef struct vrrp_input_process_args
-{
- u32 vr_index;
- vrrp_header_t *pkt;
-} vrrp_input_process_args_t;
-
/* Given a VR and a pointer to the VRRP header of an incoming packet,
* compare the local src address to the peers. Return < 0 if the local
* address < the peer address, 0 if they're equal, > 0 if
* the local address > the peer address
*/
static int
-vrrp_vr_addr_cmp (vrrp_vr_t * vr, vrrp_header_t * pkt)
+vrrp_vr_addr_cmp (vrrp_vr_t *vr, ip46_address_t *peer_addr)
{
vrrp_vr_config_t *vrc = &vr->config;
- void *peer_addr, *local_addr;
+ void *peer_addr_bytes, *local_addr;
ip46_address_t addr;
int addr_size;
if (vrrp_vr_is_ipv6 (vr))
{
- peer_addr = &(((ip6_header_t *) pkt) - 1)->src_address;
+ peer_addr_bytes = &peer_addr->ip6;
local_addr = &addr.ip6;
addr_size = 16;
ip6_address_copy (local_addr,
}
else
{
- peer_addr = &(((ip4_header_t *) pkt) - 1)->src_address;
+ peer_addr_bytes = &peer_addr->ip4;
local_addr = &addr.ip4;
addr_size = 4;
- ip4_src_address_for_packet (&ip4_main.lookup_main,
- vrc->sw_if_index, local_addr);
+ fib_sas4_get (vrc->sw_if_index, NULL, local_addr);
}
- return memcmp (local_addr, peer_addr, addr_size);
+ return memcmp (local_addr, peer_addr_bytes, addr_size);
}
static void
-vrrp_input_process_master (vrrp_vr_t * vr, vrrp_header_t * pkt)
+vrrp_input_process_master (vrrp_vr_t *vr, vrrp_input_process_args_t *args)
{
/* received priority 0, another VR is shutting down. send an adv and
* remain in the master state
*/
- if (pkt->priority == 0)
+ if (args->priority == 0)
{
clib_warning ("Received shutdown message from a peer on VR %U",
format_vrrp_vr_key, vr);
+ vrrp_incr_stat_counter (VRRP_STAT_COUNTER_PRIO0_RCVD, vr->stat_index);
vrrp_adv_send (vr, 0);
vrrp_vr_timer_set (vr, VRRP_VR_TIMER_ADV);
return;
* - received priority == adjusted priority and peer addr > local addr
* allow the local VR to be preempted by the peer
*/
- if ((pkt->priority > vrrp_vr_priority (vr)) ||
- ((pkt->priority == vrrp_vr_priority (vr)) &&
- (vrrp_vr_addr_cmp (vr, pkt) < 0)))
+ if ((args->priority > vrrp_vr_priority (vr)) ||
+ ((args->priority == vrrp_vr_priority (vr)) &&
+ (vrrp_vr_addr_cmp (vr, &args->src_addr) < 0)))
{
- vrrp_vr_transition (vr, VRRP_VR_STATE_BACKUP, pkt);
+ vrrp_vr_transition (vr, VRRP_VR_STATE_BACKUP, args);
return;
}
/* RFC 5798 section 6.4.2 */
static void
-vrrp_input_process_backup (vrrp_vr_t * vr, vrrp_header_t * pkt)
+vrrp_input_process_backup (vrrp_vr_t *vr, vrrp_input_process_args_t *args)
{
vrrp_vr_config_t *vrc = &vr->config;
vrrp_vr_runtime_t *vrt = &vr->runtime;
/* master shutting down, ready for election */
- if (pkt->priority == 0)
+ if (args->priority == 0)
{
clib_warning ("Master for VR %U is shutting down", format_vrrp_vr_key,
vr);
+ vrrp_incr_stat_counter (VRRP_STAT_COUNTER_PRIO0_RCVD, vr->stat_index);
vrt->master_down_int = vrt->skew;
vrrp_vr_timer_set (vr, VRRP_VR_TIMER_MASTER_DOWN);
return;
/* no preempt set or adv from a higher priority router, update timers */
if (!(vrc->flags & VRRP_VR_PREEMPT) ||
- (pkt->priority >= vrrp_vr_priority (vr)))
+ (args->priority >= vrrp_vr_priority (vr)))
{
- vrt->master_adv_int = clib_net_to_host_u16 (pkt->rsvd_and_max_adv_int);
- vrt->master_adv_int &= ((u16) 0x0fff); /* ignore rsvd bits */
+ vrt->master_adv_int = args->max_adv_int;
vrrp_vr_skew_compute (vr);
vrrp_vr_master_down_compute (vr);
return;
}
+ vrrp_incr_stat_counter (VRRP_STAT_COUNTER_ADV_RCVD, vr->stat_index);
+
switch (vr->runtime.state)
{
case VRRP_VR_STATE_INIT:
return;
case VRRP_VR_STATE_BACKUP:
/* this is usually the only state an advertisement should be received */
- vrrp_input_process_backup (vr, args->pkt);
+ vrrp_input_process_backup (vr, args);
break;
case VRRP_VR_STATE_MASTER:
/* might be getting preempted. or have a misbehaving peer */
clib_warning ("Received advertisement for master VR %U",
format_vrrp_vr_key, vr);
- vrrp_input_process_master (vr, args->pkt);
+ vrrp_input_process_master (vr, args);
break;
default:
clib_warning ("Received advertisement for VR %U in unknown state %d",
return vrrp_arp_nd_input_inline (vm, node, frame, 0 /* is_ipv6 */ );
}
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (vrrp4_arp_input_node) =
{
.name = "vrrp4-arp-input",
return vrrp_arp_nd_input_inline (vm, node, frame, 1 /* is_ipv6 */);
}
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (vrrp6_nd_input_node) =
{
.name = "vrrp6-nd-input",
addr_len = 16;
payload_len0 = clib_net_to_host_u16 (ip6->payload_length);
vlib_buffer_advance (b0, sizeof (*ip6));
+ clib_memcpy_fast (&args0.src_addr.ip6, &ip6->src_address, addr_len);
}
else
{
addr_len = 4;
payload_len0 = clib_net_to_host_u16 (ip4->length) - sizeof(*ip4);
vlib_buffer_advance (b0, sizeof (*ip4));
+ clib_memcpy_fast (&args0.src_addr.ip4, &ip4->src_address, addr_len);
}
next0 = VRRP_INPUT_NEXT_DROP;
if (*ttl0 != 255)
{
error0 = VRRP_ERROR_BAD_TTL;
+ vrrp_incr_err_counter (VRRP_ERR_COUNTER_TTL);
goto trace;
}
if ((vrrp0->vrrp_version_and_type >> 4) != 3)
{
error0 = VRRP_ERROR_NOT_VERSION_3;
+ vrrp_incr_err_counter (VRRP_ERR_COUNTER_VERSION);
goto trace;
}
((u32) vrrp0->n_addrs) * addr_len)
{
error0 = VRRP_ERROR_INCOMPLETE_PKT;
+ vrrp_incr_err_counter (VRRP_ERR_COUNTER_PKT_LEN);
goto trace;
}
if (rx_csum0 != vrrp_adv_csum (ip0, vrrp0, is_ipv6, payload_len0))
{
error0 = VRRP_ERROR_BAD_CHECKSUM;
+ vrrp_incr_err_counter (VRRP_ERR_COUNTER_CHKSUM);
goto trace;
}
vrrp0->vr_id, is_ipv6)))
{
error0 = VRRP_ERROR_UNKNOWN_VR;
+ vrrp_incr_err_counter (VRRP_ERR_COUNTER_VRID);
goto trace;
}
if (vrrp0->n_addrs != vec_len (vr0->config.vr_addrs))
{
error0 = VRRP_ERROR_ADDR_MISMATCH;
+ vrrp_incr_err_counter (VRRP_ERR_COUNTER_ADDR_LIST);
goto trace;
}
/* signal main thread to process contents of packet */
args0.vr_index = vr0 - vmp->vrs;
- args0.pkt = vrrp0;
+ args0.priority = vrrp0->priority;
+ args0.max_adv_int = vrrp_adv_int_from_packet (vrrp0);
vl_api_rpc_call_main_thread (vrrp_input_process, (u8 *) &args0,
sizeof (args0));
return vrrp_input_inline (vm, node, frame, 0);
}
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (vrrp4_input_node) =
{
.name = "vrrp4-input",
VLIB_INIT_FUNCTION (vrrp_input_init);
-/* *INDENT-ON* */
/*
* fd.io coding-style-patch-verification: ON