blob: 82eea1794f6d5b36d6dd02f9b84b02d8ecd87340 [file] [log] [blame]
Gabriel Oginski4e88e042022-06-29 12:54:30 +00001/*
2 * Copyright (c) 2022 Intel and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <utils/debug.h>
17#include <vlibapi/api.h>
18#include <vlibmemory/api.h>
19#include <threading/thread.h>
20#include <threading/mutex.h>
21
22#define vl_typedefs
23#define vl_endianfun
24/* Include the (first) vlib-api API definition layer */
25#include <vlibmemory/vl_memory_api_h.h>
26/* Include the current layer (third) vpp API definition layer */
27#include <vpp/api/vpe_types.api.h>
28#include <vpp/api/vpe.api.h>
29
30#include <vnet/ip-neighbor/ip_neighbor.api_enum.h>
31#include <vnet/ip-neighbor/ip_neighbor.api_types.h>
32#include <vnet/ip/ip.api_enum.h>
33#include <vnet/ip/ip.api_types.h>
34#include <vnet/interface.api_enum.h>
35#include <vnet/interface.api_types.h>
36#undef vl_typedefs
37#undef vl_endianfun
38
39#include "kernel_vpp_net.h"
40#include "kernel_vpp_shared.h"
41
42typedef struct private_kernel_vpp_net_t private_kernel_vpp_net_t;
43
44/**
45 * Private data of kernel_vpp_net implementation.
46 */
47struct private_kernel_vpp_net_t
48{
49
50 /**
51 * Public interface.
52 */
53 kernel_vpp_net_t public;
54
55 /**
56 * Mutex to access interface list
57 */
58 mutex_t *mutex;
59
60 /**
61 * Known interfaces, as iface_t
62 */
63 linked_list_t *ifaces;
64
65 /**
66 * Inteface update thread
67 */
68 thread_t *net_update;
69
70 /**
71 * TRUE if interface events enabled
72 */
73 bool events_on;
74};
75
76/**
77 * Interface entry
78 */
79typedef struct
80{
81 /** interface index */
82 uint32_t index;
83 /** interface name */
84 char if_name[64];
85 /** list of known addresses, as host_t */
86 linked_list_t *addrs;
87 /** TRUE if up */
88 bool up;
89} iface_t;
90
91/**
92 * Address enumerator
93 */
94typedef struct
95{
96 /** implements enumerator_t */
97 enumerator_t public;
98 /** what kind of address should we enumerate? */
99 kernel_address_type_t which;
100 /** enumerator over interfaces */
101 enumerator_t *ifaces;
102 /** current enumerator over addresses, or NULL */
103 enumerator_t *addrs;
104 /** mutex to unlock on destruction */
105 mutex_t *mutex;
106} addr_enumerator_t;
107
108/**
109 * FIB path entry
110 */
111typedef struct
112{
113 chunk_t next_hop;
114 uint32_t sw_if_index;
115 uint8_t preference;
116} fib_path_t;
117
118/**
119 * Get an iface entry for a local address
120 */
121static iface_t *
122address2entry (private_kernel_vpp_net_t *this, host_t *ip)
123{
124 enumerator_t *ifaces, *addrs;
125 iface_t *entry, *found = NULL;
126 host_t *host;
127
128 ifaces = this->ifaces->create_enumerator (this->ifaces);
129 while (!found && ifaces->enumerate (ifaces, &entry))
130 {
131 addrs = entry->addrs->create_enumerator (entry->addrs);
132 while (!found && addrs->enumerate (addrs, &host))
133 {
134 if (host->ip_equals (host, ip))
135 {
136 found = entry;
137 }
138 }
139 addrs->destroy (addrs);
140 }
141 ifaces->destroy (ifaces);
142
143 return found;
144}
145
146/**
147 * Add or remove a route
148 */
149static status_t
150manage_route (private_kernel_vpp_net_t *this, bool add, chunk_t dst,
151 uint8_t prefixlen, host_t *gtw, char *name)
152{
153 char *out;
154 int out_len;
155 enumerator_t *enumerator;
156 iface_t *entry;
157 vl_api_ip_route_add_del_t *mp;
158 vl_api_ip_route_add_del_reply_t *rmp;
159 vl_api_fib_path_t *apath;
160 bool exists = FALSE;
161
Gabriel Oginski0e1fe7b2023-07-14 07:22:12 +0000162 for (int i = 0; i < N_RETRY_GET_IF; i++)
Gabriel Oginski4e88e042022-06-29 12:54:30 +0000163 {
Gabriel Oginski0e1fe7b2023-07-14 07:22:12 +0000164 this->mutex->lock (this->mutex);
165 enumerator = this->ifaces->create_enumerator (this->ifaces);
166 while (enumerator->enumerate (enumerator, &entry))
Gabriel Oginski4e88e042022-06-29 12:54:30 +0000167 {
Gabriel Oginski0e1fe7b2023-07-14 07:22:12 +0000168 if (streq (name, entry->if_name))
169 {
170 exists = TRUE;
171 break;
172 }
Gabriel Oginski4e88e042022-06-29 12:54:30 +0000173 }
Gabriel Oginski0e1fe7b2023-07-14 07:22:12 +0000174 enumerator->destroy (enumerator);
175 this->mutex->unlock (this->mutex);
176
177 if (!exists)
178 {
179 DBG1 (DBG_NET, "if_name %s not found", name);
180 sleep (1);
181 }
182 else
183 break;
Gabriel Oginski4e88e042022-06-29 12:54:30 +0000184 }
Gabriel Oginski4e88e042022-06-29 12:54:30 +0000185
186 if (!exists)
187 {
188 DBG1 (DBG_NET, "if_name %s not found", name);
189 return NOT_FOUND;
190 }
191
192 mp = vl_msg_api_alloc (sizeof (*mp) + sizeof (*apath));
193 memset (mp, 0, sizeof (*mp) + sizeof (*apath));
194 u16 msg_id = vl_msg_api_get_msg_index ((u8 *) "ip_route_add_del_b8ecfe0d");
195 mp->_vl_msg_id = ntohs (msg_id);
196 mp->is_add = add;
197 mp->route.prefix.len = prefixlen;
198 mp->route.n_paths = 1;
199 apath = &mp->route.paths[0];
200 apath->sw_if_index = ntohl (entry->index);
201 apath->rpf_id = ~0;
202 apath->weight = 1;
203 switch (dst.len)
204 {
205 case 4:
206 mp->route.prefix.address.af = ntohl (ADDRESS_IP4);
207 memcpy (&mp->route.prefix.address.un.ip4, dst.ptr, dst.len);
208 if (gtw)
209 {
210 chunk_t addr = gtw->get_address (gtw);
211 apath->proto = ntohl (FIB_API_PATH_NH_PROTO_IP4);
212 memcpy (&apath->nh.address.ip4, addr.ptr, dst.len);
213 }
214 break;
215 case 16:
216 mp->route.prefix.address.af = ntohl (ADDRESS_IP6);
217 memcpy (&mp->route.prefix.address.un.ip6, dst.ptr, dst.len);
218 if (gtw)
219 {
220 chunk_t addr = gtw->get_address (gtw);
221 apath->proto = ntohl (FIB_API_PATH_NH_PROTO_IP6);
222 memcpy (&apath->nh.address.ip6, addr.ptr, dst.len);
223 }
224 break;
225 default:
226 vl_msg_api_free (mp);
227 return FAILED;
228 }
229
230 if (vac->send (vac, (char *) mp, sizeof (*mp) + sizeof (*apath), &out,
231 &out_len))
232 {
233 DBG1 (DBG_KNL, "vac %sing route failed", add ? "add" : "remov");
234 vl_msg_api_free (mp);
235 return FAILED;
236 }
237 rmp = (void *) out;
238 vl_msg_api_free (mp);
239 if (rmp->retval)
240 {
241 DBG1 (DBG_KNL, "%s route failed %d", add ? "add" : "delete",
242 ntohl (rmp->retval));
243 free (out);
244 return FAILED;
245 }
246 free (out);
247 return SUCCESS;
248}
249
250/**
251 * Check if an address or net (addr with prefix net bits) is in
252 * subnet (net with net_len net bits)
253 */
254static bool
255addr_in_subnet (chunk_t addr, int prefix, chunk_t net, int net_len)
256{
257 static const u_char mask[] = {
258 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe
259 };
260 int byte = 0;
261
262 if (net_len == 0)
263 { /* any address matches a /0 network */
264 return TRUE;
265 }
266 if (addr.len != net.len || net_len > 8 * net.len || prefix < net_len)
267 {
268 return FALSE;
269 }
270 /* scan through all bytes in network order */
271 while (net_len > 0)
272 {
273 if (net_len < 8)
274 {
275 return (mask[net_len] & addr.ptr[byte]) ==
276 (mask[net_len] & net.ptr[byte]);
277 }
278 else
279 {
280 if (addr.ptr[byte] != net.ptr[byte])
281 {
282 return FALSE;
283 }
284 byte++;
285 net_len -= 8;
286 }
287 }
288 return TRUE;
289}
290
291/**
292 * Get a route: If "nexthop" the nexthop is returned, source addr otherwise
293 */
294static host_t *
295get_route (private_kernel_vpp_net_t *this, host_t *dest, int prefix,
296 bool nexthop, char **iface, host_t *src)
297{
298 fib_path_t path;
299 char *out, *tmp;
300 int out_len, i, num;
301 vl_api_fib_path_t *fp;
302 host_t *addr = NULL;
303 enumerator_t *enumerator;
304 iface_t *entry;
305 int family;
306
307 path.sw_if_index = ~0;
308 path.preference = ~0;
309 path.next_hop = chunk_empty;
310
311 vl_api_ip_route_dump_t *mp;
312 vl_api_ip_route_details_t *rmp;
313
314 mp = vl_msg_api_alloc (sizeof (*mp));
315 clib_memset (mp, 0, sizeof (*mp));
316 u16 msg_id = vl_msg_api_get_msg_index ((u8 *) "ip_route_dump_b9d2e09e");
317 mp->_vl_msg_id = htons (msg_id);
318 mp->table.is_ip6 = dest->get_family (dest) == AF_INET6 ? 1 : 0;
319 if (vac->send_dump (vac, (char *) mp, sizeof (*mp), &out, &out_len))
320 {
321 vl_msg_api_free (mp);
322 DBG2 (DBG_KNL, "send VL_API_IP_ROUTE_ADD_DEL failed");
323 return NULL;
324 }
325 vl_msg_api_free (mp);
326
327 if (dest->get_family (dest) == AF_INET)
328 {
329 i = 0;
330 family = AF_INET;
331 if (prefix == -1)
332 prefix = 32;
333
334 tmp = out;
335 while (tmp < (out + out_len))
336 {
337 rmp = (void *) tmp;
338 num = rmp->route.n_paths;
339
340 if (rmp->route.prefix.len &&
341 addr_in_subnet (
342 dest->get_address (dest), prefix,
343 chunk_create (rmp->route.prefix.address.un.ip4, 4),
344 rmp->route.prefix.len))
345 {
346 fp = rmp->route.paths;
347 for (i = 0; i < num; i++)
348 {
349#define IS_IP4_ANY(a) (a[0] == 0 && a[1] == 0 && a[2] == 0 & a[3] == 0)
350 if (fp->type == FIB_API_PATH_TYPE_DROP)
351 {
352 fp++;
353 continue;
354 }
355 if ((fp->preference < path.preference) ||
356 (path.sw_if_index == ~0) ||
357 IS_IP4_ANY (path.next_hop.ptr))
358 {
359 path.sw_if_index = ntohl (fp->sw_if_index);
360 path.preference = fp->preference;
361 if (path.next_hop.ptr)
362 vl_msg_api_free (path.next_hop.ptr);
363 path.next_hop = chunk_create (fp->nh.address.ip4, 4);
364 }
365 fp++;
366 }
367 }
368 tmp += sizeof (*rmp) + (sizeof (*fp) * num);
369 }
370 }
371 else
372 {
373 DBG1 (DBG_KNL, "not yet support ip6");
374 return NULL;
375 }
376
377 if (path.next_hop.len)
378 {
379 if (nexthop)
380 {
381 if (iface)
382 {
383 *iface = NULL;
384 this->mutex->lock (this->mutex);
385 enumerator = this->ifaces->create_enumerator (this->ifaces);
386 while (enumerator->enumerate (enumerator, &entry))
387 {
388 if (entry->index == path.sw_if_index)
389 {
390 *iface = strdup (entry->if_name);
391 break;
392 }
393 }
394 enumerator->destroy (enumerator);
395 this->mutex->unlock (this->mutex);
396 }
397 addr = host_create_from_chunk (family, path.next_hop, 0);
398 }
399 else
400 {
401 if (src)
402 {
403 addr = src->clone (src);
404 }
405 }
406 }
407
408 free (out);
409
410 return addr;
411}
412
413METHOD (enumerator_t, addr_enumerate, bool, addr_enumerator_t *this,
414 va_list args)
415{
416 iface_t *entry;
417 host_t **host;
418
419 VA_ARGS_VGET (args, host);
420
421 while (TRUE)
422 {
423 while (!this->addrs)
424 {
425 if (!this->ifaces->enumerate (this->ifaces, &entry))
426 {
427 return FALSE;
428 }
429 if (!entry->up && !(this->which & ADDR_TYPE_DOWN))
430 {
431 continue;
432 }
433 this->addrs = entry->addrs->create_enumerator (entry->addrs);
434 }
435 if (this->addrs->enumerate (this->addrs, host))
436 {
437 return TRUE;
438 }
439 this->addrs->destroy (this->addrs);
440 this->addrs = NULL;
441 }
442}
443
444METHOD (enumerator_t, addr_destroy, void, addr_enumerator_t *this)
445{
446 DESTROY_IF (this->addrs);
447 this->ifaces->destroy (this->ifaces);
448 this->mutex->unlock (this->mutex);
449 free (this);
450}
451
452METHOD (kernel_net_t, get_interface_name, bool, private_kernel_vpp_net_t *this,
453 host_t *ip, char **name)
454{
455 iface_t *entry;
456
457 this->mutex->lock (this->mutex);
458 entry = address2entry (this, ip);
459 if (entry && name)
460 {
461 *name = strdup (entry->if_name);
462 }
463 this->mutex->unlock (this->mutex);
464
465 return entry != NULL;
466}
467
468METHOD (kernel_net_t, create_address_enumerator, enumerator_t *,
469 private_kernel_vpp_net_t *this, kernel_address_type_t which)
470{
471 addr_enumerator_t *enumerator;
472
473 if (!(which & ADDR_TYPE_REGULAR))
474 {
475 /* we currently have no virtual, but regular IPs only */
476 return enumerator_create_empty ();
477 }
478
479 this->mutex->lock (this->mutex);
480
481 INIT(enumerator,
482 .public = {
483 .enumerate = enumerator_enumerate_default,
484 .venumerate = _addr_enumerate,
485 .destroy = _addr_destroy,
486 },
487 .which = which,
488 .ifaces = this->ifaces->create_enumerator(this->ifaces),
489 .mutex = this->mutex,
490 );
491 return &enumerator->public;
492}
493
494METHOD (kernel_net_t, get_source_addr, host_t *,
495 private_kernel_vpp_net_t *this, host_t *dest, host_t *src)
496{
497 return get_route (this, dest, -1, FALSE, NULL, src);
498}
499
500METHOD (kernel_net_t, get_nexthop, host_t *, private_kernel_vpp_net_t *this,
501 host_t *dest, int prefix, host_t *src, char **iface)
502{
503 return get_route (this, dest, prefix, TRUE, iface, src);
504}
505
506METHOD (kernel_net_t, add_ip, status_t, private_kernel_vpp_net_t *this,
507 host_t *virtual_ip, int prefix, char *iface_name)
508{
509 return NOT_SUPPORTED;
510}
511
512METHOD (kernel_net_t, del_ip, status_t, private_kernel_vpp_net_t *this,
513 host_t *virtual_ip, int prefix, bool wait)
514{
515 return NOT_SUPPORTED;
516}
517
518METHOD (kernel_net_t, add_route, status_t, private_kernel_vpp_net_t *this,
519 chunk_t dst_net, u_int8_t prefixlen, host_t *gateway, host_t *src_ip,
520 char *if_name)
521{
522 return manage_route (this, TRUE, dst_net, prefixlen, gateway, if_name);
523}
524
525METHOD (kernel_net_t, del_route, status_t, private_kernel_vpp_net_t *this,
526 chunk_t dst_net, u_int8_t prefixlen, host_t *gateway, host_t *src_ip,
527 char *if_name)
528{
529 return manage_route (this, FALSE, dst_net, prefixlen, gateway, if_name);
530}
531
532static void
533iface_destroy (iface_t *this)
534{
535 this->addrs->destroy_offset (this->addrs, offsetof (host_t, destroy));
536 free (this);
537}
538
539METHOD (kernel_net_t, destroy, void, private_kernel_vpp_net_t *this)
540{
541 this->net_update->cancel (this->net_update);
542 this->mutex->destroy (this->mutex);
543 this->ifaces->destroy_function (this->ifaces, (void *) iface_destroy);
544 free (this);
545}
546
547/**
548 * Update addresses for an iface entry
549 */
550static void
551update_addrs (private_kernel_vpp_net_t *this, iface_t *entry)
552{
553 char *out;
554 int out_len, i, num;
555 vl_api_ip_address_dump_t *mp;
556 vl_api_ip_address_details_t *rmp, *tmp;
557 linked_list_t *addrs;
558 host_t *host;
Gabriel Oginski2da99e52023-02-14 08:46:36 +0000559 enumerator_t *enumerator;
Gabriel Oginski4e88e042022-06-29 12:54:30 +0000560
561 mp = vl_msg_api_alloc (sizeof (*mp));
562 clib_memset (mp, 0, sizeof (*mp));
563 u16 msg_id = vl_msg_api_get_msg_index ((u8 *) "ip_address_dump_2d033de4");
564 mp->_vl_msg_id = htons (msg_id);
565 mp->sw_if_index = htonl (entry->index);
566 mp->is_ipv6 = 0;
567 if (vac->send_dump (vac, (char *) mp, sizeof (*mp), &out, &out_len))
568 {
569 DBG2 (DBG_NET, "update_addrs : send VL_API_IP_ADDRESS_DUMP ipv4 failed");
570 vl_msg_api_free (mp);
571 return;
572 }
573 num = out_len / sizeof (*rmp);
574 addrs = linked_list_create ();
575 tmp = (vl_api_ip_address_details_t *) out;
576 for (i = 0; i < num; i++)
577 {
Gabriel Oginski4e88e042022-06-29 12:54:30 +0000578 rmp = tmp;
Timur Celik20721172022-11-22 17:03:14 +0100579 tmp += 1;
Gabriel Oginski4e88e042022-06-29 12:54:30 +0000580 host = host_create_from_chunk (
581 AF_INET, chunk_create (rmp->prefix.address.un.ip4, 4), 0);
582 addrs->insert_last (addrs, host);
583 }
584 free (out);
585
586 mp->is_ipv6 = 1;
587 if (vac->send_dump (vac, (char *) mp, sizeof (*mp), &out, &out_len))
588 {
589 DBG2 (DBG_NET, "update_addrs : send VL_API_IP_ADDRESS_DUMP ipv6 failed");
590 vl_msg_api_free (mp);
591 return;
592 }
593 num = out_len / sizeof (*rmp);
594 tmp = (vl_api_ip_address_details_t *) out;
595 for (i = 0; i < num; i++)
596 {
Gabriel Oginski4e88e042022-06-29 12:54:30 +0000597 rmp = tmp;
Timur Celik20721172022-11-22 17:03:14 +0100598 tmp += 1;
Gabriel Oginski4e88e042022-06-29 12:54:30 +0000599 host = host_create_from_chunk (
600 AF_INET6, chunk_create (rmp->prefix.address.un.ip6, 16), 0);
601 addrs->insert_last (addrs, host);
602 }
603 vl_msg_api_free (mp);
604 free (out);
605
Gabriel Oginski2da99e52023-02-14 08:46:36 +0000606 /* clean-up */
607 enumerator = entry->addrs->create_enumerator (entry->addrs);
608 while (enumerator->enumerate (enumerator, &host))
609 {
610 host->destroy (host);
611 }
612 enumerator->destroy (enumerator);
Gabriel Oginski4e88e042022-06-29 12:54:30 +0000613 entry->addrs->destroy (entry->addrs);
614 entry->addrs =
615 linked_list_create_from_enumerator (addrs->create_enumerator (addrs));
616 addrs->destroy (addrs);
617}
618
619/**
620 * VPP API interface event callback
621 */
622static void
623event_cb (char *data, int data_len, void *ctx)
624{
625 private_kernel_vpp_net_t *this = ctx;
626 vl_api_sw_interface_event_t *event;
Gabriel Oginskiefd23502023-07-06 11:13:16 +0000627 vl_api_if_status_flags_t flags;
Gabriel Oginski4e88e042022-06-29 12:54:30 +0000628 iface_t *entry;
629 enumerator_t *enumerator;
630
631 event = (void *) data;
632 this->mutex->lock (this->mutex);
633 enumerator = this->ifaces->create_enumerator (this->ifaces);
634 while (enumerator->enumerate (enumerator, &entry))
635 {
636 if (entry->index == ntohl (event->sw_if_index))
637 {
Gabriel Oginskiefd23502023-07-06 11:13:16 +0000638 flags = ntohl (event->flags);
Gabriel Oginski4e88e042022-06-29 12:54:30 +0000639 if (event->deleted)
640 {
641 this->ifaces->remove_at (this->ifaces, enumerator);
642 DBG2 (DBG_NET, "interface deleted %u %s", entry->index,
643 entry->if_name);
644 iface_destroy (entry);
645 }
Gabriel Oginskiefd23502023-07-06 11:13:16 +0000646 else if (entry->up != (flags & IF_STATUS_API_FLAG_LINK_UP))
Gabriel Oginski4e88e042022-06-29 12:54:30 +0000647 {
Gabriel Oginskiefd23502023-07-06 11:13:16 +0000648 entry->up = (flags & IF_STATUS_API_FLAG_LINK_UP) ? TRUE : FALSE;
Gabriel Oginski4e88e042022-06-29 12:54:30 +0000649 DBG2 (DBG_NET, "interface state changed %u %s %s", entry->index,
650 entry->if_name, entry->up ? "UP" : "DOWN");
651 }
652 break;
653 }
654 }
655 enumerator->destroy (enumerator);
656 this->mutex->unlock (this->mutex);
Gabriel Oginski4e88e042022-06-29 12:54:30 +0000657}
658
659/**
660 * Inteface update thread (update interface list and interface address)
661 */
662static void *
663net_update_thread_fn (private_kernel_vpp_net_t *this)
664{
665 status_t rv;
666 while (1)
667 {
668 char *out;
669 int out_len;
670 vl_api_sw_interface_dump_t *mp;
671 vl_api_sw_interface_details_t *rmp;
672 enumerator_t *enumerator;
673 iface_t *entry;
674
675 mp = vl_msg_api_alloc (sizeof (*mp));
676 memset (mp, 0, sizeof (*mp));
677 u16 msg_id =
678 vl_msg_api_get_msg_index ((u8 *) "sw_interface_dump_aa610c27");
679 mp->_vl_msg_id = htons (msg_id);
680 mp->name_filter_valid = 0;
681 rv = vac->send_dump (vac, (u8 *) mp, sizeof (*mp), &out, &out_len);
682 if (!rv)
683 {
684 int i, num;
685 this->mutex->lock (this->mutex);
686 enumerator = this->ifaces->create_enumerator (this->ifaces);
687 num = out_len / sizeof (*rmp);
688 rmp = (vl_api_sw_interface_details_t *) out;
689 for (i = 0; i < num; i++)
690 {
691 bool exists = FALSE;
692 if (i)
693 rmp += 1;
694 while (enumerator->enumerate (enumerator, &entry))
695 {
696 if (entry->index == ntohl (rmp->sw_if_index))
697 {
698 exists = TRUE;
699 break;
700 }
701 }
702 if (!exists)
703 {
704 INIT (entry, .index = ntohl (rmp->sw_if_index),
705 .up = (rmp->flags & IF_STATUS_API_FLAG_LINK_UP) ?
706 TRUE :
707 FALSE,
708 .addrs = linked_list_create (), );
709 memcpy (entry->if_name, rmp->interface_name, 63);
710 this->ifaces->insert_last (this->ifaces, entry);
711 }
712 update_addrs (this, entry);
713 }
714 enumerator->destroy (enumerator);
715 this->mutex->unlock (this->mutex);
716 free (out);
717 }
718 vl_msg_api_free (mp);
719
720 if (!this->events_on)
721 {
722 vl_api_want_interface_events_t *emp;
723 api_main_t *am = vlibapi_get_main ();
724
725 emp = vl_msg_api_alloc (sizeof (*emp));
726 clib_memset (emp, 0, sizeof (*emp));
727 u16 msg_id =
728 vl_msg_api_get_msg_index ((u8 *) "want_interface_events_476f5a08");
729 emp->_vl_msg_id = ntohs (msg_id);
730 emp->enable_disable = 1;
731 emp->pid = ntohl (am->our_pid);
Gabriel Oginskiefd23502023-07-06 11:13:16 +0000732 u16 msg_id_sw_interface_event =
733 vl_msg_api_get_msg_index ((u8 *) "sw_interface_event_2d3d95a7");
Gabriel Oginski4e88e042022-06-29 12:54:30 +0000734 rv = vac->register_event (vac, (char *) emp, sizeof (*emp), event_cb,
Gabriel Oginskiefd23502023-07-06 11:13:16 +0000735 msg_id_sw_interface_event, this);
Gabriel Oginski4e88e042022-06-29 12:54:30 +0000736 if (!rv)
737 this->events_on = TRUE;
738 }
739
740 sleep (2);
741 }
742 return NULL;
743}
744
745kernel_vpp_net_t *
746kernel_vpp_net_create ()
747{
748 private_kernel_vpp_net_t *this;
749
750 INIT(this,
751 .public = {
752 .interface = {
753 .get_interface = _get_interface_name,
754 .create_address_enumerator = _create_address_enumerator,
755 .get_source_addr = _get_source_addr,
756 .get_nexthop = _get_nexthop,
757 .add_ip = _add_ip,
758 .del_ip = _del_ip,
759 .add_route = _add_route,
760 .del_route = _del_route,
761 .destroy = _destroy,
762 },
763 },
764 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
765 .ifaces = linked_list_create(),
766 .events_on = FALSE,
767 );
768
769 this->net_update =
770 thread_create ((thread_main_t) net_update_thread_fn, this);
771
772 return &this->public;
773}