]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * This is an implementation of PIM MLAG Functionality | |
3 | * | |
4 | * Module name: PIM MLAG | |
5 | * | |
6 | * Author: sathesh Kumar karra <sathk@cumulusnetworks.com> | |
7 | * | |
8 | * Copyright (C) 2019 Cumulus Networks http://www.cumulusnetworks.com | |
9 | * | |
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) | |
13 | * any later version. | |
14 | * | |
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 | |
18 | * more details. | |
19 | * | |
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 | |
23 | */ | |
24 | #include <zebra.h> | |
25 | ||
26 | #include "pimd.h" | |
27 | #include "pim_mlag.h" | |
28 | ||
29 | extern struct zclient *zclient; | |
30 | ||
31 | ||
32 | /********************API to process PIM MLAG Data ************************/ | |
33 | ||
34 | static void pim_mlag_process_mlagd_state_change(struct mlag_status msg) | |
35 | { | |
36 | char buf[MLAG_ROLE_STRSIZE]; | |
37 | ||
38 | if (PIM_DEBUG_MLAG) | |
39 | zlog_debug("%s: msg dump: my_role: %s, peer_state: %s", | |
40 | __func__, | |
41 | mlag_role2str(msg.my_role, buf, sizeof(buf)), | |
42 | (msg.peer_state == MLAG_STATE_RUNNING ? "RUNNING" | |
43 | : "DOWN")); | |
44 | } | |
45 | ||
46 | static void pim_mlag_process_peer_frr_state_change(struct mlag_frr_status msg) | |
47 | { | |
48 | if (PIM_DEBUG_MLAG) | |
49 | zlog_debug( | |
50 | "%s: msg dump: peer_frr_state: %s", __func__, | |
51 | (msg.frr_state == MLAG_FRR_STATE_UP ? "UP" : "DOWN")); | |
52 | } | |
53 | ||
54 | static void pim_mlag_process_vxlan_update(struct mlag_vxlan *msg) | |
55 | { | |
56 | } | |
57 | ||
58 | static void pim_mlag_process_mroute_add(struct mlag_mroute_add msg) | |
59 | { | |
60 | if (PIM_DEBUG_MLAG) { | |
61 | zlog_debug( | |
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, | |
64 | msg.cost_to_rp); | |
65 | zlog_debug( | |
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); | |
69 | } | |
70 | } | |
71 | ||
72 | static void pim_mlag_process_mroute_del(struct mlag_mroute_del msg) | |
73 | { | |
74 | if (PIM_DEBUG_MLAG) { | |
75 | zlog_debug( | |
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); | |
80 | } | |
81 | } | |
82 | ||
83 | ||
84 | int pim_zebra_mlag_handle_msg(struct stream *s, int len) | |
85 | { | |
86 | struct mlag_msg mlag_msg; | |
87 | char buf[ZLOG_FILTER_LENGTH_MAX]; | |
88 | int rc = 0; | |
89 | ||
90 | rc = mlag_lib_decode_mlag_hdr(s, &mlag_msg); | |
91 | if (rc) | |
92 | return (rc); | |
93 | ||
94 | if (PIM_DEBUG_MLAG) | |
95 | zlog_debug("%s: Received msg type: %s length: %d, bulk_cnt: %d", | |
96 | __func__, | |
97 | mlag_lib_msgid_to_str(mlag_msg.msg_type, buf, | |
98 | sizeof(buf)), | |
99 | mlag_msg.data_len, mlag_msg.msg_cnt); | |
100 | ||
101 | switch (mlag_msg.msg_type) { | |
102 | case MLAG_STATUS_UPDATE: { | |
103 | struct mlag_status msg; | |
104 | ||
105 | rc = mlag_lib_decode_mlag_status(s, &msg); | |
106 | if (rc) | |
107 | return (rc); | |
108 | pim_mlag_process_mlagd_state_change(msg); | |
109 | } break; | |
110 | case MLAG_PEER_FRR_STATUS: { | |
111 | struct mlag_frr_status msg; | |
112 | ||
113 | rc = mlag_lib_decode_frr_status(s, &msg); | |
114 | if (rc) | |
115 | return (rc); | |
116 | pim_mlag_process_peer_frr_state_change(msg); | |
117 | } break; | |
118 | case MLAG_VXLAN_UPDATE: { | |
119 | struct mlag_vxlan msg; | |
120 | ||
121 | rc = mlag_lib_decode_vxlan_update(s, &msg); | |
122 | if (rc) | |
123 | return rc; | |
124 | pim_mlag_process_vxlan_update(&msg); | |
125 | } break; | |
126 | case MLAG_MROUTE_ADD: { | |
127 | struct mlag_mroute_add msg; | |
128 | ||
129 | rc = mlag_lib_decode_mroute_add(s, &msg); | |
130 | if (rc) | |
131 | return (rc); | |
132 | pim_mlag_process_mroute_add(msg); | |
133 | } break; | |
134 | case MLAG_MROUTE_DEL: { | |
135 | struct mlag_mroute_del msg; | |
136 | ||
137 | rc = mlag_lib_decode_mroute_del(s, &msg); | |
138 | if (rc) | |
139 | return (rc); | |
140 | pim_mlag_process_mroute_del(msg); | |
141 | } break; | |
142 | case MLAG_MROUTE_ADD_BULK: { | |
143 | struct mlag_mroute_add msg; | |
144 | int i; | |
145 | ||
146 | for (i = 0; i < mlag_msg.msg_cnt; i++) { | |
147 | ||
148 | rc = mlag_lib_decode_mroute_add(s, &msg); | |
149 | if (rc) | |
150 | return (rc); | |
151 | pim_mlag_process_mroute_add(msg); | |
152 | } | |
153 | } break; | |
154 | case MLAG_MROUTE_DEL_BULK: { | |
155 | struct mlag_mroute_del msg; | |
156 | int i; | |
157 | ||
158 | for (i = 0; i < mlag_msg.msg_cnt; i++) { | |
159 | ||
160 | rc = mlag_lib_decode_mroute_del(s, &msg); | |
161 | if (rc) | |
162 | return (rc); | |
163 | pim_mlag_process_mroute_del(msg); | |
164 | } | |
165 | } break; | |
166 | default: | |
167 | break; | |
168 | } | |
169 | return 0; | |
170 | } | |
171 | ||
172 | /****************End of PIM Mesasge processing handler********************/ | |
173 | ||
174 | int pim_zebra_mlag_process_up(void) | |
175 | { | |
176 | if (PIM_DEBUG_MLAG) | |
177 | zlog_debug("%s: Received Process-Up from Mlag", __func__); | |
178 | ||
179 | return 0; | |
180 | } | |
181 | ||
182 | int pim_zebra_mlag_process_down(void) | |
183 | { | |
184 | if (PIM_DEBUG_MLAG) | |
185 | zlog_debug("%s: Received Process-Down from Mlag", __func__); | |
186 | ||
187 | return 0; | |
188 | } | |
189 | ||
190 | static int pim_mlag_register_handler(struct thread *thread) | |
191 | { | |
192 | uint32_t bit_mask = 0; | |
193 | ||
194 | if (!zclient) | |
195 | return -1; | |
196 | ||
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)); | |
206 | ||
207 | if (PIM_DEBUG_MLAG) | |
208 | zlog_debug("%s: Posting Client Register to MLAG mask: 0x%x", | |
209 | __func__, bit_mask); | |
210 | ||
211 | zclient_send_mlag_register(zclient, bit_mask); | |
212 | return 0; | |
213 | } | |
214 | ||
215 | void pim_mlag_register(void) | |
216 | { | |
217 | if (router->mlag_process_register) | |
218 | return; | |
219 | ||
220 | router->mlag_process_register = true; | |
221 | ||
222 | thread_add_event(router->master, pim_mlag_register_handler, NULL, 0, | |
223 | NULL); | |
224 | } | |
225 | ||
226 | static int pim_mlag_deregister_handler(struct thread *thread) | |
227 | { | |
228 | if (!zclient) | |
229 | return -1; | |
230 | ||
231 | if (PIM_DEBUG_MLAG) | |
232 | zlog_debug("%s: Posting Client De-Register to MLAG from PIM", | |
233 | __func__); | |
234 | router->connected_to_mlag = false; | |
235 | zclient_send_mlag_deregister(zclient); | |
236 | return 0; | |
237 | } | |
238 | ||
239 | void pim_mlag_deregister(void) | |
240 | { | |
241 | /* if somebody still interested in the MLAG channel skip de-reg */ | |
242 | if (router->pim_mlag_intf_cnt) | |
243 | return; | |
244 | ||
245 | /* not registered; nothing do */ | |
246 | if (!router->mlag_process_register) | |
247 | return; | |
248 | ||
249 | router->mlag_process_register = false; | |
250 | ||
251 | thread_add_event(router->master, pim_mlag_deregister_handler, NULL, 0, | |
252 | NULL); | |
253 | } | |
254 | ||
255 | void pim_if_configure_mlag_dualactive(struct pim_interface *pim_ifp) | |
256 | { | |
257 | if (!pim_ifp || !pim_ifp->pim || pim_ifp->activeactive == true) | |
258 | return; | |
259 | ||
260 | if (PIM_DEBUG_MLAG) | |
261 | zlog_debug("%s: Configuring active-active on Interface: %s", | |
262 | __func__, "NULL"); | |
263 | ||
264 | pim_ifp->activeactive = true; | |
265 | if (pim_ifp->pim) | |
266 | pim_ifp->pim->inst_mlag_intf_cnt++; | |
267 | ||
268 | router->pim_mlag_intf_cnt++; | |
269 | if (PIM_DEBUG_MLAG) | |
270 | zlog_debug( | |
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); | |
274 | ||
275 | if (router->pim_mlag_intf_cnt == 1) { | |
276 | /* | |
277 | * atleast one Interface is configured for MLAG, send register | |
278 | * to Zebra for receiving MLAG Updates | |
279 | */ | |
280 | pim_mlag_register(); | |
281 | } | |
282 | } | |
283 | ||
284 | void pim_if_unconfigure_mlag_dualactive(struct pim_interface *pim_ifp) | |
285 | { | |
286 | if (!pim_ifp || !pim_ifp->pim || pim_ifp->activeactive == false) | |
287 | return; | |
288 | ||
289 | if (PIM_DEBUG_MLAG) | |
290 | zlog_debug("%s: UnConfiguring active-active on Interface: %s", | |
291 | __func__, "NULL"); | |
292 | ||
293 | pim_ifp->activeactive = false; | |
294 | pim_ifp->pim->inst_mlag_intf_cnt--; | |
295 | ||
296 | router->pim_mlag_intf_cnt--; | |
297 | if (PIM_DEBUG_MLAG) | |
298 | zlog_debug( | |
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); | |
302 | ||
303 | if (router->pim_mlag_intf_cnt == 0) { | |
304 | /* | |
305 | * all the Interfaces are MLAG un-configured, post MLAG | |
306 | * De-register to Zebra | |
307 | */ | |
308 | pim_mlag_deregister(); | |
309 | } | |
310 | } | |
311 | ||
312 | ||
313 | void pim_instance_mlag_init(struct pim_instance *pim) | |
314 | { | |
315 | if (!pim) | |
316 | return; | |
317 | ||
318 | pim->inst_mlag_intf_cnt = 0; | |
319 | } | |
320 | ||
321 | ||
322 | void pim_instance_mlag_terminate(struct pim_instance *pim) | |
323 | { | |
324 | struct interface *ifp; | |
325 | ||
326 | if (!pim) | |
327 | return; | |
328 | ||
329 | FOR_ALL_INTERFACES (pim->vrf, ifp) { | |
330 | struct pim_interface *pim_ifp = ifp->info; | |
331 | ||
332 | if (!pim_ifp || pim_ifp->activeactive == false) | |
333 | continue; | |
334 | ||
335 | pim_if_unconfigure_mlag_dualactive(pim_ifp); | |
336 | } | |
337 | pim->inst_mlag_intf_cnt = 0; | |
338 | } | |
339 | ||
340 | void pim_mlag_init(void) | |
341 | { | |
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); | |
347 | } |