Line data Source code
1 : /*
2 : * vrrp.c - VRRP vpp-api-test plug-in
3 : *
4 : * Copyright 2019-2020 Rubicon Communications, LLC (Netgate)
5 : *
6 : * SPDX-License-Identifier: Apache-2.0
7 : *
8 : */
9 : #include <vat/vat.h>
10 : #include <vlibapi/api.h>
11 : #include <vlibmemory/api.h>
12 : #include <vppinfra/error.h>
13 :
14 : #include <vnet/ip/ip.h>
15 :
16 : uword unformat_sw_if_index (unformat_input_t * input, va_list * args);
17 :
18 : /* Declare message IDs */
19 : #include <vnet/format_fns.h>
20 : #include <vrrp/vrrp.api_enum.h>
21 : #include <vrrp/vrrp.api_types.h>
22 : #include <vlibmemory/vlib.api_types.h>
23 :
24 : typedef struct
25 : {
26 : /* API message ID base */
27 : u16 msg_id_base;
28 : u32 ping_id;
29 : vat_main_t *vat_main;
30 : } vrrp_test_main_t;
31 :
32 : vrrp_test_main_t vrrp_test_main;
33 :
34 : #define __plugin_msg_base vrrp_test_main.msg_id_base
35 : #include <vlibapi/vat_helper_macros.h>
36 :
37 : static int
38 0 : api_vrrp_vr_update (vat_main_t *vam)
39 : {
40 0 : unformat_input_t *i = vam->input;
41 0 : u32 sw_if_index = ~0;
42 : u32 vr_id, priority, interval, vrrp_index;
43 : u8 is_ipv6, no_preempt, accept_mode, vr_unicast;
44 : u8 n_addrs4, n_addrs6;
45 : vl_api_vrrp_vr_update_t *mp;
46 : vl_api_address_t *api_addr;
47 0 : ip46_address_t *ip_addr, *ip_addrs = 0;
48 : ip46_address_t addr;
49 0 : int ret = 0;
50 :
51 0 : interval = priority = 100;
52 0 : n_addrs4 = n_addrs6 = 0;
53 0 : vr_id = is_ipv6 = no_preempt = accept_mode = vr_unicast = 0;
54 0 : vrrp_index = INDEX_INVALID;
55 :
56 0 : clib_memset (&addr, 0, sizeof (addr));
57 :
58 : /* Parse args required to build the message */
59 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
60 : {
61 0 : if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
62 : ;
63 0 : else if (unformat (i, "sw_if_index %u", &sw_if_index))
64 : ;
65 0 : else if (unformat (i, "vr_id %u", &vr_id))
66 : ;
67 0 : else if (unformat (i, "vrrp_index %u", &vrrp_index))
68 : ;
69 0 : else if (unformat (i, "ipv6"))
70 0 : is_ipv6 = 1;
71 0 : else if (unformat (i, "priority %u", &priority))
72 : ;
73 0 : else if (unformat (i, "interval %u", &interval))
74 : ;
75 0 : else if (unformat (i, "no_preempt"))
76 0 : no_preempt = 1;
77 0 : else if (unformat (i, "accept_mode"))
78 0 : accept_mode = 1;
79 0 : else if (unformat (i, "unicast"))
80 0 : vr_unicast = 1;
81 0 : else if (unformat (i, "%U", unformat_ip4_address, &addr.ip4))
82 : {
83 0 : vec_add1 (ip_addrs, addr);
84 0 : n_addrs4++;
85 0 : clib_memset (&addr, 0, sizeof (addr));
86 : }
87 0 : else if (unformat (i, "%U", unformat_ip6_address, &addr.ip6))
88 : {
89 0 : vec_add1 (ip_addrs, addr);
90 0 : n_addrs6++;
91 0 : clib_memset (&addr, 0, sizeof (addr));
92 : }
93 : else
94 0 : break;
95 : }
96 :
97 0 : if (sw_if_index == ~0)
98 : {
99 0 : errmsg ("Interface not set\n");
100 0 : ret = -99;
101 : }
102 0 : else if (n_addrs4 && (n_addrs6 || is_ipv6))
103 : {
104 0 : errmsg ("Address family mismatch\n");
105 0 : ret = -99;
106 : }
107 :
108 0 : if (ret)
109 0 : goto done;
110 :
111 : /* Construct the API message */
112 0 : M2 (VRRP_VR_UPDATE, mp, vec_len (ip_addrs) * sizeof (*api_addr));
113 :
114 0 : mp->vrrp_index = htonl (vrrp_index);
115 0 : mp->sw_if_index = ntohl (sw_if_index);
116 0 : mp->vr_id = vr_id;
117 0 : mp->priority = priority;
118 0 : mp->interval = htons (interval);
119 0 : mp->flags = VRRP_API_VR_PREEMPT; /* preempt by default */
120 :
121 0 : if (no_preempt)
122 0 : mp->flags &= ~VRRP_API_VR_PREEMPT;
123 :
124 0 : if (accept_mode)
125 0 : mp->flags |= VRRP_API_VR_ACCEPT;
126 :
127 0 : if (vr_unicast)
128 0 : mp->flags |= VRRP_API_VR_UNICAST;
129 :
130 0 : if (is_ipv6)
131 0 : mp->flags |= VRRP_API_VR_IPV6;
132 :
133 0 : mp->flags = htonl (mp->flags);
134 :
135 0 : mp->n_addrs = n_addrs4 + n_addrs6;
136 0 : api_addr = mp->addrs;
137 :
138 0 : vec_foreach (ip_addr, ip_addrs)
139 : {
140 : void *src, *dst;
141 : int len;
142 :
143 0 : if (is_ipv6)
144 : {
145 0 : api_addr->af = ADDRESS_IP6;
146 0 : src = &ip_addr->ip6;
147 0 : dst = &api_addr->un.ip6;
148 0 : len = sizeof (api_addr->un.ip6);
149 : }
150 : else
151 : {
152 0 : api_addr->af = ADDRESS_IP4;
153 0 : src = &ip_addr->ip4;
154 0 : dst = &api_addr->un.ip4;
155 0 : len = sizeof (api_addr->un.ip4);
156 : }
157 0 : clib_memcpy (dst, src, len);
158 0 : api_addr++;
159 : }
160 :
161 : /* send it... */
162 0 : S (mp);
163 :
164 : /* Wait for a reply... */
165 0 : W (ret);
166 :
167 0 : done:
168 0 : vec_free (ip_addrs);
169 :
170 0 : return ret;
171 : }
172 :
173 : static void
174 0 : vl_api_vrrp_vr_update_reply_t_handler (vl_api_vrrp_vr_update_reply_t *mp)
175 : {
176 0 : }
177 :
178 : static int
179 0 : api_vrrp_vr_del (vat_main_t *vam)
180 : {
181 0 : unformat_input_t *i = vam->input;
182 : vl_api_vrrp_vr_del_t *mp;
183 0 : u32 vrrp_index = INDEX_INVALID;
184 : int ret;
185 :
186 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
187 : {
188 0 : if (unformat (i, "vrrp_index %u", &vrrp_index))
189 : ;
190 : else
191 0 : break;
192 : }
193 :
194 : /* Construct the API message */
195 0 : M (VRRP_VR_DEL, mp);
196 0 : mp->vrrp_index = htonl (vrrp_index);
197 :
198 : /* send it... */
199 0 : S (mp);
200 :
201 : /* Wait for a reply... */
202 0 : W (ret);
203 :
204 0 : return ret;
205 : }
206 :
207 : static int
208 0 : api_vrrp_vr_add_del (vat_main_t * vam)
209 : {
210 0 : unformat_input_t *i = vam->input;
211 0 : u32 sw_if_index = ~0;
212 : u32 vr_id, priority, interval;
213 : u8 is_ipv6, no_preempt, accept_mode, vr_unicast, is_add, is_del;
214 : u8 n_addrs4, n_addrs6;
215 : vl_api_vrrp_vr_add_del_t *mp;
216 : vl_api_address_t *api_addr;
217 0 : ip46_address_t *ip_addr, *ip_addrs = 0;
218 : ip46_address_t addr;
219 0 : int ret = 0;
220 :
221 0 : interval = priority = 100;
222 0 : n_addrs4 = n_addrs6 = 0;
223 0 : vr_id = is_ipv6 = no_preempt = accept_mode = vr_unicast = 0;
224 0 : is_add = is_del = 0;
225 :
226 0 : clib_memset (&addr, 0, sizeof (addr));
227 :
228 : /* Parse args required to build the message */
229 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
230 : {
231 0 : if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
232 : ;
233 0 : else if (unformat (i, "sw_if_index %u", &sw_if_index))
234 : ;
235 0 : else if (unformat (i, "vr_id %u", &vr_id))
236 : ;
237 0 : else if (unformat (i, "ipv6"))
238 0 : is_ipv6 = 1;
239 0 : else if (unformat (i, "priority %u", &priority))
240 : ;
241 0 : else if (unformat (i, "interval %u", &interval))
242 : ;
243 0 : else if (unformat (i, "no_preempt"))
244 0 : no_preempt = 1;
245 0 : else if (unformat (i, "accept_mode"))
246 0 : accept_mode = 1;
247 0 : else if (unformat (i, "unicast"))
248 0 : vr_unicast = 1;
249 0 : else if (unformat (i, "%U", unformat_ip4_address, &addr.ip4))
250 : {
251 0 : vec_add1 (ip_addrs, addr);
252 0 : n_addrs4++;
253 0 : clib_memset (&addr, 0, sizeof (addr));
254 : }
255 0 : else if (unformat (i, "%U", unformat_ip6_address, &addr.ip6))
256 : {
257 0 : vec_add1 (ip_addrs, addr);
258 0 : n_addrs6++;
259 0 : clib_memset (&addr, 0, sizeof (addr));
260 : }
261 0 : else if (unformat (i, "add"))
262 0 : is_add = 1;
263 0 : else if (unformat (i, "del"))
264 0 : is_del = 1;
265 : else
266 0 : break;
267 : }
268 :
269 0 : if (is_add == is_del)
270 : {
271 0 : errmsg ("One of add or del must be specified\n");
272 0 : ret = -99;
273 : }
274 0 : else if (sw_if_index == ~0)
275 : {
276 0 : errmsg ("Interface not set\n");
277 0 : ret = -99;
278 : }
279 0 : else if (n_addrs4 && (n_addrs6 || is_ipv6))
280 : {
281 0 : errmsg ("Address family mismatch\n");
282 0 : ret = -99;
283 : }
284 :
285 0 : if (ret)
286 0 : goto done;
287 :
288 : /* Construct the API message */
289 0 : M2 (VRRP_VR_ADD_DEL, mp, vec_len (ip_addrs) * sizeof (*api_addr));
290 :
291 0 : mp->is_add = is_add;
292 0 : mp->sw_if_index = ntohl (sw_if_index);
293 0 : mp->vr_id = vr_id;
294 0 : mp->priority = priority;
295 0 : mp->interval = htons (interval);
296 0 : mp->flags = VRRP_API_VR_PREEMPT; /* preempt by default */
297 :
298 0 : if (no_preempt)
299 0 : mp->flags &= ~VRRP_API_VR_PREEMPT;
300 :
301 0 : if (accept_mode)
302 0 : mp->flags |= VRRP_API_VR_ACCEPT;
303 :
304 0 : if (vr_unicast)
305 0 : mp->flags |= VRRP_API_VR_UNICAST;
306 :
307 0 : if (is_ipv6)
308 0 : mp->flags |= VRRP_API_VR_IPV6;
309 :
310 0 : mp->flags = htonl (mp->flags);
311 :
312 0 : mp->n_addrs = n_addrs4 + n_addrs6;
313 0 : api_addr = mp->addrs;
314 :
315 0 : vec_foreach (ip_addr, ip_addrs)
316 : {
317 : void *src, *dst;
318 : int len;
319 :
320 0 : if (is_ipv6)
321 : {
322 0 : api_addr->af = ADDRESS_IP6;
323 0 : src = &ip_addr->ip6;
324 0 : dst = &api_addr->un.ip6;
325 0 : len = sizeof (api_addr->un.ip6);
326 : }
327 : else
328 : {
329 0 : api_addr->af = ADDRESS_IP4;
330 0 : src = &ip_addr->ip4;
331 0 : dst = &api_addr->un.ip4;
332 0 : len = sizeof (api_addr->un.ip4);
333 : }
334 0 : clib_memcpy (dst, src, len);
335 0 : api_addr++;
336 : }
337 :
338 : /* send it... */
339 0 : S (mp);
340 :
341 : /* Wait for a reply... */
342 0 : W (ret);
343 :
344 0 : done:
345 0 : vec_free (ip_addrs);
346 :
347 0 : return ret;
348 : }
349 :
350 : static int
351 0 : api_vrrp_vr_dump (vat_main_t * vam)
352 : {
353 0 : vrrp_test_main_t *vtm = &vrrp_test_main;
354 0 : unformat_input_t *i = vam->input;
355 : vl_api_vrrp_vr_dump_t *mp;
356 : vl_api_control_ping_t *mp_ping;
357 0 : u32 sw_if_index = ~0;
358 : int ret;
359 :
360 0 : if (vam->json_output)
361 : {
362 0 : clib_warning ("JSON output not supported for vrrp_vr_dump");
363 0 : return -99;
364 : }
365 :
366 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
367 : {
368 0 : if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
369 : ;
370 0 : else if (unformat (i, "sw_if_index %u", &sw_if_index))
371 : ;
372 : else
373 0 : break;
374 : }
375 :
376 0 : M (VRRP_VR_DUMP, mp);
377 :
378 0 : mp->sw_if_index = htonl (sw_if_index);
379 :
380 0 : S (mp);
381 :
382 0 : mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping));
383 0 : mp_ping->_vl_msg_id = htons (vtm->ping_id);
384 0 : mp_ping->client_index = vam->my_client_index;
385 :
386 0 : vam->result_ready = 0;
387 0 : S (mp_ping);
388 :
389 0 : W (ret);
390 0 : return ret;
391 : }
392 :
393 : static void
394 0 : vl_api_vrrp_vr_details_t_handler (vl_api_vrrp_vr_details_t * mp)
395 : {
396 0 : vat_main_t *vam = vrrp_test_main.vat_main;
397 0 : u32 api_flags = ntohl (mp->config.flags);
398 : int i;
399 : u32 state;
400 0 : char *states[] = {
401 : "VRRP_API_VR_STATE_INIT",
402 : "VRRP_API_VR_STATE_BACKUP",
403 : "VRRP_API_VR_STATE_MASTER",
404 : "BAD STATE!",
405 : };
406 :
407 0 : state = ntohl (mp->runtime.state);
408 :
409 0 : if (state > ARRAY_LEN (states) - 2)
410 0 : state = ARRAY_LEN (states) - 1;
411 :
412 0 : fformat (vam->ofp, "sw_if_index %u vr_id %u IPv%d: "
413 : "priority %u interval %u preempt %s accept %s unicast %s "
414 : "state %s master_adv_interval %u skew %u master_down_interval %u "
415 : "mac %U ",
416 0 : ntohl (mp->config.sw_if_index), mp->config.vr_id,
417 0 : (mp->config.flags & VRRP_API_VR_IPV6) ? 6 : 4,
418 0 : mp->config.priority, htons (mp->config.interval),
419 0 : (api_flags & VRRP_API_VR_PREEMPT) ? "yes" : "no",
420 0 : (api_flags & VRRP_API_VR_ACCEPT) ? "yes" : "no",
421 0 : (api_flags & VRRP_API_VR_UNICAST) ? "yes" : "no",
422 : states[state],
423 0 : ntohs (mp->runtime.master_adv_int), ntohs (mp->runtime.skew),
424 0 : ntohs (mp->runtime.master_down_int),
425 : format_ethernet_address, &mp->runtime.mac);
426 :
427 0 : fformat (vam->ofp, "addresses: ");
428 :
429 0 : for (i = 0; i < mp->n_addrs; i++)
430 : {
431 0 : vl_api_address_t *addr = mp->addrs + i;
432 :
433 0 : fformat (vam->ofp, "%U ",
434 0 : (addr->af) ? format_ip6_address : format_ip4_address,
435 0 : (u8 *) & addr->un);
436 : }
437 :
438 0 : fformat (vam->ofp, "\n");
439 0 : }
440 :
441 : static int
442 0 : api_vrrp_vr_start_stop (vat_main_t * vam)
443 : {
444 0 : unformat_input_t *i = vam->input;
445 : vl_api_vrrp_vr_start_stop_t *mp;
446 0 : u32 sw_if_index = ~0, vr_id;
447 : u8 is_ipv6, is_start, is_stop;
448 : int ret;
449 :
450 0 : vr_id = is_ipv6 = is_start = is_stop = 0;
451 :
452 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
453 : {
454 0 : if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
455 : ;
456 0 : else if (unformat (i, "sw_if_index %u", &sw_if_index))
457 : ;
458 0 : else if (unformat (i, "vr_id %u", &vr_id))
459 : ;
460 0 : else if (unformat (i, "ipv6"))
461 0 : is_ipv6 = 1;
462 0 : else if (unformat (i, "start"))
463 0 : is_start = 1;
464 0 : else if (unformat (i, "stop"))
465 0 : is_stop = 1;
466 : else
467 0 : break;
468 : }
469 :
470 0 : if (is_start == is_stop)
471 : {
472 0 : errmsg ("One of add or del must be specified\n");
473 0 : return -99;
474 : }
475 0 : else if (sw_if_index == ~0)
476 : {
477 0 : errmsg ("Interface not set\n");
478 0 : return -99;
479 : }
480 0 : else if (!vr_id)
481 : {
482 0 : errmsg ("VR ID must be between 1 and 255");
483 0 : return -99;
484 : }
485 :
486 0 : M (VRRP_VR_START_STOP, mp);
487 :
488 0 : mp->sw_if_index = htonl (sw_if_index);
489 0 : mp->vr_id = vr_id;
490 0 : mp->is_ipv6 = (is_ipv6 != 0);
491 0 : mp->is_start = (is_start != 0);
492 :
493 0 : S (mp);
494 :
495 0 : W (ret);
496 0 : return ret;
497 : }
498 :
499 : static int
500 0 : api_vrrp_vr_track_if_add_del (vat_main_t * vam)
501 : {
502 0 : unformat_input_t *i = vam->input;
503 : vl_api_vrrp_vr_track_if_add_del_t *mp;
504 0 : vl_api_vrrp_vr_track_if_t *track_ifs = 0, *track_if;
505 0 : u32 sw_if_index = ~0, track_sw_if_index = ~0, vr_id, priority;
506 : u8 is_ipv6, is_add, is_del;
507 : int ret;
508 :
509 0 : is_ipv6 = is_add = is_del = 0;
510 0 : vr_id = priority = 0;
511 :
512 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
513 : {
514 0 : if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
515 : ;
516 0 : else if (unformat (i, "sw_if_index %u", &sw_if_index))
517 : ;
518 0 : else if (unformat (i, "vr_id %u", &vr_id))
519 : ;
520 0 : else if (unformat (i, "ipv6"))
521 0 : is_ipv6 = 1;
522 0 : else if (unformat (i, "track-index %u priority %u", &track_sw_if_index,
523 : &priority))
524 : {
525 0 : vec_add2 (track_ifs, track_if, 1);
526 0 : track_if->sw_if_index = ntohl (track_sw_if_index);
527 0 : track_if->priority = priority;
528 : }
529 0 : else if (unformat (i, "add"))
530 0 : is_add = 1;
531 0 : else if (unformat (i, "del"))
532 0 : is_del = 1;
533 : else
534 0 : break;
535 : }
536 :
537 0 : if (is_add == is_del)
538 : {
539 0 : errmsg ("One of add or del must be specified\n");
540 0 : ret = -99;
541 : }
542 0 : else if (sw_if_index == ~0)
543 : {
544 0 : errmsg ("VR interface not specified\n");
545 0 : return -99;
546 : }
547 0 : else if (!vr_id)
548 : {
549 0 : errmsg ("Invalid VR ID - must be between 1 and 255");
550 0 : return -99;
551 : }
552 0 : else if (vec_len (track_ifs) == 0)
553 : {
554 0 : errmsg ("No tracked interfaces specified for VR\n");
555 0 : return -99;
556 : }
557 :
558 0 : vec_foreach (track_if, track_ifs)
559 : {
560 0 : if (!track_if->priority)
561 : {
562 0 : errmsg ("Priority must be nonzero");
563 0 : vec_free (track_ifs);
564 0 : return -99;
565 : }
566 : }
567 :
568 :
569 0 : M2 (VRRP_VR_TRACK_IF_ADD_DEL, mp, vec_len (track_ifs) * sizeof (*track_if));
570 :
571 0 : mp->sw_if_index = htonl (sw_if_index);
572 0 : mp->vr_id = vr_id;
573 0 : mp->is_ipv6 = (is_ipv6 != 0);
574 0 : mp->is_add = is_add;
575 0 : mp->n_ifs = vec_len (track_ifs);
576 0 : clib_memcpy (mp->ifs, track_ifs, mp->n_ifs * sizeof (*track_if));
577 :
578 0 : S (mp);
579 :
580 0 : W (ret);
581 0 : return ret;
582 : }
583 :
584 : static int
585 0 : api_vrrp_vr_track_if_dump (vat_main_t * vam)
586 : {
587 0 : vrrp_test_main_t *vtm = &vrrp_test_main;
588 0 : unformat_input_t *i = vam->input;
589 : vl_api_vrrp_vr_track_if_dump_t *mp;
590 : vl_api_control_ping_t *mp_ping;
591 0 : u32 sw_if_index = ~0, vr_id = 0;
592 0 : u8 is_ipv6 = 0, dump_all = 0;
593 : int ret;
594 :
595 0 : if (vam->json_output)
596 : {
597 0 : clib_warning ("JSON output not supported for vrrp_vr_track_if_dump");
598 0 : return -99;
599 : }
600 :
601 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
602 : {
603 0 : if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
604 : ;
605 0 : else if (unformat (i, "sw_if_index %u", &sw_if_index))
606 : ;
607 0 : else if (unformat (i, "vr_id %u", &vr_id))
608 : ;
609 0 : else if (unformat (i, "ipv6"))
610 0 : is_ipv6 = 1;
611 : else
612 0 : break;
613 : }
614 :
615 : /* If no arguments were provided, dump all VRs */
616 0 : if ((sw_if_index == ~0) && !vr_id && !is_ipv6)
617 0 : dump_all = 1;
618 :
619 : /* If any arguments provided, sw_if_index and vr_id must be valid */
620 0 : else if (sw_if_index == ~0)
621 : {
622 0 : errmsg ("VR interface not specified\n");
623 0 : return -99;
624 : }
625 0 : else if (!vr_id)
626 : {
627 0 : errmsg ("Invalid VR ID - must be between 1 and 255");
628 0 : return -99;
629 : }
630 :
631 0 : M (VRRP_VR_TRACK_IF_DUMP, mp);
632 :
633 0 : mp->dump_all = dump_all;
634 0 : if (!dump_all)
635 : {
636 0 : mp->sw_if_index = htonl (sw_if_index);
637 0 : mp->vr_id = vr_id;
638 0 : mp->is_ipv6 = is_ipv6;
639 : }
640 :
641 0 : S (mp);
642 :
643 0 : mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping));
644 0 : mp_ping->_vl_msg_id = htons (vtm->ping_id);
645 0 : mp_ping->client_index = vam->my_client_index;
646 :
647 0 : vam->result_ready = 0;
648 0 : S (mp_ping);
649 :
650 0 : W (ret);
651 0 : return ret;
652 : }
653 :
654 : static void
655 0 : vl_api_vrrp_vr_track_if_details_t_handler
656 : (vl_api_vrrp_vr_track_if_details_t * mp)
657 : {
658 0 : vat_main_t *vam = vrrp_test_main.vat_main;
659 : int i;
660 :
661 0 : for (i = 0; i < mp->n_ifs; i++)
662 : {
663 0 : fformat (vam->ofp, "VR sw_if_index %u vr_id %u IPv%d - "
664 : "track sw_if_index %u priority %u\n",
665 0 : ntohl (mp->sw_if_index), mp->vr_id, (mp->is_ipv6) ? 6 : 4,
666 0 : ntohl (mp->ifs[i].sw_if_index), mp->ifs[i].priority);
667 : }
668 :
669 0 : fformat (vam->ofp, "\n");
670 0 : }
671 :
672 : static int
673 0 : api_vrrp_vr_set_peers (vat_main_t * vam)
674 : {
675 0 : unformat_input_t *i = vam->input;
676 0 : u32 sw_if_index = ~0;
677 : u32 vr_id;
678 : u8 is_ipv6;
679 : u8 n_addrs4, n_addrs6;
680 : vl_api_vrrp_vr_set_peers_t *mp;
681 : vl_api_address_t *api_addr;
682 0 : ip46_address_t *ip_addr, *ip_addrs = 0;
683 : ip46_address_t addr;
684 0 : int ret = 0;
685 :
686 0 : n_addrs4 = n_addrs6 = 0;
687 0 : vr_id = is_ipv6 = 0;
688 :
689 0 : clib_memset (&addr, 0, sizeof (addr));
690 :
691 : /* Parse args required to build the message */
692 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
693 : {
694 0 : if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
695 : ;
696 0 : else if (unformat (i, "sw_if_index %u", &sw_if_index))
697 : ;
698 0 : else if (unformat (i, "vr_id %u", &vr_id))
699 : ;
700 0 : else if (unformat (i, "ipv6"))
701 0 : is_ipv6 = 1;
702 0 : else if (unformat (i, "%U", unformat_ip4_address, &addr.ip4))
703 : {
704 0 : vec_add1 (ip_addrs, addr);
705 0 : n_addrs4++;
706 0 : clib_memset (&addr, 0, sizeof (addr));
707 : }
708 0 : else if (unformat (i, "%U", unformat_ip6_address, &addr.ip6))
709 : {
710 0 : vec_add1 (ip_addrs, addr);
711 0 : n_addrs6++;
712 0 : clib_memset (&addr, 0, sizeof (addr));
713 : }
714 : else
715 0 : break;
716 : }
717 :
718 0 : if (sw_if_index == ~0)
719 : {
720 0 : errmsg ("Interface not set\n");
721 0 : ret = -99;
722 : }
723 0 : else if (n_addrs4 && (n_addrs6 || is_ipv6))
724 : {
725 0 : errmsg ("Address family mismatch\n");
726 0 : ret = -99;
727 : }
728 :
729 0 : if (ret)
730 0 : goto done;
731 :
732 : /* Construct the API message */
733 0 : M2 (VRRP_VR_SET_PEERS, mp, vec_len (ip_addrs) * sizeof (*api_addr));
734 :
735 0 : mp->sw_if_index = ntohl (sw_if_index);
736 0 : mp->vr_id = vr_id;
737 0 : mp->is_ipv6 = (is_ipv6 != 0);
738 :
739 0 : mp->n_addrs = n_addrs4 + n_addrs6;
740 0 : api_addr = mp->addrs;
741 :
742 0 : vec_foreach (ip_addr, ip_addrs)
743 : {
744 : void *src, *dst;
745 : int len;
746 :
747 0 : if (is_ipv6)
748 : {
749 0 : api_addr->af = ADDRESS_IP6;
750 0 : src = &ip_addr->ip6;
751 0 : dst = &api_addr->un.ip6;
752 0 : len = sizeof (api_addr->un.ip6);
753 : }
754 : else
755 : {
756 0 : api_addr->af = ADDRESS_IP4;
757 0 : src = &ip_addr->ip4;
758 0 : dst = &api_addr->un.ip4;
759 0 : len = sizeof (api_addr->un.ip4);
760 : }
761 0 : clib_memcpy (dst, src, len);
762 0 : api_addr++;
763 : }
764 :
765 : /* send it... */
766 0 : S (mp);
767 :
768 : /* Wait for a reply... */
769 0 : W (ret);
770 :
771 0 : done:
772 0 : vec_free (ip_addrs);
773 :
774 0 : return ret;
775 : }
776 :
777 : static int
778 0 : api_vrrp_vr_peer_dump (vat_main_t * vam)
779 : {
780 0 : vrrp_test_main_t *vtm = &vrrp_test_main;
781 0 : unformat_input_t *i = vam->input;
782 : vl_api_vrrp_vr_peer_dump_t *mp;
783 : vl_api_control_ping_t *mp_ping;
784 0 : u32 sw_if_index = ~0, vr_id = 0;
785 0 : u8 is_ipv6 = 0;
786 : int ret;
787 :
788 0 : if (vam->json_output)
789 : {
790 0 : clib_warning ("JSON output not supported for vrrp_vr_track_if_dump");
791 0 : return -99;
792 : }
793 :
794 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
795 : {
796 0 : if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
797 : ;
798 0 : else if (unformat (i, "sw_if_index %u", &sw_if_index))
799 : ;
800 0 : else if (unformat (i, "vr_id %u", &vr_id))
801 : ;
802 0 : else if (unformat (i, "ipv6"))
803 0 : is_ipv6 = 1;
804 : else
805 0 : break;
806 : }
807 :
808 : /* sw_if_index and vr_id must be valid */
809 0 : if (sw_if_index == ~0)
810 : {
811 0 : errmsg ("VR interface not specified\n");
812 0 : return -99;
813 : }
814 0 : else if (!vr_id)
815 : {
816 0 : errmsg ("Invalid VR ID - must be between 1 and 255");
817 0 : return -99;
818 : }
819 :
820 0 : M (VRRP_VR_PEER_DUMP, mp);
821 :
822 0 : mp->sw_if_index = htonl (sw_if_index);
823 0 : mp->vr_id = vr_id;
824 0 : mp->is_ipv6 = is_ipv6;
825 :
826 0 : S (mp);
827 :
828 0 : mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping));
829 0 : mp_ping->_vl_msg_id = htons (vtm->ping_id);
830 0 : mp_ping->client_index = vam->my_client_index;
831 :
832 0 : vam->result_ready = 0;
833 0 : S (mp_ping);
834 :
835 0 : W (ret);
836 0 : return ret;
837 : }
838 :
839 : static void
840 0 : vl_api_vrrp_vr_peer_details_t_handler (vl_api_vrrp_vr_peer_details_t * mp)
841 : {
842 0 : vat_main_t *vam = vrrp_test_main.vat_main;
843 : int i;
844 :
845 0 : fformat (vam->ofp, "sw_if_index %u vr_id %u IPv%d ",
846 0 : ntohl (mp->sw_if_index), mp->vr_id, (mp->is_ipv6) ? 6 : 4);
847 :
848 0 : fformat (vam->ofp, "peer addresses: ");
849 :
850 0 : for (i = 0; i < mp->n_peer_addrs; i++)
851 : {
852 0 : vl_api_address_t *addr = mp->peer_addrs + i;
853 :
854 0 : fformat (vam->ofp, "%U ",
855 0 : (addr->af) ? format_ip6_address : format_ip4_address,
856 0 : (u8 *) & addr->un);
857 : }
858 :
859 0 : fformat (vam->ofp, "\n");
860 0 : }
861 :
862 : static int
863 0 : api_want_vrrp_vr_events (vat_main_t * vam)
864 : {
865 0 : unformat_input_t *i = vam->input;
866 : vl_api_want_vrrp_vr_events_t *mp;
867 0 : int enable = -1;
868 : int ret;
869 :
870 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
871 : {
872 0 : if (unformat (i, "enable"))
873 0 : enable = 1;
874 0 : else if (unformat (i, "disable"))
875 0 : enable = 0;
876 : else
877 0 : break;
878 : }
879 :
880 0 : if (enable == -1)
881 : {
882 0 : errmsg ("missing enable|disable");
883 0 : return -99;
884 : }
885 :
886 0 : M (WANT_VRRP_VR_EVENTS, mp);
887 0 : mp->enable_disable = enable;
888 0 : S (mp);
889 0 : W (ret);
890 :
891 0 : return ret;
892 : }
893 :
894 : #include <vrrp/vrrp.api_test.c>
895 : /*
896 : * fd.io coding-style-patch-verification: ON
897 : *
898 : * Local Variables:
899 : * eval: (c-set-style "gnu")
900 : * End:
901 : */
|