]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_mlag.c
Merge pull request #13646 from donaldsharp/logically_illogical
[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
ee235396
SK
341stream_failure:
342 stream_free(s);
343 if (zebra_s)
344 stream_free(zebra_s);
ee235396
SK
345}
346
347/*
348 * Start the MLAG Thread, this will be used to write client data on to
3ac4e7cc 349 * MLAG Process and to read the data from MLAG and post to clients.
ee235396
SK
350 * when all clients are un-registered, this Thread will be
351 * suspended.
352 */
353static void zebra_mlag_spawn_pthread(void)
354{
355 /* Start MLAG write pthread */
356
357 struct frr_pthread_attr pattr = {.start =
358 frr_pthread_attr_default.start,
359 .stop = frr_pthread_attr_default.stop};
360
361 zrouter.mlag_info.zebra_pth_mlag =
362 frr_pthread_new(&pattr, "Zebra MLAG thread", "Zebra MLAG");
363
364 zrouter.mlag_info.th_master = zrouter.mlag_info.zebra_pth_mlag->master;
365
366
67fa73f2 367 /* Enqueue an initial event to the Newly spawn MLAG pthread */
ee235396
SK
368 zebra_mlag_signal_write_thread();
369
370 frr_pthread_run(zrouter.mlag_info.zebra_pth_mlag, NULL);
371}
372
373/*
374 * all clients are un-registered for MLAG Updates, terminate the
375 * MLAG write thread
376 */
e6685141 377static void zebra_mlag_terminate_pthread(struct event *event)
ee235396
SK
378{
379 if (IS_ZEBRA_DEBUG_MLAG)
380 zlog_debug("Zebra MLAG write thread terminate called");
381
382 if (zrouter.mlag_info.clients_interested_cnt) {
383 if (IS_ZEBRA_DEBUG_MLAG)
384 zlog_debug(
385 "Zebra MLAG: still some clients are interested");
cc9f21da 386 return;
ee235396
SK
387 }
388
389 frr_pthread_stop(zrouter.mlag_info.zebra_pth_mlag, NULL);
390
391 /* Destroy pthread */
392 frr_pthread_destroy(zrouter.mlag_info.zebra_pth_mlag);
393 zrouter.mlag_info.zebra_pth_mlag = NULL;
394 zrouter.mlag_info.th_master = NULL;
395 zrouter.mlag_info.t_read = NULL;
396 zrouter.mlag_info.t_write = NULL;
397
398 /*
399 * Send Notification to clean private data
400 */
d621815a 401 hook_call(zebra_mlag_private_cleanup_data);
ee235396
SK
402}
403
404/*
405 * API to register zebra client for MLAG Updates
406 */
407void zebra_mlag_client_register(ZAPI_HANDLER_ARGS)
408{
409 struct stream *s;
410 uint32_t reg_mask = 0;
411 int rc = 0;
412
413 if (IS_ZEBRA_DEBUG_MLAG)
414 zlog_debug("Received MLAG Registration from client-proto:%d",
415 client->proto);
416
417
418 /* Get input stream. */
419 s = msg;
420
421 /* Get data. */
422 STREAM_GETL(s, reg_mask);
423
424 if (client->mlag_updates_interested == true) {
425
426 if (IS_ZEBRA_DEBUG_MLAG)
427 zlog_debug(
428 "Client is registered, existing mask: 0x%x, new mask: 0x%x",
429 client->mlag_reg_mask1, reg_mask);
430 if (client->mlag_reg_mask1 != reg_mask)
431 client->mlag_reg_mask1 = reg_mask;
432 /*
433 * Client might missed MLAG-UP Notification, post-it again
434 */
435 zebra_mlag_publish_process_state(client, ZEBRA_MLAG_PROCESS_UP);
436 return;
437 }
438
439
440 client->mlag_updates_interested = true;
441 client->mlag_reg_mask1 = reg_mask;
442 if (IS_ZEBRA_DEBUG_MLAG)
443 zlog_debug("Registering for MLAG Updates with mask: 0x%x, ",
444 client->mlag_reg_mask1);
445
446 zrouter.mlag_info.clients_interested_cnt++;
447
448 if (zrouter.mlag_info.clients_interested_cnt == 1) {
449 /*
450 * First-client for MLAG Updates,open the communication channel
451 * with MLAG
452 */
453 if (IS_ZEBRA_DEBUG_MLAG)
454 zlog_debug(
455 "First client, opening the channel with MLAG");
456
457 zebra_mlag_spawn_pthread();
d621815a 458 rc = hook_call(zebra_mlag_private_open_channel);
ee235396
SK
459 if (rc < 0) {
460 /*
461 * For some reason, zebra not able to open the
462 * comm-channel with MLAG, so post MLAG-DOWN to client.
463 * later when the channel is open, zebra will send
464 * MLAG-UP
465 */
466 if (IS_ZEBRA_DEBUG_MLAG)
467 zlog_debug(
468 "Fail to open channel with MLAG,rc:%d, post Proto-down",
469 rc);
470 zebra_mlag_publish_process_state(
471 client, ZEBRA_MLAG_PROCESS_DOWN);
472 }
473 }
474
475 if (IS_ZEBRA_DEBUG_MLAG)
476 zlog_debug("Client Registered successfully for MLAG Updates");
477
478 if (zrouter.mlag_info.connected == true)
479 zebra_mlag_publish_process_state(client, ZEBRA_MLAG_PROCESS_UP);
480stream_failure:
481 return;
482}
483
484/*
485 * API to un-register for MLAG Updates
486 */
487void zebra_mlag_client_unregister(ZAPI_HANDLER_ARGS)
488{
489 if (IS_ZEBRA_DEBUG_MLAG)
490 zlog_debug("Received MLAG De-Registration from client-proto:%d",
491 client->proto);
492
493 if (client->mlag_updates_interested == false)
494 /* Unexpected */
495 return;
496
497 client->mlag_updates_interested = false;
498 client->mlag_reg_mask1 = 0;
499 zrouter.mlag_info.clients_interested_cnt--;
500
501 if (zrouter.mlag_info.clients_interested_cnt == 0) {
502 /*
503 * No-client is interested for MLAG Updates,close the
504 * communication channel with MLAG
505 */
506 if (IS_ZEBRA_DEBUG_MLAG)
507 zlog_debug("Last client for MLAG, close the channel ");
508
509 /*
510 * Clean up flow:
511 * =============
512 * 1) main thread calls socket close which posts De-register
513 * to MLAG write thread
514 * 2) after MLAG write thread posts De-register it sends a
515 * signal back to main thread to do the thread cleanup
516 * this was mainly to make sure De-register is posted to MCLAGD.
517 */
d621815a 518 hook_call(zebra_mlag_private_close_channel);
ee235396
SK
519 }
520
521 if (IS_ZEBRA_DEBUG_MLAG)
522 zlog_debug(
523 "Client De-Registered successfully for MLAG Updates");
524}
525
526/*
527 * Does following things.
528 * 1) allocated new local stream, and copies the client data and enqueue
529 * to MLAG Thread
530 * 2) MLAG Thread after dequeing, encode the client data using protobuf
531 * and write on to MLAG
532 */
533void zebra_mlag_forward_client_msg(ZAPI_HANDLER_ARGS)
534{
535 struct stream *zebra_s;
536 struct stream *mlag_s;
537
538 if (IS_ZEBRA_DEBUG_MLAG)
539 zlog_debug("Received Client MLAG Data from client-proto:%d",
540 client->proto);
541
542 /* Get input stream. */
543 zebra_s = msg;
544 mlag_s = stream_new(zebra_s->endp);
545
546 /*
547 * Client data is | Zebra Header + MLAG Data |
548 * we need to enqueue only the MLAG data, skipping Zebra Header
549 */
550 stream_put(mlag_s, zebra_s->data + zebra_s->getp,
551 STREAM_READABLE(zebra_s));
552 stream_fifo_push_safe(zrouter.mlag_info.mlag_fifo, mlag_s);
553 zebra_mlag_signal_write_thread();
554
555 if (IS_ZEBRA_DEBUG_MLAG)
556 zlog_debug("%s: Enqueued Client:%d data to MLAG Thread ",
557 __func__, client->proto);
558}
559
560/***********************End of Zebra Main thread processing*************/
561
ff1fb8d5
DS
562enum mlag_role zebra_mlag_get_role(void)
563{
e96ba9da 564 return zrouter.mlag_info.role;
ff1fb8d5
DS
565}
566
14d9bbbe
DS
567int32_t zebra_mlag_test_mlag_internal(const char *none, const char *primary,
568 const char *secondary)
763ec244 569{
b120fe3b 570 enum mlag_role orig = zrouter.mlag_info.role;
67fa73f2 571 char buf1[MLAG_ROLE_STRSIZE], buf2[MLAG_ROLE_STRSIZE];
b120fe3b 572
763ec244 573 if (none)
e96ba9da 574 zrouter.mlag_info.role = MLAG_ROLE_NONE;
763ec244 575 if (primary)
e96ba9da 576 zrouter.mlag_info.role = MLAG_ROLE_PRIMARY;
763ec244 577 if (secondary)
e96ba9da 578 zrouter.mlag_info.role = MLAG_ROLE_SECONDARY;
763ec244 579
b120fe3b
DS
580 if (IS_ZEBRA_DEBUG_MLAG)
581 zlog_debug("Test: Changing role from %s to %s",
582 mlag_role2str(orig, buf1, sizeof(buf1)),
583 mlag_role2str(orig, buf2, sizeof(buf2)));
584
ee235396 585 if (orig != zrouter.mlag_info.role) {
b120fe3b 586 zsend_capabilities_all_clients();
ee235396
SK
587 if (zrouter.mlag_info.role != MLAG_ROLE_NONE) {
588 if (zrouter.mlag_info.clients_interested_cnt == 0
a8f58eb6 589 && !test_mlag_in_progress) {
1e76492b
SK
590 if (zrouter.mlag_info.zebra_pth_mlag == NULL)
591 zebra_mlag_spawn_pthread();
ee235396
SK
592 zrouter.mlag_info.clients_interested_cnt++;
593 test_mlag_in_progress = true;
d621815a 594 hook_call(zebra_mlag_private_open_channel);
ee235396
SK
595 }
596 } else {
a8f58eb6 597 if (test_mlag_in_progress) {
ee235396
SK
598 test_mlag_in_progress = false;
599 zrouter.mlag_info.clients_interested_cnt--;
d621815a 600 hook_call(zebra_mlag_private_close_channel);
ee235396
SK
601 }
602 }
603 }
b120fe3b 604
763ec244
DS
605 return CMD_SUCCESS;
606}
607
df395600
DS
608void zebra_mlag_init(void)
609{
14d9bbbe 610 zebra_mlag_vty_init();
ee235396
SK
611
612 /*
1e76492b
SK
613 * Intialiaze the MLAG Global variables
614 * write thread will be created during actual registration with MCLAG
ee235396
SK
615 */
616 zrouter.mlag_info.clients_interested_cnt = 0;
617 zrouter.mlag_info.connected = false;
618 zrouter.mlag_info.timer_running = false;
619 zrouter.mlag_info.mlag_fifo = stream_fifo_new();
620 zrouter.mlag_info.zebra_pth_mlag = NULL;
621 zrouter.mlag_info.th_master = NULL;
622 zrouter.mlag_info.t_read = NULL;
623 zrouter.mlag_info.t_write = NULL;
624 test_mlag_in_progress = false;
ee235396 625 zebra_mlag_reset_read_buffer();
df395600
DS
626}
627
628void zebra_mlag_terminate(void)
629{
630}
ee235396
SK
631
632
633/*
634 *
635 * ProtoBuf Encoding APIs
636 */
637
fd193241 638#ifdef HAVE_PROTOBUF_VERSION_3
67fa73f2 639
bf8d3d6a 640DEFINE_MTYPE_STATIC(ZEBRA, MLAG_PBUF, "ZEBRA MLAG PROTOBUF");
67fa73f2
SK
641
642int zebra_mlag_protobuf_encode_client_data(struct stream *s, uint32_t *msg_type)
643{
644 ZebraMlagHeader hdr = ZEBRA_MLAG__HEADER__INIT;
645 struct mlag_msg mlag_msg;
646 uint8_t tmp_buf[ZEBRA_MLAG_BUF_LIMIT];
647 int len = 0;
648 int n_len = 0;
649 int rc = 0;
650 char buf[ZLOG_FILTER_LENGTH_MAX];
83f8a12b 651 size_t length;
67fa73f2
SK
652
653 if (IS_ZEBRA_DEBUG_MLAG)
654 zlog_debug("%s: Entering..", __func__);
655
83f8a12b 656 rc = mlag_lib_decode_mlag_hdr(s, &mlag_msg, &length);
67fa73f2
SK
657 if (rc)
658 return rc;
659
83f8a12b
SK
660 memset(tmp_buf, 0, ZEBRA_MLAG_BUF_LIMIT);
661
67fa73f2 662 if (IS_ZEBRA_DEBUG_MLAG)
1e76492b
SK
663 zlog_debug("%s: Mlag ProtoBuf encoding of message:%s, len:%d",
664 __func__,
665 mlag_lib_msgid_to_str(mlag_msg.msg_type, buf,
666 sizeof(buf)),
67fa73f2 667 mlag_msg.data_len);
67fa73f2
SK
668 *msg_type = mlag_msg.msg_type;
669 switch (mlag_msg.msg_type) {
670 case MLAG_MROUTE_ADD: {
671 struct mlag_mroute_add msg;
672 ZebraMlagMrouteAdd pay_load = ZEBRA_MLAG_MROUTE_ADD__INIT;
673 uint32_t vrf_name_len = 0;
674
83f8a12b 675 rc = mlag_lib_decode_mroute_add(s, &msg, &length);
67fa73f2
SK
676 if (rc)
677 return rc;
83f8a12b 678
67fa73f2
SK
679 vrf_name_len = strlen(msg.vrf_name) + 1;
680 pay_load.vrf_name = XMALLOC(MTYPE_MLAG_PBUF, vrf_name_len);
681 strlcpy(pay_load.vrf_name, msg.vrf_name, vrf_name_len);
682 pay_load.source_ip = msg.source_ip;
683 pay_load.group_ip = msg.group_ip;
684 pay_load.cost_to_rp = msg.cost_to_rp;
685 pay_load.owner_id = msg.owner_id;
686 pay_load.am_i_dr = msg.am_i_dr;
687 pay_load.am_i_dual_active = msg.am_i_dual_active;
688 pay_load.vrf_id = msg.vrf_id;
689
690 if (msg.owner_id == MLAG_OWNER_INTERFACE) {
691 vrf_name_len = strlen(msg.intf_name) + 1;
692 pay_load.intf_name =
693 XMALLOC(MTYPE_MLAG_PBUF, vrf_name_len);
694 strlcpy(pay_load.intf_name, msg.intf_name,
695 vrf_name_len);
696 }
697
698 len = zebra_mlag_mroute_add__pack(&pay_load, tmp_buf);
699 XFREE(MTYPE_MLAG_PBUF, pay_load.vrf_name);
700 if (msg.owner_id == MLAG_OWNER_INTERFACE)
701 XFREE(MTYPE_MLAG_PBUF, pay_load.intf_name);
702 } break;
703 case MLAG_MROUTE_DEL: {
704 struct mlag_mroute_del msg;
705 ZebraMlagMrouteDel pay_load = ZEBRA_MLAG_MROUTE_DEL__INIT;
706 uint32_t vrf_name_len = 0;
707
83f8a12b 708 rc = mlag_lib_decode_mroute_del(s, &msg, &length);
67fa73f2
SK
709 if (rc)
710 return rc;
711 vrf_name_len = strlen(msg.vrf_name) + 1;
712 pay_load.vrf_name = XMALLOC(MTYPE_MLAG_PBUF, vrf_name_len);
713 strlcpy(pay_load.vrf_name, msg.vrf_name, vrf_name_len);
714 pay_load.source_ip = msg.source_ip;
715 pay_load.group_ip = msg.group_ip;
716 pay_load.owner_id = msg.owner_id;
717 pay_load.vrf_id = msg.vrf_id;
718
719 if (msg.owner_id == MLAG_OWNER_INTERFACE) {
720 vrf_name_len = strlen(msg.intf_name) + 1;
721 pay_load.intf_name =
722 XMALLOC(MTYPE_MLAG_PBUF, vrf_name_len);
723 strlcpy(pay_load.intf_name, msg.intf_name,
724 vrf_name_len);
725 }
726
727 len = zebra_mlag_mroute_del__pack(&pay_load, tmp_buf);
728 XFREE(MTYPE_MLAG_PBUF, pay_load.vrf_name);
729 if (msg.owner_id == MLAG_OWNER_INTERFACE)
730 XFREE(MTYPE_MLAG_PBUF, pay_load.intf_name);
731 } break;
732 case MLAG_MROUTE_ADD_BULK: {
733 struct mlag_mroute_add msg;
734 ZebraMlagMrouteAddBulk Bulk_msg =
735 ZEBRA_MLAG_MROUTE_ADD_BULK__INIT;
736 ZebraMlagMrouteAdd **pay_load = NULL;
67fa73f2 737 bool cleanup = false;
83f8a12b 738 uint32_t i, actual;
67fa73f2
SK
739
740 Bulk_msg.n_mroute_add = mlag_msg.msg_cnt;
741 pay_load = XMALLOC(MTYPE_MLAG_PBUF, sizeof(ZebraMlagMrouteAdd *)
742 * mlag_msg.msg_cnt);
743
83f8a12b 744 for (i = 0, actual = 0; i < mlag_msg.msg_cnt; i++, actual++) {
67fa73f2
SK
745
746 uint32_t vrf_name_len = 0;
747
83f8a12b 748 rc = mlag_lib_decode_mroute_add(s, &msg, &length);
67fa73f2
SK
749 if (rc) {
750 cleanup = true;
751 break;
752 }
753 pay_load[i] = XMALLOC(MTYPE_MLAG_PBUF,
754 sizeof(ZebraMlagMrouteAdd));
755 zebra_mlag_mroute_add__init(pay_load[i]);
756
757 vrf_name_len = strlen(msg.vrf_name) + 1;
758 pay_load[i]->vrf_name =
759 XMALLOC(MTYPE_MLAG_PBUF, vrf_name_len);
760 strlcpy(pay_load[i]->vrf_name, msg.vrf_name,
761 vrf_name_len);
762 pay_load[i]->source_ip = msg.source_ip;
763 pay_load[i]->group_ip = msg.group_ip;
764 pay_load[i]->cost_to_rp = msg.cost_to_rp;
765 pay_load[i]->owner_id = msg.owner_id;
766 pay_load[i]->am_i_dr = msg.am_i_dr;
767 pay_load[i]->am_i_dual_active = msg.am_i_dual_active;
768 pay_load[i]->vrf_id = msg.vrf_id;
769 if (msg.owner_id == MLAG_OWNER_INTERFACE) {
770 vrf_name_len = strlen(msg.intf_name) + 1;
771 pay_load[i]->intf_name =
772 XMALLOC(MTYPE_MLAG_PBUF, vrf_name_len);
773
774 strlcpy(pay_load[i]->intf_name, msg.intf_name,
775 vrf_name_len);
776 }
777 }
a8f58eb6 778 if (!cleanup) {
67fa73f2
SK
779 Bulk_msg.mroute_add = pay_load;
780 len = zebra_mlag_mroute_add_bulk__pack(&Bulk_msg,
781 tmp_buf);
782 }
783
83f8a12b
SK
784 for (i = 0; i < actual; i++) {
785 /*
786 * The mlag_lib_decode_mroute_add can
787 * fail to properly decode and cause nothing
788 * to be allocated. Prevent a crash
789 */
790 if (!pay_load[i])
791 continue;
792
5567e801 793 XFREE(MTYPE_MLAG_PBUF, pay_load[i]->vrf_name);
67fa73f2
SK
794 if (pay_load[i]->owner_id == MLAG_OWNER_INTERFACE
795 && pay_load[i]->intf_name)
796 XFREE(MTYPE_MLAG_PBUF, pay_load[i]->intf_name);
e1b36e13 797 XFREE(MTYPE_MLAG_PBUF, pay_load[i]);
67fa73f2
SK
798 }
799 XFREE(MTYPE_MLAG_PBUF, pay_load);
a8f58eb6 800 if (cleanup)
67fa73f2
SK
801 return -1;
802 } break;
803 case MLAG_MROUTE_DEL_BULK: {
804 struct mlag_mroute_del msg;
805 ZebraMlagMrouteDelBulk Bulk_msg =
806 ZEBRA_MLAG_MROUTE_DEL_BULK__INIT;
807 ZebraMlagMrouteDel **pay_load = NULL;
67fa73f2 808 bool cleanup = false;
83f8a12b 809 uint32_t i, actual;
67fa73f2
SK
810
811 Bulk_msg.n_mroute_del = mlag_msg.msg_cnt;
812 pay_load = XMALLOC(MTYPE_MLAG_PBUF, sizeof(ZebraMlagMrouteDel *)
813 * mlag_msg.msg_cnt);
814
83f8a12b 815 for (i = 0, actual = 0; i < mlag_msg.msg_cnt; i++, actual++) {
67fa73f2
SK
816
817 uint32_t vrf_name_len = 0;
818
83f8a12b 819 rc = mlag_lib_decode_mroute_del(s, &msg, &length);
67fa73f2
SK
820 if (rc) {
821 cleanup = true;
822 break;
823 }
824
825 pay_load[i] = XMALLOC(MTYPE_MLAG_PBUF,
826 sizeof(ZebraMlagMrouteDel));
827 zebra_mlag_mroute_del__init(pay_load[i]);
828
829 vrf_name_len = strlen(msg.vrf_name) + 1;
830 pay_load[i]->vrf_name =
831 XMALLOC(MTYPE_MLAG_PBUF, vrf_name_len);
832
833 strlcpy(pay_load[i]->vrf_name, msg.vrf_name,
834 vrf_name_len);
835 pay_load[i]->source_ip = msg.source_ip;
836 pay_load[i]->group_ip = msg.group_ip;
837 pay_load[i]->owner_id = msg.owner_id;
838 pay_load[i]->vrf_id = msg.vrf_id;
839 if (msg.owner_id == MLAG_OWNER_INTERFACE) {
840 vrf_name_len = strlen(msg.intf_name) + 1;
841 pay_load[i]->intf_name =
842 XMALLOC(MTYPE_MLAG_PBUF, vrf_name_len);
843
844 strlcpy(pay_load[i]->intf_name, msg.intf_name,
845 vrf_name_len);
846 }
847 }
848 if (!cleanup) {
849 Bulk_msg.mroute_del = pay_load;
850 len = zebra_mlag_mroute_del_bulk__pack(&Bulk_msg,
851 tmp_buf);
852 }
853
83f8a12b
SK
854 for (i = 0; i < actual; i++) {
855 /*
856 * The mlag_lib_decode_mroute_add can
857 * fail to properly decode and cause nothing
858 * to be allocated. Prevent a crash
859 */
860 if (!pay_load[i])
861 continue;
862
5567e801 863 XFREE(MTYPE_MLAG_PBUF, pay_load[i]->vrf_name);
67fa73f2
SK
864 if (pay_load[i]->owner_id == MLAG_OWNER_INTERFACE
865 && pay_load[i]->intf_name)
866 XFREE(MTYPE_MLAG_PBUF, pay_load[i]->intf_name);
e1b36e13 867 XFREE(MTYPE_MLAG_PBUF, pay_load[i]);
67fa73f2
SK
868 }
869 XFREE(MTYPE_MLAG_PBUF, pay_load);
870 if (cleanup)
871 return -1;
872 } break;
a98701f0
DS
873 case MLAG_REGISTER:
874 case MLAG_DEREGISTER:
875 case MLAG_STATUS_UPDATE:
876 case MLAG_DUMP:
877 case MLAG_PIM_CFG_DUMP:
878 case MLAG_VXLAN_UPDATE:
879 case MLAG_PEER_FRR_STATUS:
880 case MLAG_MSG_NONE:
67fa73f2
SK
881 break;
882 }
883
884 if (IS_ZEBRA_DEBUG_MLAG)
885 zlog_debug("%s: length of Mlag ProtoBuf encoded message:%s, %d",
886 __func__,
1e76492b
SK
887 mlag_lib_msgid_to_str(mlag_msg.msg_type, buf,
888 sizeof(buf)),
67fa73f2
SK
889 len);
890 hdr.type = (ZebraMlagHeader__MessageType)mlag_msg.msg_type;
891 if (len != 0) {
892 hdr.data.len = len;
893 hdr.data.data = XMALLOC(MTYPE_MLAG_PBUF, len);
894 memcpy(hdr.data.data, tmp_buf, len);
895 }
896
897 /*
898 * ProtoBuf Infra will not support to demarc the pointers whem multiple
899 * messages are posted inside a single Buffer.
900 * 2 -solutions exist to solve this
901 * 1. add Unenoced length at the beginning of every message, this will
902 * be used to point to next message in the buffer
903 * 2. another solution is defining all messages insides another message
904 * But this will permit only 32 messages. this can be extended with
905 * multiple levels.
906 * for simplicity we are going with solution-1.
907 */
908 len = zebra_mlag__header__pack(&hdr,
909 (mlag_wr_buffer + ZEBRA_MLAG_LEN_SIZE));
910 n_len = htonl(len);
911 memcpy(mlag_wr_buffer, &n_len, ZEBRA_MLAG_LEN_SIZE);
912 len += ZEBRA_MLAG_LEN_SIZE;
913
914 if (IS_ZEBRA_DEBUG_MLAG)
915 zlog_debug(
916 "%s: length of Mlag ProtoBuf message:%s with Header %d",
917 __func__,
1e76492b
SK
918 mlag_lib_msgid_to_str(mlag_msg.msg_type, buf,
919 sizeof(buf)),
67fa73f2 920 len);
e1b36e13 921 XFREE(MTYPE_MLAG_PBUF, hdr.data.data);
67fa73f2
SK
922
923 return len;
924}
925
83f8a12b
SK
926static void zebra_fill_protobuf_msg(struct stream *s, char *name, int len)
927{
928 int str_len = strlen(name) + 1;
929
930 stream_put(s, name, str_len);
931 /* Fill the rest with Null Character for aligning */
932 stream_put(s, NULL, len - str_len);
933}
934
67fa73f2
SK
935int zebra_mlag_protobuf_decode_message(struct stream *s, uint8_t *data,
936 uint32_t len)
937{
938 uint32_t msg_type;
939 ZebraMlagHeader *hdr;
940 char buf[80];
941
942 hdr = zebra_mlag__header__unpack(NULL, len, data);
943 if (hdr == NULL)
944 return -1;
945
946 /*
947 * ADD The MLAG Header
948 */
949 zclient_create_header(s, ZEBRA_MLAG_FORWARD_MSG, VRF_DEFAULT);
950
951 msg_type = hdr->type;
952
953 if (IS_ZEBRA_DEBUG_MLAG)
954 zlog_debug("%s: Mlag ProtoBuf decoding of message:%s", __func__,
1e76492b 955 mlag_lib_msgid_to_str(msg_type, buf, 80));
67fa73f2
SK
956
957 /*
958 * Internal MLAG Message-types & MLAG.proto message types should
959 * always match, otherwise there can be decoding errors
960 * To avoid exposing clients with Protobuf flags, using internal
961 * message-types
962 */
963 stream_putl(s, hdr->type);
964
965 if (hdr->data.len == 0) {
966 /* NULL Payload */
967 stream_putw(s, MLAG_MSG_NULL_PAYLOAD);
968 /* No Batching */
969 stream_putw(s, MLAG_MSG_NO_BATCH);
970 } else {
971 switch (msg_type) {
972 case ZEBRA_MLAG__HEADER__MESSAGE_TYPE__ZEBRA_MLAG_STATUS_UPDATE: {
973 ZebraMlagStatusUpdate *msg = NULL;
974
975 msg = zebra_mlag_status_update__unpack(
976 NULL, hdr->data.len, hdr->data.data);
977 if (msg == NULL) {
978 zebra_mlag__header__free_unpacked(hdr, NULL);
979 return -1;
980 }
981 /* Payload len */
982 stream_putw(s, sizeof(struct mlag_status));
983 /* No Batching */
984 stream_putw(s, MLAG_MSG_NO_BATCH);
985 /* Actual Data */
83f8a12b
SK
986 zebra_fill_protobuf_msg(s, msg->peerlink,
987 INTERFACE_NAMSIZ);
67fa73f2
SK
988 stream_putl(s, msg->my_role);
989 stream_putl(s, msg->peer_state);
990 zebra_mlag_status_update__free_unpacked(msg, NULL);
991 } break;
992 case ZEBRA_MLAG__HEADER__MESSAGE_TYPE__ZEBRA_MLAG_VXLAN_UPDATE: {
993 ZebraMlagVxlanUpdate *msg = NULL;
994
995 msg = zebra_mlag_vxlan_update__unpack(
996 NULL, hdr->data.len, hdr->data.data);
997 if (msg == NULL) {
998 zebra_mlag__header__free_unpacked(hdr, NULL);
999 return -1;
1000 }
1001 /* Payload len */
1002 stream_putw(s, sizeof(struct mlag_vxlan));
1003 /* No Batching */
1004 stream_putw(s, MLAG_MSG_NO_BATCH);
1005 /* Actual Data */
1006 stream_putl(s, msg->anycast_ip);
1007 stream_putl(s, msg->local_ip);
1008 zebra_mlag_vxlan_update__free_unpacked(msg, NULL);
1009 } break;
1010 case ZEBRA_MLAG__HEADER__MESSAGE_TYPE__ZEBRA_MLAG_MROUTE_ADD: {
1011 ZebraMlagMrouteAdd *msg = NULL;
1012
1013 msg = zebra_mlag_mroute_add__unpack(NULL, hdr->data.len,
1014 hdr->data.data);
1015 if (msg == NULL) {
1016 zebra_mlag__header__free_unpacked(hdr, NULL);
1017 return -1;
1018 }
1019 /* Payload len */
1020 stream_putw(s, sizeof(struct mlag_mroute_add));
1021 /* No Batching */
1022 stream_putw(s, MLAG_MSG_NO_BATCH);
1023 /* Actual Data */
83f8a12b 1024 zebra_fill_protobuf_msg(s, msg->vrf_name, VRF_NAMSIZ);
67fa73f2
SK
1025
1026 stream_putl(s, msg->source_ip);
1027 stream_putl(s, msg->group_ip);
1028 stream_putl(s, msg->cost_to_rp);
1029 stream_putl(s, msg->owner_id);
1030 stream_putc(s, msg->am_i_dr);
1031 stream_putc(s, msg->am_i_dual_active);
1032 stream_putl(s, msg->vrf_id);
1033 if (msg->owner_id == MLAG_OWNER_INTERFACE)
83f8a12b
SK
1034 zebra_fill_protobuf_msg(s, msg->intf_name,
1035 INTERFACE_NAMSIZ);
67fa73f2
SK
1036 else
1037 stream_put(s, NULL, INTERFACE_NAMSIZ);
1038 zebra_mlag_mroute_add__free_unpacked(msg, NULL);
1039 } break;
1040 case ZEBRA_MLAG__HEADER__MESSAGE_TYPE__ZEBRA_MLAG_MROUTE_DEL: {
1041 ZebraMlagMrouteDel *msg = NULL;
1042
1043 msg = zebra_mlag_mroute_del__unpack(NULL, hdr->data.len,
1044 hdr->data.data);
1045 if (msg == NULL) {
1046 zebra_mlag__header__free_unpacked(hdr, NULL);
1047 return -1;
1048 }
1049 /* Payload len */
1050 stream_putw(s, sizeof(struct mlag_mroute_del));
1051 /* No Batching */
1052 stream_putw(s, MLAG_MSG_NO_BATCH);
1053 /* Actual Data */
83f8a12b 1054 zebra_fill_protobuf_msg(s, msg->vrf_name, VRF_NAMSIZ);
67fa73f2
SK
1055
1056 stream_putl(s, msg->source_ip);
1057 stream_putl(s, msg->group_ip);
67fa73f2
SK
1058 stream_putl(s, msg->owner_id);
1059 stream_putl(s, msg->vrf_id);
1060 if (msg->owner_id == MLAG_OWNER_INTERFACE)
83f8a12b
SK
1061 zebra_fill_protobuf_msg(s, msg->intf_name,
1062 INTERFACE_NAMSIZ);
67fa73f2
SK
1063 else
1064 stream_put(s, NULL, INTERFACE_NAMSIZ);
1065 zebra_mlag_mroute_del__free_unpacked(msg, NULL);
1066 } break;
1067 case ZEBRA_MLAG__HEADER__MESSAGE_TYPE__ZEBRA_MLAG_MROUTE_ADD_BULK: {
1068 ZebraMlagMrouteAddBulk *Bulk_msg = NULL;
1069 ZebraMlagMrouteAdd *msg = NULL;
010b575b 1070 size_t i, length_spot;
67fa73f2
SK
1071
1072 Bulk_msg = zebra_mlag_mroute_add_bulk__unpack(
1073 NULL, hdr->data.len, hdr->data.data);
1074 if (Bulk_msg == NULL) {
1075 zebra_mlag__header__free_unpacked(hdr, NULL);
1076 return -1;
1077 }
1078 /* Payload len */
1079 stream_putw(s, (Bulk_msg->n_mroute_add
1080 * sizeof(struct mlag_mroute_add)));
1081 /* No. of msgs in Batch */
010b575b 1082 length_spot = stream_putw(s, Bulk_msg->n_mroute_add);
67fa73f2
SK
1083
1084 /* Actual Data */
1085 for (i = 0; i < Bulk_msg->n_mroute_add; i++) {
010b575b
DS
1086 if (STREAM_SIZE(s)
1087 < VRF_NAMSIZ + 22 + INTERFACE_NAMSIZ) {
1088 zlog_warn(
1089 "We have received more messages than we can parse at this point in time: %zu",
1090 Bulk_msg->n_mroute_add);
1091 break;
1092 }
67fa73f2
SK
1093
1094 msg = Bulk_msg->mroute_add[i];
1095
83f8a12b
SK
1096 zebra_fill_protobuf_msg(s, msg->vrf_name,
1097 VRF_NAMSIZ);
67fa73f2
SK
1098 stream_putl(s, msg->source_ip);
1099 stream_putl(s, msg->group_ip);
1100 stream_putl(s, msg->cost_to_rp);
1101 stream_putl(s, msg->owner_id);
1102 stream_putc(s, msg->am_i_dr);
1103 stream_putc(s, msg->am_i_dual_active);
1104 stream_putl(s, msg->vrf_id);
1105 if (msg->owner_id == MLAG_OWNER_INTERFACE)
83f8a12b
SK
1106 zebra_fill_protobuf_msg(
1107 s, msg->intf_name,
1108 INTERFACE_NAMSIZ);
67fa73f2
SK
1109 else
1110 stream_put(s, NULL, INTERFACE_NAMSIZ);
1111 }
010b575b
DS
1112
1113 stream_putw_at(s, length_spot, i + 1);
1114
67fa73f2
SK
1115 zebra_mlag_mroute_add_bulk__free_unpacked(Bulk_msg,
1116 NULL);
1117 } break;
1118 case ZEBRA_MLAG__HEADER__MESSAGE_TYPE__ZEBRA_MLAG_MROUTE_DEL_BULK: {
1119 ZebraMlagMrouteDelBulk *Bulk_msg = NULL;
1120 ZebraMlagMrouteDel *msg = NULL;
010b575b 1121 size_t i, length_spot;
67fa73f2
SK
1122
1123 Bulk_msg = zebra_mlag_mroute_del_bulk__unpack(
1124 NULL, hdr->data.len, hdr->data.data);
1125 if (Bulk_msg == NULL) {
1126 zebra_mlag__header__free_unpacked(hdr, NULL);
1127 return -1;
1128 }
1129 /* Payload len */
1130 stream_putw(s, (Bulk_msg->n_mroute_del
1131 * sizeof(struct mlag_mroute_del)));
1132 /* No. of msgs in Batch */
010b575b 1133 length_spot = stream_putw(s, Bulk_msg->n_mroute_del);
67fa73f2
SK
1134
1135 /* Actual Data */
1136 for (i = 0; i < Bulk_msg->n_mroute_del; i++) {
010b575b
DS
1137 if (STREAM_SIZE(s)
1138 < VRF_NAMSIZ + 16 + INTERFACE_NAMSIZ) {
1139 zlog_warn(
1140 "We have received more messages than we can parse at this time");
1141 break;
1142 }
67fa73f2
SK
1143
1144 msg = Bulk_msg->mroute_del[i];
1145
83f8a12b
SK
1146 zebra_fill_protobuf_msg(s, msg->vrf_name,
1147 VRF_NAMSIZ);
67fa73f2
SK
1148 stream_putl(s, msg->source_ip);
1149 stream_putl(s, msg->group_ip);
1150 stream_putl(s, msg->owner_id);
1151 stream_putl(s, msg->vrf_id);
1152 if (msg->owner_id == MLAG_OWNER_INTERFACE)
83f8a12b
SK
1153 zebra_fill_protobuf_msg(
1154 s, msg->intf_name,
1155 INTERFACE_NAMSIZ);
67fa73f2
SK
1156 else
1157 stream_put(s, NULL, INTERFACE_NAMSIZ);
1158 }
010b575b
DS
1159
1160 stream_putw_at(s, length_spot, i + 1);
1161
67fa73f2
SK
1162 zebra_mlag_mroute_del_bulk__free_unpacked(Bulk_msg,
1163 NULL);
1164 } break;
1165 case ZEBRA_MLAG__HEADER__MESSAGE_TYPE__ZEBRA_MLAG_ZEBRA_STATUS_UPDATE: {
1166 ZebraMlagZebraStatusUpdate *msg = NULL;
1167
1168 msg = zebra_mlag_zebra_status_update__unpack(
1169 NULL, hdr->data.len, hdr->data.data);
1170 if (msg == NULL) {
1171 zebra_mlag__header__free_unpacked(hdr, NULL);
1172 return -1;
1173 }
1174 /* Payload len */
1175 stream_putw(s, sizeof(struct mlag_frr_status));
1176 /* No Batching */
1177 stream_putw(s, MLAG_MSG_NO_BATCH);
1178 /* Actual Data */
1179 stream_putl(s, msg->peer_frrstate);
1180 zebra_mlag_zebra_status_update__free_unpacked(msg,
1181 NULL);
1182 } break;
1183 default:
1184 break;
1185 }
1186 }
1187 zebra_mlag__header__free_unpacked(hdr, NULL);
1188 return msg_type;
1189}
1190
1191#else
ee235396
SK
1192int zebra_mlag_protobuf_encode_client_data(struct stream *s, uint32_t *msg_type)
1193{
1194 return 0;
1195}
1196
67fa73f2 1197int zebra_mlag_protobuf_decode_message(struct stream *s, uint8_t *data,
ee235396
SK
1198 uint32_t len)
1199{
1200 return 0;
1201}
67fa73f2 1202#endif