]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_zpthread.c
Merge pull request #12837 from donaldsharp/unlikely_routemap
[mirror_frr.git] / pimd / pim_zpthread.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
17823cdd
DS
2/*
3 * PIM for Quagga
4 * Copyright (C) 2008 Everton da Silva Marques
17823cdd
DS
5 */
6
7#include <zebra.h>
8#include <lib/log.h>
9#include <lib/lib_errors.h>
10
11#include "pimd.h"
993e3d8e 12#include "pim_instance.h"
17823cdd
DS
13#include "pim_mlag.h"
14#include "pim_zebra.h"
15
16extern struct zclient *zclient;
17
18#define PIM_MLAG_POST_LIMIT 100
19
20int32_t mlag_bulk_cnt;
21
22static void pim_mlag_zebra_fill_header(enum mlag_msg_type msg_type)
23{
24 uint32_t fill_msg_type = msg_type;
da21ae9d 25 uint16_t data_len = 0;
17823cdd
DS
26 uint16_t msg_cnt = 1;
27
17823cdd
DS
28 switch (msg_type) {
29 case MLAG_REGISTER:
30 case MLAG_DEREGISTER:
31 data_len = sizeof(struct mlag_msg);
32 break;
33 case MLAG_MROUTE_ADD:
34 data_len = sizeof(struct mlag_mroute_add);
35 fill_msg_type = MLAG_MROUTE_ADD_BULK;
36 break;
37 case MLAG_MROUTE_DEL:
38 data_len = sizeof(struct mlag_mroute_del);
39 fill_msg_type = MLAG_MROUTE_DEL_BULK;
40 break;
da21ae9d 41 case MLAG_MSG_NONE:
88c1f613 42 return;
da21ae9d
DS
43 case MLAG_STATUS_UPDATE:
44 case MLAG_DUMP:
45 case MLAG_MROUTE_ADD_BULK:
46 case MLAG_MROUTE_DEL_BULK:
47 case MLAG_PIM_CFG_DUMP:
48 case MLAG_VXLAN_UPDATE:
49 case MLAG_PEER_FRR_STATUS:
17823cdd
DS
50 data_len = 0;
51 break;
52 }
53
54 stream_reset(router->mlag_stream);
55 /* ADD Hedaer */
56 stream_putl(router->mlag_stream, fill_msg_type);
57 /*
58 * In case of Bulk actual size & msg_cnt will be updated
59 * just before writing onto zebra
60 */
61 stream_putw(router->mlag_stream, data_len);
62 stream_putw(router->mlag_stream, msg_cnt);
63
64 if (PIM_DEBUG_MLAG)
65 zlog_debug(":%s: msg_type: %d/%d len %d",
66 __func__, msg_type, fill_msg_type, data_len);
67}
68
69static void pim_mlag_zebra_flush_buffer(void)
70{
71 uint32_t msg_type;
72
73 /* Stream had bulk messages update the Hedaer */
74 if (mlag_bulk_cnt > 1) {
75 /*
76 * No need to reset the pointer, below api reads from data[0]
77 */
78 STREAM_GETL(router->mlag_stream, msg_type);
79 if (msg_type == MLAG_MROUTE_ADD_BULK) {
80 stream_putw_at(
81 router->mlag_stream, 4,
82 (mlag_bulk_cnt * sizeof(struct mlag_mroute_add)));
83 stream_putw_at(router->mlag_stream, 6, mlag_bulk_cnt);
84 } else if (msg_type == MLAG_MROUTE_DEL_BULK) {
85 stream_putw_at(
86 router->mlag_stream, 4,
87 (mlag_bulk_cnt * sizeof(struct mlag_mroute_del)));
88 stream_putw_at(router->mlag_stream, 6, mlag_bulk_cnt);
89 } else {
90 flog_err(EC_LIB_ZAPI_ENCODE,
91 "unknown bulk message type %d bulk_count %d",
92 msg_type, mlag_bulk_cnt);
93 stream_reset(router->mlag_stream);
94 mlag_bulk_cnt = 0;
95 return;
96 }
97 }
98
99 zclient_send_mlag_data(zclient, router->mlag_stream);
100stream_failure:
101 stream_reset(router->mlag_stream);
102 mlag_bulk_cnt = 0;
103}
104
105/*
106 * Only ROUTE add & Delete will be bulked.
107 * Buffer will be flushed, when
108 * 1) there were no messages in the queue
109 * 2) Curr_msg_type != prev_msg_type
110 */
111
112static void pim_mlag_zebra_check_for_buffer_flush(uint32_t curr_msg_type,
113 uint32_t prev_msg_type)
114{
115 /* First Message, keep bulking */
116 if (prev_msg_type == MLAG_MSG_NONE) {
117 mlag_bulk_cnt = 1;
118 return;
119 }
120
121 /*msg type is route add & delete, keep bulking */
122 if (curr_msg_type == prev_msg_type
123 && (curr_msg_type == MLAG_MROUTE_ADD
124 || curr_msg_type == MLAG_MROUTE_DEL)) {
125 mlag_bulk_cnt++;
126 return;
127 }
128
129 pim_mlag_zebra_flush_buffer();
130}
131
132/*
133 * Thsi thread reads the clients data from the Gloabl queue and encodes with
134 * protobuf and pass on to the MLAG socket.
135 */
e6685141 136static void pim_mlag_zthread_handler(struct event *event)
17823cdd
DS
137{
138 struct stream *read_s;
139 uint32_t wr_count = 0;
140 uint32_t prev_msg_type = MLAG_MSG_NONE;
141 uint32_t curr_msg_type = MLAG_MSG_NONE;
142
143 router->zpthread_mlag_write = NULL;
144 wr_count = stream_fifo_count_safe(router->mlag_fifo);
145
146 if (PIM_DEBUG_MLAG)
147 zlog_debug(":%s: Processing MLAG write, %d messages in queue",
148 __func__, wr_count);
149
150 if (wr_count == 0)
cc9f21da 151 return;
17823cdd
DS
152
153 for (wr_count = 0; wr_count < PIM_MLAG_POST_LIMIT; wr_count++) {
154 /* FIFO is empty,wait for teh message to be add */
155 if (stream_fifo_count_safe(router->mlag_fifo) == 0)
156 break;
157
158 read_s = stream_fifo_pop_safe(router->mlag_fifo);
159 if (!read_s) {
160 zlog_debug(":%s: Got a NULL Messages, some thing wrong",
161 __func__);
162 break;
163 }
164 STREAM_GETL(read_s, curr_msg_type);
165 /*
166 * Check for Buffer Overflow,
167 * MLAG Can't process more than 'PIM_MLAG_BUF_LIMIT' bytes
168 */
169 if (router->mlag_stream->endp + read_s->endp + ZEBRA_HEADER_SIZE
170 > MLAG_BUF_LIMIT)
171 pim_mlag_zebra_flush_buffer();
172
173 pim_mlag_zebra_check_for_buffer_flush(curr_msg_type,
174 prev_msg_type);
175
176 /*
177 * First message to Buffer, fill the Header
178 */
179 if (router->mlag_stream->endp == 0)
180 pim_mlag_zebra_fill_header(curr_msg_type);
181
182 /*
183 * add the data now
184 */
185 stream_put(router->mlag_stream, read_s->data + read_s->getp,
186 read_s->endp - read_s->getp);
187
188 stream_free(read_s);
189 prev_msg_type = curr_msg_type;
190 }
191
192stream_failure:
193 /*
194 * we are here , because
195 * 1. Queue might be empty
196 * 2. we crossed the max Q Read limit
197 * In any acse flush the buffer towards zebra
198 */
199 pim_mlag_zebra_flush_buffer();
200
201 if (wr_count >= PIM_MLAG_POST_LIMIT)
202 pim_mlag_signal_zpthread();
17823cdd
DS
203}
204
205
206int pim_mlag_signal_zpthread(void)
207{
208 if (router->master) {
209 if (PIM_DEBUG_MLAG)
210 zlog_debug(":%s: Scheduling PIM MLAG write Thread",
211 __func__);
907a2395
DS
212 event_add_event(router->master, pim_mlag_zthread_handler, NULL,
213 0, &router->zpthread_mlag_write);
17823cdd
DS
214 }
215 return (0);
216}