]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_mlag_private.c
doc: Update sharp watch command documentation slightly
[mirror_frr.git] / zebra / zebra_mlag_private.c
CommitLineData
ee235396
SK
1/*
2 * This is an implementation of MLAG Functionality
3 *
4 * Module name: Zebra 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 "hook.h"
27#include "module.h"
28#include "thread.h"
67fa73f2 29#include "frr_pthread.h"
ee235396
SK
30#include "libfrr.h"
31#include "version.h"
32#include "network.h"
33
34#include "lib/stream.h"
35
36#include "zebra/debug.h"
37#include "zebra/zebra_router.h"
38#include "zebra/zebra_mlag.h"
ee235396
SK
39
40#include <sys/un.h>
41
42
43/*
44 * This file will have platform specific apis to communicate with MCLAG.
45 *
46 */
47
ee235396
SK
48static struct thread_master *zmlag_master;
49static int mlag_socket;
50
51static int zebra_mlag_connect(struct thread *thread);
52static int zebra_mlag_read(struct thread *thread);
53
54/*
55 * Write the data to MLAGD
56 */
d621815a 57static int zebra_mlag_private_write_data(uint8_t *data, uint32_t len)
ee235396
SK
58{
59 int rc = 0;
60
61 if (IS_ZEBRA_DEBUG_MLAG) {
62 zlog_debug("%s: Writing %d length Data to clag", __func__, len);
63 zlog_hexdump(data, len);
64 }
65 rc = write(mlag_socket, data, len);
66 return rc;
67}
68
69static void zebra_mlag_sched_read(void)
70{
1e76492b
SK
71 thread_add_read(zmlag_master, zebra_mlag_read, NULL, mlag_socket,
72 &zrouter.mlag_info.t_read);
ee235396
SK
73}
74
75static int zebra_mlag_read(struct thread *thread)
76{
77 uint32_t *msglen;
78 uint32_t h_msglen;
79 uint32_t tot_len, curr_len = mlag_rd_buf_offset;
80
17823cdd
DS
81 zrouter.mlag_info.t_read = NULL;
82
ee235396
SK
83 /*
84 * Received message in sock_stream looks like below
85 * | len-1 (4 Bytes) | payload-1 (len-1) |
86 * len-2 (4 Bytes) | payload-2 (len-2) | ..
87 *
88 * Idea is read one message completely, then process, until message is
89 * read completely, keep on reading from the socket
90 */
91 if (curr_len < ZEBRA_MLAG_LEN_SIZE) {
92 ssize_t data_len;
93
94 data_len = read(mlag_socket, mlag_rd_buffer + curr_len,
95 ZEBRA_MLAG_LEN_SIZE - curr_len);
96 if (data_len == 0 || data_len == -1) {
97 if (IS_ZEBRA_DEBUG_MLAG)
98 zlog_debug("MLAG connection closed socket : %d",
99 mlag_socket);
100 close(mlag_socket);
101 zebra_mlag_handle_process_state(MLAG_DOWN);
102 return -1;
103 }
67fa73f2 104 mlag_rd_buf_offset += data_len;
668b6011 105 if (data_len != (ssize_t)(ZEBRA_MLAG_LEN_SIZE - curr_len)) {
ee235396
SK
106 /* Try again later */
107 zebra_mlag_sched_read();
108 return 0;
109 }
110 curr_len = ZEBRA_MLAG_LEN_SIZE;
111 }
112
113 /* Get the actual packet length */
114 msglen = (uint32_t *)mlag_rd_buffer;
115 h_msglen = ntohl(*msglen);
116
117 /* This will be the actual length of the packet */
118 tot_len = h_msglen + ZEBRA_MLAG_LEN_SIZE;
119
120 if (curr_len < tot_len) {
121 ssize_t data_len;
122
123 data_len = read(mlag_socket, mlag_rd_buffer + curr_len,
124 tot_len - curr_len);
125 if (data_len == 0 || data_len == -1) {
126 if (IS_ZEBRA_DEBUG_MLAG)
127 zlog_debug("MLAG connection closed socket : %d",
128 mlag_socket);
129 close(mlag_socket);
130 zebra_mlag_handle_process_state(MLAG_DOWN);
131 return -1;
132 }
67fa73f2 133 mlag_rd_buf_offset += data_len;
668b6011 134 if (data_len != (ssize_t)(tot_len - curr_len)) {
ee235396
SK
135 /* Try again later */
136 zebra_mlag_sched_read();
137 return 0;
138 }
139 }
140
141 if (IS_ZEBRA_DEBUG_MLAG) {
142 zlog_debug("Received a MLAG Message from socket: %d, len:%u ",
143 mlag_socket, tot_len);
144 zlog_hexdump(mlag_rd_buffer, tot_len);
145 }
146
147 tot_len -= ZEBRA_MLAG_LEN_SIZE;
148
149 /* Process the packet */
150 zebra_mlag_process_mlag_data(mlag_rd_buffer + ZEBRA_MLAG_LEN_SIZE,
151 tot_len);
152
153 /* Register read thread. */
154 zebra_mlag_reset_read_buffer();
155 zebra_mlag_sched_read();
156 return 0;
157}
158
159static int zebra_mlag_connect(struct thread *thread)
160{
161 struct sockaddr_un svr = {0};
ee235396
SK
162
163 /* Reset the Timer-running flag */
164 zrouter.mlag_info.timer_running = false;
165
ee235396
SK
166 svr.sun_family = AF_UNIX;
167#define MLAG_SOCK_NAME "/var/run/clag-zebra.socket"
168 strlcpy(svr.sun_path, MLAG_SOCK_NAME, sizeof(MLAG_SOCK_NAME) + 1);
169
170 mlag_socket = socket(svr.sun_family, SOCK_STREAM, 0);
171 if (mlag_socket < 0)
172 return -1;
173
174 if (connect(mlag_socket, (struct sockaddr *)&svr, sizeof(svr)) == -1) {
175 if (IS_ZEBRA_DEBUG_MLAG)
176 zlog_debug(
177 "Unable to connect to %s try again in 10 secs",
178 svr.sun_path);
179 close(mlag_socket);
180 zrouter.mlag_info.timer_running = true;
181 thread_add_timer(zmlag_master, zebra_mlag_connect, NULL, 10,
182 &zrouter.mlag_info.t_read);
183 return 0;
184 }
ee235396
SK
185
186 set_nonblocking(mlag_socket);
ee235396
SK
187
188 if (IS_ZEBRA_DEBUG_MLAG)
189 zlog_debug("%s: Connection with MLAG is established ",
190 __func__);
191
192 thread_add_read(zmlag_master, zebra_mlag_read, NULL, mlag_socket,
193 &zrouter.mlag_info.t_read);
194 /*
195 * Connection is established with MLAGD, post to clients
196 */
197 zebra_mlag_handle_process_state(MLAG_UP);
198 return 0;
199}
200
201/*
202 * Currently we are doing polling later we will look for better options
203 */
d621815a 204static int zebra_mlag_private_monitor_state(void)
ee235396
SK
205{
206 thread_add_event(zmlag_master, zebra_mlag_connect, NULL, 0,
207 &zrouter.mlag_info.t_read);
d621815a 208 return 0;
ee235396
SK
209}
210
d621815a 211static int zebra_mlag_private_open_channel(void)
ee235396
SK
212{
213 zmlag_master = zrouter.mlag_info.th_master;
214
215 if (zrouter.mlag_info.connected == true) {
216 if (IS_ZEBRA_DEBUG_MLAG)
217 zlog_debug("%s: Zebra already connected to MLAGD",
218 __func__);
219 return 0;
220 }
221
222 if (zrouter.mlag_info.timer_running == true) {
223 if (IS_ZEBRA_DEBUG_MLAG)
224 zlog_debug(
225 "%s: Connection retry is in progress for MLAGD",
226 __func__);
227 return 0;
228 }
229
230 if (zrouter.mlag_info.clients_interested_cnt) {
231 /*
232 * Connect only if any clients are showing interest
233 */
234 thread_add_event(zmlag_master, zebra_mlag_connect, NULL, 0,
235 &zrouter.mlag_info.t_read);
236 }
237 return 0;
238}
239
d621815a 240static int zebra_mlag_private_close_channel(void)
ee235396
SK
241{
242 if (zmlag_master == NULL)
243 return -1;
244
245 if (zrouter.mlag_info.clients_interested_cnt) {
246 if (IS_ZEBRA_DEBUG_MLAG)
247 zlog_debug("%s: still %d clients are connected, skip",
248 __func__,
249 zrouter.mlag_info.clients_interested_cnt);
250 return -1;
251 }
252
253 /*
254 * Post the De-register to MLAG, so that it can do necesasry cleanup
255 */
256 zebra_mlag_send_deregister();
257
258 return 0;
259}
260
d621815a 261static int zebra_mlag_private_cleanup_data(void)
ee235396
SK
262{
263 zmlag_master = NULL;
264 zrouter.mlag_info.connected = false;
265 zrouter.mlag_info.timer_running = false;
266
267 close(mlag_socket);
ee235396
SK
268 return 0;
269}
270
d621815a 271static int zebra_mlag_module_init(void)
ee235396 272{
d621815a
DL
273 hook_register(zebra_mlag_private_write_data,
274 zebra_mlag_private_write_data);
275 hook_register(zebra_mlag_private_monitor_state,
276 zebra_mlag_private_monitor_state);
277 hook_register(zebra_mlag_private_open_channel,
278 zebra_mlag_private_open_channel);
279 hook_register(zebra_mlag_private_close_channel,
280 zebra_mlag_private_close_channel);
281 hook_register(zebra_mlag_private_cleanup_data,
282 zebra_mlag_private_cleanup_data);
ee235396
SK
283 return 0;
284}
285
d621815a
DL
286FRR_MODULE_SETUP(
287 .name = "zebra_cumulus_mlag",
288 .version = FRR_VERSION,
289 .description = "zebra Cumulus MLAG interface",
290 .init = zebra_mlag_module_init,
291)