admin管理员组文章数量:1642169
功能:
1、分析收到的 vrrp 包。若包分析返回结果:VRRP_PACKET_OK,则直接返回 false;
2、若满足以下任一条件:
1)master 收到一个 priority = 0 的通告;
2)配置文件指定了:higher_prio_send_advert(若 master 收到一个更高优先级的 vrrp,则自身在变成 backup 之前发送一个通告)
且 对端 vrrp 的优先级 > 本端 vrrp 的优先级,或者 两者的优先级相同但ip相同;
则:
发送 vrrp 通告;
3、若对端与本端 vrrp 优先级均为 VRRP_PRIO_OWNER(255),则本端 vrrp 优先级-1;
4、若满足以下任一条件:
1)对端 vrrp 的优先级 < 本端 vrrp 的优先级;
2)两端优先级相同,所使用的的 ip 不同;
则:
1)发送 vrrp 通告(若配置项未指定 lower_prio_no_advert,即:如果收到低优先级的通告,不发送任何通告);
2)发送 ARP 数据包,更新远端 ARP 缓冲区;
5、若对端 vrrp 优先级 > 本端 vrrp 优先级 或者两者优先级相同但地址不同,
则:本端 vrrp 切换为 master
返回值 True:离开 master 状态,false:保留 master 状态
bool
vrrp_state_master_rx(vrrp_t * vrrp, const vrrphdr_t *hd, const char *buf, ssize_t buflen)
{
ssize_t ret;
#ifdef _WITH_VRRP_AUTH_
const ipsec_ah_t *ah;
#endif
unsigned master_adver_int;
int addr_cmp;
vrrp_t *gvrrp;
element e;
// TODO - could we get here with wantstate == FAULT and STATE != FAULT?
/* return on link failure */
// TODO - not needed???
/* vrrp 出现故障 */
if (vrrp->wantstate == VRRP_STATE_FAULT) {
vrrp->master_adver_int = vrrp->adver_int;
vrrp->ms_down_timer = 3 * vrrp->master_adver_int + VRRP_TIMER_SKEW(vrrp);
vrrp->state = VRRP_STATE_FAULT;
send_instance_notifies(vrrp);
vrrp->last_transition = timer_now();
return true;
}
/* 分析收到的数据包 */
ret = vrrp_check_packet(vrrp, hd, buf, buflen, true);
/* 包无效,直接返回 */
if (ret != VRRP_PACKET_OK)
return false;
/* 比较数据包地址 与 vrrp 地址*/
addr_cmp = vrrp_saddr_cmp(&vrrp->pkt_saddr, vrrp);
/*
若满足以下任一条件:
1、master 收到一个 priority = 0 的通告;
2、配置文件指定了:higher_prio_send_advert(若 master 收到一个更高优先级的 vrrp,则自身在变成 backup 之前发送一个通告)
且 对端 vrrp 的优先级 > 本端 vrrp 的优先级,或者 两者的优先级相同但ip相同;
则:
发送 vrrp 通告
*/
if (hd->priority == 0 ||
(vrrp->higher_prio_send_advert &&
(hd->priority > vrrp->effective_priority ||
(hd->priority == vrrp->effective_priority && addr_cmp > 0)))) {
log_message(LOG_INFO, "(%s) Master received priority 0 or lower priority advert", vrrp->iname);
vrrp_send_adv(vrrp, vrrp->effective_priority);/* 发送 vrrp 通告 */
if (hd->priority == 0)
return false;
}
/* 若对端与本端 vrrp 优先级均为 VRRP_PRIO_OWNER(255),则本端 vrrp 优先级-1 */
if (hd->priority == vrrp->effective_priority) {
if (addr_cmp == 0)
/* 对端使用与本端相同的ip发送优先级一样的 vrrp */
log_message(LOG_INFO, "(%s) WARNING - equal priority advert received from remote host with our IP address.", vrrp->iname);
else if (vrrp->effective_priority == VRRP_PRIO_OWNER) {
/* If we are configured as the address owner (priority == 255), and we receive an advertisement
* from another system indicating it is also the address owner, then there is a clear conflict.
* Report a configuration error, and drop our priority as a workaround. */
log_message(LOG_INFO, "(%s) CONFIGURATION ERROR: local instance and a remote instance are both configured as address owner, please fix - reducing local priority", vrrp->iname);
vrrp->effective_priority = VRRP_PRIO_OWNER - 1;
vrrp->base_priority = VRRP_PRIO_OWNER - 1;
}
}
/*
若满足以下任一条件:
1、对端 vrrp 的优先级 < 本端 vrrp 的优先级;
2、两端优先级相同,所使用的的 ip 不同;
则:
1)发送 vrrp 通告(若配置项未指定 lower_prio_no_advert,即:如果收到低优先级的通告,不发送任何通告);
2)发送 ARP 数据包,更新远端 ARP 缓冲区;
*/
if (hd->priority < vrrp->effective_priority ||
(hd->priority == vrrp->effective_priority &&
addr_cmp < 0)) {
/* We receive a lower prio adv we just refresh remote ARP cache */
log_message(LOG_INFO, "(%s) Received advert from %s with lower priority %d, ours %d%s",
vrrp->iname,
inet_sockaddrtos(&vrrp->pkt_saddr),
hd->priority,
vrrp->effective_priority,
!vrrp->lower_prio_no_advert ? ", forcing new election" : "");
#ifdef _WITH_VRRP_AUTH_
if (vrrp->auth_type == VRRP_AUTH_AH) {
ah = (const ipsec_ah_t *) (buf + sizeof(struct iphdr));
log_message(LOG_INFO, "(%s) IPSEC-AH : Syncing seq_num"
" - Increment seq"
, vrrp->iname);
// TODO - why is seq_number taken from lower priority advert?
vrrp->ipsecah_counter.seq_number = ntohl(ah->seq_number) + 1;
vrrp->ipsecah_counter.cycle = false;
}
#endif
/*
若配置项未指定 lower_prio_no_advert(如果收到低优先级的通告,不发送任何通告),
则发送 vrrp 通告
*/
if (!vrrp->lower_prio_no_advert)
vrrp_send_adv(vrrp, vrrp->effective_priority);
/*
若指定了 garp_lower_prio_rep(当 master 接收到一个较低优先级的 vrrp 后,一次发送 gratuitous apr 的数量组),
则发送 ARP 数据包,更新远端 ARP 缓冲区
*/
if (vrrp->garp_lower_prio_rep) {
vrrp_send_link_update(vrrp, vrrp->garp_lower_prio_rep);
if (vrrp->garp_lower_prio_delay)
thread_add_timer(master, vrrp_lower_prio_gratuitous_arp_thread,
vrrp, vrrp->garp_lower_prio_delay);
/* If we are a member of a sync group, send GARP messages
* for any other member of the group that has
* garp_lower_prio_rep set */
if (vrrp->sync) {
LIST_FOREACH(vrrp->sync->vrrp_instances, gvrrp, e) {
if (gvrrp == vrrp)
continue;
if (!gvrrp->garp_lower_prio_rep)
continue;
vrrp_send_link_update(gvrrp, gvrrp->garp_lower_prio_rep);
if (gvrrp->garp_lower_prio_delay)
thread_add_timer(master, vrrp_lower_prio_gratuitous_arp_thread,
gvrrp, gvrrp->garp_lower_prio_delay);
}
}
}
/* If a lower priority router has transitioned to master, there has presumably
* been an intermittent communications break between the master and backup. It
* appears that servers in an Amazon AWS environment can experience this.
* The problem then occurs if a notify_master script is executed on the backup
* that has just transitioned to master and the script executes something like
* a `aws ec2 assign-private-ip-addresses` command, thereby removing the address
* from the 'proper' master. Executing notify_master_rx_lower_pri notification
* allows the 'proper' master to recover the secondary addresses. */
send_event_notify(vrrp, VRRP_EVENT_MASTER_RX_LOWER_PRI);
return false;
}
/*
若对端 vrrp 优先级 > 本端 vrrp 优先级 或者两者优先级相同但地址不同,
则:本端 vrrp 切换为 master
*/
if (hd->priority > vrrp->effective_priority ||
(hd->priority == vrrp->effective_priority && addr_cmp > 0)) {
if (hd->priority > vrrp->effective_priority)
log_message(LOG_INFO, "(%s) Master received advert from %s with higher priority %d, ours %d",
vrrp->iname,
inet_sockaddrtos(&vrrp->pkt_saddr),
hd->priority,
vrrp->effective_priority);
else
log_message(LOG_INFO, "(%s) Master received advert from %s with same priority %d but higher IP address than ours",
vrrp->iname,
inet_sockaddrtos(&vrrp->pkt_saddr),
hd->priority);
#ifdef _WITH_VRRP_AUTH_
if (vrrp->auth_type == VRRP_AUTH_AH)
vrrp->ipsecah_counter.cycle = false;
#endif
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 from %u to %u milli-sec from higher priority master",
vrrp->iname, vrrp->master_adver_int / (TIMER_HZ / 1000), 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->master_priority = hd->priority;
vrrp->wantstate = VRRP_STATE_BACK;
vrrp->state = VRRP_STATE_BACK;
return true;
}
return false;
}
本文标签: 源码Keepalivedvrrpstatemasterrx
版权声明:本文标题:keepalived源码解析 —— vrrp_state_master_rx() 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/xitong/1729328578a1196083.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论