diff options
Diffstat (limited to 'src/plugins/vrrp/node.c')
-rw-r--r-- | src/plugins/vrrp/node.c | 60 |
1 files changed, 31 insertions, 29 deletions
diff --git a/src/plugins/vrrp/node.c b/src/plugins/vrrp/node.c index 7ba18c4f75c..d5594ae0e43 100644 --- a/src/plugins/vrrp/node.c +++ b/src/plugins/vrrp/node.c @@ -86,22 +86,16 @@ typedef enum 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; @@ -109,7 +103,7 @@ vrrp_vr_addr_cmp (vrrp_vr_t * vr, vrrp_header_t * pkt) 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, @@ -117,25 +111,26 @@ vrrp_vr_addr_cmp (vrrp_vr_t * vr, vrrp_header_t * pkt) } else { - peer_addr = &(((ip4_header_t *) pkt) - 1)->src_address; + peer_addr_bytes = &peer_addr->ip4; local_addr = &addr.ip4; addr_size = 4; 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; @@ -146,11 +141,11 @@ vrrp_input_process_master (vrrp_vr_t * vr, vrrp_header_t * pkt) * - 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; } @@ -163,16 +158,17 @@ vrrp_input_process_master (vrrp_vr_t * vr, vrrp_header_t * pkt) /* 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; @@ -180,10 +176,9 @@ vrrp_input_process_backup (vrrp_vr_t * vr, vrrp_header_t * pkt) /* 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); @@ -208,19 +203,21 @@ vrrp_input_process (vrrp_input_process_args_t * args) 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", @@ -489,7 +486,6 @@ VLIB_NODE_FN (vrrp4_arp_input_node) (vlib_main_t * vm, 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", @@ -522,7 +518,6 @@ VLIB_NODE_FN (vrrp6_nd_input_node) (vlib_main_t * vm, 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", @@ -586,6 +581,7 @@ vrrp_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, 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 { @@ -596,6 +592,7 @@ vrrp_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, 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; @@ -612,6 +609,7 @@ vrrp_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, if (*ttl0 != 255) { error0 = VRRP_ERROR_BAD_TTL; + vrrp_incr_err_counter (VRRP_ERR_COUNTER_TTL); goto trace; } @@ -619,6 +617,7 @@ vrrp_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, if ((vrrp0->vrrp_version_and_type >> 4) != 3) { error0 = VRRP_ERROR_NOT_VERSION_3; + vrrp_incr_err_counter (VRRP_ERR_COUNTER_VERSION); goto trace; } @@ -627,6 +626,7 @@ vrrp_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, ((u32) vrrp0->n_addrs) * addr_len) { error0 = VRRP_ERROR_INCOMPLETE_PKT; + vrrp_incr_err_counter (VRRP_ERR_COUNTER_PKT_LEN); goto trace; } @@ -634,6 +634,7 @@ vrrp_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, 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; } @@ -643,6 +644,7 @@ vrrp_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, vrrp0->vr_id, is_ipv6))) { error0 = VRRP_ERROR_UNKNOWN_VR; + vrrp_incr_err_counter (VRRP_ERR_COUNTER_VRID); goto trace; } @@ -651,12 +653,14 @@ vrrp_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, 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)); @@ -693,7 +697,6 @@ VLIB_NODE_FN (vrrp4_input_node) (vlib_main_t * vm, vlib_node_runtime_t * node, return vrrp_input_inline (vm, node, frame, 0); } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (vrrp4_input_node) = { .name = "vrrp4-input", @@ -1098,7 +1101,6 @@ vrrp_input_init (vlib_main_t *vm) VLIB_INIT_FUNCTION (vrrp_input_init); -/* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON |