Line data Source code
1 : /*
2 : * vrrp.c - vpp vrrp plug-in
3 : *
4 : * Copyright 2019-2020 Rubicon Communications, LLC (Netgate)
5 : *
6 : * SPDX-License-Identifier: Apache-2.0
7 : *
8 : */
9 :
10 : #include <vnet/vnet.h>
11 : #include <vnet/plugin/plugin.h>
12 : #include <vrrp/vrrp.h>
13 :
14 : #include <vlibapi/api.h>
15 : #include <vlibmemory/api.h>
16 : #include <vpp/app/version.h>
17 :
18 : /* define message IDs */
19 : #include <vnet/format_fns.h>
20 : #include <vrrp/vrrp.api_enum.h>
21 : #include <vrrp/vrrp.api_types.h>
22 :
23 : #define REPLY_MSG_ID_BASE vrrp_main.msg_id_base
24 : #include <vlibapi/api_helper_macros.h>
25 :
26 : /* API message handlers */
27 : static void
28 0 : vl_api_vrrp_vr_update_t_handler (vl_api_vrrp_vr_update_t *mp)
29 : {
30 : vl_api_vrrp_vr_update_reply_t *rmp;
31 : vrrp_vr_config_t vr_conf;
32 : u32 api_flags;
33 0 : u32 vrrp_index = INDEX_INVALID;
34 0 : ip46_address_t *addrs = 0;
35 : int rv;
36 :
37 0 : VALIDATE_SW_IF_INDEX (mp);
38 :
39 0 : api_flags = htonl (mp->flags);
40 :
41 0 : clib_memset (&vr_conf, 0, sizeof (vr_conf));
42 :
43 0 : vr_conf.sw_if_index = ntohl (mp->sw_if_index);
44 0 : vr_conf.vr_id = mp->vr_id;
45 0 : vr_conf.priority = mp->priority;
46 0 : vr_conf.adv_interval = ntohs (mp->interval);
47 :
48 0 : if (api_flags & VRRP_API_VR_PREEMPT)
49 0 : vr_conf.flags |= VRRP_VR_PREEMPT;
50 :
51 0 : if (api_flags & VRRP_API_VR_ACCEPT)
52 0 : vr_conf.flags |= VRRP_VR_ACCEPT;
53 :
54 0 : if (api_flags & VRRP_API_VR_UNICAST)
55 0 : vr_conf.flags |= VRRP_VR_UNICAST;
56 :
57 0 : if (api_flags & VRRP_API_VR_IPV6)
58 0 : vr_conf.flags |= VRRP_VR_IPV6;
59 :
60 : int i;
61 0 : for (i = 0; i < mp->n_addrs; i++)
62 : {
63 : ip46_address_t *addr;
64 : void *src, *dst;
65 : int len;
66 :
67 0 : vec_add2 (addrs, addr, 1);
68 :
69 0 : if (ntohl (mp->addrs[i].af) == ADDRESS_IP4)
70 : {
71 0 : src = &mp->addrs[i].un.ip4;
72 0 : dst = &addr->ip4;
73 0 : len = sizeof (addr->ip4);
74 : }
75 : else
76 : {
77 0 : src = &mp->addrs[i].un.ip6;
78 0 : dst = &addr->ip6;
79 0 : len = sizeof (addr->ip6);
80 : }
81 :
82 0 : clib_memcpy (dst, src, len);
83 : }
84 :
85 0 : vr_conf.vr_addrs = addrs;
86 :
87 0 : if (vr_conf.priority == 0)
88 : {
89 0 : clib_warning ("VR priority must be > 0");
90 0 : rv = VNET_API_ERROR_INVALID_VALUE;
91 : }
92 0 : else if (vr_conf.adv_interval == 0)
93 : {
94 0 : clib_warning ("VR advertisement interval must be > 0");
95 0 : rv = VNET_API_ERROR_INVALID_VALUE;
96 : }
97 0 : else if (vr_conf.vr_id == 0)
98 : {
99 0 : clib_warning ("VR ID must be > 0");
100 0 : rv = VNET_API_ERROR_INVALID_VALUE;
101 : }
102 : else
103 : {
104 0 : vrrp_index = ntohl (mp->vrrp_index);
105 0 : rv = vrrp_vr_update (&vrrp_index, &vr_conf);
106 : }
107 :
108 0 : vec_free (addrs);
109 :
110 0 : BAD_SW_IF_INDEX_LABEL;
111 : // clang-format off
112 0 : REPLY_MACRO2 (VL_API_VRRP_VR_UPDATE_REPLY,
113 : ({
114 : rmp->vrrp_index = htonl (vrrp_index);
115 : }));
116 : // clang-format on
117 : }
118 :
119 : static void
120 0 : vl_api_vrrp_vr_del_t_handler (vl_api_vrrp_vr_del_t *mp)
121 : {
122 : vl_api_vrrp_vr_del_reply_t *rmp;
123 : int rv;
124 :
125 0 : rv = vrrp_vr_del (ntohl (mp->vrrp_index));
126 :
127 0 : REPLY_MACRO (VL_API_VRRP_VR_DEL_REPLY);
128 : }
129 :
130 : static void
131 4 : vl_api_vrrp_vr_add_del_t_handler (vl_api_vrrp_vr_add_del_t * mp)
132 : {
133 : vl_api_vrrp_vr_add_del_reply_t *rmp;
134 : vrrp_vr_config_t vr_conf;
135 : u32 api_flags;
136 4 : ip46_address_t *addrs = 0;
137 : int rv;
138 :
139 4 : VALIDATE_SW_IF_INDEX (mp);
140 :
141 4 : api_flags = htonl (mp->flags);
142 :
143 4 : clib_memset (&vr_conf, 0, sizeof (vr_conf));
144 :
145 4 : vr_conf.sw_if_index = ntohl (mp->sw_if_index);
146 4 : vr_conf.vr_id = mp->vr_id;
147 4 : vr_conf.priority = mp->priority;
148 4 : vr_conf.adv_interval = ntohs (mp->interval);
149 :
150 4 : if (api_flags & VRRP_API_VR_PREEMPT)
151 4 : vr_conf.flags |= VRRP_VR_PREEMPT;
152 :
153 4 : if (api_flags & VRRP_API_VR_ACCEPT)
154 0 : vr_conf.flags |= VRRP_VR_ACCEPT;
155 :
156 4 : if (api_flags & VRRP_API_VR_UNICAST)
157 0 : vr_conf.flags |= VRRP_VR_UNICAST;
158 :
159 4 : if (api_flags & VRRP_API_VR_IPV6)
160 2 : vr_conf.flags |= VRRP_VR_IPV6;
161 :
162 4 : if (mp->is_add)
163 : {
164 : int i;
165 :
166 4 : for (i = 0; i < mp->n_addrs; i++)
167 : {
168 : ip46_address_t *addr;
169 : void *src, *dst;
170 : int len;
171 :
172 2 : vec_add2 (addrs, addr, 1);
173 :
174 2 : if (ntohl (mp->addrs[i].af) == ADDRESS_IP4)
175 : {
176 1 : src = &mp->addrs[i].un.ip4;
177 1 : dst = &addr->ip4;
178 1 : len = sizeof (addr->ip4);
179 : }
180 : else
181 : {
182 1 : src = &mp->addrs[i].un.ip6;
183 1 : dst = &addr->ip6;
184 1 : len = sizeof (addr->ip6);
185 : }
186 :
187 2 : clib_memcpy (dst, src, len);
188 : }
189 :
190 2 : vr_conf.vr_addrs = addrs;
191 : }
192 :
193 4 : if (vr_conf.priority == 0)
194 : {
195 0 : clib_warning ("VR priority must be > 0");
196 0 : rv = VNET_API_ERROR_INVALID_VALUE;
197 : }
198 4 : else if (vr_conf.adv_interval == 0)
199 : {
200 0 : clib_warning ("VR advertisement interval must be > 0");
201 0 : rv = VNET_API_ERROR_INVALID_VALUE;
202 : }
203 4 : else if (vr_conf.vr_id == 0)
204 : {
205 0 : clib_warning ("VR ID must be > 0");
206 0 : rv = VNET_API_ERROR_INVALID_VALUE;
207 : }
208 : else
209 4 : rv = vrrp_vr_add_del (mp->is_add, &vr_conf, NULL);
210 :
211 4 : vec_free (addrs);
212 :
213 4 : BAD_SW_IF_INDEX_LABEL;
214 4 : REPLY_MACRO (VL_API_VRRP_VR_ADD_DEL_REPLY);
215 : }
216 :
217 : static vl_api_vrrp_vr_state_t
218 0 : vrrp_vr_state_encode (vrrp_vr_state_t vr_state)
219 : {
220 0 : if (vr_state == VRRP_VR_STATE_BACKUP)
221 0 : return VRRP_API_VR_STATE_BACKUP;
222 0 : if (vr_state == VRRP_VR_STATE_MASTER)
223 0 : return VRRP_API_VR_STATE_MASTER;
224 0 : if (vr_state == VRRP_VR_STATE_INTF_DOWN)
225 0 : return VRRP_API_VR_STATE_INTF_DOWN;
226 :
227 0 : return VRRP_API_VR_STATE_INIT;
228 : }
229 :
230 : static void
231 0 : send_vrrp_vr_details (vrrp_vr_t * vr, vl_api_registration_t * reg,
232 : u32 context)
233 : {
234 0 : vrrp_main_t *vmp = &vrrp_main;
235 : vl_api_vrrp_vr_details_t *mp;
236 : int n_addrs, msg_size;
237 : ip46_address_t *addr;
238 : vl_api_address_t *api_addr;
239 0 : u32 api_flags = 0;
240 :
241 0 : n_addrs = vec_len (vr->config.vr_addrs);
242 0 : msg_size = sizeof (*mp) + n_addrs * sizeof (*api_addr);
243 0 : mp = vl_msg_api_alloc (msg_size);
244 0 : if (!mp)
245 0 : return;
246 0 : clib_memset (mp, 0, msg_size);
247 0 : mp->_vl_msg_id = htons (VL_API_VRRP_VR_DETAILS + vmp->msg_id_base);
248 0 : mp->context = context;
249 :
250 : /* config */
251 0 : mp->config.sw_if_index = htonl (vr->config.sw_if_index);
252 0 : mp->config.vr_id = vr->config.vr_id;
253 0 : mp->config.priority = vr->config.priority;
254 0 : mp->config.interval = htons (vr->config.adv_interval);
255 :
256 0 : if (vr->config.flags & VRRP_VR_PREEMPT)
257 0 : api_flags |= VRRP_API_VR_PREEMPT;
258 0 : if (vr->config.flags & VRRP_VR_ACCEPT)
259 0 : api_flags |= VRRP_API_VR_ACCEPT;
260 0 : if (vrrp_vr_is_unicast (vr))
261 0 : api_flags |= VRRP_API_VR_UNICAST;
262 0 : if (vrrp_vr_is_ipv6 (vr))
263 0 : api_flags |= VRRP_API_VR_IPV6;
264 :
265 0 : mp->config.flags = htonl (api_flags);
266 :
267 : /* runtime */
268 0 : mp->runtime.state = htonl (vrrp_vr_state_encode (vr->runtime.state));
269 :
270 0 : mp->runtime.master_adv_int = htons (vr->runtime.master_adv_int);
271 0 : mp->runtime.skew = htons (vr->runtime.skew);
272 0 : mp->runtime.master_down_int = htons (vr->runtime.master_down_int);
273 0 : clib_memcpy (&mp->runtime.mac, &vr->runtime.mac, sizeof (vr->runtime.mac));
274 :
275 0 : mp->runtime.tracking.interfaces_dec = htonl (vr->tracking.interfaces_dec);
276 0 : mp->runtime.tracking.priority = vrrp_vr_priority (vr);
277 :
278 : /* addrs */
279 0 : mp->n_addrs = vec_len (vr->config.vr_addrs);
280 0 : api_addr = mp->addrs;
281 0 : vec_foreach (addr, vr->config.vr_addrs)
282 : {
283 : void *src, *dst;
284 : size_t len;
285 :
286 0 : if (vrrp_vr_is_ipv6 (vr))
287 : {
288 0 : api_addr->af = ADDRESS_IP6;
289 0 : dst = &api_addr->un.ip6;
290 0 : src = &addr->ip6;
291 0 : len = sizeof (addr->ip6);
292 : }
293 : else
294 : {
295 0 : api_addr->af = ADDRESS_IP4;
296 0 : dst = &api_addr->un.ip4;
297 0 : src = &addr->ip4;
298 0 : len = sizeof (addr->ip4);
299 : }
300 0 : clib_memcpy (dst, src, len);
301 0 : api_addr++;
302 : }
303 :
304 0 : vl_api_send_msg (reg, (u8 *) mp);
305 : }
306 :
307 : static void
308 0 : vl_api_vrrp_vr_dump_t_handler (vl_api_vrrp_vr_dump_t * mp)
309 : {
310 0 : vrrp_main_t *vmp = &vrrp_main;
311 : vl_api_registration_t *reg;
312 : vrrp_vr_t *vr;
313 : u32 sw_if_index;
314 :
315 0 : reg = vl_api_client_index_to_registration (mp->client_index);
316 0 : if (!reg)
317 0 : return;
318 :
319 0 : sw_if_index = htonl (mp->sw_if_index);
320 :
321 : /* *INDENT-OFF* */
322 0 : pool_foreach (vr, vmp->vrs) {
323 :
324 0 : if (sw_if_index && (sw_if_index != ~0) &&
325 0 : (sw_if_index != vr->config.sw_if_index))
326 0 : continue;
327 :
328 0 : send_vrrp_vr_details (vr, reg, mp->context);
329 : }
330 : /* *INDENT-ON* */
331 : }
332 :
333 : static void
334 4 : vl_api_vrrp_vr_start_stop_t_handler (vl_api_vrrp_vr_start_stop_t * mp)
335 : {
336 : vl_api_vrrp_vr_start_stop_reply_t *rmp;
337 : vrrp_vr_key_t vr_key;
338 : int rv;
339 :
340 4 : clib_memset (&vr_key, 0, sizeof (vr_key));
341 :
342 4 : vr_key.sw_if_index = ntohl (mp->sw_if_index);
343 4 : vr_key.vr_id = mp->vr_id;
344 4 : vr_key.is_ipv6 = (mp->is_ipv6 != 0);
345 :
346 4 : rv = vrrp_vr_start_stop ((mp->is_start != 0), &vr_key);
347 :
348 4 : REPLY_MACRO (VL_API_VRRP_VR_START_STOP_REPLY);
349 : }
350 :
351 : static void
352 0 : vl_api_vrrp_vr_set_peers_t_handler (vl_api_vrrp_vr_set_peers_t * mp)
353 : {
354 : vl_api_vrrp_vr_set_peers_reply_t *rmp;
355 : vrrp_vr_key_t vr_key;
356 0 : ip46_address_t *peer_addrs = 0;
357 : int i;
358 : int rv;
359 :
360 0 : clib_memset (&vr_key, 0, sizeof (vr_key));
361 :
362 0 : vr_key.sw_if_index = ntohl (mp->sw_if_index);
363 0 : vr_key.vr_id = mp->vr_id;
364 0 : vr_key.is_ipv6 = (mp->is_ipv6 != 0);
365 :
366 0 : for (i = 0; i < mp->n_addrs; i++)
367 : {
368 : ip46_address_t *peer;
369 :
370 0 : vec_add2 (peer_addrs, peer, 1);
371 :
372 0 : if (mp->is_ipv6)
373 0 : clib_memcpy (&peer->ip6, mp->addrs[i].un.ip6, 16);
374 : else
375 0 : clib_memcpy (&peer->ip4, mp->addrs[i].un.ip4, 4);
376 : }
377 :
378 0 : rv = vrrp_vr_set_peers (&vr_key, peer_addrs);
379 :
380 0 : vec_free (peer_addrs);
381 0 : REPLY_MACRO (VL_API_VRRP_VR_SET_PEERS_REPLY);
382 : }
383 :
384 : static void
385 0 : send_vrrp_vr_peer_details (vrrp_vr_t * vr, vl_api_registration_t * reg,
386 : u32 context)
387 : {
388 0 : vrrp_main_t *vmp = &vrrp_main;
389 : vl_api_vrrp_vr_peer_details_t *mp;
390 : int n_addrs, msg_size;
391 : ip46_address_t *addr;
392 : vl_api_address_t *api_addr;
393 :
394 0 : n_addrs = vec_len (vr->config.peer_addrs);
395 0 : msg_size = sizeof (*mp) + n_addrs * sizeof (*api_addr);
396 0 : mp = vl_msg_api_alloc (msg_size);
397 0 : if (!mp)
398 0 : return;
399 0 : clib_memset (mp, 0, msg_size);
400 0 : mp->_vl_msg_id = htons (VL_API_VRRP_VR_PEER_DETAILS + vmp->msg_id_base);
401 0 : mp->context = context;
402 :
403 0 : mp->sw_if_index = htonl (vr->config.sw_if_index);
404 0 : mp->vr_id = vr->config.vr_id;
405 0 : mp->is_ipv6 = vrrp_vr_is_ipv6 (vr);
406 :
407 : /* addrs */
408 0 : mp->n_peer_addrs = n_addrs;
409 0 : api_addr = mp->peer_addrs;
410 0 : vec_foreach (addr, vr->config.peer_addrs)
411 : {
412 : void *src, *dst;
413 : size_t len;
414 :
415 0 : if (vrrp_vr_is_ipv6 (vr))
416 : {
417 0 : api_addr->af = ADDRESS_IP6;
418 0 : dst = &api_addr->un.ip6;
419 0 : src = &addr->ip6;
420 0 : len = sizeof (addr->ip6);
421 : }
422 : else
423 : {
424 0 : api_addr->af = ADDRESS_IP4;
425 0 : dst = &api_addr->un.ip4;
426 0 : src = &addr->ip4;
427 0 : len = sizeof (addr->ip4);
428 : }
429 0 : clib_memcpy (dst, src, len);
430 0 : api_addr++;
431 : }
432 :
433 0 : vl_api_send_msg (reg, (u8 *) mp);
434 : }
435 :
436 : static void
437 0 : vl_api_vrrp_vr_peer_dump_t_handler (vl_api_vrrp_vr_peer_dump_t * mp)
438 : {
439 0 : vrrp_main_t *vmp = &vrrp_main;
440 : vl_api_registration_t *reg;
441 : vrrp_vr_t *vr;
442 : vrrp_vr_key_t vr_key;
443 :
444 0 : reg = vl_api_client_index_to_registration (mp->client_index);
445 0 : if (!reg)
446 0 : return;
447 :
448 0 : vr_key.sw_if_index = ntohl (mp->sw_if_index);
449 :
450 0 : if (vr_key.sw_if_index && (vr_key.sw_if_index != ~0))
451 : {
452 : uword *p;
453 0 : u32 vr_index = ~0;
454 :
455 0 : vr_key.vr_id = mp->vr_id;
456 0 : vr_key.is_ipv6 = mp->is_ipv6;
457 :
458 0 : p = mhash_get (&vmp->vr_index_by_key, &vr_key);
459 0 : if (!p)
460 0 : return;
461 :
462 0 : vr_index = p[0];
463 0 : vr = pool_elt_at_index (vmp->vrs, vr_index);
464 0 : send_vrrp_vr_peer_details (vr, reg, mp->context);
465 :
466 0 : return;
467 : }
468 :
469 : /* *INDENT-OFF* */
470 0 : pool_foreach (vr, vmp->vrs) {
471 :
472 0 : if (!vec_len (vr->config.peer_addrs))
473 0 : continue;
474 :
475 0 : send_vrrp_vr_details (vr, reg, mp->context);
476 :
477 : }
478 : /* *INDENT-ON* */
479 : }
480 :
481 : static void
482 0 : vl_api_vrrp_vr_track_if_add_del_t_handler
483 : (vl_api_vrrp_vr_track_if_add_del_t * mp)
484 : {
485 : vl_api_vrrp_vr_track_if_add_del_reply_t *rmp;
486 : vrrp_vr_t *vr;
487 0 : vrrp_vr_tracking_if_t *track_if, *track_ifs = 0;
488 0 : int rv = 0, i;
489 :
490 : /* lookup VR and return error if it does not exist */
491 : vr =
492 0 : vrrp_vr_lookup (ntohl (mp->sw_if_index), mp->vr_id, (mp->is_ipv6 != 0));
493 0 : if (!vr)
494 : {
495 0 : rv = VNET_API_ERROR_INVALID_VALUE;
496 0 : goto done;
497 : }
498 :
499 0 : for (i = 0; i < mp->n_ifs; i++)
500 : {
501 0 : vl_api_vrrp_vr_track_if_t *api_track_if = &mp->ifs[i];
502 :
503 0 : vec_add2 (track_ifs, track_if, 1);
504 0 : track_if->sw_if_index = ntohl (api_track_if->sw_if_index);
505 0 : track_if->priority = api_track_if->priority;
506 : }
507 :
508 0 : rv = vrrp_vr_tracking_ifs_add_del (vr, track_ifs, mp->is_add != 0);
509 :
510 0 : done:
511 0 : vec_free (track_ifs);
512 0 : REPLY_MACRO (VL_API_VRRP_VR_TRACK_IF_ADD_DEL_REPLY);
513 : }
514 :
515 : static void
516 0 : send_vrrp_vr_track_if_details (vrrp_vr_t * vr, vl_api_registration_t * reg,
517 : u32 context)
518 : {
519 0 : vrrp_main_t *vmp = &vrrp_main;
520 : vl_api_vrrp_vr_track_if_details_t *mp;
521 : int n_ifs, msg_size;
522 : vl_api_vrrp_vr_track_if_t *api_track_if;
523 : vrrp_vr_tracking_if_t *track_if;
524 :
525 0 : if (!vr)
526 0 : return;
527 :
528 0 : n_ifs = vec_len (vr->tracking.interfaces);
529 0 : msg_size = sizeof (*mp) + n_ifs * sizeof (*api_track_if);
530 0 : mp = vl_msg_api_alloc (msg_size);
531 0 : if (!mp)
532 0 : return;
533 0 : clib_memset (mp, 0, msg_size);
534 0 : mp->_vl_msg_id = htons (VL_API_VRRP_VR_TRACK_IF_DETAILS + vmp->msg_id_base);
535 0 : mp->context = context;
536 :
537 0 : mp->sw_if_index = htonl (vr->config.sw_if_index);
538 0 : mp->vr_id = vr->config.vr_id;
539 0 : mp->is_ipv6 = vrrp_vr_is_ipv6 (vr);
540 :
541 : /* tracked interfaces */
542 0 : mp->n_ifs = n_ifs;
543 0 : api_track_if = mp->ifs;
544 0 : vec_foreach (track_if, vr->tracking.interfaces)
545 : {
546 0 : api_track_if->sw_if_index = htonl (track_if->sw_if_index);
547 0 : api_track_if->priority = track_if->priority;
548 0 : api_track_if += 1;
549 : }
550 :
551 0 : vl_api_send_msg (reg, (u8 *) mp);
552 : }
553 :
554 : static void
555 0 : vl_api_vrrp_vr_track_if_dump_t_handler (vl_api_vrrp_vr_track_if_dump_t * mp)
556 : {
557 0 : vrrp_main_t *vmp = &vrrp_main;
558 : vl_api_registration_t *reg;
559 : vrrp_vr_t *vr;
560 :
561 0 : reg = vl_api_client_index_to_registration (mp->client_index);
562 0 : if (!reg)
563 0 : return;
564 :
565 0 : if (!mp->dump_all)
566 : {
567 0 : vr = vrrp_vr_lookup (ntohl (mp->sw_if_index), mp->vr_id, mp->is_ipv6);
568 0 : send_vrrp_vr_track_if_details (vr, reg, mp->context);
569 :
570 0 : return;
571 : }
572 :
573 : /* *INDENT-OFF* */
574 0 : pool_foreach (vr, vmp->vrs) {
575 :
576 0 : if (!vec_len (vr->tracking.interfaces))
577 0 : continue;
578 :
579 0 : send_vrrp_vr_track_if_details (vr, reg, mp->context);
580 :
581 : }
582 : /* *INDENT-ON* */
583 : }
584 :
585 : static void
586 0 : send_vrrp_vr_event (vpe_client_registration_t * reg,
587 : vl_api_registration_t * vl_reg,
588 : vrrp_vr_t * vr, vrrp_vr_state_t new_state)
589 : {
590 0 : vrrp_main_t *vmp = &vrrp_main;
591 : vl_api_vrrp_vr_event_t *mp;
592 :
593 0 : mp = vl_msg_api_alloc (sizeof (*mp));
594 :
595 0 : clib_memset (mp, 0, sizeof (*mp));
596 0 : mp->_vl_msg_id = ntohs (VL_API_VRRP_VR_EVENT + vmp->msg_id_base);
597 0 : mp->client_index = reg->client_index;
598 0 : mp->pid = reg->client_pid;
599 0 : mp->vr.sw_if_index = ntohl (vr->config.sw_if_index);
600 0 : mp->vr.vr_id = vr->config.vr_id;
601 0 : mp->vr.is_ipv6 = ((vr->config.flags & VRRP_VR_IPV6) != 0);
602 :
603 0 : mp->old_state = htonl (vrrp_vr_state_encode (vr->runtime.state));
604 0 : mp->new_state = htonl (vrrp_vr_state_encode (new_state));
605 :
606 0 : vl_api_send_msg (vl_reg, (u8 *) mp);
607 0 : }
608 :
609 : void
610 4 : vrrp_vr_event (vrrp_vr_t * vr, vrrp_vr_state_t new_state)
611 : {
612 4 : vpe_api_main_t *vam = &vpe_api_main;
613 : vpe_client_registration_t *reg;
614 : vl_api_registration_t *vl_reg;
615 :
616 : /* *INDENT-OFF* */
617 4 : pool_foreach (reg, vam->vrrp_vr_events_registrations)
618 : {
619 0 : vl_reg = vl_api_client_index_to_registration (reg->client_index);
620 0 : if (vl_reg)
621 0 : send_vrrp_vr_event (reg, vl_reg, vr, new_state);
622 : }
623 : /* *INDENT-ON* */
624 4 : }
625 :
626 1766 : pub_sub_handler (vrrp_vr_events, VRRP_VR_EVENTS);
627 :
628 : /* Set up the API message handling tables */
629 : #include <vrrp/vrrp.api.c>
630 : clib_error_t *
631 559 : vrrp_plugin_api_hookup (vlib_main_t * vm)
632 : {
633 559 : vrrp_main_t *vmp = &vrrp_main;
634 :
635 : /* Ask for a correctly-sized block of API message decode slots */
636 559 : vmp->msg_id_base = setup_message_id_table ();
637 :
638 559 : return 0;
639 : }
640 :
641 : /* *INDENT-ON* */
642 :
643 : /*
644 : * fd.io coding-style-patch-verification: ON
645 : *
646 : * Local Variables:
647 : * eval: (c-set-style "gnu")
648 : * End:
649 : */
|