]> git.proxmox.com Git - mirror_frr.git/blob - zebra/rt_netlink.c
Merge pull request #5430 from taruta811/build-docker-centos
[mirror_frr.git] / zebra / rt_netlink.c
1 /* Kernel routing table updates using netlink over GNU/Linux system.
2 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <zebra.h>
22
23 #ifdef HAVE_NETLINK
24
25 #include <net/if_arp.h>
26 #include <linux/lwtunnel.h>
27 #include <linux/mpls_iptunnel.h>
28 #include <linux/neighbour.h>
29 #include <linux/rtnetlink.h>
30 #include <linux/nexthop.h>
31
32 /* Hack for GNU libc version 2. */
33 #ifndef MSG_TRUNC
34 #define MSG_TRUNC 0x20
35 #endif /* MSG_TRUNC */
36
37 #include "linklist.h"
38 #include "if.h"
39 #include "log.h"
40 #include "prefix.h"
41 #include "connected.h"
42 #include "table.h"
43 #include "memory.h"
44 #include "zebra_memory.h"
45 #include "rib.h"
46 #include "thread.h"
47 #include "privs.h"
48 #include "nexthop.h"
49 #include "vrf.h"
50 #include "vty.h"
51 #include "mpls.h"
52 #include "vxlan.h"
53 #include "printfrr.h"
54
55 #include "zebra/zapi_msg.h"
56 #include "zebra/zebra_ns.h"
57 #include "zebra/zebra_vrf.h"
58 #include "zebra/rt.h"
59 #include "zebra/redistribute.h"
60 #include "zebra/interface.h"
61 #include "zebra/debug.h"
62 #include "zebra/rtadv.h"
63 #include "zebra/zebra_ptm.h"
64 #include "zebra/zebra_mpls.h"
65 #include "zebra/kernel_netlink.h"
66 #include "zebra/rt_netlink.h"
67 #include "zebra/zebra_nhg.h"
68 #include "zebra/zebra_mroute.h"
69 #include "zebra/zebra_vxlan.h"
70 #include "zebra/zebra_errors.h"
71
72 #ifndef AF_MPLS
73 #define AF_MPLS 28
74 #endif
75
76 static vlanid_t filter_vlan = 0;
77
78 static bool supports_nh;
79
80 struct gw_family_t {
81 uint16_t filler;
82 uint16_t family;
83 union g_addr gate;
84 };
85
86 static const char ipv4_ll_buf[16] = "169.254.0.1";
87 static struct in_addr ipv4_ll;
88
89 /*
90 * The ipv4_ll data structure is used for all 5549
91 * additions to the kernel. Let's figure out the
92 * correct value one time instead for every
93 * install/remove of a 5549 type route
94 */
95 void rt_netlink_init(void)
96 {
97 inet_pton(AF_INET, ipv4_ll_buf, &ipv4_ll);
98 }
99
100 /*
101 * Mapping from dataplane neighbor flags to netlink flags
102 */
103 static uint8_t neigh_flags_to_netlink(uint8_t dplane_flags)
104 {
105 uint8_t flags = 0;
106
107 if (dplane_flags & DPLANE_NTF_EXT_LEARNED)
108 flags |= NTF_EXT_LEARNED;
109 if (dplane_flags & DPLANE_NTF_ROUTER)
110 flags |= NTF_ROUTER;
111
112 return flags;
113 }
114
115 /*
116 * Mapping from dataplane neighbor state to netlink state
117 */
118 static uint16_t neigh_state_to_netlink(uint16_t dplane_state)
119 {
120 uint16_t state = 0;
121
122 if (dplane_state & DPLANE_NUD_REACHABLE)
123 state |= NUD_REACHABLE;
124 if (dplane_state & DPLANE_NUD_STALE)
125 state |= NUD_STALE;
126 if (dplane_state & DPLANE_NUD_NOARP)
127 state |= NUD_NOARP;
128 if (dplane_state & DPLANE_NUD_PROBE)
129 state |= NUD_PROBE;
130
131 return state;
132 }
133
134
135 static inline int is_selfroute(int proto)
136 {
137 if ((proto == RTPROT_BGP) || (proto == RTPROT_OSPF)
138 || (proto == RTPROT_ZSTATIC) || (proto == RTPROT_ZEBRA)
139 || (proto == RTPROT_ISIS) || (proto == RTPROT_RIPNG)
140 || (proto == RTPROT_NHRP) || (proto == RTPROT_EIGRP)
141 || (proto == RTPROT_LDP) || (proto == RTPROT_BABEL)
142 || (proto == RTPROT_RIP) || (proto == RTPROT_SHARP)
143 || (proto == RTPROT_PBR) || (proto == RTPROT_OPENFABRIC)) {
144 return 1;
145 }
146
147 return 0;
148 }
149
150 static inline int zebra2proto(int proto)
151 {
152 switch (proto) {
153 case ZEBRA_ROUTE_BABEL:
154 proto = RTPROT_BABEL;
155 break;
156 case ZEBRA_ROUTE_BGP:
157 proto = RTPROT_BGP;
158 break;
159 case ZEBRA_ROUTE_OSPF:
160 case ZEBRA_ROUTE_OSPF6:
161 proto = RTPROT_OSPF;
162 break;
163 case ZEBRA_ROUTE_STATIC:
164 proto = RTPROT_ZSTATIC;
165 break;
166 case ZEBRA_ROUTE_ISIS:
167 proto = RTPROT_ISIS;
168 break;
169 case ZEBRA_ROUTE_RIP:
170 proto = RTPROT_RIP;
171 break;
172 case ZEBRA_ROUTE_RIPNG:
173 proto = RTPROT_RIPNG;
174 break;
175 case ZEBRA_ROUTE_NHRP:
176 proto = RTPROT_NHRP;
177 break;
178 case ZEBRA_ROUTE_EIGRP:
179 proto = RTPROT_EIGRP;
180 break;
181 case ZEBRA_ROUTE_LDP:
182 proto = RTPROT_LDP;
183 break;
184 case ZEBRA_ROUTE_SHARP:
185 proto = RTPROT_SHARP;
186 break;
187 case ZEBRA_ROUTE_PBR:
188 proto = RTPROT_PBR;
189 break;
190 case ZEBRA_ROUTE_OPENFABRIC:
191 proto = RTPROT_OPENFABRIC;
192 break;
193 case ZEBRA_ROUTE_TABLE:
194 case ZEBRA_ROUTE_NHG:
195 proto = RTPROT_ZEBRA;
196 break;
197 default:
198 /*
199 * When a user adds a new protocol this will show up
200 * to let them know to do something about it. This
201 * is intentionally a warn because we should see
202 * this as part of development of a new protocol
203 */
204 zlog_debug(
205 "%s: Please add this protocol(%d) to proper rt_netlink.c handling",
206 __PRETTY_FUNCTION__, proto);
207 proto = RTPROT_ZEBRA;
208 break;
209 }
210
211 return proto;
212 }
213
214 static inline int proto2zebra(int proto, int family, bool is_nexthop)
215 {
216 switch (proto) {
217 case RTPROT_BABEL:
218 proto = ZEBRA_ROUTE_BABEL;
219 break;
220 case RTPROT_BGP:
221 proto = ZEBRA_ROUTE_BGP;
222 break;
223 case RTPROT_OSPF:
224 proto = (family == AFI_IP) ? ZEBRA_ROUTE_OSPF
225 : ZEBRA_ROUTE_OSPF6;
226 break;
227 case RTPROT_ISIS:
228 proto = ZEBRA_ROUTE_ISIS;
229 break;
230 case RTPROT_RIP:
231 proto = ZEBRA_ROUTE_RIP;
232 break;
233 case RTPROT_RIPNG:
234 proto = ZEBRA_ROUTE_RIPNG;
235 break;
236 case RTPROT_NHRP:
237 proto = ZEBRA_ROUTE_NHRP;
238 break;
239 case RTPROT_EIGRP:
240 proto = ZEBRA_ROUTE_EIGRP;
241 break;
242 case RTPROT_LDP:
243 proto = ZEBRA_ROUTE_LDP;
244 break;
245 case RTPROT_STATIC:
246 case RTPROT_ZSTATIC:
247 proto = ZEBRA_ROUTE_STATIC;
248 break;
249 case RTPROT_SHARP:
250 proto = ZEBRA_ROUTE_SHARP;
251 break;
252 case RTPROT_PBR:
253 proto = ZEBRA_ROUTE_PBR;
254 break;
255 case RTPROT_OPENFABRIC:
256 proto = ZEBRA_ROUTE_OPENFABRIC;
257 break;
258 case RTPROT_ZEBRA:
259 if (is_nexthop) {
260 proto = ZEBRA_ROUTE_NHG;
261 break;
262 }
263 /* Intentional fall thru */
264 default:
265 /*
266 * When a user adds a new protocol this will show up
267 * to let them know to do something about it. This
268 * is intentionally a warn because we should see
269 * this as part of development of a new protocol
270 */
271 zlog_debug(
272 "%s: Please add this protocol(%d) to proper rt_netlink.c handling",
273 __PRETTY_FUNCTION__, proto);
274 proto = ZEBRA_ROUTE_KERNEL;
275 break;
276 }
277 return proto;
278 }
279
280 /*
281 Pending: create an efficient table_id (in a tree/hash) based lookup)
282 */
283 static vrf_id_t vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id)
284 {
285 struct vrf *vrf;
286 struct zebra_vrf *zvrf;
287
288 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
289 zvrf = vrf->info;
290 if (zvrf == NULL)
291 continue;
292 /* case vrf with netns : match the netnsid */
293 if (vrf_is_backend_netns()) {
294 if (ns_id == zvrf_id(zvrf))
295 return zvrf_id(zvrf);
296 } else {
297 /* VRF is VRF_BACKEND_VRF_LITE */
298 if (zvrf->table_id != table_id)
299 continue;
300 return zvrf_id(zvrf);
301 }
302 }
303
304 return VRF_DEFAULT;
305 }
306
307 /**
308 * @parse_encap_mpls() - Parses encapsulated mpls attributes
309 * @tb: Pointer to rtattr to look for nested items in.
310 * @labels: Pointer to store labels in.
311 *
312 * Return: Number of mpls labels found.
313 */
314 static int parse_encap_mpls(struct rtattr *tb, mpls_label_t *labels)
315 {
316 struct rtattr *tb_encap[MPLS_IPTUNNEL_MAX + 1] = {0};
317 mpls_lse_t *lses = NULL;
318 int num_labels = 0;
319 uint32_t ttl = 0;
320 uint32_t bos = 0;
321 uint32_t exp = 0;
322 mpls_label_t label = 0;
323
324 netlink_parse_rtattr_nested(tb_encap, MPLS_IPTUNNEL_MAX, tb);
325 lses = (mpls_lse_t *)RTA_DATA(tb_encap[MPLS_IPTUNNEL_DST]);
326 while (!bos && num_labels < MPLS_MAX_LABELS) {
327 mpls_lse_decode(lses[num_labels], &label, &ttl, &exp, &bos);
328 labels[num_labels++] = label;
329 }
330
331 return num_labels;
332 }
333
334 static struct nexthop
335 parse_nexthop_unicast(ns_id_t ns_id, struct rtmsg *rtm, struct rtattr **tb,
336 enum blackhole_type bh_type, int index, void *prefsrc,
337 void *gate, afi_t afi, vrf_id_t vrf_id)
338 {
339 struct interface *ifp = NULL;
340 struct nexthop nh = {0};
341 mpls_label_t labels[MPLS_MAX_LABELS] = {0};
342 int num_labels = 0;
343
344 vrf_id_t nh_vrf_id = vrf_id;
345 size_t sz = (afi == AFI_IP) ? 4 : 16;
346
347 if (bh_type == BLACKHOLE_UNSPEC) {
348 if (index && !gate)
349 nh.type = NEXTHOP_TYPE_IFINDEX;
350 else if (index && gate)
351 nh.type = (afi == AFI_IP) ? NEXTHOP_TYPE_IPV4_IFINDEX
352 : NEXTHOP_TYPE_IPV6_IFINDEX;
353 else if (!index && gate)
354 nh.type = (afi == AFI_IP) ? NEXTHOP_TYPE_IPV4
355 : NEXTHOP_TYPE_IPV6;
356 else {
357 nh.type = NEXTHOP_TYPE_BLACKHOLE;
358 nh.bh_type = bh_type;
359 }
360 } else {
361 nh.type = NEXTHOP_TYPE_BLACKHOLE;
362 nh.bh_type = bh_type;
363 }
364 nh.ifindex = index;
365 if (prefsrc)
366 memcpy(&nh.src, prefsrc, sz);
367 if (gate)
368 memcpy(&nh.gate, gate, sz);
369
370 if (index) {
371 ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), index);
372 if (ifp)
373 nh_vrf_id = ifp->vrf_id;
374 }
375 nh.vrf_id = nh_vrf_id;
376
377 if (tb[RTA_ENCAP] && tb[RTA_ENCAP_TYPE]
378 && *(uint16_t *)RTA_DATA(tb[RTA_ENCAP_TYPE])
379 == LWTUNNEL_ENCAP_MPLS) {
380 num_labels = parse_encap_mpls(tb[RTA_ENCAP], labels);
381 }
382
383 if (rtm->rtm_flags & RTNH_F_ONLINK)
384 SET_FLAG(nh.flags, NEXTHOP_FLAG_ONLINK);
385
386 if (num_labels)
387 nexthop_add_labels(&nh, ZEBRA_LSP_STATIC, num_labels, labels);
388
389 return nh;
390 }
391
392 static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id,
393 struct route_entry *re,
394 struct rtmsg *rtm,
395 struct rtnexthop *rtnh,
396 struct rtattr **tb,
397 void *prefsrc, vrf_id_t vrf_id)
398 {
399 void *gate = NULL;
400 struct interface *ifp = NULL;
401 int index = 0;
402 /* MPLS labels */
403 mpls_label_t labels[MPLS_MAX_LABELS] = {0};
404 int num_labels = 0;
405 struct rtattr *rtnh_tb[RTA_MAX + 1] = {};
406
407 int len = RTA_PAYLOAD(tb[RTA_MULTIPATH]);
408 vrf_id_t nh_vrf_id = vrf_id;
409
410 re->ng = nexthop_group_new();
411
412 for (;;) {
413 struct nexthop *nh = NULL;
414
415 if (len < (int)sizeof(*rtnh) || rtnh->rtnh_len > len)
416 break;
417
418 index = rtnh->rtnh_ifindex;
419 if (index) {
420 /*
421 * Yes we are looking this up
422 * for every nexthop and just
423 * using the last one looked
424 * up right now
425 */
426 ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
427 index);
428 if (ifp)
429 nh_vrf_id = ifp->vrf_id;
430 else {
431 flog_warn(
432 EC_ZEBRA_UNKNOWN_INTERFACE,
433 "%s: Unknown interface %u specified, defaulting to VRF_DEFAULT",
434 __PRETTY_FUNCTION__, index);
435 nh_vrf_id = VRF_DEFAULT;
436 }
437 } else
438 nh_vrf_id = vrf_id;
439
440 if (rtnh->rtnh_len > sizeof(*rtnh)) {
441 memset(rtnh_tb, 0, sizeof(rtnh_tb));
442
443 netlink_parse_rtattr(rtnh_tb, RTA_MAX, RTNH_DATA(rtnh),
444 rtnh->rtnh_len - sizeof(*rtnh));
445 if (rtnh_tb[RTA_GATEWAY])
446 gate = RTA_DATA(rtnh_tb[RTA_GATEWAY]);
447 if (rtnh_tb[RTA_ENCAP] && rtnh_tb[RTA_ENCAP_TYPE]
448 && *(uint16_t *)RTA_DATA(rtnh_tb[RTA_ENCAP_TYPE])
449 == LWTUNNEL_ENCAP_MPLS) {
450 num_labels = parse_encap_mpls(
451 rtnh_tb[RTA_ENCAP], labels);
452 }
453 }
454
455 if (gate && rtm->rtm_family == AF_INET) {
456 if (index)
457 nh = route_entry_nexthop_ipv4_ifindex_add(
458 re, gate, prefsrc, index, nh_vrf_id);
459 else
460 nh = route_entry_nexthop_ipv4_add(
461 re, gate, prefsrc, nh_vrf_id);
462 } else if (gate && rtm->rtm_family == AF_INET6) {
463 if (index)
464 nh = route_entry_nexthop_ipv6_ifindex_add(
465 re, gate, index, nh_vrf_id);
466 else
467 nh = route_entry_nexthop_ipv6_add(re, gate,
468 nh_vrf_id);
469 } else
470 nh = route_entry_nexthop_ifindex_add(re, index,
471 nh_vrf_id);
472
473 if (nh) {
474 if (num_labels)
475 nexthop_add_labels(nh, ZEBRA_LSP_STATIC,
476 num_labels, labels);
477
478 if (rtnh->rtnh_flags & RTNH_F_ONLINK)
479 SET_FLAG(nh->flags, NEXTHOP_FLAG_ONLINK);
480 }
481
482 if (rtnh->rtnh_len == 0)
483 break;
484
485 len -= NLMSG_ALIGN(rtnh->rtnh_len);
486 rtnh = RTNH_NEXT(rtnh);
487 }
488
489 uint8_t nhop_num = nexthop_group_nexthop_num(re->ng);
490
491 if (!nhop_num)
492 nexthop_group_delete(&re->ng);
493
494 return nhop_num;
495 }
496
497 /* Looking up routing table by netlink interface. */
498 static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
499 int startup)
500 {
501 int len;
502 struct rtmsg *rtm;
503 struct rtattr *tb[RTA_MAX + 1];
504 uint8_t flags = 0;
505 struct prefix p;
506 struct prefix_ipv6 src_p = {};
507 vrf_id_t vrf_id;
508
509 char anyaddr[16] = {0};
510
511 int proto = ZEBRA_ROUTE_KERNEL;
512 int index = 0;
513 int table;
514 int metric = 0;
515 uint32_t mtu = 0;
516 uint8_t distance = 0;
517 route_tag_t tag = 0;
518 uint32_t nhe_id = 0;
519
520 void *dest = NULL;
521 void *gate = NULL;
522 void *prefsrc = NULL; /* IPv4 preferred source host address */
523 void *src = NULL; /* IPv6 srcdest source prefix */
524 enum blackhole_type bh_type = BLACKHOLE_UNSPEC;
525
526 rtm = NLMSG_DATA(h);
527
528 if (startup && h->nlmsg_type != RTM_NEWROUTE)
529 return 0;
530 switch (rtm->rtm_type) {
531 case RTN_UNICAST:
532 break;
533 case RTN_BLACKHOLE:
534 bh_type = BLACKHOLE_NULL;
535 break;
536 case RTN_UNREACHABLE:
537 bh_type = BLACKHOLE_REJECT;
538 break;
539 case RTN_PROHIBIT:
540 bh_type = BLACKHOLE_ADMINPROHIB;
541 break;
542 default:
543 if (IS_ZEBRA_DEBUG_KERNEL)
544 zlog_debug("Route rtm_type: %s(%d) intentionally ignoring",
545 nl_rttype_to_str(rtm->rtm_type),
546 rtm->rtm_type);
547 return 0;
548 }
549
550 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
551 if (len < 0) {
552 zlog_err("%s: Message received from netlink is of a broken size %d %zu",
553 __PRETTY_FUNCTION__, h->nlmsg_len,
554 (size_t)NLMSG_LENGTH(sizeof(struct rtmsg)));
555 return -1;
556 }
557
558 memset(tb, 0, sizeof tb);
559 netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len);
560
561 if (rtm->rtm_flags & RTM_F_CLONED)
562 return 0;
563 if (rtm->rtm_protocol == RTPROT_REDIRECT)
564 return 0;
565 if (rtm->rtm_protocol == RTPROT_KERNEL)
566 return 0;
567
568 if (!startup && is_selfroute(rtm->rtm_protocol)
569 && h->nlmsg_type == RTM_NEWROUTE) {
570 if (IS_ZEBRA_DEBUG_KERNEL)
571 zlog_debug("Route type: %d Received that we think we have originated, ignoring",
572 rtm->rtm_protocol);
573 return 0;
574 }
575
576 /* We don't care about change notifications for the MPLS table. */
577 /* TODO: Revisit this. */
578 if (rtm->rtm_family == AF_MPLS)
579 return 0;
580
581 /* Table corresponding to route. */
582 if (tb[RTA_TABLE])
583 table = *(int *)RTA_DATA(tb[RTA_TABLE]);
584 else
585 table = rtm->rtm_table;
586
587 /* Map to VRF */
588 vrf_id = vrf_lookup_by_table(table, ns_id);
589 if (vrf_id == VRF_DEFAULT) {
590 if (!is_zebra_valid_kernel_table(table)
591 && !is_zebra_main_routing_table(table))
592 return 0;
593 }
594
595 /* Route which inserted by Zebra. */
596 if (is_selfroute(rtm->rtm_protocol)) {
597 flags |= ZEBRA_FLAG_SELFROUTE;
598 proto = proto2zebra(rtm->rtm_protocol, rtm->rtm_family, false);
599 }
600 if (tb[RTA_OIF])
601 index = *(int *)RTA_DATA(tb[RTA_OIF]);
602
603 if (tb[RTA_DST])
604 dest = RTA_DATA(tb[RTA_DST]);
605 else
606 dest = anyaddr;
607
608 if (tb[RTA_SRC])
609 src = RTA_DATA(tb[RTA_SRC]);
610 else
611 src = anyaddr;
612
613 if (tb[RTA_PREFSRC])
614 prefsrc = RTA_DATA(tb[RTA_PREFSRC]);
615
616 if (tb[RTA_GATEWAY])
617 gate = RTA_DATA(tb[RTA_GATEWAY]);
618
619 if (tb[RTA_NH_ID])
620 nhe_id = *(uint32_t *)RTA_DATA(tb[RTA_NH_ID]);
621
622 if (tb[RTA_PRIORITY])
623 metric = *(int *)RTA_DATA(tb[RTA_PRIORITY]);
624
625 #if defined(SUPPORT_REALMS)
626 if (tb[RTA_FLOW])
627 tag = *(uint32_t *)RTA_DATA(tb[RTA_FLOW]);
628 #endif
629
630 if (tb[RTA_METRICS]) {
631 struct rtattr *mxrta[RTAX_MAX + 1];
632
633 memset(mxrta, 0, sizeof mxrta);
634 netlink_parse_rtattr(mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
635 RTA_PAYLOAD(tb[RTA_METRICS]));
636
637 if (mxrta[RTAX_MTU])
638 mtu = *(uint32_t *)RTA_DATA(mxrta[RTAX_MTU]);
639 }
640
641 if (rtm->rtm_family == AF_INET) {
642 p.family = AF_INET;
643 if (rtm->rtm_dst_len > IPV4_MAX_BITLEN) {
644 zlog_err(
645 "Invalid destination prefix length: %u received from kernel route change",
646 rtm->rtm_dst_len);
647 return -1;
648 }
649 memcpy(&p.u.prefix4, dest, 4);
650 p.prefixlen = rtm->rtm_dst_len;
651
652 if (rtm->rtm_src_len != 0) {
653 char buf[PREFIX_STRLEN];
654 flog_warn(
655 EC_ZEBRA_UNSUPPORTED_V4_SRCDEST,
656 "unsupported IPv4 sourcedest route (dest %s vrf %u)",
657 prefix2str(&p, buf, sizeof(buf)), vrf_id);
658 return 0;
659 }
660
661 /* Force debug below to not display anything for source */
662 src_p.prefixlen = 0;
663 } else if (rtm->rtm_family == AF_INET6) {
664 p.family = AF_INET6;
665 if (rtm->rtm_dst_len > IPV6_MAX_BITLEN) {
666 zlog_err(
667 "Invalid destination prefix length: %u received from kernel route change",
668 rtm->rtm_dst_len);
669 return -1;
670 }
671 memcpy(&p.u.prefix6, dest, 16);
672 p.prefixlen = rtm->rtm_dst_len;
673
674 src_p.family = AF_INET6;
675 if (rtm->rtm_src_len > IPV6_MAX_BITLEN) {
676 zlog_err(
677 "Invalid source prefix length: %u received from kernel route change",
678 rtm->rtm_src_len);
679 return -1;
680 }
681 memcpy(&src_p.prefix, src, 16);
682 src_p.prefixlen = rtm->rtm_src_len;
683 }
684
685 /*
686 * For ZEBRA_ROUTE_KERNEL types:
687 *
688 * The metric/priority of the route received from the kernel
689 * is a 32 bit number. We are going to interpret the high
690 * order byte as the Admin Distance and the low order 3 bytes
691 * as the metric.
692 *
693 * This will allow us to do two things:
694 * 1) Allow the creation of kernel routes that can be
695 * overridden by zebra.
696 * 2) Allow the old behavior for 'most' kernel route types
697 * if a user enters 'ip route ...' v4 routes get a metric
698 * of 0 and v6 routes get a metric of 1024. Both of these
699 * values will end up with a admin distance of 0, which
700 * will cause them to win for the purposes of zebra.
701 */
702 if (proto == ZEBRA_ROUTE_KERNEL) {
703 distance = (metric >> 24) & 0xFF;
704 metric = (metric & 0x00FFFFFF);
705 }
706
707 if (IS_ZEBRA_DEBUG_KERNEL) {
708 char buf[PREFIX_STRLEN];
709 char buf2[PREFIX_STRLEN];
710 zlog_debug("%s %s%s%s vrf %u(%u) metric: %d Admin Distance: %d",
711 nl_msg_type_to_str(h->nlmsg_type),
712 prefix2str(&p, buf, sizeof(buf)),
713 src_p.prefixlen ? " from " : "",
714 src_p.prefixlen
715 ? prefix2str(&src_p, buf2, sizeof(buf2))
716 : "",
717 vrf_id, table, metric, distance);
718 }
719
720 afi_t afi = AFI_IP;
721 if (rtm->rtm_family == AF_INET6)
722 afi = AFI_IP6;
723
724 if (h->nlmsg_type == RTM_NEWROUTE) {
725
726 if (!tb[RTA_MULTIPATH]) {
727 struct nexthop nh = {0};
728
729 if (!nhe_id) {
730 nh = parse_nexthop_unicast(
731 ns_id, rtm, tb, bh_type, index, prefsrc,
732 gate, afi, vrf_id);
733 }
734 rib_add(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, &p,
735 &src_p, &nh, nhe_id, table, metric, mtu,
736 distance, tag);
737 } else {
738 /* This is a multipath route */
739 struct route_entry *re;
740 struct rtnexthop *rtnh =
741 (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]);
742
743 re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
744 re->type = proto;
745 re->distance = distance;
746 re->flags = flags;
747 re->metric = metric;
748 re->mtu = mtu;
749 re->vrf_id = vrf_id;
750 re->table = table;
751 re->uptime = monotime(NULL);
752 re->tag = tag;
753 re->nhe_id = nhe_id;
754
755 if (!nhe_id) {
756 uint8_t nhop_num =
757 parse_multipath_nexthops_unicast(
758 ns_id, re, rtm, rtnh, tb,
759 prefsrc, vrf_id);
760
761 zserv_nexthop_num_warn(
762 __func__, (const struct prefix *)&p,
763 nhop_num);
764 }
765
766 if (nhe_id || re->ng)
767 rib_add_multipath(afi, SAFI_UNICAST, &p,
768 &src_p, re);
769 else
770 XFREE(MTYPE_RE, re);
771 }
772 } else {
773 if (nhe_id) {
774 rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags,
775 &p, &src_p, NULL, nhe_id, table, metric,
776 distance, true);
777 } else {
778 if (!tb[RTA_MULTIPATH]) {
779 struct nexthop nh;
780 size_t sz = (afi == AFI_IP) ? 4 : 16;
781
782 memset(&nh, 0, sizeof(nh));
783 if (bh_type == BLACKHOLE_UNSPEC) {
784 if (index && !gate)
785 nh.type = NEXTHOP_TYPE_IFINDEX;
786 else if (index && gate)
787 nh.type =
788 (afi == AFI_IP)
789 ? NEXTHOP_TYPE_IPV4_IFINDEX
790 : NEXTHOP_TYPE_IPV6_IFINDEX;
791 else if (!index && gate)
792 nh.type =
793 (afi == AFI_IP)
794 ? NEXTHOP_TYPE_IPV4
795 : NEXTHOP_TYPE_IPV6;
796 else {
797 nh.type =
798 NEXTHOP_TYPE_BLACKHOLE;
799 nh.bh_type = BLACKHOLE_UNSPEC;
800 }
801 } else {
802 nh.type = NEXTHOP_TYPE_BLACKHOLE;
803 nh.bh_type = bh_type;
804 }
805 nh.ifindex = index;
806 if (gate)
807 memcpy(&nh.gate, gate, sz);
808 rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0,
809 flags, &p, &src_p, &nh, 0, table,
810 metric, distance, true);
811 } else {
812 /* XXX: need to compare the entire list of
813 * nexthops here for NLM_F_APPEND stupidity */
814 rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0,
815 flags, &p, &src_p, NULL, 0, table,
816 metric, distance, true);
817 }
818 }
819 }
820
821 return 0;
822 }
823
824 static struct mcast_route_data *mroute = NULL;
825
826 static int netlink_route_change_read_multicast(struct nlmsghdr *h,
827 ns_id_t ns_id, int startup)
828 {
829 int len;
830 struct rtmsg *rtm;
831 struct rtattr *tb[RTA_MAX + 1];
832 struct mcast_route_data *m;
833 struct mcast_route_data mr;
834 int iif = 0;
835 int count;
836 int oif[256];
837 int oif_count = 0;
838 char sbuf[40];
839 char gbuf[40];
840 char oif_list[256] = "\0";
841 vrf_id_t vrf;
842 int table;
843
844 if (mroute)
845 m = mroute;
846 else {
847 memset(&mr, 0, sizeof(mr));
848 m = &mr;
849 }
850
851 rtm = NLMSG_DATA(h);
852
853 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
854
855 memset(tb, 0, sizeof tb);
856 netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len);
857
858 if (tb[RTA_TABLE])
859 table = *(int *)RTA_DATA(tb[RTA_TABLE]);
860 else
861 table = rtm->rtm_table;
862
863 vrf = vrf_lookup_by_table(table, ns_id);
864
865 if (tb[RTA_IIF])
866 iif = *(int *)RTA_DATA(tb[RTA_IIF]);
867
868 if (tb[RTA_SRC])
869 m->sg.src = *(struct in_addr *)RTA_DATA(tb[RTA_SRC]);
870
871 if (tb[RTA_DST])
872 m->sg.grp = *(struct in_addr *)RTA_DATA(tb[RTA_DST]);
873
874 if (tb[RTA_EXPIRES])
875 m->lastused = *(unsigned long long *)RTA_DATA(tb[RTA_EXPIRES]);
876
877 if (tb[RTA_MULTIPATH]) {
878 struct rtnexthop *rtnh =
879 (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]);
880
881 len = RTA_PAYLOAD(tb[RTA_MULTIPATH]);
882 for (;;) {
883 if (len < (int)sizeof(*rtnh) || rtnh->rtnh_len > len)
884 break;
885
886 oif[oif_count] = rtnh->rtnh_ifindex;
887 oif_count++;
888
889 if (rtnh->rtnh_len == 0)
890 break;
891
892 len -= NLMSG_ALIGN(rtnh->rtnh_len);
893 rtnh = RTNH_NEXT(rtnh);
894 }
895 }
896
897 if (IS_ZEBRA_DEBUG_KERNEL) {
898 struct interface *ifp = NULL;
899 struct zebra_vrf *zvrf = NULL;
900
901 strlcpy(sbuf, inet_ntoa(m->sg.src), sizeof(sbuf));
902 strlcpy(gbuf, inet_ntoa(m->sg.grp), sizeof(gbuf));
903 for (count = 0; count < oif_count; count++) {
904 ifp = if_lookup_by_index(oif[count], vrf);
905 char temp[256];
906
907 sprintf(temp, "%s(%d) ", ifp ? ifp->name : "Unknown",
908 oif[count]);
909 strlcat(oif_list, temp, sizeof(oif_list));
910 }
911 zvrf = zebra_vrf_lookup_by_id(vrf);
912 ifp = if_lookup_by_index(iif, vrf);
913 zlog_debug(
914 "MCAST VRF: %s(%d) %s (%s,%s) IIF: %s(%d) OIF: %s jiffies: %lld",
915 (zvrf ? zvrf->vrf->name : "Unknown"), vrf,
916 nl_msg_type_to_str(h->nlmsg_type), sbuf, gbuf,
917 ifp ? ifp->name : "Unknown", iif, oif_list,
918 m->lastused);
919 }
920 return 0;
921 }
922
923 int netlink_route_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
924 {
925 int len;
926 struct rtmsg *rtm;
927
928 rtm = NLMSG_DATA(h);
929
930 if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) {
931 /* If this is not route add/delete message print warning. */
932 zlog_debug("Kernel message: %s NS %u",
933 nl_msg_type_to_str(h->nlmsg_type), ns_id);
934 return 0;
935 }
936
937 if (!(rtm->rtm_family == AF_INET ||
938 rtm->rtm_family == AF_INET6 ||
939 rtm->rtm_family == RTNL_FAMILY_IPMR )) {
940 flog_warn(
941 EC_ZEBRA_UNKNOWN_FAMILY,
942 "Invalid address family: %u received from kernel route change: %s",
943 rtm->rtm_family, nl_msg_type_to_str(h->nlmsg_type));
944 return 0;
945 }
946
947 /* Connected route. */
948 if (IS_ZEBRA_DEBUG_KERNEL)
949 zlog_debug("%s %s %s proto %s NS %u",
950 nl_msg_type_to_str(h->nlmsg_type),
951 nl_family_to_str(rtm->rtm_family),
952 nl_rttype_to_str(rtm->rtm_type),
953 nl_rtproto_to_str(rtm->rtm_protocol), ns_id);
954
955
956 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
957 if (len < 0) {
958 zlog_err("%s: Message received from netlink is of a broken size: %d %zu",
959 __PRETTY_FUNCTION__,
960 h->nlmsg_len,
961 (size_t)NLMSG_LENGTH(sizeof(struct rtmsg)));
962 return -1;
963 }
964
965 if (rtm->rtm_type == RTN_MULTICAST)
966 netlink_route_change_read_multicast(h, ns_id, startup);
967 else
968 netlink_route_change_read_unicast(h, ns_id, startup);
969 return 0;
970 }
971
972 /* Request for specific route information from the kernel */
973 static int netlink_request_route(struct zebra_ns *zns, int family, int type)
974 {
975 struct {
976 struct nlmsghdr n;
977 struct rtmsg rtm;
978 } req;
979
980 /* Form the request, specifying filter (rtattr) if needed. */
981 memset(&req, 0, sizeof(req));
982 req.n.nlmsg_type = type;
983 req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
984 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
985 req.rtm.rtm_family = family;
986
987 return netlink_request(&zns->netlink_cmd, &req.n);
988 }
989
990 /* Routing table read function using netlink interface. Only called
991 bootstrap time. */
992 int netlink_route_read(struct zebra_ns *zns)
993 {
994 int ret;
995 struct zebra_dplane_info dp_info;
996
997 zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
998
999 /* Get IPv4 routing table. */
1000 ret = netlink_request_route(zns, AF_INET, RTM_GETROUTE);
1001 if (ret < 0)
1002 return ret;
1003 ret = netlink_parse_info(netlink_route_change_read_unicast,
1004 &zns->netlink_cmd, &dp_info, 0, 1);
1005 if (ret < 0)
1006 return ret;
1007
1008 /* Get IPv6 routing table. */
1009 ret = netlink_request_route(zns, AF_INET6, RTM_GETROUTE);
1010 if (ret < 0)
1011 return ret;
1012 ret = netlink_parse_info(netlink_route_change_read_unicast,
1013 &zns->netlink_cmd, &dp_info, 0, 1);
1014 if (ret < 0)
1015 return ret;
1016
1017 return 0;
1018 }
1019
1020 static void _netlink_route_nl_add_gateway_info(uint8_t route_family,
1021 uint8_t gw_family,
1022 struct nlmsghdr *nlmsg,
1023 size_t req_size, int bytelen,
1024 const struct nexthop *nexthop)
1025 {
1026 if (route_family == AF_MPLS) {
1027 struct gw_family_t gw_fam;
1028
1029 gw_fam.family = gw_family;
1030 if (gw_family == AF_INET)
1031 memcpy(&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen);
1032 else
1033 memcpy(&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen);
1034 addattr_l(nlmsg, req_size, RTA_VIA, &gw_fam.family,
1035 bytelen + 2);
1036 } else {
1037 if (gw_family == AF_INET)
1038 addattr_l(nlmsg, req_size, RTA_GATEWAY,
1039 &nexthop->gate.ipv4, bytelen);
1040 else
1041 addattr_l(nlmsg, req_size, RTA_GATEWAY,
1042 &nexthop->gate.ipv6, bytelen);
1043 }
1044 }
1045
1046 static void _netlink_route_rta_add_gateway_info(uint8_t route_family,
1047 uint8_t gw_family,
1048 struct rtattr *rta,
1049 struct rtnexthop *rtnh,
1050 size_t req_size, int bytelen,
1051 const struct nexthop *nexthop)
1052 {
1053 if (route_family == AF_MPLS) {
1054 struct gw_family_t gw_fam;
1055
1056 gw_fam.family = gw_family;
1057 if (gw_family == AF_INET)
1058 memcpy(&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen);
1059 else
1060 memcpy(&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen);
1061 rta_addattr_l(rta, req_size, RTA_VIA, &gw_fam.family,
1062 bytelen + 2);
1063 rtnh->rtnh_len += RTA_LENGTH(bytelen + 2);
1064 } else {
1065 if (gw_family == AF_INET)
1066 rta_addattr_l(rta, req_size, RTA_GATEWAY,
1067 &nexthop->gate.ipv4, bytelen);
1068 else
1069 rta_addattr_l(rta, req_size, RTA_GATEWAY,
1070 &nexthop->gate.ipv6, bytelen);
1071 rtnh->rtnh_len += sizeof(struct rtattr) + bytelen;
1072 }
1073 }
1074
1075 static int build_label_stack(struct mpls_label_stack *nh_label,
1076 mpls_lse_t *out_lse, char *label_buf,
1077 size_t label_buf_size)
1078 {
1079 char label_buf1[20];
1080 int num_labels = 0;
1081
1082 for (int i = 0; nh_label && i < nh_label->num_labels; i++) {
1083 if (nh_label->label[i] == MPLS_LABEL_IMPLICIT_NULL)
1084 continue;
1085
1086 if (IS_ZEBRA_DEBUG_KERNEL) {
1087 if (!num_labels)
1088 sprintf(label_buf, "label %u",
1089 nh_label->label[i]);
1090 else {
1091 sprintf(label_buf1, "/%u", nh_label->label[i]);
1092 strlcat(label_buf, label_buf1, label_buf_size);
1093 }
1094 }
1095
1096 out_lse[num_labels] =
1097 mpls_lse_encode(nh_label->label[i], 0, 0, 0);
1098 num_labels++;
1099 }
1100
1101 return num_labels;
1102 }
1103
1104 /* This function takes a nexthop as argument and adds
1105 * the appropriate netlink attributes to an existing
1106 * netlink message.
1107 *
1108 * @param routedesc: Human readable description of route type
1109 * (direct/recursive, single-/multipath)
1110 * @param bytelen: Length of addresses in bytes.
1111 * @param nexthop: Nexthop information
1112 * @param nlmsg: nlmsghdr structure to fill in.
1113 * @param req_size: The size allocated for the message.
1114 */
1115 static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
1116 const struct nexthop *nexthop,
1117 struct nlmsghdr *nlmsg,
1118 struct rtmsg *rtmsg,
1119 size_t req_size, int cmd)
1120 {
1121
1122 mpls_lse_t out_lse[MPLS_MAX_LABELS];
1123 char label_buf[256];
1124 int num_labels = 0;
1125
1126 assert(nexthop);
1127
1128 /*
1129 * label_buf is *only* currently used within debugging.
1130 * As such when we assign it we are guarding it inside
1131 * a debug test. If you want to change this make sure
1132 * you fix this assumption
1133 */
1134 label_buf[0] = '\0';
1135
1136 num_labels = build_label_stack(nexthop->nh_label, out_lse, label_buf,
1137 sizeof(label_buf));
1138
1139 if (num_labels) {
1140 /* Set the BoS bit */
1141 out_lse[num_labels - 1] |= htonl(1 << MPLS_LS_S_SHIFT);
1142
1143 if (rtmsg->rtm_family == AF_MPLS)
1144 addattr_l(nlmsg, req_size, RTA_NEWDST, &out_lse,
1145 num_labels * sizeof(mpls_lse_t));
1146 else {
1147 struct rtattr *nest;
1148 uint16_t encap = LWTUNNEL_ENCAP_MPLS;
1149
1150 addattr_l(nlmsg, req_size, RTA_ENCAP_TYPE, &encap,
1151 sizeof(uint16_t));
1152 nest = addattr_nest(nlmsg, req_size, RTA_ENCAP);
1153 addattr_l(nlmsg, req_size, MPLS_IPTUNNEL_DST, &out_lse,
1154 num_labels * sizeof(mpls_lse_t));
1155 addattr_nest_end(nlmsg, nest);
1156 }
1157 }
1158
1159 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
1160 rtmsg->rtm_flags |= RTNH_F_ONLINK;
1161
1162 if (rtmsg->rtm_family == AF_INET
1163 && (nexthop->type == NEXTHOP_TYPE_IPV6
1164 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) {
1165 rtmsg->rtm_flags |= RTNH_F_ONLINK;
1166 addattr_l(nlmsg, req_size, RTA_GATEWAY, &ipv4_ll, 4);
1167 addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
1168
1169 if (nexthop->rmap_src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
1170 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1171 &nexthop->rmap_src.ipv4, bytelen);
1172 else if (nexthop->src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
1173 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1174 &nexthop->src.ipv4, bytelen);
1175
1176 if (IS_ZEBRA_DEBUG_KERNEL)
1177 zlog_debug(
1178 " 5549: _netlink_route_build_singlepath() (%s): "
1179 "nexthop via %s %s if %u(%u)",
1180 routedesc, ipv4_ll_buf, label_buf,
1181 nexthop->ifindex, nexthop->vrf_id);
1182 return;
1183 }
1184
1185 if (nexthop->type == NEXTHOP_TYPE_IPV4
1186 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
1187 /* Send deletes to the kernel without specifying the next-hop */
1188 if (cmd != RTM_DELROUTE)
1189 _netlink_route_nl_add_gateway_info(
1190 rtmsg->rtm_family, AF_INET, nlmsg, req_size,
1191 bytelen, nexthop);
1192
1193 if (cmd == RTM_NEWROUTE) {
1194 if (nexthop->rmap_src.ipv4.s_addr)
1195 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1196 &nexthop->rmap_src.ipv4, bytelen);
1197 else if (nexthop->src.ipv4.s_addr)
1198 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1199 &nexthop->src.ipv4, bytelen);
1200 }
1201
1202 if (IS_ZEBRA_DEBUG_KERNEL)
1203 zlog_debug(
1204 "netlink_route_multipath() (%s): "
1205 "nexthop via %s %s if %u(%u)",
1206 routedesc, inet_ntoa(nexthop->gate.ipv4),
1207 label_buf, nexthop->ifindex, nexthop->vrf_id);
1208 }
1209
1210 if (nexthop->type == NEXTHOP_TYPE_IPV6
1211 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
1212 _netlink_route_nl_add_gateway_info(rtmsg->rtm_family, AF_INET6,
1213 nlmsg, req_size, bytelen,
1214 nexthop);
1215
1216 if (cmd == RTM_NEWROUTE) {
1217 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
1218 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1219 &nexthop->rmap_src.ipv6, bytelen);
1220 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
1221 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1222 &nexthop->src.ipv6, bytelen);
1223 }
1224
1225 if (IS_ZEBRA_DEBUG_KERNEL)
1226 zlog_debug(
1227 "netlink_route_multipath() (%s): "
1228 "nexthop via %s %s if %u(%u)",
1229 routedesc, inet6_ntoa(nexthop->gate.ipv6),
1230 label_buf, nexthop->ifindex, nexthop->vrf_id);
1231 }
1232
1233 /*
1234 * We have the ifindex so we should always send it
1235 * This is especially useful if we are doing route
1236 * leaking.
1237 */
1238 if (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)
1239 addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
1240
1241 if (nexthop->type == NEXTHOP_TYPE_IFINDEX) {
1242 if (cmd == RTM_NEWROUTE) {
1243 if (nexthop->rmap_src.ipv4.s_addr)
1244 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1245 &nexthop->rmap_src.ipv4, bytelen);
1246 else if (nexthop->src.ipv4.s_addr)
1247 addattr_l(nlmsg, req_size, RTA_PREFSRC,
1248 &nexthop->src.ipv4, bytelen);
1249 }
1250
1251 if (IS_ZEBRA_DEBUG_KERNEL)
1252 zlog_debug(
1253 "netlink_route_multipath() (%s): "
1254 "nexthop via if %u(%u)",
1255 routedesc, nexthop->ifindex, nexthop->vrf_id);
1256 }
1257 }
1258
1259 /* This function takes a nexthop as argument and
1260 * appends to the given rtattr/rtnexthop pair the
1261 * representation of the nexthop. If the nexthop
1262 * defines a preferred source, the src parameter
1263 * will be modified to point to that src, otherwise
1264 * it will be kept unmodified.
1265 *
1266 * @param routedesc: Human readable description of route type
1267 * (direct/recursive, single-/multipath)
1268 * @param bytelen: Length of addresses in bytes.
1269 * @param nexthop: Nexthop information
1270 * @param rta: rtnetlink attribute structure
1271 * @param rtnh: pointer to an rtnetlink nexthop structure
1272 * @param src: pointer pointing to a location where
1273 * the prefsrc should be stored.
1274 */
1275 static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
1276 const struct nexthop *nexthop,
1277 struct rtattr *rta,
1278 struct rtnexthop *rtnh,
1279 struct rtmsg *rtmsg,
1280 const union g_addr **src)
1281 {
1282 mpls_lse_t out_lse[MPLS_MAX_LABELS];
1283 char label_buf[256];
1284 int num_labels = 0;
1285
1286 rtnh->rtnh_len = sizeof(*rtnh);
1287 rtnh->rtnh_flags = 0;
1288 rtnh->rtnh_hops = 0;
1289 rta->rta_len += rtnh->rtnh_len;
1290
1291 assert(nexthop);
1292
1293 /*
1294 * label_buf is *only* currently used within debugging.
1295 * As such when we assign it we are guarding it inside
1296 * a debug test. If you want to change this make sure
1297 * you fix this assumption
1298 */
1299 label_buf[0] = '\0';
1300
1301 num_labels = build_label_stack(nexthop->nh_label, out_lse, label_buf,
1302 sizeof(label_buf));
1303
1304 if (num_labels) {
1305 /* Set the BoS bit */
1306 out_lse[num_labels - 1] |= htonl(1 << MPLS_LS_S_SHIFT);
1307
1308 if (rtmsg->rtm_family == AF_MPLS) {
1309 rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_NEWDST,
1310 &out_lse,
1311 num_labels * sizeof(mpls_lse_t));
1312 rtnh->rtnh_len +=
1313 RTA_LENGTH(num_labels * sizeof(mpls_lse_t));
1314 } else {
1315 struct rtattr *nest;
1316 uint16_t encap = LWTUNNEL_ENCAP_MPLS;
1317 int len = rta->rta_len;
1318
1319 rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_ENCAP_TYPE,
1320 &encap, sizeof(uint16_t));
1321 nest = rta_nest(rta, NL_PKT_BUF_SIZE, RTA_ENCAP);
1322 rta_addattr_l(rta, NL_PKT_BUF_SIZE, MPLS_IPTUNNEL_DST,
1323 &out_lse,
1324 num_labels * sizeof(mpls_lse_t));
1325 rta_nest_end(rta, nest);
1326 rtnh->rtnh_len += rta->rta_len - len;
1327 }
1328 }
1329
1330 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
1331 rtnh->rtnh_flags |= RTNH_F_ONLINK;
1332
1333 if (rtmsg->rtm_family == AF_INET
1334 && (nexthop->type == NEXTHOP_TYPE_IPV6
1335 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) {
1336 bytelen = 4;
1337 rtnh->rtnh_flags |= RTNH_F_ONLINK;
1338 rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_GATEWAY, &ipv4_ll,
1339 bytelen);
1340 rtnh->rtnh_len += sizeof(struct rtattr) + bytelen;
1341 rtnh->rtnh_ifindex = nexthop->ifindex;
1342
1343 if (nexthop->rmap_src.ipv4.s_addr)
1344 *src = &nexthop->rmap_src;
1345 else if (nexthop->src.ipv4.s_addr)
1346 *src = &nexthop->src;
1347
1348 if (IS_ZEBRA_DEBUG_KERNEL)
1349 zlog_debug(
1350 " 5549: netlink_route_build_multipath() (%s): "
1351 "nexthop via %s %s if %u",
1352 routedesc, ipv4_ll_buf, label_buf,
1353 nexthop->ifindex);
1354 return;
1355 }
1356
1357 if (nexthop->type == NEXTHOP_TYPE_IPV4
1358 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
1359 _netlink_route_rta_add_gateway_info(rtmsg->rtm_family, AF_INET,
1360 rta, rtnh, NL_PKT_BUF_SIZE,
1361 bytelen, nexthop);
1362 if (nexthop->rmap_src.ipv4.s_addr)
1363 *src = &nexthop->rmap_src;
1364 else if (nexthop->src.ipv4.s_addr)
1365 *src = &nexthop->src;
1366
1367 if (IS_ZEBRA_DEBUG_KERNEL)
1368 zlog_debug(
1369 "netlink_route_multipath() (%s): "
1370 "nexthop via %s %s if %u",
1371 routedesc, inet_ntoa(nexthop->gate.ipv4),
1372 label_buf, nexthop->ifindex);
1373 }
1374 if (nexthop->type == NEXTHOP_TYPE_IPV6
1375 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
1376 _netlink_route_rta_add_gateway_info(rtmsg->rtm_family, AF_INET6,
1377 rta, rtnh, NL_PKT_BUF_SIZE,
1378 bytelen, nexthop);
1379
1380 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
1381 *src = &nexthop->rmap_src;
1382 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
1383 *src = &nexthop->src;
1384
1385 if (IS_ZEBRA_DEBUG_KERNEL)
1386 zlog_debug(
1387 "netlink_route_multipath() (%s): "
1388 "nexthop via %s %s if %u",
1389 routedesc, inet6_ntoa(nexthop->gate.ipv6),
1390 label_buf, nexthop->ifindex);
1391 }
1392
1393 /*
1394 * We have figured out the ifindex so we should always send it
1395 * This is especially useful if we are doing route
1396 * leaking.
1397 */
1398 if (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)
1399 rtnh->rtnh_ifindex = nexthop->ifindex;
1400
1401 /* ifindex */
1402 if (nexthop->type == NEXTHOP_TYPE_IFINDEX) {
1403 if (nexthop->rmap_src.ipv4.s_addr)
1404 *src = &nexthop->rmap_src;
1405 else if (nexthop->src.ipv4.s_addr)
1406 *src = &nexthop->src;
1407
1408 if (IS_ZEBRA_DEBUG_KERNEL)
1409 zlog_debug(
1410 "netlink_route_multipath() (%s): "
1411 "nexthop via if %u",
1412 routedesc, nexthop->ifindex);
1413 }
1414 }
1415
1416 static inline void _netlink_mpls_build_singlepath(const char *routedesc,
1417 const zebra_nhlfe_t *nhlfe,
1418 struct nlmsghdr *nlmsg,
1419 struct rtmsg *rtmsg,
1420 size_t req_size, int cmd)
1421 {
1422 int bytelen;
1423 uint8_t family;
1424
1425 family = NHLFE_FAMILY(nhlfe);
1426 bytelen = (family == AF_INET ? 4 : 16);
1427 _netlink_route_build_singlepath(routedesc, bytelen, nhlfe->nexthop,
1428 nlmsg, rtmsg, req_size, cmd);
1429 }
1430
1431
1432 static inline void
1433 _netlink_mpls_build_multipath(const char *routedesc, const zebra_nhlfe_t *nhlfe,
1434 struct rtattr *rta, struct rtnexthop *rtnh,
1435 struct rtmsg *rtmsg, const union g_addr **src)
1436 {
1437 int bytelen;
1438 uint8_t family;
1439
1440 family = NHLFE_FAMILY(nhlfe);
1441 bytelen = (family == AF_INET ? 4 : 16);
1442 _netlink_route_build_multipath(routedesc, bytelen, nhlfe->nexthop, rta,
1443 rtnh, rtmsg, src);
1444 }
1445
1446
1447 /* Log debug information for netlink_route_multipath
1448 * if debug logging is enabled.
1449 *
1450 * @param cmd: Netlink command which is to be processed
1451 * @param p: Prefix for which the change is due
1452 * @param family: Address family which the change concerns
1453 * @param zvrf: The vrf we are in
1454 * @param tableid: The table we are working on
1455 */
1456 static void _netlink_route_debug(int cmd, const struct prefix *p,
1457 int family, vrf_id_t vrfid,
1458 uint32_t tableid)
1459 {
1460 if (IS_ZEBRA_DEBUG_KERNEL) {
1461 char buf[PREFIX_STRLEN];
1462 zlog_debug(
1463 "netlink_route_multipath(): %s %s vrf %u(%u)",
1464 nl_msg_type_to_str(cmd),
1465 prefix2str(p, buf, sizeof(buf)),
1466 vrfid, tableid);
1467 }
1468 }
1469
1470 static void _netlink_nexthop_debug(int cmd, uint32_t id)
1471 {
1472 if (IS_ZEBRA_DEBUG_KERNEL)
1473 zlog_debug("netlink_nexthop(): %s, id=%u",
1474 nl_msg_type_to_str(cmd), id);
1475 }
1476
1477 static void _netlink_mpls_debug(int cmd, uint32_t label, const char *routedesc)
1478 {
1479 if (IS_ZEBRA_DEBUG_KERNEL)
1480 zlog_debug("netlink_mpls_multipath() (%s): %s %u/20", routedesc,
1481 nl_msg_type_to_str(cmd), label);
1482 }
1483
1484 static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
1485 int llalen, ns_id_t ns_id)
1486 {
1487 uint8_t protocol = RTPROT_ZEBRA;
1488 struct {
1489 struct nlmsghdr n;
1490 struct ndmsg ndm;
1491 char buf[256];
1492 } req;
1493
1494 struct zebra_ns *zns = zebra_ns_lookup(ns_id);
1495
1496 memset(&req, 0, sizeof(req));
1497
1498 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
1499 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1500 req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH
1501 req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
1502
1503 req.ndm.ndm_family = AF_INET;
1504 req.ndm.ndm_state = NUD_PERMANENT;
1505 req.ndm.ndm_ifindex = ifindex;
1506 req.ndm.ndm_type = RTN_UNICAST;
1507
1508 addattr_l(&req.n, sizeof(req),
1509 NDA_PROTOCOL, &protocol, sizeof(protocol));
1510 addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4);
1511 addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
1512
1513 return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
1514 0);
1515 }
1516
1517 /*
1518 * Routing table change via netlink interface, using a dataplane context object
1519 */
1520 static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
1521 {
1522 int bytelen;
1523 struct nexthop *nexthop = NULL;
1524 unsigned int nexthop_num;
1525 int family;
1526 const char *routedesc;
1527 int setsrc = 0;
1528 union g_addr src;
1529 const struct prefix *p, *src_p;
1530 uint32_t table_id;
1531
1532 struct {
1533 struct nlmsghdr n;
1534 struct rtmsg r;
1535 char buf[NL_PKT_BUF_SIZE];
1536 } req;
1537
1538 p = dplane_ctx_get_dest(ctx);
1539 src_p = dplane_ctx_get_src(ctx);
1540
1541 family = PREFIX_FAMILY(p);
1542
1543 memset(&req, 0, sizeof(req) - NL_PKT_BUF_SIZE);
1544
1545 bytelen = (family == AF_INET ? 4 : 16);
1546
1547 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
1548 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1549
1550 if ((cmd == RTM_NEWROUTE) &&
1551 ((p->family == AF_INET) || v6_rr_semantics))
1552 req.n.nlmsg_flags |= NLM_F_REPLACE;
1553
1554 req.n.nlmsg_type = cmd;
1555
1556 req.n.nlmsg_pid = dplane_ctx_get_ns(ctx)->nls.snl.nl_pid;
1557
1558 req.r.rtm_family = family;
1559 req.r.rtm_dst_len = p->prefixlen;
1560 req.r.rtm_src_len = src_p ? src_p->prefixlen : 0;
1561 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1562
1563 if (cmd == RTM_DELROUTE)
1564 req.r.rtm_protocol = zebra2proto(dplane_ctx_get_old_type(ctx));
1565 else
1566 req.r.rtm_protocol = zebra2proto(dplane_ctx_get_type(ctx));
1567
1568 /*
1569 * blackhole routes are not RTN_UNICAST, they are
1570 * RTN_ BLACKHOLE|UNREACHABLE|PROHIBIT
1571 * so setting this value as a RTN_UNICAST would
1572 * cause the route lookup of just the prefix
1573 * to fail. So no need to specify this for
1574 * the RTM_DELROUTE case
1575 */
1576 if (cmd != RTM_DELROUTE)
1577 req.r.rtm_type = RTN_UNICAST;
1578
1579 addattr_l(&req.n, sizeof(req), RTA_DST, &p->u.prefix, bytelen);
1580 if (src_p)
1581 addattr_l(&req.n, sizeof(req), RTA_SRC, &src_p->u.prefix,
1582 bytelen);
1583
1584 /* Metric. */
1585 /* Hardcode the metric for all routes coming from zebra. Metric isn't
1586 * used
1587 * either by the kernel or by zebra. Its purely for calculating best
1588 * path(s)
1589 * by the routing protocol and for communicating with protocol peers.
1590 */
1591 addattr32(&req.n, sizeof(req), RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC);
1592
1593 #if defined(SUPPORT_REALMS)
1594 {
1595 route_tag_t tag;
1596
1597 if (cmd == RTM_DELROUTE)
1598 tag = dplane_ctx_get_old_tag(ctx);
1599 else
1600 tag = dplane_ctx_get_tag(ctx);
1601
1602 if (tag > 0 && tag <= 255)
1603 addattr32(&req.n, sizeof(req), RTA_FLOW, tag);
1604 }
1605 #endif
1606 /* Table corresponding to this route. */
1607 table_id = dplane_ctx_get_table(ctx);
1608 if (table_id < 256)
1609 req.r.rtm_table = table_id;
1610 else {
1611 req.r.rtm_table = RT_TABLE_UNSPEC;
1612 addattr32(&req.n, sizeof(req), RTA_TABLE, table_id);
1613 }
1614
1615 _netlink_route_debug(cmd, p, family, dplane_ctx_get_vrf(ctx), table_id);
1616
1617 /*
1618 * If we are not updating the route and we have received
1619 * a route delete, then all we need to fill in is the
1620 * prefix information to tell the kernel to schwack
1621 * it.
1622 */
1623 if (cmd == RTM_DELROUTE)
1624 goto skip;
1625
1626 if (dplane_ctx_get_mtu(ctx) || dplane_ctx_get_nh_mtu(ctx)) {
1627 char buf[NL_PKT_BUF_SIZE];
1628 struct rtattr *rta = (void *)buf;
1629 uint32_t mtu = dplane_ctx_get_mtu(ctx);
1630 uint32_t nexthop_mtu = dplane_ctx_get_nh_mtu(ctx);
1631
1632 if (!mtu || (nexthop_mtu && nexthop_mtu < mtu))
1633 mtu = nexthop_mtu;
1634 rta->rta_type = RTA_METRICS;
1635 rta->rta_len = RTA_LENGTH(0);
1636 rta_addattr_l(rta, NL_PKT_BUF_SIZE,
1637 RTAX_MTU, &mtu, sizeof(mtu));
1638 addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA(rta),
1639 RTA_PAYLOAD(rta));
1640 }
1641
1642 if (supports_nh) {
1643 /* Kernel supports nexthop objects */
1644 addattr32(&req.n, sizeof(req), RTA_NH_ID,
1645 dplane_ctx_get_nhe_id(ctx));
1646 goto skip;
1647 }
1648
1649 /* Count overall nexthops so we can decide whether to use singlepath
1650 * or multipath case.
1651 */
1652 nexthop_num = 0;
1653 for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) {
1654 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1655 continue;
1656 if (cmd == RTM_NEWROUTE && !NEXTHOP_IS_ACTIVE(nexthop->flags))
1657 continue;
1658
1659 nexthop_num++;
1660 }
1661
1662 /* Singlepath case. */
1663 if (nexthop_num == 1) {
1664 nexthop_num = 0;
1665 for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) {
1666 /*
1667 * So we want to cover 2 types of blackhole
1668 * routes here:
1669 * 1) A normal blackhole route( ala from a static
1670 * install.
1671 * 2) A recursively resolved blackhole route
1672 */
1673 if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) {
1674 switch (nexthop->bh_type) {
1675 case BLACKHOLE_ADMINPROHIB:
1676 req.r.rtm_type = RTN_PROHIBIT;
1677 break;
1678 case BLACKHOLE_REJECT:
1679 req.r.rtm_type = RTN_UNREACHABLE;
1680 break;
1681 default:
1682 req.r.rtm_type = RTN_BLACKHOLE;
1683 break;
1684 }
1685 goto skip;
1686 }
1687 if (CHECK_FLAG(nexthop->flags,
1688 NEXTHOP_FLAG_RECURSIVE)) {
1689
1690 if (setsrc)
1691 continue;
1692
1693 if (family == AF_INET) {
1694 if (nexthop->rmap_src.ipv4.s_addr
1695 != 0) {
1696 src.ipv4 =
1697 nexthop->rmap_src.ipv4;
1698 setsrc = 1;
1699 } else if (nexthop->src.ipv4.s_addr
1700 != 0) {
1701 src.ipv4 =
1702 nexthop->src.ipv4;
1703 setsrc = 1;
1704 }
1705 } else if (family == AF_INET6) {
1706 if (!IN6_IS_ADDR_UNSPECIFIED(
1707 &nexthop->rmap_src.ipv6)) {
1708 src.ipv6 =
1709 nexthop->rmap_src.ipv6;
1710 setsrc = 1;
1711 } else if (
1712 !IN6_IS_ADDR_UNSPECIFIED(
1713 &nexthop->src.ipv6)) {
1714 src.ipv6 =
1715 nexthop->src.ipv6;
1716 setsrc = 1;
1717 }
1718 }
1719 continue;
1720 }
1721
1722 if ((cmd == RTM_NEWROUTE
1723 && NEXTHOP_IS_ACTIVE(nexthop->flags))) {
1724 routedesc = nexthop->rparent
1725 ? "recursive, single-path"
1726 : "single-path";
1727
1728 _netlink_route_build_singlepath(
1729 routedesc, bytelen, nexthop, &req.n,
1730 &req.r, sizeof(req), cmd);
1731 nexthop_num++;
1732 break;
1733 }
1734 }
1735 if (setsrc && (cmd == RTM_NEWROUTE)) {
1736 if (family == AF_INET)
1737 addattr_l(&req.n, sizeof(req), RTA_PREFSRC,
1738 &src.ipv4, bytelen);
1739 else if (family == AF_INET6)
1740 addattr_l(&req.n, sizeof(req), RTA_PREFSRC,
1741 &src.ipv6, bytelen);
1742 }
1743 } else { /* Multipath case */
1744 char buf[NL_PKT_BUF_SIZE];
1745 struct rtattr *rta = (void *)buf;
1746 struct rtnexthop *rtnh;
1747 const union g_addr *src1 = NULL;
1748
1749 rta->rta_type = RTA_MULTIPATH;
1750 rta->rta_len = RTA_LENGTH(0);
1751 rtnh = RTA_DATA(rta);
1752
1753 nexthop_num = 0;
1754 for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) {
1755 if (CHECK_FLAG(nexthop->flags,
1756 NEXTHOP_FLAG_RECURSIVE)) {
1757 /* This only works for IPv4 now */
1758 if (setsrc)
1759 continue;
1760
1761 if (family == AF_INET) {
1762 if (nexthop->rmap_src.ipv4.s_addr
1763 != 0) {
1764 src.ipv4 =
1765 nexthop->rmap_src.ipv4;
1766 setsrc = 1;
1767 } else if (nexthop->src.ipv4.s_addr
1768 != 0) {
1769 src.ipv4 =
1770 nexthop->src.ipv4;
1771 setsrc = 1;
1772 }
1773 } else if (family == AF_INET6) {
1774 if (!IN6_IS_ADDR_UNSPECIFIED(
1775 &nexthop->rmap_src.ipv6)) {
1776 src.ipv6 =
1777 nexthop->rmap_src.ipv6;
1778 setsrc = 1;
1779 } else if (
1780 !IN6_IS_ADDR_UNSPECIFIED(
1781 &nexthop->src.ipv6)) {
1782 src.ipv6 =
1783 nexthop->src.ipv6;
1784 setsrc = 1;
1785 }
1786 }
1787
1788 continue;
1789 }
1790
1791 if ((cmd == RTM_NEWROUTE
1792 && NEXTHOP_IS_ACTIVE(nexthop->flags))) {
1793 routedesc = nexthop->rparent
1794 ? "recursive, multipath"
1795 : "multipath";
1796 nexthop_num++;
1797
1798 _netlink_route_build_multipath(
1799 routedesc, bytelen, nexthop, rta, rtnh,
1800 &req.r, &src1);
1801 rtnh = RTNH_NEXT(rtnh);
1802
1803 if (!setsrc && src1) {
1804 if (family == AF_INET)
1805 src.ipv4 = src1->ipv4;
1806 else if (family == AF_INET6)
1807 src.ipv6 = src1->ipv6;
1808
1809 setsrc = 1;
1810 }
1811 }
1812 }
1813 if (setsrc && (cmd == RTM_NEWROUTE)) {
1814 if (family == AF_INET)
1815 addattr_l(&req.n, sizeof(req), RTA_PREFSRC,
1816 &src.ipv4, bytelen);
1817 else if (family == AF_INET6)
1818 addattr_l(&req.n, sizeof(req), RTA_PREFSRC,
1819 &src.ipv6, bytelen);
1820 if (IS_ZEBRA_DEBUG_KERNEL)
1821 zlog_debug("Setting source");
1822 }
1823
1824 if (rta->rta_len > RTA_LENGTH(0))
1825 addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH,
1826 RTA_DATA(rta), RTA_PAYLOAD(rta));
1827 }
1828
1829 /* If there is no useful nexthop then return. */
1830 if (nexthop_num == 0) {
1831 if (IS_ZEBRA_DEBUG_KERNEL)
1832 zlog_debug(
1833 "netlink_route_multipath(): No useful nexthop.");
1834 return 0;
1835 }
1836
1837 skip:
1838 /* Talk to netlink socket. */
1839 return netlink_talk_info(netlink_talk_filter, &req.n,
1840 dplane_ctx_get_ns(ctx), 0);
1841 }
1842
1843 int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in)
1844 {
1845 uint32_t actual_table;
1846 int suc = 0;
1847 struct mcast_route_data *mr = (struct mcast_route_data *)in;
1848 struct {
1849 struct nlmsghdr n;
1850 struct ndmsg ndm;
1851 char buf[256];
1852 } req;
1853
1854 mroute = mr;
1855 struct zebra_ns *zns;
1856
1857 zns = zvrf->zns;
1858 memset(&req, 0, sizeof(req));
1859
1860 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
1861 req.n.nlmsg_flags = NLM_F_REQUEST;
1862 req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
1863
1864 req.ndm.ndm_family = RTNL_FAMILY_IPMR;
1865 req.n.nlmsg_type = RTM_GETROUTE;
1866
1867 addattr_l(&req.n, sizeof(req), RTA_IIF, &mroute->ifindex, 4);
1868 addattr_l(&req.n, sizeof(req), RTA_OIF, &mroute->ifindex, 4);
1869 addattr_l(&req.n, sizeof(req), RTA_SRC, &mroute->sg.src.s_addr, 4);
1870 addattr_l(&req.n, sizeof(req), RTA_DST, &mroute->sg.grp.s_addr, 4);
1871 /*
1872 * What?
1873 *
1874 * So during the namespace cleanup we started storing
1875 * the zvrf table_id for the default table as RT_TABLE_MAIN
1876 * which is what the normal routing table for ip routing is.
1877 * This change caused this to break our lookups of sg data
1878 * because prior to this change the zvrf->table_id was 0
1879 * and when the pim multicast kernel code saw a 0,
1880 * it was auto-translated to RT_TABLE_DEFAULT. But since
1881 * we are now passing in RT_TABLE_MAIN there is no auto-translation
1882 * and the kernel goes screw you and the delicious cookies you
1883 * are trying to give me. So now we have this little hack.
1884 */
1885 actual_table = (zvrf->table_id == RT_TABLE_MAIN) ? RT_TABLE_DEFAULT :
1886 zvrf->table_id;
1887 addattr_l(&req.n, sizeof(req), RTA_TABLE, &actual_table, 4);
1888
1889 suc = netlink_talk(netlink_route_change_read_multicast, &req.n,
1890 &zns->netlink_cmd, zns, 0);
1891
1892 mroute = NULL;
1893 return suc;
1894 }
1895
1896 /* Char length to debug ID with */
1897 #define ID_LENGTH 10
1898
1899 static void _netlink_nexthop_build_group(struct nlmsghdr *n, size_t req_size,
1900 uint32_t id,
1901 const struct nh_grp *z_grp,
1902 const uint8_t count)
1903 {
1904 struct nexthop_grp grp[count];
1905 /* Need space for max group size, "/", and null term */
1906 char buf[(MULTIPATH_NUM * (ID_LENGTH + 1)) + 1];
1907 char buf1[ID_LENGTH + 2];
1908
1909 buf[0] = '\0';
1910
1911 memset(grp, 0, sizeof(grp));
1912
1913 if (count) {
1914 for (int i = 0; i < count; i++) {
1915 grp[i].id = z_grp[i].id;
1916 grp[i].weight = z_grp[i].weight;
1917
1918 if (IS_ZEBRA_DEBUG_KERNEL) {
1919 if (i == 0)
1920 snprintf(buf, sizeof(buf1), "group %u",
1921 grp[i].id);
1922 else {
1923 snprintf(buf1, sizeof(buf1), "/%u",
1924 grp[i].id);
1925 strlcat(buf, buf1, sizeof(buf));
1926 }
1927 }
1928 }
1929 addattr_l(n, req_size, NHA_GROUP, grp, count * sizeof(*grp));
1930 }
1931
1932 if (IS_ZEBRA_DEBUG_KERNEL)
1933 zlog_debug("%s: ID (%u): %s", __func__, id, buf);
1934 }
1935
1936 /**
1937 * netlink_nexthop() - Nexthop change via the netlink interface
1938 *
1939 * @ctx: Dataplane ctx
1940 *
1941 * Return: Result status
1942 */
1943 static int netlink_nexthop(int cmd, struct zebra_dplane_ctx *ctx)
1944 {
1945 struct {
1946 struct nlmsghdr n;
1947 struct nhmsg nhm;
1948 char buf[NL_PKT_BUF_SIZE];
1949 } req;
1950
1951 mpls_lse_t out_lse[MPLS_MAX_LABELS];
1952 char label_buf[256];
1953 int num_labels = 0;
1954 size_t req_size = sizeof(req);
1955
1956 /* Nothing to do if the kernel doesn't support nexthop objects */
1957 if (!supports_nh)
1958 return 0;
1959
1960 label_buf[0] = '\0';
1961
1962 memset(&req, 0, req_size);
1963
1964 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct nhmsg));
1965 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1966
1967 if (cmd == RTM_NEWNEXTHOP)
1968 req.n.nlmsg_flags |= NLM_F_REPLACE;
1969
1970 req.n.nlmsg_type = cmd;
1971 req.n.nlmsg_pid = dplane_ctx_get_ns(ctx)->nls.snl.nl_pid;
1972
1973 req.nhm.nh_family = AF_UNSPEC;
1974 /* TODO: Scope? */
1975
1976 uint32_t id = dplane_ctx_get_nhe_id(ctx);
1977
1978 if (!id) {
1979 flog_err(
1980 EC_ZEBRA_NHG_FIB_UPDATE,
1981 "Failed trying to update a nexthop group in the kernel that does not have an ID");
1982 return -1;
1983 }
1984
1985 addattr32(&req.n, req_size, NHA_ID, id);
1986
1987 if (cmd == RTM_NEWNEXTHOP) {
1988 if (dplane_ctx_get_nhe_nh_grp_count(ctx))
1989 _netlink_nexthop_build_group(
1990 &req.n, req_size, id,
1991 dplane_ctx_get_nhe_nh_grp(ctx),
1992 dplane_ctx_get_nhe_nh_grp_count(ctx));
1993 else {
1994 const struct nexthop *nh =
1995 dplane_ctx_get_nhe_ng(ctx)->nexthop;
1996 afi_t afi = dplane_ctx_get_nhe_afi(ctx);
1997
1998 if (afi == AFI_IP)
1999 req.nhm.nh_family = AF_INET;
2000 else if (afi == AFI_IP6)
2001 req.nhm.nh_family = AF_INET6;
2002
2003 switch (nh->type) {
2004 case NEXTHOP_TYPE_IPV4:
2005 case NEXTHOP_TYPE_IPV4_IFINDEX:
2006 addattr_l(&req.n, req_size, NHA_GATEWAY,
2007 &nh->gate.ipv4, IPV4_MAX_BYTELEN);
2008 break;
2009 case NEXTHOP_TYPE_IPV6:
2010 case NEXTHOP_TYPE_IPV6_IFINDEX:
2011 addattr_l(&req.n, req_size, NHA_GATEWAY,
2012 &nh->gate.ipv6, IPV6_MAX_BYTELEN);
2013 break;
2014 case NEXTHOP_TYPE_BLACKHOLE:
2015 addattr_l(&req.n, req_size, NHA_BLACKHOLE, NULL,
2016 0);
2017 /* Blackhole shouldn't have anymore attributes
2018 */
2019 goto nexthop_done;
2020 case NEXTHOP_TYPE_IFINDEX:
2021 /* Don't need anymore info for this */
2022 break;
2023 }
2024
2025 if (!nh->ifindex) {
2026 flog_err(
2027 EC_ZEBRA_NHG_FIB_UPDATE,
2028 "Context received for kernel nexthop update without an interface");
2029 return -1;
2030 }
2031
2032 addattr32(&req.n, req_size, NHA_OIF, nh->ifindex);
2033
2034 num_labels =
2035 build_label_stack(nh->nh_label, out_lse,
2036 label_buf, sizeof(label_buf));
2037
2038 if (num_labels) {
2039 /* Set the BoS bit */
2040 out_lse[num_labels - 1] |=
2041 htonl(1 << MPLS_LS_S_SHIFT);
2042
2043 /*
2044 * TODO: MPLS unsupported for now in kernel.
2045 */
2046 if (req.nhm.nh_family == AF_MPLS)
2047 goto nexthop_done;
2048 #if 0
2049 addattr_l(&req.n, req_size, NHA_NEWDST,
2050 &out_lse,
2051 num_labels
2052 * sizeof(mpls_lse_t));
2053 #endif
2054 else {
2055 struct rtattr *nest;
2056 uint16_t encap = LWTUNNEL_ENCAP_MPLS;
2057
2058 addattr_l(&req.n, req_size,
2059 NHA_ENCAP_TYPE, &encap,
2060 sizeof(uint16_t));
2061 nest = addattr_nest(&req.n, req_size,
2062 NHA_ENCAP);
2063 addattr_l(&req.n, req_size,
2064 MPLS_IPTUNNEL_DST, &out_lse,
2065 num_labels
2066 * sizeof(mpls_lse_t));
2067 addattr_nest_end(&req.n, nest);
2068 }
2069 }
2070
2071 nexthop_done:
2072 if (IS_ZEBRA_DEBUG_KERNEL) {
2073 char buf[NEXTHOP_STRLEN];
2074
2075 snprintfrr(buf, sizeof(buf), "%pNHv", nh);
2076 zlog_debug("%s: ID (%u): %s (%u) %s ", __func__,
2077 id, buf, nh->vrf_id, label_buf);
2078 }
2079 }
2080
2081 req.nhm.nh_protocol = zebra2proto(dplane_ctx_get_nhe_type(ctx));
2082
2083 } else if (cmd != RTM_DELNEXTHOP) {
2084 flog_err(
2085 EC_ZEBRA_NHG_FIB_UPDATE,
2086 "Nexthop group kernel update command (%d) does not exist",
2087 cmd);
2088 return -1;
2089 }
2090
2091 _netlink_nexthop_debug(cmd, id);
2092
2093 return netlink_talk_info(netlink_talk_filter, &req.n,
2094 dplane_ctx_get_ns(ctx), 0);
2095 }
2096
2097 /**
2098 * kernel_nexthop_update() - Update/delete a nexthop from the kernel
2099 *
2100 * @ctx: Dataplane context
2101 *
2102 * Return: Dataplane result flag
2103 */
2104 enum zebra_dplane_result kernel_nexthop_update(struct zebra_dplane_ctx *ctx)
2105 {
2106 int cmd = 0;
2107 int ret = 0;
2108
2109 switch (dplane_ctx_get_op(ctx)) {
2110 case DPLANE_OP_NH_DELETE:
2111 cmd = RTM_DELNEXTHOP;
2112 break;
2113 case DPLANE_OP_NH_INSTALL:
2114 case DPLANE_OP_NH_UPDATE:
2115 cmd = RTM_NEWNEXTHOP;
2116 break;
2117 case DPLANE_OP_ROUTE_INSTALL:
2118 case DPLANE_OP_ROUTE_UPDATE:
2119 case DPLANE_OP_ROUTE_DELETE:
2120 case DPLANE_OP_ROUTE_NOTIFY:
2121 case DPLANE_OP_LSP_INSTALL:
2122 case DPLANE_OP_LSP_UPDATE:
2123 case DPLANE_OP_LSP_DELETE:
2124 case DPLANE_OP_LSP_NOTIFY:
2125 case DPLANE_OP_PW_INSTALL:
2126 case DPLANE_OP_PW_UNINSTALL:
2127 case DPLANE_OP_SYS_ROUTE_ADD:
2128 case DPLANE_OP_SYS_ROUTE_DELETE:
2129 case DPLANE_OP_ADDR_INSTALL:
2130 case DPLANE_OP_ADDR_UNINSTALL:
2131 case DPLANE_OP_MAC_INSTALL:
2132 case DPLANE_OP_MAC_DELETE:
2133 case DPLANE_OP_NEIGH_INSTALL:
2134 case DPLANE_OP_NEIGH_UPDATE:
2135 case DPLANE_OP_NEIGH_DELETE:
2136 case DPLANE_OP_VTEP_ADD:
2137 case DPLANE_OP_VTEP_DELETE:
2138 case DPLANE_OP_NONE:
2139 flog_err(
2140 EC_ZEBRA_NHG_FIB_UPDATE,
2141 "Context received for kernel nexthop update with incorrect OP code (%u)",
2142 dplane_ctx_get_op(ctx));
2143 return ZEBRA_DPLANE_REQUEST_FAILURE;
2144 }
2145
2146 ret = netlink_nexthop(cmd, ctx);
2147
2148 return (ret == 0 ? ZEBRA_DPLANE_REQUEST_SUCCESS
2149 : ZEBRA_DPLANE_REQUEST_FAILURE);
2150 }
2151
2152 /*
2153 * Update or delete a prefix from the kernel,
2154 * using info from a dataplane context.
2155 */
2156 enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)
2157 {
2158 int cmd, ret;
2159 const struct prefix *p = dplane_ctx_get_dest(ctx);
2160 struct nexthop *nexthop;
2161
2162 if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_DELETE) {
2163 cmd = RTM_DELROUTE;
2164 } else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_INSTALL) {
2165 cmd = RTM_NEWROUTE;
2166 } else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_UPDATE) {
2167
2168 if (p->family == AF_INET || v6_rr_semantics) {
2169 /* Single 'replace' operation */
2170 cmd = RTM_NEWROUTE;
2171
2172 /*
2173 * With route replace semantics in place
2174 * for v4 routes and the new route is a system
2175 * route we do not install anything.
2176 * The problem here is that the new system
2177 * route should cause us to withdraw from
2178 * the kernel the old non-system route
2179 */
2180 if (RSYSTEM_ROUTE(dplane_ctx_get_type(ctx)) &&
2181 !RSYSTEM_ROUTE(dplane_ctx_get_old_type(ctx)))
2182 (void)netlink_route_multipath(RTM_DELROUTE,
2183 ctx);
2184 } else {
2185 /*
2186 * So v6 route replace semantics are not in
2187 * the kernel at this point as I understand it.
2188 * so let's do a delete then an add.
2189 * In the future once v6 route replace semantics
2190 * are in we can figure out what to do here to
2191 * allow working with old and new kernels.
2192 *
2193 * I'm also intentionally ignoring the failure case
2194 * of the route delete. If that happens yeah we're
2195 * screwed.
2196 */
2197 if (!RSYSTEM_ROUTE(dplane_ctx_get_old_type(ctx)))
2198 (void)netlink_route_multipath(RTM_DELROUTE,
2199 ctx);
2200 cmd = RTM_NEWROUTE;
2201 }
2202
2203 } else {
2204 return ZEBRA_DPLANE_REQUEST_FAILURE;
2205 }
2206
2207 if (!RSYSTEM_ROUTE(dplane_ctx_get_type(ctx)))
2208 ret = netlink_route_multipath(cmd, ctx);
2209 else
2210 ret = 0;
2211 if ((cmd == RTM_NEWROUTE) && (ret == 0)) {
2212 /* Update installed nexthops to signal which have been
2213 * installed.
2214 */
2215 for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) {
2216 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
2217 continue;
2218
2219 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) {
2220 SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
2221 }
2222 }
2223 }
2224
2225 return (ret == 0 ?
2226 ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE);
2227 }
2228
2229 /**
2230 * netlink_nexthop_process_nh() - Parse the gatway/if info from a new nexthop
2231 *
2232 * @tb: Netlink RTA data
2233 * @family: Address family in the nhmsg
2234 * @ifp: Interface connected - this should be NULL, we fill it in
2235 * @ns_id: Namspace id
2236 *
2237 * Return: New nexthop
2238 */
2239 static struct nexthop netlink_nexthop_process_nh(struct rtattr **tb,
2240 unsigned char family,
2241 struct interface **ifp,
2242 ns_id_t ns_id)
2243 {
2244 struct nexthop nh = {};
2245 void *gate = NULL;
2246 enum nexthop_types_t type = 0;
2247 int if_index = 0;
2248 size_t sz = 0;
2249 struct interface *ifp_lookup;
2250
2251 if_index = *(int *)RTA_DATA(tb[NHA_OIF]);
2252
2253
2254 if (tb[NHA_GATEWAY]) {
2255 switch (family) {
2256 case AF_INET:
2257 type = NEXTHOP_TYPE_IPV4_IFINDEX;
2258 sz = 4;
2259 break;
2260 case AF_INET6:
2261 type = NEXTHOP_TYPE_IPV6_IFINDEX;
2262 sz = 16;
2263 break;
2264 default:
2265 flog_warn(
2266 EC_ZEBRA_BAD_NHG_MESSAGE,
2267 "Nexthop gateway with bad address family (%d) received from kernel",
2268 family);
2269 return nh;
2270 }
2271 gate = RTA_DATA(tb[NHA_GATEWAY]);
2272 } else
2273 type = NEXTHOP_TYPE_IFINDEX;
2274
2275 if (type)
2276 nh.type = type;
2277
2278 if (gate)
2279 memcpy(&(nh.gate), gate, sz);
2280
2281 if (if_index)
2282 nh.ifindex = if_index;
2283
2284 ifp_lookup =
2285 if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), nh.ifindex);
2286
2287 if (ifp)
2288 *ifp = ifp_lookup;
2289 if (ifp_lookup)
2290 nh.vrf_id = ifp_lookup->vrf_id;
2291 else {
2292 flog_warn(
2293 EC_ZEBRA_UNKNOWN_INTERFACE,
2294 "%s: Unknown nexthop interface %u received, defaulting to VRF_DEFAULT",
2295 __PRETTY_FUNCTION__, nh.ifindex);
2296
2297 nh.vrf_id = VRF_DEFAULT;
2298 }
2299
2300 if (tb[NHA_ENCAP] && tb[NHA_ENCAP_TYPE]) {
2301 uint16_t encap_type = *(uint16_t *)RTA_DATA(tb[NHA_ENCAP_TYPE]);
2302 int num_labels = 0;
2303
2304 mpls_label_t labels[MPLS_MAX_LABELS] = {0};
2305
2306 if (encap_type == LWTUNNEL_ENCAP_MPLS)
2307 num_labels = parse_encap_mpls(tb[NHA_ENCAP], labels);
2308
2309 if (num_labels)
2310 nexthop_add_labels(&nh, ZEBRA_LSP_STATIC, num_labels,
2311 labels);
2312 }
2313
2314 return nh;
2315 }
2316
2317 static int netlink_nexthop_process_group(struct rtattr **tb,
2318 struct nh_grp *z_grp, int z_grp_size)
2319 {
2320 uint8_t count = 0;
2321 /* linux/nexthop.h group struct */
2322 struct nexthop_grp *n_grp = NULL;
2323
2324 n_grp = (struct nexthop_grp *)RTA_DATA(tb[NHA_GROUP]);
2325 count = (RTA_PAYLOAD(tb[NHA_GROUP]) / sizeof(*n_grp));
2326
2327 if (!count || (count * sizeof(*n_grp)) != RTA_PAYLOAD(tb[NHA_GROUP])) {
2328 flog_warn(EC_ZEBRA_BAD_NHG_MESSAGE,
2329 "Invalid nexthop group received from the kernel");
2330 return count;
2331 }
2332
2333 #if 0
2334 // TODO: Need type for something?
2335 zlog_debug("Nexthop group type: %d",
2336 *((uint16_t *)RTA_DATA(tb[NHA_GROUP_TYPE])));
2337
2338 #endif
2339
2340 for (int i = 0; ((i < count) && (i < z_grp_size)); i++) {
2341 z_grp[i].id = n_grp[i].id;
2342 z_grp[i].weight = n_grp[i].weight;
2343 }
2344 return count;
2345 }
2346
2347 /**
2348 * netlink_nexthop_change() - Read in change about nexthops from the kernel
2349 *
2350 * @h: Netlink message header
2351 * @ns_id: Namspace id
2352 * @startup: Are we reading under startup conditions?
2353 *
2354 * Return: Result status
2355 */
2356 int netlink_nexthop_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
2357 {
2358 int len;
2359 /* nexthop group id */
2360 uint32_t id;
2361 unsigned char family;
2362 int type;
2363 afi_t afi = AFI_UNSPEC;
2364 vrf_id_t vrf_id = 0;
2365 struct interface *ifp = NULL;
2366 struct nhmsg *nhm = NULL;
2367 struct nexthop nh = {};
2368 struct nh_grp grp[MULTIPATH_NUM] = {};
2369 /* Count of nexthops in group array */
2370 uint8_t grp_count = 0;
2371 struct rtattr *tb[NHA_MAX + 1] = {};
2372
2373 nhm = NLMSG_DATA(h);
2374
2375 if (startup && h->nlmsg_type != RTM_NEWNEXTHOP)
2376 return 0;
2377
2378 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct nhmsg));
2379 if (len < 0) {
2380 zlog_warn(
2381 "%s: Message received from netlink is of a broken size %d %zu",
2382 __PRETTY_FUNCTION__, h->nlmsg_len,
2383 (size_t)NLMSG_LENGTH(sizeof(struct nhmsg)));
2384 return -1;
2385 }
2386
2387 netlink_parse_rtattr(tb, NHA_MAX, RTM_NHA(nhm), len);
2388
2389
2390 if (!tb[NHA_ID]) {
2391 flog_warn(
2392 EC_ZEBRA_BAD_NHG_MESSAGE,
2393 "Nexthop group without an ID received from the kernel");
2394 return -1;
2395 }
2396
2397 /* We use the ID key'd nhg table for kernel updates */
2398 id = *((uint32_t *)RTA_DATA(tb[NHA_ID]));
2399
2400 family = nhm->nh_family;
2401 afi = family2afi(family);
2402
2403 type = proto2zebra(nhm->nh_protocol, 0, true);
2404
2405 if (IS_ZEBRA_DEBUG_KERNEL)
2406 zlog_debug("%s ID (%u) %s NS %u",
2407 nl_msg_type_to_str(h->nlmsg_type), id,
2408 nl_family_to_str(family), ns_id);
2409
2410
2411 if (h->nlmsg_type == RTM_NEWNEXTHOP) {
2412 if (tb[NHA_GROUP]) {
2413 /**
2414 * If this is a group message its only going to have
2415 * an array of nexthop IDs associated with it
2416 */
2417 grp_count = netlink_nexthop_process_group(
2418 tb, grp, array_size(grp));
2419 } else {
2420 if (tb[NHA_BLACKHOLE]) {
2421 /**
2422 * This nexthop is just for blackhole-ing
2423 * traffic, it should not have an OIF, GATEWAY,
2424 * or ENCAP
2425 */
2426 nh.type = NEXTHOP_TYPE_BLACKHOLE;
2427 nh.bh_type = BLACKHOLE_UNSPEC;
2428 } else if (tb[NHA_OIF])
2429 /**
2430 * This is a true new nexthop, so we need
2431 * to parse the gateway and device info
2432 */
2433 nh = netlink_nexthop_process_nh(tb, family,
2434 &ifp, ns_id);
2435 else {
2436
2437 flog_warn(
2438 EC_ZEBRA_BAD_NHG_MESSAGE,
2439 "Invalid Nexthop message received from the kernel with ID (%u)",
2440 id);
2441 return -1;
2442 }
2443 SET_FLAG(nh.flags, NEXTHOP_FLAG_ACTIVE);
2444 if (nhm->nh_flags & RTNH_F_ONLINK)
2445 SET_FLAG(nh.flags, NEXTHOP_FLAG_ONLINK);
2446 vrf_id = nh.vrf_id;
2447 }
2448
2449 if (zebra_nhg_kernel_find(id, &nh, grp, grp_count, vrf_id, afi,
2450 type, startup))
2451 return -1;
2452
2453 } else if (h->nlmsg_type == RTM_DELNEXTHOP)
2454 zebra_nhg_kernel_del(id);
2455
2456 return 0;
2457 }
2458
2459 /**
2460 * netlink_request_nexthop() - Request nextop information from the kernel
2461 * @zns: Zebra namespace
2462 * @family: AF_* netlink family
2463 * @type: RTM_* route type
2464 *
2465 * Return: Result status
2466 */
2467 static int netlink_request_nexthop(struct zebra_ns *zns, int family, int type)
2468 {
2469 struct {
2470 struct nlmsghdr n;
2471 struct nhmsg nhm;
2472 } req;
2473
2474 /* Form the request, specifying filter (rtattr) if needed. */
2475 memset(&req, 0, sizeof(req));
2476 req.n.nlmsg_type = type;
2477 req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
2478 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct nhmsg));
2479 req.nhm.nh_family = family;
2480
2481 return netlink_request(&zns->netlink_cmd, &req.n);
2482 }
2483
2484
2485 /**
2486 * netlink_nexthop_read() - Nexthop read function using netlink interface
2487 *
2488 * @zns: Zebra name space
2489 *
2490 * Return: Result status
2491 * Only called at bootstrap time.
2492 */
2493 int netlink_nexthop_read(struct zebra_ns *zns)
2494 {
2495 int ret;
2496 struct zebra_dplane_info dp_info;
2497
2498 zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
2499
2500 /* Get nexthop objects */
2501 ret = netlink_request_nexthop(zns, AF_UNSPEC, RTM_GETNEXTHOP);
2502 if (ret < 0)
2503 return ret;
2504 ret = netlink_parse_info(netlink_nexthop_change, &zns->netlink_cmd,
2505 &dp_info, 0, 1);
2506
2507 if (!ret)
2508 /* If we succesfully read in nexthop objects,
2509 * this kernel must support them.
2510 */
2511 supports_nh = true;
2512 else if (IS_ZEBRA_DEBUG_KERNEL)
2513 zlog_debug("Nexthop objects not supported on this kernel");
2514
2515 return ret;
2516 }
2517
2518
2519 int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
2520 int llalen, ns_id_t ns_id)
2521 {
2522 return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex,
2523 addr, lla, llalen, ns_id);
2524 }
2525
2526 /*
2527 * Add remote VTEP to the flood list for this VxLAN interface (VNI). This
2528 * is done by adding an FDB entry with a MAC of 00:00:00:00:00:00.
2529 */
2530 static int netlink_vxlan_flood_update_ctx(const struct zebra_dplane_ctx *ctx,
2531 int cmd)
2532 {
2533 uint8_t protocol = RTPROT_ZEBRA;
2534 struct {
2535 struct nlmsghdr n;
2536 struct ndmsg ndm;
2537 char buf[256];
2538 } req;
2539 uint8_t dst_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
2540 const struct ipaddr *addr;
2541
2542 memset(&req, 0, sizeof(req));
2543
2544 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
2545 req.n.nlmsg_flags = NLM_F_REQUEST;
2546 if (cmd == RTM_NEWNEIGH)
2547 req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_APPEND);
2548 req.n.nlmsg_type = cmd;
2549 req.ndm.ndm_family = PF_BRIDGE;
2550 req.ndm.ndm_state = NUD_NOARP | NUD_PERMANENT;
2551 req.ndm.ndm_flags |= NTF_SELF; /* Handle by "self", not "master" */
2552
2553
2554 addattr_l(&req.n, sizeof(req),
2555 NDA_PROTOCOL, &protocol, sizeof(protocol));
2556 addattr_l(&req.n, sizeof(req), NDA_LLADDR, &dst_mac, 6);
2557 req.ndm.ndm_ifindex = dplane_ctx_get_ifindex(ctx);
2558
2559 addr = dplane_ctx_neigh_get_ipaddr(ctx);
2560
2561 addattr_l(&req.n, sizeof(req), NDA_DST, &(addr->ipaddr_v4), 4);
2562
2563 return netlink_talk_info(netlink_talk_filter, &req.n,
2564 dplane_ctx_get_ns(ctx), 0);
2565 }
2566
2567 #ifndef NDA_RTA
2568 #define NDA_RTA(r) \
2569 ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
2570 #endif
2571
2572 static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
2573 {
2574 struct ndmsg *ndm;
2575 struct interface *ifp;
2576 struct zebra_if *zif;
2577 struct rtattr *tb[NDA_MAX + 1];
2578 struct interface *br_if;
2579 struct ethaddr mac;
2580 vlanid_t vid = 0;
2581 struct prefix vtep_ip;
2582 int vid_present = 0, dst_present = 0;
2583 char buf[ETHER_ADDR_STRLEN];
2584 char vid_buf[20];
2585 char dst_buf[30];
2586 bool sticky;
2587
2588 ndm = NLMSG_DATA(h);
2589
2590 /* We only process macfdb notifications if EVPN is enabled */
2591 if (!is_evpn_enabled())
2592 return 0;
2593
2594 /* The interface should exist. */
2595 ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
2596 ndm->ndm_ifindex);
2597 if (!ifp || !ifp->info) {
2598 if (IS_ZEBRA_DEBUG_KERNEL)
2599 zlog_debug("\t%s without associated interface: %u",
2600 __PRETTY_FUNCTION__, ndm->ndm_ifindex);
2601 return 0;
2602 }
2603
2604 /* The interface should be something we're interested in. */
2605 if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) {
2606 if (IS_ZEBRA_DEBUG_KERNEL)
2607 zlog_debug("\t%s Not interested in %s, not a slave",
2608 __PRETTY_FUNCTION__, ifp->name);
2609 return 0;
2610 }
2611
2612 /* Drop "permanent" entries. */
2613 if (ndm->ndm_state & NUD_PERMANENT) {
2614 if (IS_ZEBRA_DEBUG_KERNEL)
2615 zlog_debug("\t%s Entry is PERMANENT, dropping",
2616 __PRETTY_FUNCTION__);
2617 return 0;
2618 }
2619
2620 zif = (struct zebra_if *)ifp->info;
2621 if ((br_if = zif->brslave_info.br_if) == NULL) {
2622 if (IS_ZEBRA_DEBUG_KERNEL)
2623 zlog_debug(
2624 "%s family %s IF %s(%u) brIF %u - no bridge master",
2625 nl_msg_type_to_str(h->nlmsg_type),
2626 nl_family_to_str(ndm->ndm_family), ifp->name,
2627 ndm->ndm_ifindex,
2628 zif->brslave_info.bridge_ifindex);
2629 return 0;
2630 }
2631
2632 /* Parse attributes and extract fields of interest. */
2633 memset(tb, 0, sizeof tb);
2634 netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);
2635
2636 if (!tb[NDA_LLADDR]) {
2637 if (IS_ZEBRA_DEBUG_KERNEL)
2638 zlog_debug("%s family %s IF %s(%u) brIF %u - no LLADDR",
2639 nl_msg_type_to_str(h->nlmsg_type),
2640 nl_family_to_str(ndm->ndm_family), ifp->name,
2641 ndm->ndm_ifindex,
2642 zif->brslave_info.bridge_ifindex);
2643 return 0;
2644 }
2645
2646 if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETH_ALEN) {
2647 if (IS_ZEBRA_DEBUG_KERNEL)
2648 zlog_debug(
2649 "%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %lu",
2650 nl_msg_type_to_str(h->nlmsg_type),
2651 nl_family_to_str(ndm->ndm_family), ifp->name,
2652 ndm->ndm_ifindex,
2653 zif->brslave_info.bridge_ifindex,
2654 (unsigned long)RTA_PAYLOAD(tb[NDA_LLADDR]));
2655 return 0;
2656 }
2657
2658 memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETH_ALEN);
2659
2660 if ((NDA_VLAN <= NDA_MAX) && tb[NDA_VLAN]) {
2661 vid_present = 1;
2662 vid = *(uint16_t *)RTA_DATA(tb[NDA_VLAN]);
2663 sprintf(vid_buf, " VLAN %u", vid);
2664 }
2665
2666 if (tb[NDA_DST]) {
2667 /* TODO: Only IPv4 supported now. */
2668 dst_present = 1;
2669 vtep_ip.family = AF_INET;
2670 vtep_ip.prefixlen = IPV4_MAX_BITLEN;
2671 memcpy(&(vtep_ip.u.prefix4.s_addr), RTA_DATA(tb[NDA_DST]),
2672 IPV4_MAX_BYTELEN);
2673 sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip.u.prefix4));
2674 }
2675
2676 sticky = !!(ndm->ndm_state & NUD_NOARP);
2677
2678 if (IS_ZEBRA_DEBUG_KERNEL)
2679 zlog_debug("Rx %s family %s IF %s(%u)%s %sMAC %s%s",
2680 nl_msg_type_to_str(h->nlmsg_type),
2681 nl_family_to_str(ndm->ndm_family), ifp->name,
2682 ndm->ndm_ifindex, vid_present ? vid_buf : "",
2683 sticky ? "sticky " : "",
2684 prefix_mac2str(&mac, buf, sizeof(buf)),
2685 dst_present ? dst_buf : "");
2686
2687 if (filter_vlan && vid != filter_vlan) {
2688 if (IS_ZEBRA_DEBUG_KERNEL)
2689 zlog_debug("\tFiltered due to filter vlan: %d",
2690 filter_vlan);
2691 return 0;
2692 }
2693
2694 /* If add or update, do accordingly if learnt on a "local" interface; if
2695 * the notification is over VxLAN, this has to be related to
2696 * multi-homing,
2697 * so perform an implicit delete of any local entry (if it exists).
2698 */
2699 if (h->nlmsg_type == RTM_NEWNEIGH) {
2700 if (IS_ZEBRA_IF_VXLAN(ifp))
2701 return zebra_vxlan_check_del_local_mac(ifp, br_if, &mac,
2702 vid);
2703
2704 return zebra_vxlan_local_mac_add_update(ifp, br_if, &mac, vid,
2705 sticky);
2706 }
2707
2708 /* This is a delete notification.
2709 * 1. For a MAC over VxLan, check if it needs to be refreshed(readded)
2710 * 2. For a MAC over "local" interface, delete the mac
2711 * Note: We will get notifications from both bridge driver and VxLAN
2712 * driver.
2713 * Ignore the notification from VxLan driver as it is also generated
2714 * when mac moves from remote to local.
2715 */
2716 if (dst_present) {
2717 if (IS_ZEBRA_DEBUG_KERNEL)
2718 zlog_debug("\tNo Destination Present");
2719 return 0;
2720 }
2721
2722 if (IS_ZEBRA_IF_VXLAN(ifp))
2723 return zebra_vxlan_check_readd_remote_mac(ifp, br_if, &mac,
2724 vid);
2725
2726 return zebra_vxlan_local_mac_del(ifp, br_if, &mac, vid);
2727 }
2728
2729 static int netlink_macfdb_table(struct nlmsghdr *h, ns_id_t ns_id, int startup)
2730 {
2731 int len;
2732 struct ndmsg *ndm;
2733
2734 if (h->nlmsg_type != RTM_NEWNEIGH)
2735 return 0;
2736
2737 /* Length validity. */
2738 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg));
2739 if (len < 0)
2740 return -1;
2741
2742 /* We are interested only in AF_BRIDGE notifications. */
2743 ndm = NLMSG_DATA(h);
2744 if (ndm->ndm_family != AF_BRIDGE)
2745 return 0;
2746
2747 return netlink_macfdb_change(h, len, ns_id);
2748 }
2749
2750 /* Request for MAC FDB information from the kernel */
2751 static int netlink_request_macs(struct nlsock *netlink_cmd, int family,
2752 int type, ifindex_t master_ifindex)
2753 {
2754 struct {
2755 struct nlmsghdr n;
2756 struct ifinfomsg ifm;
2757 char buf[256];
2758 } req;
2759
2760 /* Form the request, specifying filter (rtattr) if needed. */
2761 memset(&req, 0, sizeof(req));
2762 req.n.nlmsg_type = type;
2763 req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
2764 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
2765 req.ifm.ifi_family = family;
2766 if (master_ifindex)
2767 addattr32(&req.n, sizeof(req), IFLA_MASTER, master_ifindex);
2768
2769 return netlink_request(netlink_cmd, &req.n);
2770 }
2771
2772 /*
2773 * MAC forwarding database read using netlink interface. This is invoked
2774 * at startup.
2775 */
2776 int netlink_macfdb_read(struct zebra_ns *zns)
2777 {
2778 int ret;
2779 struct zebra_dplane_info dp_info;
2780
2781 zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
2782
2783 /* Get bridge FDB table. */
2784 ret = netlink_request_macs(&zns->netlink_cmd, AF_BRIDGE, RTM_GETNEIGH,
2785 0);
2786 if (ret < 0)
2787 return ret;
2788 /* We are reading entire table. */
2789 filter_vlan = 0;
2790 ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd,
2791 &dp_info, 0, 1);
2792
2793 return ret;
2794 }
2795
2796 /*
2797 * MAC forwarding database read using netlink interface. This is for a
2798 * specific bridge and matching specific access VLAN (if VLAN-aware bridge).
2799 */
2800 int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp,
2801 struct interface *br_if)
2802 {
2803 struct zebra_if *br_zif;
2804 struct zebra_if *zif;
2805 struct zebra_l2info_vxlan *vxl;
2806 struct zebra_dplane_info dp_info;
2807 int ret = 0;
2808
2809 zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
2810
2811 /* Save VLAN we're filtering on, if needed. */
2812 br_zif = (struct zebra_if *)br_if->info;
2813 zif = (struct zebra_if *)ifp->info;
2814 vxl = &zif->l2info.vxl;
2815 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif))
2816 filter_vlan = vxl->access_vlan;
2817
2818 /* Get bridge FDB table for specific bridge - we do the VLAN filtering.
2819 */
2820 ret = netlink_request_macs(&zns->netlink_cmd, AF_BRIDGE, RTM_GETNEIGH,
2821 br_if->ifindex);
2822 if (ret < 0)
2823 return ret;
2824 ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd,
2825 &dp_info, 0, 0);
2826
2827 /* Reset VLAN filter. */
2828 filter_vlan = 0;
2829 return ret;
2830 }
2831
2832
2833 /* Request for MAC FDB for a specific MAC address in VLAN from the kernel */
2834 static int netlink_request_specific_mac_in_bridge(struct zebra_ns *zns,
2835 int family,
2836 int type,
2837 struct interface *br_if,
2838 struct ethaddr *mac,
2839 vlanid_t vid)
2840 {
2841 struct {
2842 struct nlmsghdr n;
2843 struct ndmsg ndm;
2844 char buf[256];
2845 } req;
2846 struct zebra_if *br_zif;
2847 char buf[ETHER_ADDR_STRLEN];
2848
2849 memset(&req, 0, sizeof(req));
2850 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
2851 req.n.nlmsg_type = type; /* RTM_GETNEIGH */
2852 req.n.nlmsg_flags = NLM_F_REQUEST;
2853 req.ndm.ndm_family = family; /* AF_BRIDGE */
2854 /* req.ndm.ndm_state = NUD_REACHABLE; */
2855
2856 addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
2857
2858 br_zif = (struct zebra_if *)br_if->info;
2859 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0)
2860 addattr16(&req.n, sizeof(req), NDA_VLAN, vid);
2861
2862 addattr32(&req.n, sizeof(req), NDA_MASTER, br_if->ifindex);
2863
2864 if (IS_ZEBRA_DEBUG_KERNEL)
2865 zlog_debug("%s: Tx family %s IF %s(%u) MAC %s vid %u",
2866 __PRETTY_FUNCTION__,
2867 nl_family_to_str(req.ndm.ndm_family), br_if->name,
2868 br_if->ifindex,
2869 prefix_mac2str(mac, buf, sizeof(buf)), vid);
2870
2871 return netlink_request(&zns->netlink_cmd, &req.n);
2872 }
2873
2874 int netlink_macfdb_read_specific_mac(struct zebra_ns *zns,
2875 struct interface *br_if,
2876 struct ethaddr *mac, vlanid_t vid)
2877 {
2878 int ret = 0;
2879 struct zebra_dplane_info dp_info;
2880
2881 zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
2882
2883 /* Get bridge FDB table for specific bridge - we do the VLAN filtering.
2884 */
2885 ret = netlink_request_specific_mac_in_bridge(zns, AF_BRIDGE,
2886 RTM_GETNEIGH,
2887 br_if, mac, vid);
2888 if (ret < 0)
2889 return ret;
2890
2891 ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd,
2892 &dp_info, 1, 0);
2893
2894 return ret;
2895 }
2896
2897 /*
2898 * Netlink-specific handler for MAC updates using dataplane context object.
2899 */
2900 static enum zebra_dplane_result
2901 netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx)
2902 {
2903 uint8_t protocol = RTPROT_ZEBRA;
2904 struct {
2905 struct nlmsghdr n;
2906 struct ndmsg ndm;
2907 char buf[256];
2908 } req;
2909 int ret;
2910 int dst_alen;
2911 int vid_present = 0;
2912 int cmd;
2913 struct in_addr vtep_ip;
2914 vlanid_t vid;
2915
2916 if (dplane_ctx_get_op(ctx) == DPLANE_OP_MAC_INSTALL)
2917 cmd = RTM_NEWNEIGH;
2918 else
2919 cmd = RTM_DELNEIGH;
2920
2921 memset(&req, 0, sizeof(req));
2922
2923 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
2924 req.n.nlmsg_flags = NLM_F_REQUEST;
2925 if (cmd == RTM_NEWNEIGH)
2926 req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
2927 req.n.nlmsg_type = cmd;
2928 req.ndm.ndm_family = AF_BRIDGE;
2929 req.ndm.ndm_flags |= NTF_SELF | NTF_MASTER;
2930 req.ndm.ndm_state = NUD_REACHABLE;
2931
2932 if (dplane_ctx_mac_is_sticky(ctx))
2933 req.ndm.ndm_state |= NUD_NOARP;
2934 else
2935 req.ndm.ndm_flags |= NTF_EXT_LEARNED;
2936
2937 addattr_l(&req.n, sizeof(req),
2938 NDA_PROTOCOL, &protocol, sizeof(protocol));
2939 addattr_l(&req.n, sizeof(req), NDA_LLADDR,
2940 dplane_ctx_mac_get_addr(ctx), 6);
2941 req.ndm.ndm_ifindex = dplane_ctx_get_ifindex(ctx);
2942
2943 dst_alen = 4; // TODO: hardcoded
2944 vtep_ip = *(dplane_ctx_mac_get_vtep_ip(ctx));
2945 addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip, dst_alen);
2946
2947 vid = dplane_ctx_mac_get_vlan(ctx);
2948
2949 if (vid > 0) {
2950 addattr16(&req.n, sizeof(req), NDA_VLAN, vid);
2951 vid_present = 1;
2952 }
2953 addattr32(&req.n, sizeof(req), NDA_MASTER,
2954 dplane_ctx_mac_get_br_ifindex(ctx));
2955
2956 if (IS_ZEBRA_DEBUG_KERNEL) {
2957 char ipbuf[PREFIX_STRLEN];
2958 char buf[ETHER_ADDR_STRLEN];
2959 char dst_buf[PREFIX_STRLEN + 10];
2960 char vid_buf[20];
2961
2962 if (vid_present)
2963 snprintf(vid_buf, sizeof(vid_buf), " VLAN %u", vid);
2964 else
2965 vid_buf[0] = '\0';
2966
2967 inet_ntop(AF_INET, &vtep_ip, ipbuf, sizeof(ipbuf));
2968 snprintf(dst_buf, sizeof(dst_buf), " dst %s", ipbuf);
2969 prefix_mac2str(dplane_ctx_mac_get_addr(ctx), buf, sizeof(buf));
2970
2971 zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s%s",
2972 nl_msg_type_to_str(cmd),
2973 nl_family_to_str(req.ndm.ndm_family),
2974 dplane_ctx_get_ifname(ctx),
2975 dplane_ctx_get_ifindex(ctx), vid_buf,
2976 dplane_ctx_mac_is_sticky(ctx) ? "sticky " : "",
2977 buf, dst_buf);
2978 }
2979
2980 ret = netlink_talk_info(netlink_talk_filter, &req.n,
2981 dplane_ctx_get_ns(ctx), 0);
2982 if (ret == 0)
2983 return ZEBRA_DPLANE_REQUEST_SUCCESS;
2984 else
2985 return ZEBRA_DPLANE_REQUEST_FAILURE;
2986 }
2987
2988 /*
2989 * In the event the kernel deletes ipv4 link-local neighbor entries created for
2990 * 5549 support, re-install them.
2991 */
2992 static void netlink_handle_5549(struct ndmsg *ndm, struct zebra_if *zif,
2993 struct interface *ifp, struct ipaddr *ip,
2994 bool handle_failed)
2995 {
2996 if (ndm->ndm_family != AF_INET)
2997 return;
2998
2999 if (!zif->v6_2_v4_ll_neigh_entry)
3000 return;
3001
3002 if (ipv4_ll.s_addr != ip->ip._v4_addr.s_addr)
3003 return;
3004
3005 if (handle_failed && ndm->ndm_state & NUD_FAILED) {
3006 zlog_info("Neighbor Entry for %s has entered a failed state, not reinstalling",
3007 ifp->name);
3008 return;
3009 }
3010
3011 if_nbr_ipv6ll_to_ipv4ll_neigh_update(ifp, &zif->v6_2_v4_ll_addr6, true);
3012 }
3013
3014 #define NUD_VALID \
3015 (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE | NUD_PROBE | NUD_STALE \
3016 | NUD_DELAY)
3017
3018 static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
3019 {
3020 struct ndmsg *ndm;
3021 struct interface *ifp;
3022 struct zebra_if *zif;
3023 struct rtattr *tb[NDA_MAX + 1];
3024 struct interface *link_if;
3025 struct ethaddr mac;
3026 struct ipaddr ip;
3027 char buf[ETHER_ADDR_STRLEN];
3028 char buf2[INET6_ADDRSTRLEN];
3029 int mac_present = 0;
3030 bool is_ext;
3031 bool is_router;
3032
3033 ndm = NLMSG_DATA(h);
3034
3035 /* The interface should exist. */
3036 ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
3037 ndm->ndm_ifindex);
3038 if (!ifp || !ifp->info)
3039 return 0;
3040
3041 zif = (struct zebra_if *)ifp->info;
3042
3043 /* Parse attributes and extract fields of interest. */
3044 memset(tb, 0, sizeof tb);
3045 netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);
3046
3047 if (!tb[NDA_DST]) {
3048 zlog_debug("%s family %s IF %s(%u) - no DST",
3049 nl_msg_type_to_str(h->nlmsg_type),
3050 nl_family_to_str(ndm->ndm_family), ifp->name,
3051 ndm->ndm_ifindex);
3052 return 0;
3053 }
3054
3055 memset(&ip, 0, sizeof(struct ipaddr));
3056 ip.ipa_type = (ndm->ndm_family == AF_INET) ? IPADDR_V4 : IPADDR_V6;
3057 memcpy(&ip.ip.addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
3058
3059 /* if kernel deletes our rfc5549 neighbor entry, re-install it */
3060 if (h->nlmsg_type == RTM_DELNEIGH && (ndm->ndm_state & NUD_PERMANENT)) {
3061 netlink_handle_5549(ndm, zif, ifp, &ip, false);
3062 if (IS_ZEBRA_DEBUG_KERNEL)
3063 zlog_debug(
3064 "\tNeighbor Entry Received is a 5549 entry, finished");
3065 return 0;
3066 }
3067
3068 /* if kernel marks our rfc5549 neighbor entry invalid, re-install it */
3069 if (h->nlmsg_type == RTM_NEWNEIGH && !(ndm->ndm_state & NUD_VALID))
3070 netlink_handle_5549(ndm, zif, ifp, &ip, true);
3071
3072 /* The neighbor is present on an SVI. From this, we locate the
3073 * underlying
3074 * bridge because we're only interested in neighbors on a VxLAN bridge.
3075 * The bridge is located based on the nature of the SVI:
3076 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN
3077 * interface
3078 * and is linked to the bridge
3079 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge
3080 * inteface
3081 * itself
3082 */
3083 if (IS_ZEBRA_IF_VLAN(ifp)) {
3084 link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
3085 zif->link_ifindex);
3086 if (!link_if)
3087 return 0;
3088 } else if (IS_ZEBRA_IF_BRIDGE(ifp))
3089 link_if = ifp;
3090 else {
3091 if (IS_ZEBRA_DEBUG_KERNEL)
3092 zlog_debug(
3093 "\tNeighbor Entry received is not on a VLAN or a BRIDGE, ignoring");
3094 return 0;
3095 }
3096
3097 memset(&mac, 0, sizeof(struct ethaddr));
3098 if (h->nlmsg_type == RTM_NEWNEIGH) {
3099 if (tb[NDA_LLADDR]) {
3100 if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETH_ALEN) {
3101 if (IS_ZEBRA_DEBUG_KERNEL)
3102 zlog_debug(
3103 "%s family %s IF %s(%u) - LLADDR is not MAC, len %lu",
3104 nl_msg_type_to_str(
3105 h->nlmsg_type),
3106 nl_family_to_str(
3107 ndm->ndm_family),
3108 ifp->name, ndm->ndm_ifindex,
3109 (unsigned long)RTA_PAYLOAD(
3110 tb[NDA_LLADDR]));
3111 return 0;
3112 }
3113
3114 mac_present = 1;
3115 memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETH_ALEN);
3116 }
3117
3118 is_ext = !!(ndm->ndm_flags & NTF_EXT_LEARNED);
3119 is_router = !!(ndm->ndm_flags & NTF_ROUTER);
3120
3121 if (IS_ZEBRA_DEBUG_KERNEL)
3122 zlog_debug(
3123 "Rx %s family %s IF %s(%u) IP %s MAC %s state 0x%x flags 0x%x",
3124 nl_msg_type_to_str(h->nlmsg_type),
3125 nl_family_to_str(ndm->ndm_family), ifp->name,
3126 ndm->ndm_ifindex,
3127 ipaddr2str(&ip, buf2, sizeof(buf2)),
3128 mac_present
3129 ? prefix_mac2str(&mac, buf, sizeof(buf))
3130 : "",
3131 ndm->ndm_state, ndm->ndm_flags);
3132
3133 /* If the neighbor state is valid for use, process as an add or
3134 * update
3135 * else process as a delete. Note that the delete handling may
3136 * result
3137 * in re-adding the neighbor if it is a valid "remote" neighbor.
3138 */
3139 if (ndm->ndm_state & NUD_VALID)
3140 return zebra_vxlan_handle_kernel_neigh_update(
3141 ifp, link_if, &ip, &mac, ndm->ndm_state,
3142 is_ext, is_router);
3143
3144 return zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip);
3145 }
3146
3147 if (IS_ZEBRA_DEBUG_KERNEL)
3148 zlog_debug("Rx %s family %s IF %s(%u) IP %s",
3149 nl_msg_type_to_str(h->nlmsg_type),
3150 nl_family_to_str(ndm->ndm_family), ifp->name,
3151 ndm->ndm_ifindex,
3152 ipaddr2str(&ip, buf2, sizeof(buf2)));
3153
3154 /* Process the delete - it may result in re-adding the neighbor if it is
3155 * a valid "remote" neighbor.
3156 */
3157 return zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip);
3158 }
3159
3160 static int netlink_neigh_table(struct nlmsghdr *h, ns_id_t ns_id, int startup)
3161 {
3162 int len;
3163 struct ndmsg *ndm;
3164
3165 if (h->nlmsg_type != RTM_NEWNEIGH)
3166 return 0;
3167
3168 /* Length validity. */
3169 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg));
3170 if (len < 0)
3171 return -1;
3172
3173 /* We are interested only in AF_INET or AF_INET6 notifications. */
3174 ndm = NLMSG_DATA(h);
3175 if (ndm->ndm_family != AF_INET && ndm->ndm_family != AF_INET6)
3176 return 0;
3177
3178 return netlink_neigh_change(h, len);
3179 }
3180
3181 /* Request for IP neighbor information from the kernel */
3182 static int netlink_request_neigh(struct nlsock *netlink_cmd, int family,
3183 int type, ifindex_t ifindex)
3184 {
3185 struct {
3186 struct nlmsghdr n;
3187 struct ndmsg ndm;
3188 char buf[256];
3189 } req;
3190
3191 /* Form the request, specifying filter (rtattr) if needed. */
3192 memset(&req, 0, sizeof(req));
3193 req.n.nlmsg_type = type;
3194 req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
3195 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
3196 req.ndm.ndm_family = family;
3197 if (ifindex)
3198 addattr32(&req.n, sizeof(req), NDA_IFINDEX, ifindex);
3199
3200 return netlink_request(netlink_cmd, &req.n);
3201 }
3202
3203 /*
3204 * IP Neighbor table read using netlink interface. This is invoked
3205 * at startup.
3206 */
3207 int netlink_neigh_read(struct zebra_ns *zns)
3208 {
3209 int ret;
3210 struct zebra_dplane_info dp_info;
3211
3212 zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
3213
3214 /* Get IP neighbor table. */
3215 ret = netlink_request_neigh(&zns->netlink_cmd, AF_UNSPEC, RTM_GETNEIGH,
3216 0);
3217 if (ret < 0)
3218 return ret;
3219 ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd,
3220 &dp_info, 0, 1);
3221
3222 return ret;
3223 }
3224
3225 /*
3226 * IP Neighbor table read using netlink interface. This is for a specific
3227 * VLAN device.
3228 */
3229 int netlink_neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if)
3230 {
3231 int ret = 0;
3232 struct zebra_dplane_info dp_info;
3233
3234 zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
3235
3236 ret = netlink_request_neigh(&zns->netlink_cmd, AF_UNSPEC, RTM_GETNEIGH,
3237 vlan_if->ifindex);
3238 if (ret < 0)
3239 return ret;
3240 ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd,
3241 &dp_info, 0, 0);
3242
3243 return ret;
3244 }
3245
3246 /*
3247 * Request for a specific IP in VLAN (SVI) device from IP Neighbor table,
3248 * read using netlink interface.
3249 */
3250 static int netlink_request_specific_neigh_in_vlan(struct zebra_ns *zns,
3251 int type, struct ipaddr *ip,
3252 ifindex_t ifindex)
3253 {
3254 struct {
3255 struct nlmsghdr n;
3256 struct ndmsg ndm;
3257 char buf[256];
3258 } req;
3259 int ipa_len;
3260
3261 /* Form the request, specifying filter (rtattr) if needed. */
3262 memset(&req, 0, sizeof(req));
3263 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
3264 req.n.nlmsg_flags = NLM_F_REQUEST;
3265 req.n.nlmsg_type = type; /* RTM_GETNEIGH */
3266 req.ndm.ndm_ifindex = ifindex;
3267
3268 if (IS_IPADDR_V4(ip)) {
3269 ipa_len = IPV4_MAX_BYTELEN;
3270 req.ndm.ndm_family = AF_INET;
3271
3272 } else {
3273 ipa_len = IPV6_MAX_BYTELEN;
3274 req.ndm.ndm_family = AF_INET6;
3275 }
3276
3277 addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
3278
3279 return netlink_request(&zns->netlink_cmd, &req.n);
3280 }
3281
3282 int netlink_neigh_read_specific_ip(struct ipaddr *ip,
3283 struct interface *vlan_if)
3284 {
3285 int ret = 0;
3286 struct zebra_ns *zns;
3287 struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(vlan_if->vrf_id);
3288 char buf[INET6_ADDRSTRLEN];
3289 struct zebra_dplane_info dp_info;
3290
3291 zns = zvrf->zns;
3292
3293 zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
3294
3295 if (IS_ZEBRA_DEBUG_KERNEL)
3296 zlog_debug("%s: neigh request IF %s(%u) IP %s vrf_id %u",
3297 __PRETTY_FUNCTION__, vlan_if->name,
3298 vlan_if->ifindex,
3299 ipaddr2str(ip, buf, sizeof(buf)),
3300 vlan_if->vrf_id);
3301
3302 ret = netlink_request_specific_neigh_in_vlan(zns, RTM_GETNEIGH, ip,
3303 vlan_if->ifindex);
3304 if (ret < 0)
3305 return ret;
3306
3307 ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd,
3308 &dp_info, 1, 0);
3309
3310 return ret;
3311 }
3312
3313 int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id)
3314 {
3315 int len;
3316 struct ndmsg *ndm;
3317
3318 if (!(h->nlmsg_type == RTM_NEWNEIGH || h->nlmsg_type == RTM_DELNEIGH))
3319 return 0;
3320
3321 /* Length validity. */
3322 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg));
3323 if (len < 0) {
3324 zlog_err("%s: Message received from netlink is of a broken size %d %zu",
3325 __PRETTY_FUNCTION__, h->nlmsg_len,
3326 (size_t)NLMSG_LENGTH(sizeof(struct ndmsg)));
3327 return -1;
3328 }
3329
3330 /* Is this a notification for the MAC FDB or IP neighbor table? */
3331 ndm = NLMSG_DATA(h);
3332 if (ndm->ndm_family == AF_BRIDGE)
3333 return netlink_macfdb_change(h, len, ns_id);
3334
3335 if (ndm->ndm_type != RTN_UNICAST)
3336 return 0;
3337
3338 if (ndm->ndm_family == AF_INET || ndm->ndm_family == AF_INET6)
3339 return netlink_ipneigh_change(h, len, ns_id);
3340 else {
3341 flog_warn(
3342 EC_ZEBRA_UNKNOWN_FAMILY,
3343 "Invalid address family: %u received from kernel neighbor change: %s",
3344 ndm->ndm_family, nl_msg_type_to_str(h->nlmsg_type));
3345 return 0;
3346 }
3347
3348 return 0;
3349 }
3350
3351 /*
3352 * Utility neighbor-update function, using info from dplane context.
3353 */
3354 static int netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx,
3355 int cmd)
3356 {
3357 uint8_t protocol = RTPROT_ZEBRA;
3358 struct {
3359 struct nlmsghdr n;
3360 struct ndmsg ndm;
3361 char buf[256];
3362 } req;
3363 int ipa_len;
3364 char buf[INET6_ADDRSTRLEN];
3365 char buf2[ETHER_ADDR_STRLEN];
3366 const struct ipaddr *ip;
3367 const struct ethaddr *mac;
3368 uint8_t flags;
3369 uint16_t state;
3370
3371 memset(&req, 0, sizeof(req));
3372
3373 ip = dplane_ctx_neigh_get_ipaddr(ctx);
3374 mac = dplane_ctx_neigh_get_mac(ctx);
3375 if (is_zero_mac(mac))
3376 mac = NULL;
3377
3378 flags = neigh_flags_to_netlink(dplane_ctx_neigh_get_flags(ctx));
3379 state = neigh_state_to_netlink(dplane_ctx_neigh_get_state(ctx));
3380
3381 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
3382 req.n.nlmsg_flags = NLM_F_REQUEST;
3383 if (cmd == RTM_NEWNEIGH)
3384 req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
3385 req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH
3386 req.ndm.ndm_family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6;
3387 req.ndm.ndm_state = state;
3388 req.ndm.ndm_ifindex = dplane_ctx_get_ifindex(ctx);
3389 req.ndm.ndm_type = RTN_UNICAST;
3390 req.ndm.ndm_flags = flags;
3391
3392 addattr_l(&req.n, sizeof(req),
3393 NDA_PROTOCOL, &protocol, sizeof(protocol));
3394 ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN;
3395 addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
3396 if (mac)
3397 addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
3398
3399 if (IS_ZEBRA_DEBUG_KERNEL)
3400 zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s flags 0x%x state 0x%x",
3401 nl_msg_type_to_str(cmd),
3402 nl_family_to_str(req.ndm.ndm_family),
3403 dplane_ctx_get_ifname(ctx),
3404 dplane_ctx_get_ifindex(ctx),
3405 ipaddr2str(ip, buf, sizeof(buf)),
3406 mac ? prefix_mac2str(mac, buf2, sizeof(buf2))
3407 : "null",
3408 flags, state);
3409
3410 return netlink_talk_info(netlink_talk_filter, &req.n,
3411 dplane_ctx_get_ns(ctx), 0);
3412 }
3413
3414 /*
3415 * Update MAC, using dataplane context object.
3416 */
3417 enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx)
3418 {
3419 return netlink_macfdb_update_ctx(ctx);
3420 }
3421
3422 enum zebra_dplane_result kernel_neigh_update_ctx(struct zebra_dplane_ctx *ctx)
3423 {
3424 int ret = -1;
3425
3426 switch (dplane_ctx_get_op(ctx)) {
3427 case DPLANE_OP_NEIGH_INSTALL:
3428 case DPLANE_OP_NEIGH_UPDATE:
3429 ret = netlink_neigh_update_ctx(ctx, RTM_NEWNEIGH);
3430 break;
3431 case DPLANE_OP_NEIGH_DELETE:
3432 ret = netlink_neigh_update_ctx(ctx, RTM_DELNEIGH);
3433 break;
3434 case DPLANE_OP_VTEP_ADD:
3435 ret = netlink_vxlan_flood_update_ctx(ctx, RTM_NEWNEIGH);
3436 break;
3437 case DPLANE_OP_VTEP_DELETE:
3438 ret = netlink_vxlan_flood_update_ctx(ctx, RTM_DELNEIGH);
3439 break;
3440 default:
3441 break;
3442 }
3443
3444 return (ret == 0 ?
3445 ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE);
3446 }
3447
3448 /*
3449 * MPLS label forwarding table change via netlink interface, using dataplane
3450 * context information.
3451 */
3452 int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx)
3453 {
3454 mpls_lse_t lse;
3455 const zebra_nhlfe_t *nhlfe;
3456 struct nexthop *nexthop = NULL;
3457 unsigned int nexthop_num;
3458 const char *routedesc;
3459 int route_type;
3460
3461 struct {
3462 struct nlmsghdr n;
3463 struct rtmsg r;
3464 char buf[NL_PKT_BUF_SIZE];
3465 } req;
3466
3467 memset(&req, 0, sizeof(req) - NL_PKT_BUF_SIZE);
3468
3469 /*
3470 * Count # nexthops so we can decide whether to use singlepath
3471 * or multipath case.
3472 */
3473 nexthop_num = 0;
3474 for (nhlfe = dplane_ctx_get_nhlfe(ctx); nhlfe; nhlfe = nhlfe->next) {
3475 nexthop = nhlfe->nexthop;
3476 if (!nexthop)
3477 continue;
3478 if (cmd == RTM_NEWROUTE) {
3479 /* Count all selected NHLFEs */
3480 if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
3481 && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
3482 nexthop_num++;
3483 } else { /* DEL */
3484 /* Count all installed NHLFEs */
3485 if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)
3486 && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
3487 nexthop_num++;
3488 }
3489 }
3490
3491 if ((nexthop_num == 0) ||
3492 (!dplane_ctx_get_best_nhlfe(ctx) && (cmd != RTM_DELROUTE)))
3493 return 0;
3494
3495 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
3496 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
3497 req.n.nlmsg_type = cmd;
3498 req.n.nlmsg_pid = dplane_ctx_get_ns(ctx)->nls.snl.nl_pid;
3499
3500 req.r.rtm_family = AF_MPLS;
3501 req.r.rtm_table = RT_TABLE_MAIN;
3502 req.r.rtm_dst_len = MPLS_LABEL_LEN_BITS;
3503 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
3504 req.r.rtm_type = RTN_UNICAST;
3505
3506 if (cmd == RTM_NEWROUTE) {
3507 /* We do a replace to handle update. */
3508 req.n.nlmsg_flags |= NLM_F_REPLACE;
3509
3510 /* set the protocol value if installing */
3511 route_type = re_type_from_lsp_type(
3512 dplane_ctx_get_best_nhlfe(ctx)->type);
3513 req.r.rtm_protocol = zebra2proto(route_type);
3514 }
3515
3516 /* Fill destination */
3517 lse = mpls_lse_encode(dplane_ctx_get_in_label(ctx), 0, 0, 1);
3518 addattr_l(&req.n, sizeof(req), RTA_DST, &lse, sizeof(mpls_lse_t));
3519
3520 /* Fill nexthops (paths) based on single-path or multipath. The paths
3521 * chosen depend on the operation.
3522 */
3523 if (nexthop_num == 1) {
3524 routedesc = "single-path";
3525 _netlink_mpls_debug(cmd, dplane_ctx_get_in_label(ctx),
3526 routedesc);
3527
3528 nexthop_num = 0;
3529 for (nhlfe = dplane_ctx_get_nhlfe(ctx);
3530 nhlfe; nhlfe = nhlfe->next) {
3531 nexthop = nhlfe->nexthop;
3532 if (!nexthop)
3533 continue;
3534
3535 if ((cmd == RTM_NEWROUTE
3536 && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
3537 && CHECK_FLAG(nexthop->flags,
3538 NEXTHOP_FLAG_ACTIVE)))
3539 || (cmd == RTM_DELROUTE
3540 && (CHECK_FLAG(nhlfe->flags,
3541 NHLFE_FLAG_INSTALLED)
3542 && CHECK_FLAG(nexthop->flags,
3543 NEXTHOP_FLAG_FIB)))) {
3544 /* Add the gateway */
3545 _netlink_mpls_build_singlepath(
3546 routedesc, nhlfe,
3547 &req.n, &req.r,
3548 sizeof(req), cmd);
3549
3550 nexthop_num++;
3551 break;
3552 }
3553 }
3554 } else { /* Multipath case */
3555 char buf[NL_PKT_BUF_SIZE];
3556 struct rtattr *rta = (void *)buf;
3557 struct rtnexthop *rtnh;
3558 const union g_addr *src1 = NULL;
3559
3560 rta->rta_type = RTA_MULTIPATH;
3561 rta->rta_len = RTA_LENGTH(0);
3562 rtnh = RTA_DATA(rta);
3563
3564 routedesc = "multipath";
3565 _netlink_mpls_debug(cmd, dplane_ctx_get_in_label(ctx),
3566 routedesc);
3567
3568 nexthop_num = 0;
3569 for (nhlfe = dplane_ctx_get_nhlfe(ctx);
3570 nhlfe; nhlfe = nhlfe->next) {
3571 nexthop = nhlfe->nexthop;
3572 if (!nexthop)
3573 continue;
3574
3575 if ((cmd == RTM_NEWROUTE
3576 && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
3577 && CHECK_FLAG(nexthop->flags,
3578 NEXTHOP_FLAG_ACTIVE)))
3579 || (cmd == RTM_DELROUTE
3580 && (CHECK_FLAG(nhlfe->flags,
3581 NHLFE_FLAG_INSTALLED)
3582 && CHECK_FLAG(nexthop->flags,
3583 NEXTHOP_FLAG_FIB)))) {
3584 nexthop_num++;
3585
3586 /* Build the multipath */
3587 _netlink_mpls_build_multipath(routedesc, nhlfe,
3588 rta, rtnh, &req.r,
3589 &src1);
3590 rtnh = RTNH_NEXT(rtnh);
3591 }
3592 }
3593
3594 /* Add the multipath */
3595 if (rta->rta_len > RTA_LENGTH(0))
3596 addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH,
3597 RTA_DATA(rta), RTA_PAYLOAD(rta));
3598 }
3599
3600 /* Talk to netlink socket. */
3601 return netlink_talk_info(netlink_talk_filter, &req.n,
3602 dplane_ctx_get_ns(ctx), 0);
3603 }
3604 #endif /* HAVE_NETLINK */