]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_mlag.c
Merge pull request #13414 from LabNConsulting/chopps/no-mgmtd-nowrite-on-off
[mirror_frr.git] / zebra / zebra_mlag.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
df395600 2/* Zebra Mlag Code.
6a597223 3 * Copyright (C) 2018 Cumulus Networks, Inc.
df395600 4 * Donald Sharp
df395600
DS
5 */
6#include "zebra.h"
7
763ec244 8#include "command.h"
df395600 9#include "hook.h"
ee235396
SK
10#include "frr_pthread.h"
11#include "mlag.h"
df395600
DS
12
13#include "zebra/zebra_mlag.h"
fd193241 14#include "zebra/zebra_mlag_vty.h"
e96ba9da 15#include "zebra/zebra_router.h"
b120fe3b
DS
16#include "zebra/zapi_msg.h"
17#include "zebra/debug.h"
df395600 18
4b7272c7
DL
19#ifdef HAVE_PROTOBUF_VERSION_3
20#include "mlag/mlag.pb-c.h"
21#endif
22
d621815a 23DEFINE_HOOK(zebra_mlag_private_write_data,
8451921b
DL
24 (uint8_t *data, uint32_t len), (data, len));
25DEFINE_HOOK(zebra_mlag_private_monitor_state, (), ());
26DEFINE_HOOK(zebra_mlag_private_open_channel, (), ());
27DEFINE_HOOK(zebra_mlag_private_close_channel, (), ());
28DEFINE_HOOK(zebra_mlag_private_cleanup_data, (), ());
d621815a 29
ee235396
SK
30#define ZEBRA_MLAG_METADATA_LEN 4
31#define ZEBRA_MLAG_MSG_BCAST 0xFFFFFFFF
32
33uint8_t mlag_wr_buffer[ZEBRA_MLAG_BUF_LIMIT];
34uint8_t mlag_rd_buffer[ZEBRA_MLAG_BUF_LIMIT];
ee235396
SK
35
36static bool test_mlag_in_progress;
37
38static int zebra_mlag_signal_write_thread(void);
e6685141
DS
39static void zebra_mlag_terminate_pthread(struct event *event);
40static void zebra_mlag_post_data_from_main_thread(struct event *thread);
ee235396
SK
41static void zebra_mlag_publish_process_state(struct zserv *client,
42 zebra_message_types_t msg_type);
43
44/**********************MLAG Interaction***************************************/
45
46/*
47 * API to post the Registration to MLAGD
48 * MLAG will not process any messages with out the registration
49 */
50void zebra_mlag_send_register(void)
51{
52 struct stream *s = NULL;
53
54 s = stream_new(sizeof(struct mlag_msg));
55
56 stream_putl(s, MLAG_REGISTER);
57 stream_putw(s, MLAG_MSG_NULL_PAYLOAD);
58 stream_putw(s, MLAG_MSG_NO_BATCH);
59 stream_fifo_push_safe(zrouter.mlag_info.mlag_fifo, s);
60 zebra_mlag_signal_write_thread();
61
62 if (IS_ZEBRA_DEBUG_MLAG)
63 zlog_debug("%s: Enqueued MLAG Register to MLAG Thread ",
64 __func__);
65}
66
67/*
68 * API to post the De-Registration to MLAGD
69 * MLAG will not process any messages after the de-registration
70 */
71void zebra_mlag_send_deregister(void)
72{
73 struct stream *s = NULL;
74
75 s = stream_new(sizeof(struct mlag_msg));
76
77 stream_putl(s, MLAG_DEREGISTER);
78 stream_putw(s, MLAG_MSG_NULL_PAYLOAD);
79 stream_putw(s, MLAG_MSG_NO_BATCH);
80 stream_fifo_push_safe(zrouter.mlag_info.mlag_fifo, s);
81 zebra_mlag_signal_write_thread();
82
83 if (IS_ZEBRA_DEBUG_MLAG)
84 zlog_debug("%s: Enqueued MLAG De-Register to MLAG Thread ",
85 __func__);
86}
87
88/*
89 * API To handle MLAG Received data
90 * Decodes the data using protobuf and enqueue to main thread
91 * main thread publish this to clients based on client subscription
92 */
93void zebra_mlag_process_mlag_data(uint8_t *data, uint32_t len)
94{
95 struct stream *s = NULL;
ee235396
SK
96 int msg_type = 0;
97
010b575b 98 s = stream_new(ZEBRA_MLAG_BUF_LIMIT);
f24d9ab6
DS
99 /*
100 * Place holder we need the message type first
101 */
102 stream_putl(s, msg_type);
67fa73f2 103 msg_type = zebra_mlag_protobuf_decode_message(s, data, len);
ee235396
SK
104
105 if (msg_type <= 0) {
106 /* Something went wrong in decoding */
107 stream_free(s);
108 zlog_err("%s: failed to process mlag data-%d, %u", __func__,
109 msg_type, len);
110 return;
111 }
112
113 /*
114 * additional four bytes are for message type
115 */
f24d9ab6 116 stream_putl_at(s, 0, msg_type);
907a2395
DS
117 event_add_event(zrouter.master, zebra_mlag_post_data_from_main_thread,
118 s, 0, NULL);
ee235396
SK
119}
120
121/**********************End of MLAG Interaction********************************/
122
123/************************MLAG Thread Processing*******************************/
124
125/*
126 * after posting every 'ZEBRA_MLAG_POST_LIMIT' packets, MLAG Thread will be
127 * yielded to give CPU for other threads
128 */
129#define ZEBRA_MLAG_POST_LIMIT 100
130
131/*
132 * This thread reads the clients data from the Global queue and encodes with
133 * protobuf and pass on to the MLAG socket.
134 */
e6685141 135static void zebra_mlag_client_msg_handler(struct event *event)
ee235396
SK
136{
137 struct stream *s;
138 uint32_t wr_count = 0;
139 uint32_t msg_type = 0;
67fa73f2 140 uint32_t max_count = 0;
ee235396
SK
141 int len = 0;
142
143 wr_count = stream_fifo_count_safe(zrouter.mlag_info.mlag_fifo);
144 if (IS_ZEBRA_DEBUG_MLAG)
1e76492b 145 zlog_debug(":%s: Processing MLAG write, %u messages in queue",
ee235396
SK
146 __func__, wr_count);
147
67fa73f2 148 max_count = MIN(wr_count, ZEBRA_MLAG_POST_LIMIT);
ee235396 149
67fa73f2 150 for (wr_count = 0; wr_count < max_count; wr_count++) {
ee235396
SK
151 s = stream_fifo_pop_safe(zrouter.mlag_info.mlag_fifo);
152 if (!s) {
153 zlog_debug(":%s: Got a NULL Messages, some thing wrong",
154 __func__);
155 break;
156 }
157
ee235396
SK
158 /*
159 * Encode the data now
160 */
161 len = zebra_mlag_protobuf_encode_client_data(s, &msg_type);
162
163 /*
164 * write to MCLAGD
165 */
67fa73f2 166 if (len > 0) {
d621815a
DL
167 hook_call(zebra_mlag_private_write_data,
168 mlag_wr_buffer, len);
ee235396 169
67fa73f2
SK
170 /*
171 * If message type is De-register, send a signal to main
172 * thread, so that necessary cleanup will be done by
173 * main thread.
174 */
175 if (msg_type == MLAG_DEREGISTER) {
907a2395
DS
176 event_add_event(zrouter.master,
177 zebra_mlag_terminate_pthread,
178 NULL, 0, NULL);
67fa73f2 179 }
ee235396
SK
180 }
181
182 stream_free(s);
183 }
184
185 if (IS_ZEBRA_DEBUG_MLAG)
186 zlog_debug(":%s: Posted %d messages to MLAGD", __func__,
187 wr_count);
188 /*
189 * Currently there is only message write task is enqueued to this
190 * thread, yielding was added for future purpose, so that this thread
191 * can server other tasks also and in case FIFO is empty, this task will
192 * be schedule when main thread adds some messages
193 */
194 if (wr_count >= ZEBRA_MLAG_POST_LIMIT)
195 zebra_mlag_signal_write_thread();
ee235396
SK
196}
197
198/*
199 * API to handle the process state.
200 * In case of Down, Zebra keep monitoring the MLAG state.
201 * all the state Notifications will be published to clients
202 */
203void zebra_mlag_handle_process_state(enum zebra_mlag_state state)
204{
205 if (state == MLAG_UP) {
206 zrouter.mlag_info.connected = true;
207 zebra_mlag_publish_process_state(NULL, ZEBRA_MLAG_PROCESS_UP);
208 zebra_mlag_send_register();
209 } else if (state == MLAG_DOWN) {
210 zrouter.mlag_info.connected = false;
211 zebra_mlag_publish_process_state(NULL, ZEBRA_MLAG_PROCESS_DOWN);
d621815a 212 hook_call(zebra_mlag_private_monitor_state);
ee235396
SK
213 }
214}
215
216/***********************End of MLAG Thread processing*************************/
217
218/*************************Multi-entratnt Api's********************************/
219
220/*
221 * Provider api to signal that work/events are available
222 * for the Zebra MLAG Write pthread.
223 * This API is called from 2 pthreads..
224 * 1) by main thread when client posts a MLAG Message
225 * 2) by MLAG Thread, in case of yield
226 * though this api, is called from two threads we don't need any locking
227 * because Thread task enqueue is thread safe means internally it had
228 * necessary protection
229 */
230static int zebra_mlag_signal_write_thread(void)
231{
1e76492b
SK
232 if (IS_ZEBRA_DEBUG_MLAG)
233 zlog_debug(":%s: Scheduling MLAG write", __func__);
234 /*
235 * This api will be called from Both main & MLAG Threads.
236 * main thread writes, "zrouter.mlag_info.th_master" only
237 * during Zebra Init/after MLAG thread is destroyed.
238 * so it is safe to use without any locking
239 */
907a2395
DS
240 event_add_event(zrouter.mlag_info.th_master,
241 zebra_mlag_client_msg_handler, NULL, 0,
242 &zrouter.mlag_info.t_write);
ee235396
SK
243 return 0;
244}
245
246/*
247 * API will be used to publish the MLAG state to interested clients
248 * In case client is passed, state is posted only for that client,
249 * otherwise to all interested clients
250 * this api can be called from two threads.
251 * 1) from main thread: when client is passed
252 * 2) from MLAG Thread: when client is NULL
253 *
254 * In second case, to avoid global data access data will be post to Main
255 * thread, so that actual posting to clients will happen from Main thread.
256 */
257static void zebra_mlag_publish_process_state(struct zserv *client,
258 zebra_message_types_t msg_type)
259{
260 struct stream *s;
261
262 if (IS_ZEBRA_DEBUG_MLAG)
263 zlog_debug("%s: Publishing MLAG process state:%s to %s Client",
264 __func__,
265 (msg_type == ZEBRA_MLAG_PROCESS_UP) ? "UP" : "DOWN",
266 (client) ? "one" : "all");
267
268 if (client) {
269 s = stream_new(ZEBRA_HEADER_SIZE);
270 zclient_create_header(s, msg_type, VRF_DEFAULT);
271 zserv_send_message(client, s);
272 return;
273 }
274
275
276 /*
277 * additional four bytes are for mesasge type
278 */
279 s = stream_new(ZEBRA_HEADER_SIZE + ZEBRA_MLAG_METADATA_LEN);
280 stream_putl(s, ZEBRA_MLAG_MSG_BCAST);
281 zclient_create_header(s, msg_type, VRF_DEFAULT);
907a2395
DS
282 event_add_event(zrouter.master, zebra_mlag_post_data_from_main_thread,
283 s, 0, NULL);
ee235396
SK
284}
285
286/**************************End of Multi-entrant Apis**************************/
287
288/***********************Zebra Main thread processing**************************/
289
290/*
291 * To avoid data corruption, messages will be post to clients only from
292 * main thread, because for that access was needed for clients list.
293 * so instead of forcing the locks, messages will be posted from main thread.
294 */
e6685141 295static void zebra_mlag_post_data_from_main_thread(struct event *thread)
ee235396 296{
e16d030c 297 struct stream *s = EVENT_ARG(thread);
ee235396
SK
298 struct stream *zebra_s = NULL;
299 struct listnode *node;
300 struct zserv *client;
301 uint32_t msg_type = 0;
302 uint32_t msg_len = 0;
303
304 if (!s)
cc9f21da 305 return;
ee235396
SK
306
307 STREAM_GETL(s, msg_type);
308 if (IS_ZEBRA_DEBUG_MLAG)
309 zlog_debug(
3ac4e7cc 310 "%s: Posting MLAG data for msg_type:0x%x to interested clients",
ee235396
SK
311 __func__, msg_type);
312
313 msg_len = s->endp - ZEBRA_MLAG_METADATA_LEN;
314 for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
315 if (client->mlag_updates_interested == true) {
316 if (msg_type != ZEBRA_MLAG_MSG_BCAST
317 && !CHECK_FLAG(client->mlag_reg_mask1,
318 (1 << msg_type))) {
319 continue;
320 }
321
322 if (IS_ZEBRA_DEBUG_MLAG)
323 zlog_debug(
324 "%s: Posting MLAG data of length-%d to client:%d ",
325 __func__, msg_len, client->proto);
326
327 zebra_s = stream_new(msg_len);
328 STREAM_GET(zebra_s->data, s, msg_len);
329 zebra_s->endp = msg_len;
330 stream_putw_at(zebra_s, 0, msg_len);
331
332 /*
333 * This stream will be enqueued to client_obuf, it will
334 * be freed after posting to client socket.
335 */
336 zserv_send_message(client, zebra_s);
337 zebra_s = NULL;
338 }
339 }
340
341 stream_free(s);
cc9f21da 342 return;
ee235396
SK
343stream_failure:
344 stream_free(s);
345 if (zebra_s)
346 stream_free(zebra_s);
ee235396
SK
347}
348
349/*
350 * Start the MLAG Thread, this will be used to write client data on to
3ac4e7cc 351 * MLAG Process and to read the data from MLAG and post to clients.
ee235396
SK
352 * when all clients are un-registered, this Thread will be
353 * suspended.
354 */
355static void zebra_mlag_spawn_pthread(void)
356{
357 /* Start MLAG write pthread */
358
359 struct frr_pthread_attr pattr = {.start =
360 frr_pthread_attr_default.start,
361 .stop = frr_pthread_attr_default.stop};
362
363 zrouter.mlag_info.zebra_pth_mlag =
364 frr_pthread_new(&pattr, "Zebra MLAG thread", "Zebra MLAG");
365
366 zrouter.mlag_info.th_master = zrouter.mlag_info.zebra_pth_mlag->master;
367
368
67fa73f2 369 /* Enqueue an initial event to the Newly spawn MLAG pthread */
ee235396
SK
370 zebra_mlag_signal_write_thread();
371
372 frr_pthread_run(zrouter.mlag_info.zebra_pth_mlag, NULL);
373}
374
375/*
376 * all clients are un-registered for MLAG Updates, terminate the
377 * MLAG write thread
378 */
e6685141 379static void zebra_mlag_terminate_pthread(struct event *event)
ee235396
SK
380{
381 if (IS_ZEBRA_DEBUG_MLAG)
382 zlog_debug("Zebra MLAG write thread terminate called");
383
384 if (zrouter.mlag_info.clients_interested_cnt) {
385 if (IS_ZEBRA_DEBUG_MLAG)
386 zlog_debug(
387 "Zebra MLAG: still some clients are interested");
cc9f21da 388 return;
ee235396
SK
389 }
390
391 frr_pthread_stop(zrouter.mlag_info.zebra_pth_mlag, NULL);
392
393 /* Destroy pthread */
394 frr_pthread_destroy(zrouter.mlag_info.zebra_pth_mlag);
395 zrouter.mlag_info.zebra_pth_mlag = NULL;
396 zrouter.mlag_info.th_master = NULL;
397 zrouter.mlag_info.t_read = NULL;
398 zrouter.mlag_info.t_write = NULL;
399
400 /*
401 * Send Notification to clean private data
402 */
d621815a 403 hook_call(zebra_mlag_private_cleanup_data);
ee235396
SK
404}
405
406/*
407 * API to register zebra client for MLAG Updates
408 */
409void zebra_mlag_client_register(ZAPI_HANDLER_ARGS)
410{
411 struct stream *s;
412 uint32_t reg_mask = 0;
413 int rc = 0;
414
415 if (IS_ZEBRA_DEBUG_MLAG)
416 zlog_debug("Received MLAG Registration from client-proto:%d",
417 client->proto);
418
419
420 /* Get input stream. */
421 s = msg;
422
423 /* Get data. */
424 STREAM_GETL(s, reg_mask);
425
426 if (client->mlag_updates_interested == true) {
427
428 if (IS_ZEBRA_DEBUG_MLAG)
429 zlog_debug(
430 "Client is registered, existing mask: 0x%x, new mask: 0x%x",
431 client->mlag_reg_mask1, reg_mask);
432 if (client->mlag_reg_mask1 != reg_mask)
433 client->mlag_reg_mask1 = reg_mask;
434 /*
435 * Client might missed MLAG-UP Notification, post-it again
436 */
437 zebra_mlag_publish_process_state(client, ZEBRA_MLAG_PROCESS_UP);
438 return;
439 }
440
441
442 client->mlag_updates_interested = true;
443 client->mlag_reg_mask1 = reg_mask;
444 if (IS_ZEBRA_DEBUG_MLAG)
445 zlog_debug("Registering for MLAG Updates with mask: 0x%x, ",
446 client->mlag_reg_mask1);
447
448 zrouter.mlag_info.clients_interested_cnt++;
449
450 if (zrouter.mlag_info.clients_interested_cnt == 1) {
451 /*
452 * First-client for MLAG Updates,open the communication channel
453 * with MLAG
454 */
455 if (IS_ZEBRA_DEBUG_MLAG)
456 zlog_debug(
457 "First client, opening the channel with MLAG");
458
459 zebra_mlag_spawn_pthread();
d621815a 460 rc = hook_call(zebra_mlag_private_open_channel);
ee235396
SK
461 if (rc < 0) {
462 /*
463 * For some reason, zebra not able to open the
464 * comm-channel with MLAG, so post MLAG-DOWN to client.
465 * later when the channel is open, zebra will send
466 * MLAG-UP
467 */
468 if (IS_ZEBRA_DEBUG_MLAG)
469 zlog_debug(
470 "Fail to open channel with MLAG,rc:%d, post Proto-down",
471 rc);
472 zebra_mlag_publish_process_state(
473 client, ZEBRA_MLAG_PROCESS_DOWN);
474 }
475 }
476
477 if (IS_ZEBRA_DEBUG_MLAG)
478 zlog_debug("Client Registered successfully for MLAG Updates");
479
480 if (zrouter.mlag_info.connected == true)
481 zebra_mlag_publish_process_state(client, ZEBRA_MLAG_PROCESS_UP);
482stream_failure:
483 return;
484}
485
486/*
487 * API to un-register for MLAG Updates
488 */
489void zebra_mlag_client_unregister(ZAPI_HANDLER_ARGS)
490{
491 if (IS_ZEBRA_DEBUG_MLAG)
492 zlog_debug("Received MLAG De-Registration from client-proto:%d",
493 client->proto);
494
495 if (client->mlag_updates_interested == false)
496 /* Unexpected */
497 return;
498
499 client->mlag_updates_interested = false;
500 client->mlag_reg_mask1 = 0;
501 zrouter.mlag_info.clients_interested_cnt--;
502
503 if (zrouter.mlag_info.clients_interested_cnt == 0) {
504 /*
505 * No-client is interested for MLAG Updates,close the
506 * communication channel with MLAG
507 */
508 if (IS_ZEBRA_DEBUG_MLAG)
509 zlog_debug("Last client for MLAG, close the channel ");
510
511 /*
512 * Clean up flow:
513 * =============
514 * 1) main thread calls socket close which posts De-register
515 * to MLAG write thread
516 * 2) after MLAG write thread posts De-register it sends a
517 * signal back to main thread to do the thread cleanup
518 * this was mainly to make sure De-register is posted to MCLAGD.
519 */
d621815a 520 hook_call(zebra_mlag_private_close_channel);
ee235396
SK
521 }
522
523 if (IS_ZEBRA_DEBUG_MLAG)
524 zlog_debug(
525 "Client De-Registered successfully for MLAG Updates");
526}
527
528/*
529 * Does following things.
530 * 1) allocated new local stream, and copies the client data and enqueue
531 * to MLAG Thread
532 * 2) MLAG Thread after dequeing, encode the client data using protobuf
533 * and write on to MLAG
534 */
535void zebra_mlag_forward_client_msg(ZAPI_HANDLER_ARGS)
536{
537 struct stream *zebra_s;
538 struct stream *mlag_s;
539
540 if (IS_ZEBRA_DEBUG_MLAG)
541 zlog_debug("Received Client MLAG Data from client-proto:%d",
542 client->proto);
543
544 /* Get input stream. */
545 zebra_s = msg;
546 mlag_s = stream_new(zebra_s->endp);
547
548 /*
549 * Client data is | Zebra Header + MLAG Data |
550 * we need to enqueue only the MLAG data, skipping Zebra Header
551 */
552 stream_put(mlag_s, zebra_s->data + zebra_s->getp,
553 STREAM_READABLE(zebra_s));
554 stream_fifo_push_safe(zrouter.mlag_info.mlag_fifo, mlag_s);
555 zebra_mlag_signal_write_thread();
556
557 if (IS_ZEBRA_DEBUG_MLAG)
558 zlog_debug("%s: Enqueued Client:%d data to MLAG Thread ",
559 __func__, client->proto);
560}
561
562/***********************End of Zebra Main thread processing*************/
563
ff1fb8d5
DS
564enum mlag_role zebra_mlag_get_role(void)
565{
e96ba9da 566 return zrouter.mlag_info.role;
ff1fb8d5
DS
567}
568
14d9bbbe
DS
569int32_t zebra_mlag_test_mlag_internal(const char *none, const char *primary,
570 const char *secondary)
763ec244 571{
b120fe3b 572 enum mlag_role orig = zrouter.mlag_info.role;
67fa73f2 573 char buf1[MLAG_ROLE_STRSIZE], buf2[MLAG_ROLE_STRSIZE];
b120fe3b 574
763ec244 575 if (none)
e96ba9da 576 zrouter.mlag_info.role = MLAG_ROLE_NONE;
763ec244 577 if (primary)
e96ba9da 578 zrouter.mlag_info.role = MLAG_ROLE_PRIMARY;
763ec244 579 if (secondary)
e96ba9da 580 zrouter.mlag_info.role = MLAG_ROLE_SECONDARY;
763ec244 581
b120fe3b
DS
582 if (IS_ZEBRA_DEBUG_MLAG)
583 zlog_debug("Test: Changing role from %s to %s",
584 mlag_role2str(orig, buf1, sizeof(buf1)),
585 mlag_role2str(orig, buf2, sizeof(buf2)));
586
ee235396 587 if (orig != zrouter.mlag_info.role) {
b120fe3b 588 zsend_capabilities_all_clients();
ee235396
SK
589 if (zrouter.mlag_info.role != MLAG_ROLE_NONE) {
590 if (zrouter.mlag_info.clients_interested_cnt == 0
a8f58eb6 591 && !test_mlag_in_progress) {
1e76492b
SK
592 if (zrouter.mlag_info.zebra_pth_mlag == NULL)
593 zebra_mlag_spawn_pthread();
ee235396
SK
594 zrouter.mlag_info.clients_interested_cnt++;
595 test_mlag_in_progress = true;
d621815a 596 hook_call(zebra_mlag_private_open_channel);
ee235396
SK
597 }
598 } else {
a8f58eb6 599 if (test_mlag_in_progress) {
ee235396
SK
600 test_mlag_in_progress = false;
601 zrouter.mlag_info.clients_interested_cnt--;
d621815a 602 hook_call(zebra_mlag_private_close_channel);
ee235396
SK
603 }
604 }
605 }
b120fe3b 606
763ec244
DS
607 return CMD_SUCCESS;
608}
609
df395600
DS
610void zebra_mlag_init(void)
611{
14d9bbbe 612 zebra_mlag_vty_init();
ee235396
SK
613
614 /*
1e76492b
SK
615 * Intialiaze the MLAG Global variables
616 * write thread will be created during actual registration with MCLAG
ee235396
SK
617 */
618 zrouter.mlag_info.clients_interested_cnt = 0;
619 zrouter.mlag_info.connected = false;
620 zrouter.mlag_info.timer_running = false;
621 zrouter.mlag_info.mlag_fifo = stream_fifo_new();
622 zrouter.mlag_info.zebra_pth_mlag = NULL;
623 zrouter.mlag_info.th_master = NULL;
624 zrouter.mlag_info.t_read = NULL;
625 zrouter.mlag_info.t_write = NULL;
626 test_mlag_in_progress = false;
ee235396 627 zebra_mlag_reset_read_buffer();
df395600
DS
628}
629
630void zebra_mlag_terminate(void)
631{
632}
ee235396
SK
633
634
635/*
636 *
637 * ProtoBuf Encoding APIs
638 */
639
fd193241 640#ifdef HAVE_PROTOBUF_VERSION_3
67fa73f2 641
bf8d3d6a 642DEFINE_MTYPE_STATIC(ZEBRA, MLAG_PBUF, "ZEBRA MLAG PROTOBUF");
67fa73f2
SK
643
644int zebra_mlag_protobuf_encode_client_data(struct stream *s, uint32_t *msg_type)
645{
646 ZebraMlagHeader hdr = ZEBRA_MLAG__HEADER__INIT;
647 struct mlag_msg mlag_msg;
648 uint8_t tmp_buf[ZEBRA_MLAG_BUF_LIMIT];
649 int len = 0;
650 int n_len = 0;
651 int rc = 0;
652 char buf[ZLOG_FILTER_LENGTH_MAX];
83f8a12b 653 size_t length;
67fa73f2
SK
654
655 if (IS_ZEBRA_DEBUG_MLAG)
656 zlog_debug("%s: Entering..", __func__);
657
83f8a12b 658 rc = mlag_lib_decode_mlag_hdr(s, &mlag_msg, &length);
67fa73f2
SK
659 if (rc)
660 return rc;
661
83f8a12b
SK
662 memset(tmp_buf, 0, ZEBRA_MLAG_BUF_LIMIT);
663
67fa73f2 664 if (IS_ZEBRA_DEBUG_MLAG)
1e76492b
SK
665 zlog_debug("%s: Mlag ProtoBuf encoding of message:%s, len:%d",
666 __func__,
667 mlag_lib_msgid_to_str(mlag_msg.msg_type, buf,
668 sizeof(buf)),
67fa73f2 669 mlag_msg.data_len);
67fa73f2
SK
670 *msg_type = mlag_msg.msg_type;
671 switch (mlag_msg.msg_type) {
672 case MLAG_MROUTE_ADD: {
673 struct mlag_mroute_add msg;
674 ZebraMlagMrouteAdd pay_load = ZEBRA_MLAG_MROUTE_ADD__INIT;
675 uint32_t vrf_name_len = 0;
676
83f8a12b 677 rc = mlag_lib_decode_mroute_add(s, &msg, &length);
67fa73f2
SK
678 if (rc)
679 return rc;
83f8a12b 680
67fa73f2
SK
681 vrf_name_len = strlen(msg.vrf_name) + 1;
682 pay_load.vrf_name = XMALLOC(MTYPE_MLAG_PBUF, vrf_name_len);
683 strlcpy(pay_load.vrf_name, msg.vrf_name, vrf_name_len);
684 pay_load.source_ip = msg.source_ip;
685 pay_load.group_ip = msg.group_ip;
686 pay_load.cost_to_rp = msg.cost_to_rp;
687 pay_load.owner_id = msg.owner_id;
688 pay_load.am_i_dr = msg.am_i_dr;
689 pay_load.am_i_dual_active = msg.am_i_dual_active;
690 pay_load.vrf_id = msg.vrf_id;
691
692 if (msg.owner_id == MLAG_OWNER_INTERFACE) {
693 vrf_name_len = strlen(msg.intf_name) + 1;
694 pay_load.intf_name =
695 XMALLOC(MTYPE_MLAG_PBUF, vrf_name_len);
696 strlcpy(pay_load.intf_name, msg.intf_name,
697 vrf_name_len);
698 }
699
700 len = zebra_mlag_mroute_add__pack(&pay_load, tmp_buf);
701 XFREE(MTYPE_MLAG_PBUF, pay_load.vrf_name);
702 if (msg.owner_id == MLAG_OWNER_INTERFACE)
703 XFREE(MTYPE_MLAG_PBUF, pay_load.intf_name);
704 } break;
705 case MLAG_MROUTE_DEL: {
706 struct mlag_mroute_del msg;
707 ZebraMlagMrouteDel pay_load = ZEBRA_MLAG_MROUTE_DEL__INIT;
708 uint32_t vrf_name_len = 0;
709
83f8a12b 710 rc = mlag_lib_decode_mroute_del(s, &msg, &length);
67fa73f2
SK
711 if (rc)
712 return rc;
713 vrf_name_len = strlen(msg.vrf_name) + 1;
714 pay_load.vrf_name = XMALLOC(MTYPE_MLAG_PBUF, vrf_name_len);
715 strlcpy(pay_load.vrf_name, msg.vrf_name, vrf_name_len);
716 pay_load.source_ip = msg.source_ip;
717 pay_load.group_ip = msg.group_ip;
718 pay_load.owner_id = msg.owner_id;
719 pay_load.vrf_id = msg.vrf_id;
720
721 if (msg.owner_id == MLAG_OWNER_INTERFACE) {
722 vrf_name_len = strlen(msg.intf_name) + 1;
723 pay_load.intf_name =
724 XMALLOC(MTYPE_MLAG_PBUF, vrf_name_len);
725 strlcpy(pay_load.intf_name, msg.intf_name,
726 vrf_name_len);
727 }
728
729 len = zebra_mlag_mroute_del__pack(&pay_load, tmp_buf);
730 XFREE(MTYPE_MLAG_PBUF, pay_load.vrf_name);
731 if (msg.owner_id == MLAG_OWNER_INTERFACE)
732 XFREE(MTYPE_MLAG_PBUF, pay_load.intf_name);
733 } break;
734 case MLAG_MROUTE_ADD_BULK: {
735 struct mlag_mroute_add msg;
736 ZebraMlagMrouteAddBulk Bulk_msg =
737 ZEBRA_MLAG_MROUTE_ADD_BULK__INIT;
738 ZebraMlagMrouteAdd **pay_load = NULL;
67fa73f2 739 bool cleanup = false;
83f8a12b 740 uint32_t i, actual;
67fa73f2
SK
741
742 Bulk_msg.n_mroute_add = mlag_msg.msg_cnt;
743 pay_load = XMALLOC(MTYPE_MLAG_PBUF, sizeof(ZebraMlagMrouteAdd *)
744 * mlag_msg.msg_cnt);
745
83f8a12b 746 for (i = 0, actual = 0; i < mlag_msg.msg_cnt; i++, actual++) {
67fa73f2
SK
747
748 uint32_t vrf_name_len = 0;
749
83f8a12b 750 rc = mlag_lib_decode_mroute_add(s, &msg, &length);
67fa73f2
SK
751 if (rc) {
752 cleanup = true;
753 break;
754 }
755 pay_load[i] = XMALLOC(MTYPE_MLAG_PBUF,
756 sizeof(ZebraMlagMrouteAdd));
757 zebra_mlag_mroute_add__init(pay_load[i]);
758
759 vrf_name_len = strlen(msg.vrf_name) + 1;
760 pay_load[i]->vrf_name =
761 XMALLOC(MTYPE_MLAG_PBUF, vrf_name_len);
762 strlcpy(pay_load[i]->vrf_name, msg.vrf_name,
763 vrf_name_len);
764 pay_load[i]->source_ip = msg.source_ip;
765 pay_load[i]->group_ip = msg.group_ip;
766 pay_load[i]->cost_to_rp = msg.cost_to_rp;
767 pay_load[i]->owner_id = msg.owner_id;
768 pay_load[i]->am_i_dr = msg.am_i_dr;
769 pay_load[i]->am_i_dual_active = msg.am_i_dual_active;
770 pay_load[i]->vrf_id = msg.vrf_id;
771 if (msg.owner_id == MLAG_OWNER_INTERFACE) {
772 vrf_name_len = strlen(msg.intf_name) + 1;
773 pay_load[i]->intf_name =
774 XMALLOC(MTYPE_MLAG_PBUF, vrf_name_len);
775
776 strlcpy(pay_load[i]->intf_name, msg.intf_name,
777 vrf_name_len);
778 }
779 }
a8f58eb6 780 if (!cleanup) {
67fa73f2
SK
781 Bulk_msg.mroute_add = pay_load;
782 len = zebra_mlag_mroute_add_bulk__pack(&Bulk_msg,
783 tmp_buf);
784 }
785
83f8a12b
SK
786 for (i = 0; i < actual; i++) {
787 /*
788 * The mlag_lib_decode_mroute_add can
789 * fail to properly decode and cause nothing
790 * to be allocated. Prevent a crash
791 */
792 if (!pay_load[i])
793 continue;
794
5567e801 795 XFREE(MTYPE_MLAG_PBUF, pay_load[i]->vrf_name);
67fa73f2
SK
796 if (pay_load[i]->owner_id == MLAG_OWNER_INTERFACE
797 && pay_load[i]->intf_name)
798 XFREE(MTYPE_MLAG_PBUF, pay_load[i]->intf_name);
e1b36e13 799 XFREE(MTYPE_MLAG_PBUF, pay_load[i]);
67fa73f2
SK
800 }
801 XFREE(MTYPE_MLAG_PBUF, pay_load);
a8f58eb6 802 if (cleanup)
67fa73f2
SK
803 return -1;
804 } break;
805 case MLAG_MROUTE_DEL_BULK: {
806 struct mlag_mroute_del msg;
807 ZebraMlagMrouteDelBulk Bulk_msg =
808 ZEBRA_MLAG_MROUTE_DEL_BULK__INIT;
809 ZebraMlagMrouteDel **pay_load = NULL;
67fa73f2 810 bool cleanup = false;
83f8a12b 811 uint32_t i, actual;
67fa73f2
SK
812
813 Bulk_msg.n_mroute_del = mlag_msg.msg_cnt;
814 pay_load = XMALLOC(MTYPE_MLAG_PBUF, sizeof(ZebraMlagMrouteDel *)
815 * mlag_msg.msg_cnt);
816
83f8a12b 817 for (i = 0, actual = 0; i < mlag_msg.msg_cnt; i++, actual++) {
67fa73f2
SK
818
819 uint32_t vrf_name_len = 0;
820
83f8a12b 821 rc = mlag_lib_decode_mroute_del(s, &msg, &length);
67fa73f2
SK
822 if (rc) {
823 cleanup = true;
824 break;
825 }
826
827 pay_load[i] = XMALLOC(MTYPE_MLAG_PBUF,
828 sizeof(ZebraMlagMrouteDel));
829 zebra_mlag_mroute_del__init(pay_load[i]);
830
831 vrf_name_len = strlen(msg.vrf_name) + 1;
832 pay_load[i]->vrf_name =
833 XMALLOC(MTYPE_MLAG_PBUF, vrf_name_len);
834
835 strlcpy(pay_load[i]->vrf_name, msg.vrf_name,
836 vrf_name_len);
837 pay_load[i]->source_ip = msg.source_ip;
838 pay_load[i]->group_ip = msg.group_ip;
839 pay_load[i]->owner_id = msg.owner_id;
840 pay_load[i]->vrf_id = msg.vrf_id;
841 if (msg.owner_id == MLAG_OWNER_INTERFACE) {
842 vrf_name_len = strlen(msg.intf_name) + 1;
843 pay_load[i]->intf_name =
844 XMALLOC(MTYPE_MLAG_PBUF, vrf_name_len);
845
846 strlcpy(pay_load[i]->intf_name, msg.intf_name,
847 vrf_name_len);
848 }
849 }
850 if (!cleanup) {
851 Bulk_msg.mroute_del = pay_load;
852 len = zebra_mlag_mroute_del_bulk__pack(&Bulk_msg,
853 tmp_buf);
854 }
855
83f8a12b
SK
856 for (i = 0; i < actual; i++) {
857 /*
858 * The mlag_lib_decode_mroute_add can
859 * fail to properly decode and cause nothing
860 * to be allocated. Prevent a crash
861 */
862 if (!pay_load[i])
863 continue;
864
5567e801 865 XFREE(MTYPE_MLAG_PBUF, pay_load[i]->vrf_name);
67fa73f2
SK
866 if (pay_load[i]->owner_id == MLAG_OWNER_INTERFACE
867 && pay_load[i]->intf_name)
868 XFREE(MTYPE_MLAG_PBUF, pay_load[i]->intf_name);
e1b36e13 869 XFREE(MTYPE_MLAG_PBUF, pay_load[i]);
67fa73f2
SK
870 }
871 XFREE(MTYPE_MLAG_PBUF, pay_load);
872 if (cleanup)
873 return -1;
874 } break;
a98701f0
DS
875 case MLAG_REGISTER:
876 case MLAG_DEREGISTER:
877 case MLAG_STATUS_UPDATE:
878 case MLAG_DUMP:
879 case MLAG_PIM_CFG_DUMP:
880 case MLAG_VXLAN_UPDATE:
881 case MLAG_PEER_FRR_STATUS:
882 case MLAG_MSG_NONE:
67fa73f2
SK
883 break;
884 }
885
886 if (IS_ZEBRA_DEBUG_MLAG)
887 zlog_debug("%s: length of Mlag ProtoBuf encoded message:%s, %d",
888 __func__,
1e76492b
SK
889 mlag_lib_msgid_to_str(mlag_msg.msg_type, buf,
890 sizeof(buf)),
67fa73f2
SK
891 len);
892 hdr.type = (ZebraMlagHeader__MessageType)mlag_msg.msg_type;
893 if (len != 0) {
894 hdr.data.len = len;
895 hdr.data.data = XMALLOC(MTYPE_MLAG_PBUF, len);
896 memcpy(hdr.data.data, tmp_buf, len);
897 }
898
899 /*
900 * ProtoBuf Infra will not support to demarc the pointers whem multiple
901 * messages are posted inside a single Buffer.
902 * 2 -solutions exist to solve this
903 * 1. add Unenoced length at the beginning of every message, this will
904 * be used to point to next message in the buffer
905 * 2. another solution is defining all messages insides another message
906 * But this will permit only 32 messages. this can be extended with
907 * multiple levels.
908 * for simplicity we are going with solution-1.
909 */
910 len = zebra_mlag__header__pack(&hdr,
911 (mlag_wr_buffer + ZEBRA_MLAG_LEN_SIZE));
912 n_len = htonl(len);
913 memcpy(mlag_wr_buffer, &n_len, ZEBRA_MLAG_LEN_SIZE);
914 len += ZEBRA_MLAG_LEN_SIZE;
915
916 if (IS_ZEBRA_DEBUG_MLAG)
917 zlog_debug(
918 "%s: length of Mlag ProtoBuf message:%s with Header %d",
919 __func__,
1e76492b
SK
920 mlag_lib_msgid_to_str(mlag_msg.msg_type, buf,
921 sizeof(buf)),
67fa73f2 922 len);
e1b36e13 923 XFREE(MTYPE_MLAG_PBUF, hdr.data.data);
67fa73f2
SK
924
925 return len;
926}
927
83f8a12b
SK
928static void zebra_fill_protobuf_msg(struct stream *s, char *name, int len)
929{
930 int str_len = strlen(name) + 1;
931
932 stream_put(s, name, str_len);
933 /* Fill the rest with Null Character for aligning */
934 stream_put(s, NULL, len - str_len);
935}
936
67fa73f2
SK
937int zebra_mlag_protobuf_decode_message(struct stream *s, uint8_t *data,
938 uint32_t len)
939{
940 uint32_t msg_type;
941 ZebraMlagHeader *hdr;
942 char buf[80];
943
944 hdr = zebra_mlag__header__unpack(NULL, len, data);
945 if (hdr == NULL)
946 return -1;
947
948 /*
949 * ADD The MLAG Header
950 */
951 zclient_create_header(s, ZEBRA_MLAG_FORWARD_MSG, VRF_DEFAULT);
952
953 msg_type = hdr->type;
954
955 if (IS_ZEBRA_DEBUG_MLAG)
956 zlog_debug("%s: Mlag ProtoBuf decoding of message:%s", __func__,
1e76492b 957 mlag_lib_msgid_to_str(msg_type, buf, 80));
67fa73f2
SK
958
959 /*
960 * Internal MLAG Message-types & MLAG.proto message types should
961 * always match, otherwise there can be decoding errors
962 * To avoid exposing clients with Protobuf flags, using internal
963 * message-types
964 */
965 stream_putl(s, hdr->type);
966
967 if (hdr->data.len == 0) {
968 /* NULL Payload */
969 stream_putw(s, MLAG_MSG_NULL_PAYLOAD);
970 /* No Batching */
971 stream_putw(s, MLAG_MSG_NO_BATCH);
972 } else {
973 switch (msg_type) {
974 case ZEBRA_MLAG__HEADER__MESSAGE_TYPE__ZEBRA_MLAG_STATUS_UPDATE: {
975 ZebraMlagStatusUpdate *msg = NULL;
976
977 msg = zebra_mlag_status_update__unpack(
978 NULL, hdr->data.len, hdr->data.data);
979 if (msg == NULL) {
980 zebra_mlag__header__free_unpacked(hdr, NULL);
981 return -1;
982 }
983 /* Payload len */
984 stream_putw(s, sizeof(struct mlag_status));
985 /* No Batching */
986 stream_putw(s, MLAG_MSG_NO_BATCH);
987 /* Actual Data */
83f8a12b
SK
988 zebra_fill_protobuf_msg(s, msg->peerlink,
989 INTERFACE_NAMSIZ);
67fa73f2
SK
990 stream_putl(s, msg->my_role);
991 stream_putl(s, msg->peer_state);
992 zebra_mlag_status_update__free_unpacked(msg, NULL);
993 } break;
994 case ZEBRA_MLAG__HEADER__MESSAGE_TYPE__ZEBRA_MLAG_VXLAN_UPDATE: {
995 ZebraMlagVxlanUpdate *msg = NULL;
996
997 msg = zebra_mlag_vxlan_update__unpack(
998 NULL, hdr->data.len, hdr->data.data);
999 if (msg == NULL) {
1000 zebra_mlag__header__free_unpacked(hdr, NULL);
1001 return -1;
1002 }
1003 /* Payload len */
1004 stream_putw(s, sizeof(struct mlag_vxlan));
1005 /* No Batching */
1006 stream_putw(s, MLAG_MSG_NO_BATCH);
1007 /* Actual Data */
1008 stream_putl(s, msg->anycast_ip);
1009 stream_putl(s, msg->local_ip);
1010 zebra_mlag_vxlan_update__free_unpacked(msg, NULL);
1011 } break;
1012 case ZEBRA_MLAG__HEADER__MESSAGE_TYPE__ZEBRA_MLAG_MROUTE_ADD: {
1013 ZebraMlagMrouteAdd *msg = NULL;
1014
1015 msg = zebra_mlag_mroute_add__unpack(NULL, hdr->data.len,
1016 hdr->data.data);
1017 if (msg == NULL) {
1018 zebra_mlag__header__free_unpacked(hdr, NULL);
1019 return -1;
1020 }
1021 /* Payload len */
1022 stream_putw(s, sizeof(struct mlag_mroute_add));
1023 /* No Batching */
1024 stream_putw(s, MLAG_MSG_NO_BATCH);
1025 /* Actual Data */
83f8a12b 1026 zebra_fill_protobuf_msg(s, msg->vrf_name, VRF_NAMSIZ);
67fa73f2
SK
1027
1028 stream_putl(s, msg->source_ip);
1029 stream_putl(s, msg->group_ip);
1030 stream_putl(s, msg->cost_to_rp);
1031 stream_putl(s, msg->owner_id);
1032 stream_putc(s, msg->am_i_dr);
1033 stream_putc(s, msg->am_i_dual_active);
1034 stream_putl(s, msg->vrf_id);
1035 if (msg->owner_id == MLAG_OWNER_INTERFACE)
83f8a12b
SK
1036 zebra_fill_protobuf_msg(s, msg->intf_name,
1037 INTERFACE_NAMSIZ);
67fa73f2
SK
1038 else
1039 stream_put(s, NULL, INTERFACE_NAMSIZ);
1040 zebra_mlag_mroute_add__free_unpacked(msg, NULL);
1041 } break;
1042 case ZEBRA_MLAG__HEADER__MESSAGE_TYPE__ZEBRA_MLAG_MROUTE_DEL: {
1043 ZebraMlagMrouteDel *msg = NULL;
1044
1045 msg = zebra_mlag_mroute_del__unpack(NULL, hdr->data.len,
1046 hdr->data.data);
1047 if (msg == NULL) {
1048 zebra_mlag__header__free_unpacked(hdr, NULL);
1049 return -1;
1050 }
1051 /* Payload len */
1052 stream_putw(s, sizeof(struct mlag_mroute_del));
1053 /* No Batching */
1054 stream_putw(s, MLAG_MSG_NO_BATCH);
1055 /* Actual Data */
83f8a12b 1056 zebra_fill_protobuf_msg(s, msg->vrf_name, VRF_NAMSIZ);
67fa73f2
SK
1057
1058 stream_putl(s, msg->source_ip);
1059 stream_putl(s, msg->group_ip);
67fa73f2
SK
1060 stream_putl(s, msg->owner_id);
1061 stream_putl(s, msg->vrf_id);
1062 if (msg->owner_id == MLAG_OWNER_INTERFACE)
83f8a12b
SK
1063 zebra_fill_protobuf_msg(s, msg->intf_name,
1064 INTERFACE_NAMSIZ);
67fa73f2
SK
1065 else
1066 stream_put(s, NULL, INTERFACE_NAMSIZ);
1067 zebra_mlag_mroute_del__free_unpacked(msg, NULL);
1068 } break;
1069 case ZEBRA_MLAG__HEADER__MESSAGE_TYPE__ZEBRA_MLAG_MROUTE_ADD_BULK: {
1070 ZebraMlagMrouteAddBulk *Bulk_msg = NULL;
1071 ZebraMlagMrouteAdd *msg = NULL;
010b575b 1072 size_t i, length_spot;
67fa73f2
SK
1073
1074 Bulk_msg = zebra_mlag_mroute_add_bulk__unpack(
1075 NULL, hdr->data.len, hdr->data.data);
1076 if (Bulk_msg == NULL) {
1077 zebra_mlag__header__free_unpacked(hdr, NULL);
1078 return -1;
1079 }
1080 /* Payload len */
1081 stream_putw(s, (Bulk_msg->n_mroute_add
1082 * sizeof(struct mlag_mroute_add)));
1083 /* No. of msgs in Batch */
010b575b 1084 length_spot = stream_putw(s, Bulk_msg->n_mroute_add);
67fa73f2
SK
1085
1086 /* Actual Data */
1087 for (i = 0; i < Bulk_msg->n_mroute_add; i++) {
010b575b
DS
1088 if (STREAM_SIZE(s)
1089 < VRF_NAMSIZ + 22 + INTERFACE_NAMSIZ) {
1090 zlog_warn(
1091 "We have received more messages than we can parse at this point in time: %zu",
1092 Bulk_msg->n_mroute_add);
1093 break;
1094 }
67fa73f2
SK
1095
1096 msg = Bulk_msg->mroute_add[i];
1097
83f8a12b
SK
1098 zebra_fill_protobuf_msg(s, msg->vrf_name,
1099 VRF_NAMSIZ);
67fa73f2
SK
1100 stream_putl(s, msg->source_ip);
1101 stream_putl(s, msg->group_ip);
1102 stream_putl(s, msg->cost_to_rp);
1103 stream_putl(s, msg->owner_id);
1104 stream_putc(s, msg->am_i_dr);
1105 stream_putc(s, msg->am_i_dual_active);
1106 stream_putl(s, msg->vrf_id);
1107 if (msg->owner_id == MLAG_OWNER_INTERFACE)
83f8a12b
SK
1108 zebra_fill_protobuf_msg(
1109 s, msg->intf_name,
1110 INTERFACE_NAMSIZ);
67fa73f2
SK
1111 else
1112 stream_put(s, NULL, INTERFACE_NAMSIZ);
1113 }
010b575b
DS
1114
1115 stream_putw_at(s, length_spot, i + 1);
1116
67fa73f2
SK
1117 zebra_mlag_mroute_add_bulk__free_unpacked(Bulk_msg,
1118 NULL);
1119 } break;
1120 case ZEBRA_MLAG__HEADER__MESSAGE_TYPE__ZEBRA_MLAG_MROUTE_DEL_BULK: {
1121 ZebraMlagMrouteDelBulk *Bulk_msg = NULL;
1122 ZebraMlagMrouteDel *msg = NULL;
010b575b 1123 size_t i, length_spot;
67fa73f2
SK
1124
1125 Bulk_msg = zebra_mlag_mroute_del_bulk__unpack(
1126 NULL, hdr->data.len, hdr->data.data);
1127 if (Bulk_msg == NULL) {
1128 zebra_mlag__header__free_unpacked(hdr, NULL);
1129 return -1;
1130 }
1131 /* Payload len */
1132 stream_putw(s, (Bulk_msg->n_mroute_del
1133 * sizeof(struct mlag_mroute_del)));
1134 /* No. of msgs in Batch */
010b575b 1135 length_spot = stream_putw(s, Bulk_msg->n_mroute_del);
67fa73f2
SK
1136
1137 /* Actual Data */
1138 for (i = 0; i < Bulk_msg->n_mroute_del; i++) {
010b575b
DS
1139 if (STREAM_SIZE(s)
1140 < VRF_NAMSIZ + 16 + INTERFACE_NAMSIZ) {
1141 zlog_warn(
1142 "We have received more messages than we can parse at this time");
1143 break;
1144 }
67fa73f2
SK
1145
1146 msg = Bulk_msg->mroute_del[i];
1147
83f8a12b
SK
1148 zebra_fill_protobuf_msg(s, msg->vrf_name,
1149 VRF_NAMSIZ);
67fa73f2
SK
1150 stream_putl(s, msg->source_ip);
1151 stream_putl(s, msg->group_ip);
1152 stream_putl(s, msg->owner_id);
1153 stream_putl(s, msg->vrf_id);
1154 if (msg->owner_id == MLAG_OWNER_INTERFACE)
83f8a12b
SK
1155 zebra_fill_protobuf_msg(
1156 s, msg->intf_name,
1157 INTERFACE_NAMSIZ);
67fa73f2
SK
1158 else
1159 stream_put(s, NULL, INTERFACE_NAMSIZ);
1160 }
010b575b
DS
1161
1162 stream_putw_at(s, length_spot, i + 1);
1163
67fa73f2
SK
1164 zebra_mlag_mroute_del_bulk__free_unpacked(Bulk_msg,
1165 NULL);
1166 } break;
1167 case ZEBRA_MLAG__HEADER__MESSAGE_TYPE__ZEBRA_MLAG_ZEBRA_STATUS_UPDATE: {
1168 ZebraMlagZebraStatusUpdate *msg = NULL;
1169
1170 msg = zebra_mlag_zebra_status_update__unpack(
1171 NULL, hdr->data.len, hdr->data.data);
1172 if (msg == NULL) {
1173 zebra_mlag__header__free_unpacked(hdr, NULL);
1174 return -1;
1175 }
1176 /* Payload len */
1177 stream_putw(s, sizeof(struct mlag_frr_status));
1178 /* No Batching */
1179 stream_putw(s, MLAG_MSG_NO_BATCH);
1180 /* Actual Data */
1181 stream_putl(s, msg->peer_frrstate);
1182 zebra_mlag_zebra_status_update__free_unpacked(msg,
1183 NULL);
1184 } break;
1185 default:
1186 break;
1187 }
1188 }
1189 zebra_mlag__header__free_unpacked(hdr, NULL);
1190 return msg_type;
1191}
1192
1193#else
ee235396
SK
1194int zebra_mlag_protobuf_encode_client_data(struct stream *s, uint32_t *msg_type)
1195{
1196 return 0;
1197}
1198
67fa73f2 1199int zebra_mlag_protobuf_decode_message(struct stream *s, uint8_t *data,
ee235396
SK
1200 uint32_t len)
1201{
1202 return 0;
1203}
67fa73f2 1204#endif