keepalived源码解析 —— vrrp_state_backup()

功能:
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);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值