2 * This is an implementation of PIM MLAG Functionality
4 * Module name: PIM MLAG
6 * Author: sathesh Kumar karra <sathk@cumulusnetworks.com>
8 * Copyright (C) 2019 Cumulus Networks http://www.cumulusnetworks.com
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the Free
12 * Software Foundation; either version 2 of the License, or (at your option)
15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
20 * You should have received a copy of the GNU General Public License along
21 * with this program; see the file COPYING; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 extern struct zclient
*zclient
;
32 /********************API to process PIM MLAG Data ************************/
34 static void pim_mlag_process_mlagd_state_change(struct mlag_status msg
)
36 char buf
[MLAG_ROLE_STRSIZE
];
39 zlog_debug("%s: msg dump: my_role: %s, peer_state: %s",
41 mlag_role2str(msg
.my_role
, buf
, sizeof(buf
)),
42 (msg
.peer_state
== MLAG_STATE_RUNNING
? "RUNNING"
46 static void pim_mlag_process_peer_frr_state_change(struct mlag_frr_status msg
)
50 "%s: msg dump: peer_frr_state: %s", __func__
,
51 (msg
.frr_state
== MLAG_FRR_STATE_UP
? "UP" : "DOWN"));
54 static void pim_mlag_process_vxlan_update(struct mlag_vxlan
*msg
)
58 static void pim_mlag_process_mroute_add(struct mlag_mroute_add msg
)
62 "%s: msg dump: vrf_name: %s, s.ip: 0x%x, g.ip: 0x%x cost: %u",
63 __func__
, msg
.vrf_name
, msg
.source_ip
, msg
.group_ip
,
66 "owner_id: %d, DR: %d, Dual active: %d, vrf_id: 0x%x intf_name: %s",
67 msg
.owner_id
, msg
.am_i_dr
, msg
.am_i_dual_active
,
68 msg
.vrf_id
, msg
.intf_name
);
72 static void pim_mlag_process_mroute_del(struct mlag_mroute_del msg
)
76 "%s: msg dump: vrf_name: %s, s.ip: 0x%x, g.ip: 0x%x ",
77 __func__
, msg
.vrf_name
, msg
.source_ip
, msg
.group_ip
);
78 zlog_debug("owner_id: %d, vrf_id: 0x%x intf_name: %s",
79 msg
.owner_id
, msg
.vrf_id
, msg
.intf_name
);
84 int pim_zebra_mlag_handle_msg(struct stream
*s
, int len
)
86 struct mlag_msg mlag_msg
;
87 char buf
[ZLOG_FILTER_LENGTH_MAX
];
90 rc
= mlag_lib_decode_mlag_hdr(s
, &mlag_msg
);
95 zlog_debug("%s: Received msg type: %s length: %d, bulk_cnt: %d",
97 mlag_lib_msgid_to_str(mlag_msg
.msg_type
, buf
,
99 mlag_msg
.data_len
, mlag_msg
.msg_cnt
);
101 switch (mlag_msg
.msg_type
) {
102 case MLAG_STATUS_UPDATE
: {
103 struct mlag_status msg
;
105 rc
= mlag_lib_decode_mlag_status(s
, &msg
);
108 pim_mlag_process_mlagd_state_change(msg
);
110 case MLAG_PEER_FRR_STATUS
: {
111 struct mlag_frr_status msg
;
113 rc
= mlag_lib_decode_frr_status(s
, &msg
);
116 pim_mlag_process_peer_frr_state_change(msg
);
118 case MLAG_VXLAN_UPDATE
: {
119 struct mlag_vxlan msg
;
121 rc
= mlag_lib_decode_vxlan_update(s
, &msg
);
124 pim_mlag_process_vxlan_update(&msg
);
126 case MLAG_MROUTE_ADD
: {
127 struct mlag_mroute_add msg
;
129 rc
= mlag_lib_decode_mroute_add(s
, &msg
);
132 pim_mlag_process_mroute_add(msg
);
134 case MLAG_MROUTE_DEL
: {
135 struct mlag_mroute_del msg
;
137 rc
= mlag_lib_decode_mroute_del(s
, &msg
);
140 pim_mlag_process_mroute_del(msg
);
142 case MLAG_MROUTE_ADD_BULK
: {
143 struct mlag_mroute_add msg
;
146 for (i
= 0; i
< mlag_msg
.msg_cnt
; i
++) {
148 rc
= mlag_lib_decode_mroute_add(s
, &msg
);
151 pim_mlag_process_mroute_add(msg
);
154 case MLAG_MROUTE_DEL_BULK
: {
155 struct mlag_mroute_del msg
;
158 for (i
= 0; i
< mlag_msg
.msg_cnt
; i
++) {
160 rc
= mlag_lib_decode_mroute_del(s
, &msg
);
163 pim_mlag_process_mroute_del(msg
);
172 /****************End of PIM Mesasge processing handler********************/
174 int pim_zebra_mlag_process_up(void)
177 zlog_debug("%s: Received Process-Up from Mlag", __func__
);
182 int pim_zebra_mlag_process_down(void)
185 zlog_debug("%s: Received Process-Down from Mlag", __func__
);
190 static int pim_mlag_register_handler(struct thread
*thread
)
192 uint32_t bit_mask
= 0;
197 SET_FLAG(bit_mask
, (1 << MLAG_STATUS_UPDATE
));
198 SET_FLAG(bit_mask
, (1 << MLAG_MROUTE_ADD
));
199 SET_FLAG(bit_mask
, (1 << MLAG_MROUTE_DEL
));
200 SET_FLAG(bit_mask
, (1 << MLAG_DUMP
));
201 SET_FLAG(bit_mask
, (1 << MLAG_MROUTE_ADD_BULK
));
202 SET_FLAG(bit_mask
, (1 << MLAG_MROUTE_DEL_BULK
));
203 SET_FLAG(bit_mask
, (1 << MLAG_PIM_CFG_DUMP
));
204 SET_FLAG(bit_mask
, (1 << MLAG_VXLAN_UPDATE
));
205 SET_FLAG(bit_mask
, (1 << MLAG_PEER_FRR_STATUS
));
208 zlog_debug("%s: Posting Client Register to MLAG mask: 0x%x",
211 zclient_send_mlag_register(zclient
, bit_mask
);
215 void pim_mlag_register(void)
217 if (router
->mlag_process_register
)
220 router
->mlag_process_register
= true;
222 thread_add_event(router
->master
, pim_mlag_register_handler
, NULL
, 0,
226 static int pim_mlag_deregister_handler(struct thread
*thread
)
232 zlog_debug("%s: Posting Client De-Register to MLAG from PIM",
234 router
->connected_to_mlag
= false;
235 zclient_send_mlag_deregister(zclient
);
239 void pim_mlag_deregister(void)
241 /* if somebody still interested in the MLAG channel skip de-reg */
242 if (router
->pim_mlag_intf_cnt
)
245 /* not registered; nothing do */
246 if (!router
->mlag_process_register
)
249 router
->mlag_process_register
= false;
251 thread_add_event(router
->master
, pim_mlag_deregister_handler
, NULL
, 0,
255 void pim_if_configure_mlag_dualactive(struct pim_interface
*pim_ifp
)
257 if (!pim_ifp
|| !pim_ifp
->pim
|| pim_ifp
->activeactive
== true)
261 zlog_debug("%s: Configuring active-active on Interface: %s",
264 pim_ifp
->activeactive
= true;
266 pim_ifp
->pim
->inst_mlag_intf_cnt
++;
268 router
->pim_mlag_intf_cnt
++;
271 "%s: Total MLAG configured Interfaces on router: %d, Inst: %d",
272 __func__
, router
->pim_mlag_intf_cnt
,
273 pim_ifp
->pim
->inst_mlag_intf_cnt
);
275 if (router
->pim_mlag_intf_cnt
== 1) {
277 * atleast one Interface is configured for MLAG, send register
278 * to Zebra for receiving MLAG Updates
284 void pim_if_unconfigure_mlag_dualactive(struct pim_interface
*pim_ifp
)
286 if (!pim_ifp
|| !pim_ifp
->pim
|| pim_ifp
->activeactive
== false)
290 zlog_debug("%s: UnConfiguring active-active on Interface: %s",
293 pim_ifp
->activeactive
= false;
294 pim_ifp
->pim
->inst_mlag_intf_cnt
--;
296 router
->pim_mlag_intf_cnt
--;
299 "%s: Total MLAG configured Interfaces on router: %d, Inst: %d",
300 __func__
, router
->pim_mlag_intf_cnt
,
301 pim_ifp
->pim
->inst_mlag_intf_cnt
);
303 if (router
->pim_mlag_intf_cnt
== 0) {
305 * all the Interfaces are MLAG un-configured, post MLAG
306 * De-register to Zebra
308 pim_mlag_deregister();
313 void pim_instance_mlag_init(struct pim_instance
*pim
)
318 pim
->inst_mlag_intf_cnt
= 0;
322 void pim_instance_mlag_terminate(struct pim_instance
*pim
)
324 struct interface
*ifp
;
329 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
330 struct pim_interface
*pim_ifp
= ifp
->info
;
332 if (!pim_ifp
|| pim_ifp
->activeactive
== false)
335 pim_if_unconfigure_mlag_dualactive(pim_ifp
);
337 pim
->inst_mlag_intf_cnt
= 0;
340 void pim_mlag_init(void)
342 router
->pim_mlag_intf_cnt
= 0;
343 router
->connected_to_mlag
= false;
344 router
->mlag_fifo
= stream_fifo_new();
345 router
->zpthread_mlag_write
= NULL
;
346 router
->mlag_stream
= stream_new(MLAG_BUF_LIMIT
);