功能:
1、分析收到的 vrrp 包。若包分析返回结果:VRRP_PACKET_OK,则直接返回 false;
2、若未开启抢占模式(抢占模式只在 back 状态下有效) 或 对端 vrrp 优先级 >= 本端 vrrp 优先级,
则将对端 vrrp address 与优先级标记为为 master address 与优先级,同时本端 vrrp 继续保持 back 状态;
3、若开启了抢占模式 且 vrrp 通告的优先级 < 本端 vrrp 优先级,将本端 vrrp address 记录为 master address。
/* BACKUP state processing */
void
vrrp_state_backup(vrrp_t *vrrp, const vrrphdr_t *hd, const char *buf, ssize_t buflen)
{
ssize_t ret = 0;
unsigned master_adver_int;
bool check_addr = false;
timeval_t new_ms_down_timer;
bool ignore_advert = false;
/* Process the incoming packet */
if (!vrrp->skip_check_adv_addr ||
vrrp->master_saddr.ss_family != vrrp->pkt_saddr.ss_family)
check_addr = true;
else {
/* Check if the addresses are different */
if (vrrp->pkt_saddr.ss_family == AF_INET) {
if (((struct sockaddr_in*)&vrrp->pkt_saddr)->sin_addr.s_addr != ((struct sockaddr_in*)&vrrp->master_saddr)->sin_addr.s_addr)
check_addr = true ;
} else {
if (!IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6*)&vrrp->pkt_saddr)->sin6_addr, &((struct sockaddr_in6*)&vrrp->master_saddr)->sin6_addr))
check_addr = true;
}
}
/* 分析收到的数据包 */
ret = vrrp_check_packet(vrrp, hd, buf, buflen, check_addr);
/* 包无效 */
if (ret != VRRP_PACKET_OK)
ignore_advert = true;
/* 包有效 */
/* vrrp 通告优先级为0 */
else if (hd->priority == 0) {
log_message(LOG_INFO, "(%s) Backup received priority 0 advertisement", vrrp->iname);
vrrp->ms_down_timer = VRRP_TIMER_SKEW(vrrp);
#ifdef _WITH_SNMP_RFCV3_
vrrp->stats->next_master_reason = VRRPV3_MASTER_REASON_PRIORITY;
#endif
}
/*
若:
1、未指定抢占模式;
2、对端 vrrp 优先级 >= 本端 vrrp 优先级;
*/
else if (vrrp->nopreempt ||
hd->priority >= vrrp->effective_priority ||
(vrrp->preempt_delay &&
(!vrrp->preempt_time.tv_sec ||
timercmp(&vrrp->preempt_time, &time_now, >)))) {
if (vrrp->version == VRRP_VERSION_3) {
master_adver_int = (ntohs(hd->v3.adver_int) & 0x0FFF) * TIMER_CENTI_HZ;
/* As per RFC5798, set Master_Adver_Interval to Adver Interval contained
* in the ADVERTISEMENT
*/
if (vrrp->master_adver_int != master_adver_int) {
log_message(LOG_INFO, "(%s) advertisement interval updated to %u milli-sec from %u milli-sec",
vrrp->iname, master_adver_int / (TIMER_HZ / 1000), vrrp->master_adver_int / (TIMER_HZ / 1000));
vrrp->master_adver_int = master_adver_int;
}
}
vrrp->ms_down_timer = 3 * vrrp->master_adver_int + VRRP_TIMER_SKEW(vrrp);
/* 将对端 vrrp address 与优先级标记为为 master address 与优先级 */
vrrp->master_saddr = vrrp->pkt_saddr;
vrrp->master_priority = hd->priority;
#ifdef _WITH_SNMP_RFCV3_
vrrp->stats->next_master_reason = VRRPV3_MASTER_REASON_MASTER_NO_RESPONSE;
#endif
/* 若开启了抢占模式,且对端 vrrp 优先级 >= 本端 vrrp 优先级,*/
if (vrrp->preempt_delay) {
if (hd->priority >= vrrp->effective_priority) {
if (vrrp->preempt_time.tv_sec) {
if (__test_bit(LOG_DETAIL_BIT, &debug))
log_message(LOG_INFO,
"(%s) stop preempt delay", vrrp->iname);
vrrp->preempt_time.tv_sec = 0;
}
} else if (!vrrp->preempt_time.tv_sec) {
if (__test_bit(LOG_DETAIL_BIT, &debug))
log_message(LOG_INFO,
"(%s) start preempt delay (%lu.%6.6lu)", vrrp->iname,
vrrp->preempt_delay / TIMER_HZ, vrrp->preempt_delay % TIMER_HZ);
vrrp->preempt_time = timer_add_long(timer_now(), vrrp->preempt_delay);
}
}
/* We might have been held in backup by a sync group, but if
* ms_down_timer had expired, we would have wanted MASTER state.
* Now we have received a backup, we want to be in BACKUP state. */
vrrp->wantstate = VRRP_STATE_BACK; /* 继续保持 back 状态 */
} else {
/* 指定了延迟抢占 且 vrrp 通告的优先级 < 本端 vrrp 优先级 */
/* !nopreempt and lower priority advert and any preempt delay timer has expired */
log_message(LOG_INFO, "(%s) received lower priority (%d) advert from %s - discarding", vrrp->iname, hd->priority, inet_sockaddrtos(&vrrp->pkt_saddr));
ignore_advert = true;
#ifdef _WITH_SNMP_RFCV3_
vrrp->stats->next_master_reason = VRRPV3_MASTER_REASON_PREEMPTED;
#endif
/* We still want to record the master's address for SNMP purposes */
vrrp->master_saddr = vrrp->pkt_saddr; /* 将对端 vrrp address 记录为 master address */
}
if (ignore_advert) {
/* We need to reduce the down timer since we have ignored the advert */
set_time_now();
timersub(&vrrp->sands, &time_now, &new_ms_down_timer);
vrrp->ms_down_timer = new_ms_down_timer.tv_sec < 0 ? 0 : (uint32_t)(new_ms_down_timer.tv_sec * TIMER_HZ + new_ms_down_timer.tv_usec);
}
}