keepalived vrrp报文机制
vrrp通告报文发送机制
应用层函数:
vrrp_send_adv()
每次通告报文发送前需要调用更新函数,更新优先级和目的IP等值
vrrp_update_pkt()
完成报文更新后,调用发送函数完成发送
vrrp_send_pkt()
发送函数可以实现单播,组播。
1.带unicast_peers参数时,只会对目标内都地址发送;
2.当参数为NULL默认对组播地址进行组播。
每个vrrp实例创建和完成初始化时vrrp_complete_instance(),就已经对vrrp报文完成构建vrrp_build_pkt(),后续都通告报文只是更新vrrp头和ip头中都必要字段;
并且vrrp实例在初始化时完成对发送数据缓存区的分配和初始化vrrp_alloc_send_buffer()(主要包括ip头+vrrp头部分,还有少量ip地址区和authentication区)。
所以如果想利用vrrp报文进行数据同步,我们需要对vrrp的buffer区进行升级,使之能携带data信息,并且需要相应都data填充函数,在每次数据同步报文发送前完成对buffer区的更新。
vrrp_alloc_send_buffer()函数仅仅是根据计算得到的vrrp报文长度,malloc一块内存而已,没有具体的赋值操作。
vrrp_build_pkt()函数则是完成buffer区报文都初始化构造:
vrrp_build_ip4() 构造ip头
vrrp_build_vrrp() 构造vrrp报文
传输层函数:
sock_t类型,包含单播远地址,物理接口interface,接收socket fd,发送socket fd等信息。
/*
-
Our instance dispatcher use a socket pool.
-
That way we handle VRRP protocol type per
-
physical interface.
*/
typedef struct _sock {
sa_family_t family;
int proto;
interface_t *ifp;
const struct sockaddr_storage *unicast_src;
int fd_in;
int fd_out;
int rx_buf_size;
thread_ref_t thread;
rb_root_t rb_vrid;
rb_root_cached_t rb_sands;/* Linked list member */
list_head_t e_list;
} sock_t;
sock pool即是sock类型组成的链表。
open_sockpool_socket(sock_t *sock)函数,根据sock参数中的单播源地址信息 sock->unicast_src,完成以下操作
1.打开一个新的socket(sockt->ifd_in)并加入到多播地址组中;
sock->fd_in = open_vrrp_read_socket(sock->family, sock->proto,sock->ifp, unicast_src_p, sock->rx_buf_size) 主要操作:
a.创建socket,fd = socket()
b.配置socket相关options,setsockopt(fd)
c.单播报文,bind()到单播源地址上unicast_src;多播报文则bind()到vrrp实例多播地址组global_data->vrrp_mcast_group4
d.绑定到指定接口if_setsockopt_bindtodevice(),以只处理我们关注的报文(来自特定接口)
2.同时打开一个socket(sock->fd_out)用于发送vrrp报文。
sock->fd_out = open_vrrp_send_socket(sock->family, sock->proto, sock->ifp, unicast_src_p) 主要操作:
a.创建socket,fd = socket()
b.配置socket相关options,setsockopt(fd)
c.绑定到指定接口if_setsockopt_bindtodevice()
1.vrrp_scheduler.c模块中vrrp_open_sockpool()一次性完成对sock_t链表中所有sock的fd_in,fd_out的创建;
2.vrrp_if.c模块中setup_interface()配置vrrp实例的接口内容时,如果fd_in没有完成初始化,则调用open_sockpool_socket()完成创建。
sock_t池多路复用处理机制
/*
-
We create & allocate a socket pool here. The soft design
-
can be sum up by the following sketch :
-
fd1 fd2 fd3 fd4 fdi fdi+1
-
-----_/--------_/—…---__/—
-
| ETH0 | | ETH1 | | ETHn |
-
±-----+ ±-----+ ±-----+
-
TODO TODO - this description is way out of date
-
Here we have n physical NIC. Each NIC own a maximum of 2 fds.
-
(one for VRRP the other for IPSEC_AH). All our VRRP instances
-
are multiplexed through this fds. So our design can handle 2*n
-
multiplexing points.
*/
void
vrrp_dispatcher_init(attribute((unused)) thread_ref_t thread)
{
vrrp_create_sockpool(&vrrp_data->vrrp_socket_pool);/* open the VRRP socket pool */
vrrp_open_sockpool(&vrrp_data->vrrp_socket_pool);/* set VRRP instance fds to sockpool */
vrrp_set_fds(&vrrp_data->vrrp_socket_pool);/* create the VRRP socket pool list /
/ register read dispatcher worker thread */
vrrp_register_workers(&vrrp_data->vrrp_socket_pool);/* Dump socket pool */
if (__test_bit(LOG_DETAIL_BIT, &debug))
dump_sock_list(NULL, &vrrp_data->vrrp_socket_pool);vrrp_initialised = true;
}
epoll机制
链表+红黑树