]> git.proxmox.com Git - mirror_frr.git/blob - zebra/rt_netlink.c
Switch to using syslog for logging as the default
[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 #include <net/if_arp.h>
23
24 /* Hack for GNU libc version 2. */
25 #ifndef MSG_TRUNC
26 #define MSG_TRUNC 0x20
27 #endif /* MSG_TRUNC */
28
29 #include "linklist.h"
30 #include "if.h"
31 #include "log.h"
32 #include "prefix.h"
33 #include "connected.h"
34 #include "table.h"
35 #include "memory.h"
36 #include "zebra_memory.h"
37 #include "rib.h"
38 #include "thread.h"
39 #include "privs.h"
40 #include "nexthop.h"
41 #include "vrf.h"
42 #include "vty.h"
43 #include "mpls.h"
44 #include "vxlan.h"
45
46 #include "zebra/zserv.h"
47 #include "zebra/zebra_ns.h"
48 #include "zebra/zebra_vrf.h"
49 #include "zebra/rt.h"
50 #include "zebra/redistribute.h"
51 #include "zebra/interface.h"
52 #include "zebra/debug.h"
53 #include "zebra/rtadv.h"
54 #include "zebra/zebra_ptm.h"
55 #include "zebra/zebra_mpls.h"
56 #include "zebra/kernel_netlink.h"
57 #include "zebra/rt_netlink.h"
58 #include "zebra/zebra_mroute.h"
59 #include "zebra/zebra_vxlan.h"
60
61
62 /* TODO - Temporary definitions, need to refine. */
63 #ifndef AF_MPLS
64 #define AF_MPLS 28
65 #endif
66
67 #ifndef RTA_VIA
68 #define RTA_VIA 18
69 #endif
70
71 #ifndef RTA_NEWDST
72 #define RTA_NEWDST 19
73 #endif
74
75 #ifndef RTA_ENCAP_TYPE
76 #define RTA_ENCAP_TYPE 21
77 #endif
78
79 #ifndef RTA_ENCAP
80 #define RTA_ENCAP 22
81 #endif
82
83 #ifndef RTA_EXPIRES
84 #define RTA_EXPIRES 23
85 #endif
86
87 #ifndef LWTUNNEL_ENCAP_MPLS
88 #define LWTUNNEL_ENCAP_MPLS 1
89 #endif
90
91 #ifndef MPLS_IPTUNNEL_DST
92 #define MPLS_IPTUNNEL_DST 1
93 #endif
94
95 #ifndef NDA_MASTER
96 #define NDA_MASTER 9
97 #endif
98
99 #ifndef NTF_MASTER
100 #define NTF_MASTER 0x04
101 #endif
102
103 #ifndef NTF_SELF
104 #define NTF_SELF 0x02
105 #endif
106
107 #ifndef NTF_EXT_LEARNED
108 #define NTF_EXT_LEARNED 0x10
109 #endif
110
111 #ifndef NDA_IFINDEX
112 #define NDA_IFINDEX 8
113 #endif
114
115 #ifndef NDA_VLAN
116 #define NDA_VLAN 5
117 #endif
118 /* End of temporary definitions */
119
120 static vlanid_t filter_vlan = 0;
121
122 struct gw_family_t {
123 u_int16_t filler;
124 u_int16_t family;
125 union g_addr gate;
126 };
127
128 char ipv4_ll_buf[16] = "169.254.0.1";
129 struct in_addr ipv4_ll;
130
131 /*
132 * The ipv4_ll data structure is used for all 5549
133 * additions to the kernel. Let's figure out the
134 * correct value one time instead for every
135 * install/remove of a 5549 type route
136 */
137 void rt_netlink_init(void)
138 {
139 inet_pton(AF_INET, ipv4_ll_buf, &ipv4_ll);
140 }
141
142 static inline int is_selfroute(int proto)
143 {
144 if ((proto == RTPROT_BGP) || (proto == RTPROT_OSPF)
145 || (proto == RTPROT_STATIC) || (proto == RTPROT_ZEBRA)
146 || (proto == RTPROT_ISIS) || (proto == RTPROT_RIPNG)
147 || (proto == RTPROT_NHRP) || (proto == RTPROT_EIGRP)
148 || (proto == RTPROT_LDP) || (proto == RTPROT_BABEL)) {
149 return 1;
150 }
151
152 return 0;
153 }
154
155 static inline int get_rt_proto(int proto)
156 {
157 switch (proto) {
158 case ZEBRA_ROUTE_BABEL:
159 proto = RTPROT_BABEL;
160 break;
161 case ZEBRA_ROUTE_BGP:
162 proto = RTPROT_BGP;
163 break;
164 case ZEBRA_ROUTE_OSPF:
165 case ZEBRA_ROUTE_OSPF6:
166 proto = RTPROT_OSPF;
167 break;
168 case ZEBRA_ROUTE_STATIC:
169 proto = RTPROT_STATIC;
170 break;
171 case ZEBRA_ROUTE_ISIS:
172 proto = RTPROT_ISIS;
173 break;
174 case ZEBRA_ROUTE_RIP:
175 proto = RTPROT_RIP;
176 break;
177 case ZEBRA_ROUTE_RIPNG:
178 proto = RTPROT_RIPNG;
179 break;
180 case ZEBRA_ROUTE_NHRP:
181 proto = RTPROT_NHRP;
182 break;
183 case ZEBRA_ROUTE_EIGRP:
184 proto = RTPROT_EIGRP;
185 break;
186 case ZEBRA_ROUTE_LDP:
187 proto = RTPROT_LDP;
188 break;
189 default:
190 proto = RTPROT_ZEBRA;
191 break;
192 }
193
194 return proto;
195 }
196
197 /*
198 Pending: create an efficient table_id (in a tree/hash) based lookup)
199 */
200 static vrf_id_t vrf_lookup_by_table(u_int32_t table_id)
201 {
202 struct vrf *vrf;
203 struct zebra_vrf *zvrf;
204
205 RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id)
206 {
207 if ((zvrf = vrf->info) == NULL || (zvrf->table_id != table_id))
208 continue;
209
210 return zvrf_id(zvrf);
211 }
212
213 return VRF_DEFAULT;
214 }
215
216 /* Looking up routing table by netlink interface. */
217 static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
218 struct nlmsghdr *h, ns_id_t ns_id,
219 int startup)
220 {
221 int len;
222 struct rtmsg *rtm;
223 struct rtattr *tb[RTA_MAX + 1];
224 u_char flags = 0;
225 struct prefix p;
226 struct prefix_ipv6 src_p;
227 vrf_id_t vrf_id = VRF_DEFAULT;
228
229 char anyaddr[16] = {0};
230
231 int index = 0;
232 int table;
233 int metric = 0;
234 u_int32_t mtu = 0;
235
236 void *dest = NULL;
237 void *gate = NULL;
238 void *prefsrc = NULL; /* IPv4 preferred source host address */
239 void *src = NULL; /* IPv6 srcdest source prefix */
240
241 rtm = NLMSG_DATA(h);
242
243 if (startup && h->nlmsg_type != RTM_NEWROUTE)
244 return 0;
245 if (startup && rtm->rtm_type != RTN_UNICAST)
246 return 0;
247
248 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
249 if (len < 0)
250 return -1;
251
252 memset(tb, 0, sizeof tb);
253 netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len);
254
255 if (rtm->rtm_flags & RTM_F_CLONED)
256 return 0;
257 if (rtm->rtm_protocol == RTPROT_REDIRECT)
258 return 0;
259 if (rtm->rtm_protocol == RTPROT_KERNEL)
260 return 0;
261
262 if (!startup && is_selfroute(rtm->rtm_protocol)
263 && h->nlmsg_type == RTM_NEWROUTE)
264 return 0;
265
266 /* We don't care about change notifications for the MPLS table. */
267 /* TODO: Revisit this. */
268 if (rtm->rtm_family == AF_MPLS)
269 return 0;
270
271 /* Table corresponding to route. */
272 if (tb[RTA_TABLE])
273 table = *(int *)RTA_DATA(tb[RTA_TABLE]);
274 else
275 table = rtm->rtm_table;
276
277 /* Map to VRF */
278 vrf_id = vrf_lookup_by_table(table);
279 if (vrf_id == VRF_DEFAULT) {
280 if (!is_zebra_valid_kernel_table(table)
281 && !is_zebra_main_routing_table(table))
282 return 0;
283 }
284
285 /* Route which inserted by Zebra. */
286 if (is_selfroute(rtm->rtm_protocol))
287 flags |= ZEBRA_FLAG_SELFROUTE;
288
289 if (tb[RTA_OIF])
290 index = *(int *)RTA_DATA(tb[RTA_OIF]);
291
292 if (tb[RTA_DST])
293 dest = RTA_DATA(tb[RTA_DST]);
294 else
295 dest = anyaddr;
296
297 if (tb[RTA_SRC])
298 src = RTA_DATA(tb[RTA_SRC]);
299 else
300 src = anyaddr;
301
302 if (tb[RTA_PREFSRC])
303 prefsrc = RTA_DATA(tb[RTA_PREFSRC]);
304
305 if (tb[RTA_GATEWAY])
306 gate = RTA_DATA(tb[RTA_GATEWAY]);
307
308 if (h->nlmsg_type == RTM_NEWROUTE) {
309 if (tb[RTA_PRIORITY])
310 metric = *(int *)RTA_DATA(tb[RTA_PRIORITY]);
311
312 if (tb[RTA_METRICS]) {
313 struct rtattr *mxrta[RTAX_MAX + 1];
314
315 memset(mxrta, 0, sizeof mxrta);
316 netlink_parse_rtattr(mxrta, RTAX_MAX,
317 RTA_DATA(tb[RTA_METRICS]),
318 RTA_PAYLOAD(tb[RTA_METRICS]));
319
320 if (mxrta[RTAX_MTU])
321 mtu = *(u_int32_t *)RTA_DATA(mxrta[RTAX_MTU]);
322 }
323 }
324
325 if (rtm->rtm_family == AF_INET) {
326 p.family = AF_INET;
327 memcpy(&p.u.prefix4, dest, 4);
328 p.prefixlen = rtm->rtm_dst_len;
329
330 src_p.prefixlen =
331 0; // Forces debug below to not display anything
332 } else if (rtm->rtm_family == AF_INET6) {
333 p.family = AF_INET6;
334 memcpy(&p.u.prefix6, dest, 16);
335 p.prefixlen = rtm->rtm_dst_len;
336
337 src_p.family = AF_INET6;
338 memcpy(&src_p.prefix, src, 16);
339 src_p.prefixlen = rtm->rtm_src_len;
340 }
341
342 if (rtm->rtm_src_len != 0) {
343 char buf[PREFIX_STRLEN];
344 zlog_warn(
345 "unsupported IPv[4|6] sourcedest route (dest %s vrf %u)",
346 prefix2str(&p, buf, sizeof(buf)), vrf_id);
347 return 0;
348 }
349
350 if (IS_ZEBRA_DEBUG_KERNEL) {
351 char buf[PREFIX_STRLEN];
352 char buf2[PREFIX_STRLEN];
353 zlog_debug(
354 "%s %s%s%s vrf %u", nl_msg_type_to_str(h->nlmsg_type),
355 prefix2str(&p, buf, sizeof(buf)),
356 src_p.prefixlen ? " from " : "",
357 src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2))
358 : "",
359 vrf_id);
360 }
361
362 afi_t afi = AFI_IP;
363 if (rtm->rtm_family == AF_INET6)
364 afi = AFI_IP6;
365
366 if (h->nlmsg_type == RTM_NEWROUTE) {
367 if (!tb[RTA_MULTIPATH])
368 rib_add(afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
369 0, flags, &p, NULL, gate, prefsrc, index, table,
370 metric, mtu, 0);
371 else {
372 /* This is a multipath route */
373
374 struct route_entry *re;
375 struct rtnexthop *rtnh =
376 (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]);
377
378 len = RTA_PAYLOAD(tb[RTA_MULTIPATH]);
379
380 re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
381 re->type = ZEBRA_ROUTE_KERNEL;
382 re->distance = 0;
383 re->flags = flags;
384 re->metric = metric;
385 re->mtu = mtu;
386 re->vrf_id = vrf_id;
387 re->table = table;
388 re->nexthop_num = 0;
389 re->uptime = time(NULL);
390
391 for (;;) {
392 if (len < (int)sizeof(*rtnh)
393 || rtnh->rtnh_len > len)
394 break;
395
396 index = rtnh->rtnh_ifindex;
397 gate = 0;
398 if (rtnh->rtnh_len > sizeof(*rtnh)) {
399 memset(tb, 0, sizeof(tb));
400 netlink_parse_rtattr(
401 tb, RTA_MAX, RTNH_DATA(rtnh),
402 rtnh->rtnh_len - sizeof(*rtnh));
403 if (tb[RTA_GATEWAY])
404 gate = RTA_DATA(
405 tb[RTA_GATEWAY]);
406 }
407
408 if (gate) {
409 if (rtm->rtm_family == AF_INET) {
410 if (index)
411 route_entry_nexthop_ipv4_ifindex_add(
412 re, gate,
413 prefsrc, index);
414 else
415 route_entry_nexthop_ipv4_add(
416 re, gate,
417 prefsrc);
418 } else if (rtm->rtm_family
419 == AF_INET6) {
420 if (index)
421 route_entry_nexthop_ipv6_ifindex_add(
422 re, gate,
423 index);
424 else
425 route_entry_nexthop_ipv6_add(
426 re, gate);
427 }
428 } else
429 route_entry_nexthop_ifindex_add(re,
430 index);
431
432 len -= NLMSG_ALIGN(rtnh->rtnh_len);
433 rtnh = RTNH_NEXT(rtnh);
434 }
435
436 zserv_nexthop_num_warn(__func__,
437 (const struct prefix *)&p,
438 re->nexthop_num);
439 if (re->nexthop_num == 0)
440 XFREE(MTYPE_RE, re);
441 else
442 rib_add_multipath(AFI_IP, SAFI_UNICAST, &p,
443 NULL, re);
444 }
445 } else {
446 if (!tb[RTA_MULTIPATH])
447 rib_delete(afi, SAFI_UNICAST, vrf_id,
448 ZEBRA_ROUTE_KERNEL, 0, flags, &p, NULL, gate,
449 index, table);
450 else {
451 struct rtnexthop *rtnh =
452 (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]);
453
454 len = RTA_PAYLOAD(tb[RTA_MULTIPATH]);
455
456 for (;;) {
457 if (len < (int)sizeof(*rtnh)
458 || rtnh->rtnh_len > len)
459 break;
460
461 gate = NULL;
462 if (rtnh->rtnh_len > sizeof(*rtnh)) {
463 memset(tb, 0, sizeof(tb));
464 netlink_parse_rtattr(
465 tb, RTA_MAX, RTNH_DATA(rtnh),
466 rtnh->rtnh_len - sizeof(*rtnh));
467 if (tb[RTA_GATEWAY])
468 gate = RTA_DATA(
469 tb[RTA_GATEWAY]);
470 }
471
472 if (gate)
473 rib_delete(afi, SAFI_UNICAST, vrf_id,
474 ZEBRA_ROUTE_KERNEL, 0, flags,
475 &p, NULL, gate, index,
476 table);
477
478 len -= NLMSG_ALIGN(rtnh->rtnh_len);
479 rtnh = RTNH_NEXT(rtnh);
480 }
481 }
482 }
483
484 return 0;
485 }
486
487 static struct mcast_route_data *mroute = NULL;
488
489 static int netlink_route_change_read_multicast(struct sockaddr_nl *snl,
490 struct nlmsghdr *h,
491 ns_id_t ns_id, int startup)
492 {
493 int len;
494 struct rtmsg *rtm;
495 struct rtattr *tb[RTA_MAX + 1];
496 struct mcast_route_data *m;
497 struct mcast_route_data mr;
498 int iif = 0;
499 int count;
500 int oif[256];
501 int oif_count = 0;
502 char sbuf[40];
503 char gbuf[40];
504 char oif_list[256] = "\0";
505 vrf_id_t vrf = ns_id;
506
507 if (mroute)
508 m = mroute;
509 else {
510 memset(&mr, 0, sizeof(mr));
511 m = &mr;
512 }
513
514 rtm = NLMSG_DATA(h);
515
516 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
517
518 memset(tb, 0, sizeof tb);
519 netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len);
520
521 if (tb[RTA_IIF])
522 iif = *(int *)RTA_DATA(tb[RTA_IIF]);
523
524 if (tb[RTA_SRC])
525 m->sg.src = *(struct in_addr *)RTA_DATA(tb[RTA_SRC]);
526
527 if (tb[RTA_DST])
528 m->sg.grp = *(struct in_addr *)RTA_DATA(tb[RTA_DST]);
529
530 if ((RTA_EXPIRES <= RTA_MAX) && tb[RTA_EXPIRES])
531 m->lastused = *(unsigned long long *)RTA_DATA(tb[RTA_EXPIRES]);
532
533 if (tb[RTA_MULTIPATH]) {
534 struct rtnexthop *rtnh =
535 (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]);
536
537 len = RTA_PAYLOAD(tb[RTA_MULTIPATH]);
538 for (;;) {
539 if (len < (int)sizeof(*rtnh) || rtnh->rtnh_len > len)
540 break;
541
542 oif[oif_count] = rtnh->rtnh_ifindex;
543 oif_count++;
544
545 len -= NLMSG_ALIGN(rtnh->rtnh_len);
546 rtnh = RTNH_NEXT(rtnh);
547 }
548 }
549
550 if (IS_ZEBRA_DEBUG_KERNEL) {
551 struct interface *ifp;
552 strcpy(sbuf, inet_ntoa(m->sg.src));
553 strcpy(gbuf, inet_ntoa(m->sg.grp));
554 for (count = 0; count < oif_count; count++) {
555 ifp = if_lookup_by_index(oif[count], vrf);
556 char temp[256];
557
558 sprintf(temp, "%s ", ifp->name);
559 strcat(oif_list, temp);
560 }
561 ifp = if_lookup_by_index(iif, vrf);
562 zlog_debug("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld",
563 nl_msg_type_to_str(h->nlmsg_type), sbuf, gbuf,
564 ifp->name, oif_list, m->lastused);
565 }
566 return 0;
567 }
568
569 int netlink_route_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
570 ns_id_t ns_id, int startup)
571 {
572 int len;
573 vrf_id_t vrf_id = ns_id;
574 struct rtmsg *rtm;
575
576 rtm = NLMSG_DATA(h);
577
578 if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) {
579 /* If this is not route add/delete message print warning. */
580 zlog_warn("Kernel message: %d vrf %u\n", h->nlmsg_type, vrf_id);
581 return 0;
582 }
583
584 /* Connected route. */
585 if (IS_ZEBRA_DEBUG_KERNEL)
586 zlog_debug("%s %s %s proto %s vrf %u",
587 nl_msg_type_to_str(h->nlmsg_type),
588 nl_family_to_str(rtm->rtm_family),
589 nl_rttype_to_str(rtm->rtm_type),
590 nl_rtproto_to_str(rtm->rtm_protocol), vrf_id);
591
592 /* We don't care about change notifications for the MPLS table. */
593 /* TODO: Revisit this. */
594 if (rtm->rtm_family == AF_MPLS)
595 return 0;
596
597 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
598 if (len < 0)
599 return -1;
600
601 switch (rtm->rtm_type) {
602 case RTN_UNICAST:
603 netlink_route_change_read_unicast(snl, h, ns_id, startup);
604 break;
605 case RTN_MULTICAST:
606 netlink_route_change_read_multicast(snl, h, ns_id, startup);
607 break;
608 default:
609 return 0;
610 break;
611 }
612
613 return 0;
614 }
615
616 /* Request for specific route information from the kernel */
617 static int netlink_request_route(struct zebra_ns *zns, int family, int type)
618 {
619 struct {
620 struct nlmsghdr n;
621 struct rtmsg rtm;
622 } req;
623
624 /* Form the request, specifying filter (rtattr) if needed. */
625 memset(&req, 0, sizeof(req));
626 req.n.nlmsg_type = type;
627 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
628 req.rtm.rtm_family = family;
629
630 return netlink_request(&zns->netlink_cmd, &req.n);
631 }
632
633 /* Routing table read function using netlink interface. Only called
634 bootstrap time. */
635 int netlink_route_read(struct zebra_ns *zns)
636 {
637 int ret;
638
639 /* Get IPv4 routing table. */
640 ret = netlink_request_route(zns, AF_INET, RTM_GETROUTE);
641 if (ret < 0)
642 return ret;
643 ret = netlink_parse_info(netlink_route_change_read_unicast,
644 &zns->netlink_cmd, zns, 0, 1);
645 if (ret < 0)
646 return ret;
647
648 /* Get IPv6 routing table. */
649 ret = netlink_request_route(zns, AF_INET6, RTM_GETROUTE);
650 if (ret < 0)
651 return ret;
652 ret = netlink_parse_info(netlink_route_change_read_unicast,
653 &zns->netlink_cmd, zns, 0, 1);
654 if (ret < 0)
655 return ret;
656
657 return 0;
658 }
659
660 static void _netlink_route_nl_add_gateway_info(u_char route_family,
661 u_char gw_family,
662 struct nlmsghdr *nlmsg,
663 size_t req_size, int bytelen,
664 struct nexthop *nexthop)
665 {
666 if (route_family == AF_MPLS) {
667 struct gw_family_t gw_fam;
668
669 gw_fam.family = gw_family;
670 if (gw_family == AF_INET)
671 memcpy(&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen);
672 else
673 memcpy(&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen);
674 addattr_l(nlmsg, req_size, RTA_VIA, &gw_fam.family,
675 bytelen + 2);
676 } else {
677 if (gw_family == AF_INET)
678 addattr_l(nlmsg, req_size, RTA_GATEWAY,
679 &nexthop->gate.ipv4, bytelen);
680 else
681 addattr_l(nlmsg, req_size, RTA_GATEWAY,
682 &nexthop->gate.ipv6, bytelen);
683 }
684 }
685
686 static void _netlink_route_rta_add_gateway_info(u_char route_family,
687 u_char gw_family,
688 struct rtattr *rta,
689 struct rtnexthop *rtnh,
690 size_t req_size, int bytelen,
691 struct nexthop *nexthop)
692 {
693 if (route_family == AF_MPLS) {
694 struct gw_family_t gw_fam;
695
696 gw_fam.family = gw_family;
697 if (gw_family == AF_INET)
698 memcpy(&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen);
699 else
700 memcpy(&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen);
701 rta_addattr_l(rta, req_size, RTA_VIA, &gw_fam.family,
702 bytelen + 2);
703 rtnh->rtnh_len += RTA_LENGTH(bytelen + 2);
704 } else {
705 if (gw_family == AF_INET)
706 rta_addattr_l(rta, req_size, RTA_GATEWAY,
707 &nexthop->gate.ipv4, bytelen);
708 else
709 rta_addattr_l(rta, req_size, RTA_GATEWAY,
710 &nexthop->gate.ipv6, bytelen);
711 rtnh->rtnh_len += sizeof(struct rtattr) + bytelen;
712 }
713 }
714
715 /* This function takes a nexthop as argument and adds
716 * the appropriate netlink attributes to an existing
717 * netlink message.
718 *
719 * @param routedesc: Human readable description of route type
720 * (direct/recursive, single-/multipath)
721 * @param bytelen: Length of addresses in bytes.
722 * @param nexthop: Nexthop information
723 * @param nlmsg: nlmsghdr structure to fill in.
724 * @param req_size: The size allocated for the message.
725 */
726 static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
727 struct nexthop *nexthop,
728 struct nlmsghdr *nlmsg,
729 struct rtmsg *rtmsg,
730 size_t req_size, int cmd)
731 {
732 struct nexthop_label *nh_label;
733 mpls_lse_t out_lse[MPLS_MAX_LABELS];
734 char label_buf[100];
735
736 /*
737 * label_buf is *only* currently used within debugging.
738 * As such when we assign it we are guarding it inside
739 * a debug test. If you want to change this make sure
740 * you fix this assumption
741 */
742 label_buf[0] = '\0';
743 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
744 * (in the case of LER)
745 */
746 nh_label = nexthop->nh_label;
747 if (rtmsg->rtm_family == AF_MPLS) {
748 assert(nh_label);
749 assert(nh_label->num_labels == 1);
750 }
751
752 if (nh_label && nh_label->num_labels) {
753 int i, num_labels = 0;
754 u_int32_t bos;
755 char label_buf1[20];
756
757 for (i = 0; i < nh_label->num_labels; i++) {
758 if (nh_label->label[i] != MPLS_IMP_NULL_LABEL) {
759 bos = ((i == (nh_label->num_labels - 1)) ? 1
760 : 0);
761 out_lse[i] = mpls_lse_encode(nh_label->label[i],
762 0, 0, bos);
763 if (IS_ZEBRA_DEBUG_KERNEL) {
764 if (!num_labels)
765 sprintf(label_buf, "label %d",
766 nh_label->label[i]);
767 else {
768 sprintf(label_buf1, "/%d",
769 nh_label->label[i]);
770 strcat(label_buf, label_buf1);
771 }
772 }
773 num_labels++;
774 }
775 }
776 if (num_labels) {
777 if (rtmsg->rtm_family == AF_MPLS)
778 addattr_l(nlmsg, req_size, RTA_NEWDST, &out_lse,
779 num_labels * sizeof(mpls_lse_t));
780 else {
781 struct rtattr *nest;
782 u_int16_t encap = LWTUNNEL_ENCAP_MPLS;
783
784 addattr_l(nlmsg, req_size, RTA_ENCAP_TYPE,
785 &encap, sizeof(u_int16_t));
786 nest = addattr_nest(nlmsg, req_size, RTA_ENCAP);
787 addattr_l(nlmsg, req_size, MPLS_IPTUNNEL_DST,
788 &out_lse,
789 num_labels * sizeof(mpls_lse_t));
790 addattr_nest_end(nlmsg, nest);
791 }
792 }
793 }
794
795 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
796 rtmsg->rtm_flags |= RTNH_F_ONLINK;
797
798 if (rtmsg->rtm_family == AF_INET
799 && (nexthop->type == NEXTHOP_TYPE_IPV6
800 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) {
801 rtmsg->rtm_flags |= RTNH_F_ONLINK;
802 addattr_l(nlmsg, req_size, RTA_GATEWAY, &ipv4_ll, 4);
803 addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
804
805 if (nexthop->rmap_src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
806 addattr_l(nlmsg, req_size, RTA_PREFSRC,
807 &nexthop->rmap_src.ipv4, bytelen);
808 else if (nexthop->src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
809 addattr_l(nlmsg, req_size, RTA_PREFSRC,
810 &nexthop->src.ipv4, bytelen);
811
812 if (IS_ZEBRA_DEBUG_KERNEL)
813 zlog_debug(
814 " 5549: _netlink_route_build_singlepath() (%s): "
815 "nexthop via %s %s if %u",
816 routedesc, ipv4_ll_buf, label_buf,
817 nexthop->ifindex);
818 return;
819 }
820
821 if (nexthop->type == NEXTHOP_TYPE_IPV4
822 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
823 /* Send deletes to the kernel without specifying the next-hop */
824 if (cmd != RTM_DELROUTE)
825 _netlink_route_nl_add_gateway_info(
826 rtmsg->rtm_family, AF_INET, nlmsg, req_size,
827 bytelen, nexthop);
828
829 if (cmd == RTM_NEWROUTE) {
830 if (nexthop->rmap_src.ipv4.s_addr)
831 addattr_l(nlmsg, req_size, RTA_PREFSRC,
832 &nexthop->rmap_src.ipv4, bytelen);
833 else if (nexthop->src.ipv4.s_addr)
834 addattr_l(nlmsg, req_size, RTA_PREFSRC,
835 &nexthop->src.ipv4, bytelen);
836 }
837
838 if (IS_ZEBRA_DEBUG_KERNEL)
839 zlog_debug(
840 "netlink_route_multipath() (%s): "
841 "nexthop via %s %s if %u",
842 routedesc, inet_ntoa(nexthop->gate.ipv4),
843 label_buf, nexthop->ifindex);
844 }
845
846 if (nexthop->type == NEXTHOP_TYPE_IPV6
847 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
848 _netlink_route_nl_add_gateway_info(rtmsg->rtm_family, AF_INET6,
849 nlmsg, req_size, bytelen,
850 nexthop);
851
852 if (cmd == RTM_NEWROUTE) {
853 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
854 addattr_l(nlmsg, req_size, RTA_PREFSRC,
855 &nexthop->rmap_src.ipv6, bytelen);
856 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
857 addattr_l(nlmsg, req_size, RTA_PREFSRC,
858 &nexthop->src.ipv6, bytelen);
859 }
860
861 if (IS_ZEBRA_DEBUG_KERNEL)
862 zlog_debug(
863 "netlink_route_multipath() (%s): "
864 "nexthop via %s %s if %u",
865 routedesc, inet6_ntoa(nexthop->gate.ipv6),
866 label_buf, nexthop->ifindex);
867 }
868 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
869 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
870 addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
871
872 if (cmd == RTM_NEWROUTE) {
873 if (nexthop->rmap_src.ipv4.s_addr)
874 addattr_l(nlmsg, req_size, RTA_PREFSRC,
875 &nexthop->rmap_src.ipv4, bytelen);
876 else if (nexthop->src.ipv4.s_addr)
877 addattr_l(nlmsg, req_size, RTA_PREFSRC,
878 &nexthop->src.ipv4, bytelen);
879 }
880
881 if (IS_ZEBRA_DEBUG_KERNEL)
882 zlog_debug(
883 "netlink_route_multipath() (%s): "
884 "nexthop via if %u",
885 routedesc, nexthop->ifindex);
886 }
887
888 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
889 addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
890
891 if (cmd == RTM_NEWROUTE) {
892 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
893 addattr_l(nlmsg, req_size, RTA_PREFSRC,
894 &nexthop->rmap_src.ipv6, bytelen);
895 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
896 addattr_l(nlmsg, req_size, RTA_PREFSRC,
897 &nexthop->src.ipv6, bytelen);
898 }
899
900 if (IS_ZEBRA_DEBUG_KERNEL)
901 zlog_debug(
902 "netlink_route_multipath() (%s): "
903 "nexthop via if %u",
904 routedesc, nexthop->ifindex);
905 }
906 }
907
908 /* This function takes a nexthop as argument and
909 * appends to the given rtattr/rtnexthop pair the
910 * representation of the nexthop. If the nexthop
911 * defines a preferred source, the src parameter
912 * will be modified to point to that src, otherwise
913 * it will be kept unmodified.
914 *
915 * @param routedesc: Human readable description of route type
916 * (direct/recursive, single-/multipath)
917 * @param bytelen: Length of addresses in bytes.
918 * @param nexthop: Nexthop information
919 * @param rta: rtnetlink attribute structure
920 * @param rtnh: pointer to an rtnetlink nexthop structure
921 * @param src: pointer pointing to a location where
922 * the prefsrc should be stored.
923 */
924 static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
925 struct nexthop *nexthop,
926 struct rtattr *rta,
927 struct rtnexthop *rtnh,
928 struct rtmsg *rtmsg,
929 union g_addr **src)
930 {
931 struct nexthop_label *nh_label;
932 mpls_lse_t out_lse[MPLS_MAX_LABELS];
933 char label_buf[100];
934
935 rtnh->rtnh_len = sizeof(*rtnh);
936 rtnh->rtnh_flags = 0;
937 rtnh->rtnh_hops = 0;
938 rta->rta_len += rtnh->rtnh_len;
939
940 /*
941 * label_buf is *only* currently used within debugging.
942 * As such when we assign it we are guarding it inside
943 * a debug test. If you want to change this make sure
944 * you fix this assumption
945 */
946 label_buf[0] = '\0';
947 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
948 * (in the case of LER)
949 */
950 nh_label = nexthop->nh_label;
951 if (rtmsg->rtm_family == AF_MPLS) {
952 assert(nh_label);
953 assert(nh_label->num_labels == 1);
954 }
955
956 if (nh_label && nh_label->num_labels) {
957 int i, num_labels = 0;
958 u_int32_t bos;
959 char label_buf1[20];
960
961 for (i = 0; i < nh_label->num_labels; i++) {
962 if (nh_label->label[i] != MPLS_IMP_NULL_LABEL) {
963 bos = ((i == (nh_label->num_labels - 1)) ? 1
964 : 0);
965 out_lse[i] = mpls_lse_encode(nh_label->label[i],
966 0, 0, bos);
967 if (IS_ZEBRA_DEBUG_KERNEL) {
968 if (!num_labels)
969 sprintf(label_buf, "label %d",
970 nh_label->label[i]);
971 else {
972 sprintf(label_buf1, "/%d",
973 nh_label->label[i]);
974 strcat(label_buf, label_buf1);
975 }
976 }
977 num_labels++;
978 }
979 }
980 if (num_labels) {
981 if (rtmsg->rtm_family == AF_MPLS) {
982 rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_NEWDST,
983 &out_lse,
984 num_labels * sizeof(mpls_lse_t));
985 rtnh->rtnh_len += RTA_LENGTH(
986 num_labels * sizeof(mpls_lse_t));
987 } else {
988 struct rtattr *nest;
989 u_int16_t encap = LWTUNNEL_ENCAP_MPLS;
990 int len = rta->rta_len;
991
992 rta_addattr_l(rta, NL_PKT_BUF_SIZE,
993 RTA_ENCAP_TYPE, &encap,
994 sizeof(u_int16_t));
995 nest = rta_nest(rta, NL_PKT_BUF_SIZE,
996 RTA_ENCAP);
997 rta_addattr_l(rta, NL_PKT_BUF_SIZE,
998 MPLS_IPTUNNEL_DST, &out_lse,
999 num_labels * sizeof(mpls_lse_t));
1000 rta_nest_end(rta, nest);
1001 rtnh->rtnh_len += rta->rta_len - len;
1002 }
1003 }
1004 }
1005
1006 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
1007 rtnh->rtnh_flags |= RTNH_F_ONLINK;
1008
1009 if (rtmsg->rtm_family == AF_INET
1010 && (nexthop->type == NEXTHOP_TYPE_IPV6
1011 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) {
1012 bytelen = 4;
1013 rtnh->rtnh_flags |= RTNH_F_ONLINK;
1014 rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_GATEWAY, &ipv4_ll,
1015 bytelen);
1016 rtnh->rtnh_len += sizeof(struct rtattr) + bytelen;
1017 rtnh->rtnh_ifindex = nexthop->ifindex;
1018
1019 if (nexthop->rmap_src.ipv4.s_addr)
1020 *src = &nexthop->rmap_src;
1021 else if (nexthop->src.ipv4.s_addr)
1022 *src = &nexthop->src;
1023
1024 if (IS_ZEBRA_DEBUG_KERNEL)
1025 zlog_debug(
1026 " 5549: netlink_route_build_multipath() (%s): "
1027 "nexthop via %s %s if %u",
1028 routedesc, ipv4_ll_buf, label_buf,
1029 nexthop->ifindex);
1030 return;
1031 }
1032
1033 if (nexthop->type == NEXTHOP_TYPE_IPV4
1034 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
1035 _netlink_route_rta_add_gateway_info(rtmsg->rtm_family, AF_INET,
1036 rta, rtnh, NL_PKT_BUF_SIZE,
1037 bytelen, nexthop);
1038 if (nexthop->rmap_src.ipv4.s_addr)
1039 *src = &nexthop->rmap_src;
1040 else if (nexthop->src.ipv4.s_addr)
1041 *src = &nexthop->src;
1042
1043 if (IS_ZEBRA_DEBUG_KERNEL)
1044 zlog_debug(
1045 "netlink_route_multipath() (%s): "
1046 "nexthop via %s %s if %u",
1047 routedesc, inet_ntoa(nexthop->gate.ipv4),
1048 label_buf, nexthop->ifindex);
1049 }
1050 if (nexthop->type == NEXTHOP_TYPE_IPV6
1051 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
1052 _netlink_route_rta_add_gateway_info(rtmsg->rtm_family, AF_INET6,
1053 rta, rtnh, NL_PKT_BUF_SIZE,
1054 bytelen, nexthop);
1055
1056 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
1057 *src = &nexthop->rmap_src;
1058 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
1059 *src = &nexthop->src;
1060
1061 if (IS_ZEBRA_DEBUG_KERNEL)
1062 zlog_debug(
1063 "netlink_route_multipath() (%s): "
1064 "nexthop via %s %s if %u",
1065 routedesc, inet6_ntoa(nexthop->gate.ipv6),
1066 label_buf, nexthop->ifindex);
1067 }
1068 /* ifindex */
1069 if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1070 || nexthop->type == NEXTHOP_TYPE_IFINDEX) {
1071 rtnh->rtnh_ifindex = nexthop->ifindex;
1072
1073 if (nexthop->rmap_src.ipv4.s_addr)
1074 *src = &nexthop->rmap_src;
1075 else if (nexthop->src.ipv4.s_addr)
1076 *src = &nexthop->src;
1077
1078 if (IS_ZEBRA_DEBUG_KERNEL)
1079 zlog_debug(
1080 "netlink_route_multipath() (%s): "
1081 "nexthop via if %u",
1082 routedesc, nexthop->ifindex);
1083 } else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
1084 rtnh->rtnh_ifindex = nexthop->ifindex;
1085
1086 if (IS_ZEBRA_DEBUG_KERNEL)
1087 zlog_debug(
1088 "netlink_route_multipath() (%s): "
1089 "nexthop via if %u",
1090 routedesc, nexthop->ifindex);
1091 } else {
1092 rtnh->rtnh_ifindex = 0;
1093 }
1094 }
1095
1096 static inline void _netlink_mpls_build_singlepath(const char *routedesc,
1097 zebra_nhlfe_t *nhlfe,
1098 struct nlmsghdr *nlmsg,
1099 struct rtmsg *rtmsg,
1100 size_t req_size, int cmd)
1101 {
1102 int bytelen;
1103 u_char family;
1104
1105 family = NHLFE_FAMILY(nhlfe);
1106 bytelen = (family == AF_INET ? 4 : 16);
1107 _netlink_route_build_singlepath(routedesc, bytelen, nhlfe->nexthop,
1108 nlmsg, rtmsg, req_size, cmd);
1109 }
1110
1111
1112 static inline void
1113 _netlink_mpls_build_multipath(const char *routedesc, zebra_nhlfe_t *nhlfe,
1114 struct rtattr *rta, struct rtnexthop *rtnh,
1115 struct rtmsg *rtmsg, union g_addr **src)
1116 {
1117 int bytelen;
1118 u_char family;
1119
1120 family = NHLFE_FAMILY(nhlfe);
1121 bytelen = (family == AF_INET ? 4 : 16);
1122 _netlink_route_build_multipath(routedesc, bytelen, nhlfe->nexthop, rta,
1123 rtnh, rtmsg, src);
1124 }
1125
1126
1127 /* Log debug information for netlink_route_multipath
1128 * if debug logging is enabled.
1129 *
1130 * @param cmd: Netlink command which is to be processed
1131 * @param p: Prefix for which the change is due
1132 * @param nexthop: Nexthop which is currently processed
1133 * @param routedesc: Semantic annotation for nexthop
1134 * (recursive, multipath, etc.)
1135 * @param family: Address family which the change concerns
1136 */
1137 static void _netlink_route_debug(int cmd, struct prefix *p,
1138 struct nexthop *nexthop, const char *routedesc,
1139 int family, struct zebra_vrf *zvrf)
1140 {
1141 if (IS_ZEBRA_DEBUG_KERNEL) {
1142 char buf[PREFIX_STRLEN];
1143 zlog_debug(
1144 "netlink_route_multipath() (%s): %s %s vrf %u type %s",
1145 routedesc, nl_msg_type_to_str(cmd),
1146 prefix2str(p, buf, sizeof(buf)), zvrf_id(zvrf),
1147 (nexthop) ? nexthop_type_to_str(nexthop->type) : "UNK");
1148 }
1149 }
1150
1151 static void _netlink_mpls_debug(int cmd, u_int32_t label, const char *routedesc)
1152 {
1153 if (IS_ZEBRA_DEBUG_KERNEL)
1154 zlog_debug("netlink_mpls_multipath() (%s): %s %u/20", routedesc,
1155 nl_msg_type_to_str(cmd), label);
1156 }
1157
1158 static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
1159 int llalen)
1160 {
1161 struct {
1162 struct nlmsghdr n;
1163 struct ndmsg ndm;
1164 char buf[256];
1165 } req;
1166
1167 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
1168
1169 memset(&req.n, 0, sizeof(req.n));
1170 memset(&req.ndm, 0, sizeof(req.ndm));
1171
1172 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
1173 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1174 req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH
1175 req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
1176
1177 req.ndm.ndm_family = AF_INET;
1178 req.ndm.ndm_state = NUD_PERMANENT;
1179 req.ndm.ndm_ifindex = ifindex;
1180 req.ndm.ndm_type = RTN_UNICAST;
1181
1182 addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4);
1183 addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
1184
1185 return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
1186 0);
1187 }
1188
1189 /* Routing table change via netlink interface. */
1190 /* Update flag indicates whether this is a "replace" or not. */
1191 static int netlink_route_multipath(int cmd, struct prefix *p,
1192 struct prefix *src_p, struct route_entry *re,
1193 int update)
1194 {
1195 int bytelen;
1196 struct sockaddr_nl snl;
1197 struct nexthop *nexthop = NULL;
1198 unsigned int nexthop_num;
1199 int discard;
1200 int family = PREFIX_FAMILY(p);
1201 const char *routedesc;
1202 int setsrc = 0;
1203 union g_addr src;
1204
1205 struct {
1206 struct nlmsghdr n;
1207 struct rtmsg r;
1208 char buf[NL_PKT_BUF_SIZE];
1209 } req;
1210
1211 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
1212 struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id);
1213
1214 memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE);
1215
1216 bytelen = (family == AF_INET ? 4 : 16);
1217
1218 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
1219 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1220 if ((cmd == RTM_NEWROUTE) && update)
1221 req.n.nlmsg_flags |= NLM_F_REPLACE;
1222 req.n.nlmsg_type = cmd;
1223 req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
1224
1225 req.r.rtm_family = family;
1226 req.r.rtm_dst_len = p->prefixlen;
1227 req.r.rtm_src_len = src_p ? src_p->prefixlen : 0;
1228 req.r.rtm_protocol = get_rt_proto(re->type);
1229 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1230
1231 if ((re->flags & ZEBRA_FLAG_BLACKHOLE)
1232 || (re->flags & ZEBRA_FLAG_REJECT))
1233 discard = 1;
1234 else
1235 discard = 0;
1236
1237 if (cmd == RTM_NEWROUTE) {
1238 if (discard) {
1239 if (re->flags & ZEBRA_FLAG_BLACKHOLE)
1240 req.r.rtm_type = RTN_BLACKHOLE;
1241 else if (re->flags & ZEBRA_FLAG_REJECT)
1242 req.r.rtm_type = RTN_UNREACHABLE;
1243 else
1244 assert(RTN_BLACKHOLE
1245 != RTN_UNREACHABLE); /* false */
1246 } else
1247 req.r.rtm_type = RTN_UNICAST;
1248 }
1249
1250 addattr_l(&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
1251 if (src_p)
1252 addattr_l(&req.n, sizeof req, RTA_SRC, &src_p->u.prefix,
1253 bytelen);
1254
1255 /* Metric. */
1256 /* Hardcode the metric for all routes coming from zebra. Metric isn't
1257 * used
1258 * either by the kernel or by zebra. Its purely for calculating best
1259 * path(s)
1260 * by the routing protocol and for communicating with protocol peers.
1261 */
1262 addattr32(&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC);
1263
1264 /* Table corresponding to this route. */
1265 if (re->table < 256)
1266 req.r.rtm_table = re->table;
1267 else {
1268 req.r.rtm_table = RT_TABLE_UNSPEC;
1269 addattr32(&req.n, sizeof req, RTA_TABLE, re->table);
1270 }
1271
1272 if (re->mtu || re->nexthop_mtu) {
1273 char buf[NL_PKT_BUF_SIZE];
1274 struct rtattr *rta = (void *)buf;
1275 u_int32_t mtu = re->mtu;
1276 if (!mtu || (re->nexthop_mtu && re->nexthop_mtu < mtu))
1277 mtu = re->nexthop_mtu;
1278 rta->rta_type = RTA_METRICS;
1279 rta->rta_len = RTA_LENGTH(0);
1280 rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu);
1281 addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA(rta),
1282 RTA_PAYLOAD(rta));
1283 }
1284
1285 if (discard) {
1286 if (cmd == RTM_NEWROUTE)
1287 for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
1288 /* We shouldn't encounter recursive nexthops on
1289 * discard routes,
1290 * but it is probably better to handle that case
1291 * correctly anyway.
1292 */
1293 if (CHECK_FLAG(nexthop->flags,
1294 NEXTHOP_FLAG_RECURSIVE))
1295 continue;
1296 }
1297 goto skip;
1298 }
1299
1300 /* Count overall nexthops so we can decide whether to use singlepath
1301 * or multipath case. */
1302 nexthop_num = 0;
1303 for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
1304 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1305 continue;
1306 if (cmd == RTM_NEWROUTE
1307 && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1308 continue;
1309 if (cmd == RTM_DELROUTE
1310 && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
1311 continue;
1312
1313 nexthop_num++;
1314 }
1315
1316 /* Singlepath case. */
1317 if (nexthop_num == 1 || multipath_num == 1) {
1318 nexthop_num = 0;
1319 for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
1320 if (CHECK_FLAG(nexthop->flags,
1321 NEXTHOP_FLAG_RECURSIVE)) {
1322 if (!setsrc) {
1323 if (family == AF_INET) {
1324 if (nexthop->rmap_src.ipv4
1325 .s_addr
1326 != 0) {
1327 src.ipv4 =
1328 nexthop->rmap_src
1329 .ipv4;
1330 setsrc = 1;
1331 } else if (nexthop->src.ipv4
1332 .s_addr
1333 != 0) {
1334 src.ipv4 =
1335 nexthop->src
1336 .ipv4;
1337 setsrc = 1;
1338 }
1339 } else if (family == AF_INET6) {
1340 if (!IN6_IS_ADDR_UNSPECIFIED(
1341 &nexthop->rmap_src
1342 .ipv6)) {
1343 src.ipv6 =
1344 nexthop->rmap_src
1345 .ipv6;
1346 setsrc = 1;
1347 } else if (
1348 !IN6_IS_ADDR_UNSPECIFIED(
1349 &nexthop->src
1350 .ipv6)) {
1351 src.ipv6 =
1352 nexthop->src
1353 .ipv6;
1354 setsrc = 1;
1355 }
1356 }
1357 }
1358 continue;
1359 }
1360
1361 if ((cmd == RTM_NEWROUTE
1362 && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1363 || (cmd == RTM_DELROUTE
1364 && CHECK_FLAG(nexthop->flags,
1365 NEXTHOP_FLAG_FIB))) {
1366 routedesc = nexthop->rparent
1367 ? "recursive, 1 hop"
1368 : "single hop";
1369
1370 _netlink_route_debug(cmd, p, nexthop, routedesc,
1371 family, zvrf);
1372 _netlink_route_build_singlepath(
1373 routedesc, bytelen, nexthop, &req.n,
1374 &req.r, sizeof req, cmd);
1375 nexthop_num++;
1376 break;
1377 }
1378 }
1379 if (setsrc && (cmd == RTM_NEWROUTE)) {
1380 if (family == AF_INET)
1381 addattr_l(&req.n, sizeof req, RTA_PREFSRC,
1382 &src.ipv4, bytelen);
1383 else if (family == AF_INET6)
1384 addattr_l(&req.n, sizeof req, RTA_PREFSRC,
1385 &src.ipv6, bytelen);
1386 }
1387 } else {
1388 char buf[NL_PKT_BUF_SIZE];
1389 struct rtattr *rta = (void *)buf;
1390 struct rtnexthop *rtnh;
1391 union g_addr *src1 = NULL;
1392
1393 rta->rta_type = RTA_MULTIPATH;
1394 rta->rta_len = RTA_LENGTH(0);
1395 rtnh = RTA_DATA(rta);
1396
1397 nexthop_num = 0;
1398 for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
1399 if (nexthop_num >= multipath_num)
1400 break;
1401
1402 if (CHECK_FLAG(nexthop->flags,
1403 NEXTHOP_FLAG_RECURSIVE)) {
1404 /* This only works for IPv4 now */
1405 if (!setsrc) {
1406 if (family == AF_INET) {
1407 if (nexthop->rmap_src.ipv4
1408 .s_addr
1409 != 0) {
1410 src.ipv4 =
1411 nexthop->rmap_src
1412 .ipv4;
1413 setsrc = 1;
1414 } else if (nexthop->src.ipv4
1415 .s_addr
1416 != 0) {
1417 src.ipv4 =
1418 nexthop->src
1419 .ipv4;
1420 setsrc = 1;
1421 }
1422 } else if (family == AF_INET6) {
1423 if (!IN6_IS_ADDR_UNSPECIFIED(
1424 &nexthop->rmap_src
1425 .ipv6)) {
1426 src.ipv6 =
1427 nexthop->rmap_src
1428 .ipv6;
1429 setsrc = 1;
1430 } else if (
1431 !IN6_IS_ADDR_UNSPECIFIED(
1432 &nexthop->src
1433 .ipv6)) {
1434 src.ipv6 =
1435 nexthop->src
1436 .ipv6;
1437 setsrc = 1;
1438 }
1439 }
1440 }
1441 continue;
1442 }
1443
1444 if ((cmd == RTM_NEWROUTE
1445 && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1446 || (cmd == RTM_DELROUTE
1447 && CHECK_FLAG(nexthop->flags,
1448 NEXTHOP_FLAG_FIB))) {
1449 routedesc = nexthop->rparent
1450 ? "recursive, multihop"
1451 : "multihop";
1452 nexthop_num++;
1453
1454 _netlink_route_debug(cmd, p, nexthop, routedesc,
1455 family, zvrf);
1456 _netlink_route_build_multipath(
1457 routedesc, bytelen, nexthop, rta, rtnh,
1458 &req.r, &src1);
1459 rtnh = RTNH_NEXT(rtnh);
1460
1461 if (!setsrc && src1) {
1462 if (family == AF_INET)
1463 src.ipv4 = src1->ipv4;
1464 else if (family == AF_INET6)
1465 src.ipv6 = src1->ipv6;
1466
1467 setsrc = 1;
1468 }
1469 }
1470 }
1471 if (setsrc && (cmd == RTM_NEWROUTE)) {
1472 if (family == AF_INET)
1473 addattr_l(&req.n, sizeof req, RTA_PREFSRC,
1474 &src.ipv4, bytelen);
1475 else if (family == AF_INET6)
1476 addattr_l(&req.n, sizeof req, RTA_PREFSRC,
1477 &src.ipv6, bytelen);
1478 if (IS_ZEBRA_DEBUG_KERNEL)
1479 zlog_debug("Setting source");
1480 }
1481
1482 if (rta->rta_len > RTA_LENGTH(0))
1483 addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH,
1484 RTA_DATA(rta), RTA_PAYLOAD(rta));
1485 }
1486
1487 /* If there is no useful nexthop then return. */
1488 if (nexthop_num == 0) {
1489 if (IS_ZEBRA_DEBUG_KERNEL)
1490 zlog_debug(
1491 "netlink_route_multipath(): No useful nexthop.");
1492 return 0;
1493 }
1494
1495 skip:
1496
1497 /* Destination netlink address. */
1498 memset(&snl, 0, sizeof snl);
1499 snl.nl_family = AF_NETLINK;
1500
1501 /* Talk to netlink socket. */
1502 return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
1503 0);
1504 }
1505
1506 int kernel_get_ipmr_sg_stats(void *in)
1507 {
1508 int suc = 0;
1509 struct mcast_route_data *mr = (struct mcast_route_data *)in;
1510 struct {
1511 struct nlmsghdr n;
1512 struct ndmsg ndm;
1513 char buf[256];
1514 } req;
1515
1516 mroute = mr;
1517 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
1518
1519 memset(&req.n, 0, sizeof(req.n));
1520 memset(&req.ndm, 0, sizeof(req.ndm));
1521
1522 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
1523 req.n.nlmsg_flags = NLM_F_REQUEST;
1524 req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
1525
1526 req.ndm.ndm_family = AF_INET;
1527 req.n.nlmsg_type = RTM_GETROUTE;
1528
1529 addattr_l(&req.n, sizeof(req), RTA_IIF, &mroute->ifindex, 4);
1530 addattr_l(&req.n, sizeof(req), RTA_OIF, &mroute->ifindex, 4);
1531 addattr_l(&req.n, sizeof(req), RTA_SRC, &mroute->sg.src.s_addr, 4);
1532 addattr_l(&req.n, sizeof(req), RTA_DST, &mroute->sg.grp.s_addr, 4);
1533
1534 suc = netlink_talk(netlink_route_change_read_multicast, &req.n,
1535 &zns->netlink_cmd, zns, 0);
1536
1537 mroute = NULL;
1538 return suc;
1539 }
1540
1541 int kernel_route_rib(struct prefix *p, struct prefix *src_p,
1542 struct route_entry *old, struct route_entry *new)
1543 {
1544 if (!old && new)
1545 return netlink_route_multipath(RTM_NEWROUTE, p, src_p, new, 0);
1546 if (old && !new)
1547 return netlink_route_multipath(RTM_DELROUTE, p, src_p, old, 0);
1548
1549 return netlink_route_multipath(RTM_NEWROUTE, p, src_p, new, 1);
1550 }
1551
1552 int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
1553 int llalen)
1554 {
1555 return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex,
1556 addr, lla, llalen);
1557 }
1558
1559 /*
1560 * Add remote VTEP to the flood list for this VxLAN interface (VNI). This
1561 * is done by adding an FDB entry with a MAC of 00:00:00:00:00:00.
1562 */
1563 static int netlink_vxlan_flood_list_update(struct interface *ifp,
1564 struct in_addr *vtep_ip, int cmd)
1565 {
1566 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
1567 struct {
1568 struct nlmsghdr n;
1569 struct ndmsg ndm;
1570 char buf[256];
1571 } req;
1572 u_char dst_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
1573
1574 memset(&req.n, 0, sizeof(req.n));
1575 memset(&req.ndm, 0, sizeof(req.ndm));
1576
1577 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
1578 req.n.nlmsg_flags = NLM_F_REQUEST;
1579 if (cmd == RTM_NEWNEIGH)
1580 req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_APPEND);
1581 req.n.nlmsg_type = cmd;
1582 req.ndm.ndm_family = PF_BRIDGE;
1583 req.ndm.ndm_state = NUD_NOARP | NUD_PERMANENT;
1584 req.ndm.ndm_flags |= NTF_SELF; // Handle by "self", not "master"
1585
1586
1587 addattr_l(&req.n, sizeof(req), NDA_LLADDR, &dst_mac, 6);
1588 req.ndm.ndm_ifindex = ifp->ifindex;
1589 addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip->s_addr, 4);
1590
1591 return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
1592 0);
1593 }
1594
1595 /*
1596 * Add remote VTEP for this VxLAN interface (VNI). In Linux, this involves
1597 * adding
1598 * a "flood" MAC FDB entry.
1599 */
1600 int kernel_add_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
1601 {
1602 if (IS_ZEBRA_DEBUG_VXLAN)
1603 zlog_debug("Install %s into flood list for VNI %u intf %s(%u)",
1604 inet_ntoa(*vtep_ip), vni, ifp->name, ifp->ifindex);
1605
1606 return netlink_vxlan_flood_list_update(ifp, vtep_ip, RTM_NEWNEIGH);
1607 }
1608
1609 /*
1610 * Remove remote VTEP for this VxLAN interface (VNI). In Linux, this involves
1611 * deleting the "flood" MAC FDB entry.
1612 */
1613 int kernel_del_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
1614 {
1615 if (IS_ZEBRA_DEBUG_VXLAN)
1616 zlog_debug(
1617 "Uninstall %s from flood list for VNI %u intf %s(%u)",
1618 inet_ntoa(*vtep_ip), vni, ifp->name, ifp->ifindex);
1619
1620 return netlink_vxlan_flood_list_update(ifp, vtep_ip, RTM_DELNEIGH);
1621 }
1622
1623 #ifndef NDA_RTA
1624 #define NDA_RTA(r) \
1625 ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
1626 #endif
1627
1628 static int netlink_macfdb_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
1629 int len)
1630 {
1631 struct ndmsg *ndm;
1632 struct interface *ifp;
1633 struct zebra_if *zif;
1634 struct zebra_vrf *zvrf;
1635 struct rtattr *tb[NDA_MAX + 1];
1636 struct interface *br_if;
1637 struct ethaddr mac;
1638 vlanid_t vid = 0;
1639 struct prefix vtep_ip;
1640 int vid_present = 0, dst_present = 0;
1641 char buf[ETHER_ADDR_STRLEN];
1642 char vid_buf[20];
1643 char dst_buf[30];
1644 u_char sticky = 0;
1645
1646 ndm = NLMSG_DATA(h);
1647
1648 /* The interface should exist. */
1649 ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
1650 ndm->ndm_ifindex);
1651 if (!ifp)
1652 return 0;
1653
1654 /* Locate VRF corresponding to interface. We only process MAC
1655 * notifications
1656 * if EVPN is enabled on this VRF.
1657 */
1658 zvrf = vrf_info_lookup(ifp->vrf_id);
1659 if (!zvrf || !EVPN_ENABLED(zvrf))
1660 return 0;
1661 if (!ifp->info)
1662 return 0;
1663
1664 /* The interface should be something we're interested in. */
1665 if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
1666 return 0;
1667
1668 /* Drop "permanent" entries. */
1669 if (ndm->ndm_state & NUD_PERMANENT)
1670 return 0;
1671
1672 zif = (struct zebra_if *)ifp->info;
1673 if ((br_if = zif->brslave_info.br_if) == NULL) {
1674 zlog_warn("%s family %s IF %s(%u) brIF %u - no bridge master",
1675 nl_msg_type_to_str(h->nlmsg_type),
1676 nl_family_to_str(ndm->ndm_family), ifp->name,
1677 ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex);
1678 return 0;
1679 }
1680
1681 /* Parse attributes and extract fields of interest. */
1682 memset(tb, 0, sizeof tb);
1683 netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);
1684
1685 if (!tb[NDA_LLADDR]) {
1686 zlog_warn("%s family %s IF %s(%u) brIF %u - no LLADDR",
1687 nl_msg_type_to_str(h->nlmsg_type),
1688 nl_family_to_str(ndm->ndm_family), ifp->name,
1689 ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex);
1690 return 0;
1691 }
1692
1693 if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETHER_ADDR_LEN) {
1694 zlog_warn(
1695 "%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %ld",
1696 nl_msg_type_to_str(h->nlmsg_type),
1697 nl_family_to_str(ndm->ndm_family), ifp->name,
1698 ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex,
1699 RTA_PAYLOAD(tb[NDA_LLADDR]));
1700 return 0;
1701 }
1702
1703 memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETHER_ADDR_LEN);
1704
1705 if ((NDA_VLAN <= NDA_MAX) && tb[NDA_VLAN]) {
1706 vid_present = 1;
1707 vid = *(u_int16_t *)RTA_DATA(tb[NDA_VLAN]);
1708 sprintf(vid_buf, " VLAN %u", vid);
1709 }
1710
1711 if (tb[NDA_DST]) {
1712 /* TODO: Only IPv4 supported now. */
1713 dst_present = 1;
1714 vtep_ip.family = AF_INET;
1715 vtep_ip.prefixlen = IPV4_MAX_BITLEN;
1716 memcpy(&(vtep_ip.u.prefix4.s_addr), RTA_DATA(tb[NDA_DST]),
1717 IPV4_MAX_BYTELEN);
1718 sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip.u.prefix4));
1719 }
1720
1721 sticky = (ndm->ndm_state & NUD_NOARP) ? 1 : 0;
1722
1723 if (IS_ZEBRA_DEBUG_KERNEL)
1724 zlog_debug("Rx %s family %s IF %s(%u)%s %sMAC %s%s",
1725 nl_msg_type_to_str(h->nlmsg_type),
1726 nl_family_to_str(ndm->ndm_family), ifp->name,
1727 ndm->ndm_ifindex, vid_present ? vid_buf : "",
1728 sticky ? "sticky " : "",
1729 prefix_mac2str(&mac, buf, sizeof(buf)),
1730 dst_present ? dst_buf : "");
1731
1732 if (filter_vlan && vid != filter_vlan)
1733 return 0;
1734
1735 /* If add or update, do accordingly if learnt on a "local" interface; if
1736 * the notification is over VxLAN, this has to be related to
1737 * multi-homing,
1738 * so perform an implicit delete of any local entry (if it exists).
1739 */
1740 if (h->nlmsg_type == RTM_NEWNEIGH) {
1741 /* Drop "permanent" entries. */
1742 if (ndm->ndm_state & NUD_PERMANENT)
1743 return 0;
1744
1745 if (IS_ZEBRA_IF_VXLAN(ifp))
1746 return zebra_vxlan_check_del_local_mac(ifp, br_if, &mac,
1747 vid);
1748
1749 return zebra_vxlan_local_mac_add_update(ifp, br_if, &mac, vid,
1750 sticky);
1751 }
1752
1753 /* This is a delete notification.
1754 * 1. For a MAC over VxLan, check if it needs to be refreshed(readded)
1755 * 2. For a MAC over "local" interface, delete the mac
1756 * Note: We will get notifications from both bridge driver and VxLAN
1757 * driver.
1758 * Ignore the notification from VxLan driver as it is also generated
1759 * when mac moves from remote to local.
1760 */
1761 if (dst_present)
1762 return 0;
1763
1764 if (IS_ZEBRA_IF_VXLAN(ifp))
1765 return zebra_vxlan_check_readd_remote_mac(ifp, br_if, &mac,
1766 vid);
1767
1768 return zebra_vxlan_local_mac_del(ifp, br_if, &mac, vid);
1769 }
1770
1771 static int netlink_macfdb_table(struct sockaddr_nl *snl, struct nlmsghdr *h,
1772 ns_id_t ns_id, int startup)
1773 {
1774 int len;
1775 struct ndmsg *ndm;
1776
1777 if (h->nlmsg_type != RTM_NEWNEIGH)
1778 return 0;
1779
1780 /* Length validity. */
1781 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg));
1782 if (len < 0)
1783 return -1;
1784
1785 /* We are interested only in AF_BRIDGE notifications. */
1786 ndm = NLMSG_DATA(h);
1787 if (ndm->ndm_family != AF_BRIDGE)
1788 return 0;
1789
1790 return netlink_macfdb_change(snl, h, len);
1791 }
1792
1793 /* Request for MAC FDB information from the kernel */
1794 static int netlink_request_macs(struct zebra_ns *zns, int family, int type,
1795 ifindex_t master_ifindex)
1796 {
1797 struct {
1798 struct nlmsghdr n;
1799 struct ifinfomsg ifm;
1800 char buf[256];
1801 } req;
1802
1803 /* Form the request, specifying filter (rtattr) if needed. */
1804 memset(&req, 0, sizeof(req));
1805 req.n.nlmsg_type = type;
1806 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
1807 req.ifm.ifi_family = family;
1808 if (master_ifindex)
1809 addattr32(&req.n, sizeof(req), IFLA_MASTER, master_ifindex);
1810
1811 return netlink_request(&zns->netlink_cmd, &req.n);
1812 }
1813
1814 /*
1815 * MAC forwarding database read using netlink interface. This is invoked
1816 * at startup.
1817 */
1818 int netlink_macfdb_read(struct zebra_ns *zns)
1819 {
1820 int ret;
1821
1822 /* Get bridge FDB table. */
1823 ret = netlink_request_macs(zns, AF_BRIDGE, RTM_GETNEIGH, 0);
1824 if (ret < 0)
1825 return ret;
1826 /* We are reading entire table. */
1827 filter_vlan = 0;
1828 ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, zns,
1829 0, 1);
1830
1831 return ret;
1832 }
1833
1834 /*
1835 * MAC forwarding database read using netlink interface. This is for a
1836 * specific bridge and matching specific access VLAN (if VLAN-aware bridge).
1837 */
1838 int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp,
1839 struct interface *br_if)
1840 {
1841 struct zebra_if *br_zif;
1842 struct zebra_if *zif;
1843 struct zebra_l2info_vxlan *vxl;
1844 int ret = 0;
1845
1846
1847 /* Save VLAN we're filtering on, if needed. */
1848 br_zif = (struct zebra_if *)br_if->info;
1849 zif = (struct zebra_if *)ifp->info;
1850 vxl = &zif->l2info.vxl;
1851 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif))
1852 filter_vlan = vxl->access_vlan;
1853
1854 /* Get bridge FDB table for specific bridge - we do the VLAN filtering.
1855 */
1856 ret = netlink_request_macs(zns, AF_BRIDGE, RTM_GETNEIGH,
1857 br_if->ifindex);
1858 if (ret < 0)
1859 return ret;
1860 ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, zns,
1861 0, 0);
1862
1863 /* Reset VLAN filter. */
1864 filter_vlan = 0;
1865 return ret;
1866 }
1867
1868 static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid,
1869 struct ethaddr *mac, struct in_addr vtep_ip,
1870 int local, int cmd, u_char sticky)
1871 {
1872 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
1873 struct {
1874 struct nlmsghdr n;
1875 struct ndmsg ndm;
1876 char buf[256];
1877 } req;
1878 int dst_alen;
1879 struct zebra_if *zif;
1880 struct interface *br_if;
1881 struct zebra_if *br_zif;
1882 char buf[ETHER_ADDR_STRLEN];
1883 int vid_present = 0, dst_present = 0;
1884 char vid_buf[20];
1885 char dst_buf[30];
1886
1887 zif = ifp->info;
1888 if ((br_if = zif->brslave_info.br_if) == NULL) {
1889 zlog_warn("MAC %s on IF %s(%u) - no mapping to bridge",
1890 (cmd == RTM_NEWNEIGH) ? "add" : "del", ifp->name,
1891 ifp->ifindex);
1892 return -1;
1893 }
1894
1895 memset(&req.n, 0, sizeof(req.n));
1896 memset(&req.ndm, 0, sizeof(req.ndm));
1897
1898 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
1899 req.n.nlmsg_flags = NLM_F_REQUEST;
1900 if (cmd == RTM_NEWNEIGH)
1901 req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
1902 req.n.nlmsg_type = cmd;
1903 req.ndm.ndm_family = AF_BRIDGE;
1904 req.ndm.ndm_flags |= NTF_SELF | NTF_MASTER;
1905 req.ndm.ndm_state = NUD_REACHABLE;
1906
1907 if (sticky)
1908 req.ndm.ndm_state |= NUD_NOARP;
1909 else
1910 req.ndm.ndm_flags |= NTF_EXT_LEARNED;
1911
1912 addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
1913 req.ndm.ndm_ifindex = ifp->ifindex;
1914 if (!local) {
1915 dst_alen = 4; // TODO: hardcoded
1916 addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip, dst_alen);
1917 dst_present = 1;
1918 sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip));
1919 }
1920 br_zif = (struct zebra_if *)br_if->info;
1921 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0) {
1922 addattr16(&req.n, sizeof(req), NDA_VLAN, vid);
1923 vid_present = 1;
1924 sprintf(vid_buf, " VLAN %u", vid);
1925 }
1926 addattr32(&req.n, sizeof(req), NDA_MASTER, br_if->ifindex);
1927
1928 if (IS_ZEBRA_DEBUG_KERNEL)
1929 zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s%s",
1930 nl_msg_type_to_str(cmd),
1931 nl_family_to_str(req.ndm.ndm_family), ifp->name,
1932 ifp->ifindex, vid_present ? vid_buf : "",
1933 sticky ? "sticky " : "",
1934 prefix_mac2str(mac, buf, sizeof(buf)),
1935 dst_present ? dst_buf : "");
1936
1937 return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
1938 0);
1939 }
1940
1941 #define NUD_VALID \
1942 (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE | NUD_PROBE | NUD_STALE \
1943 | NUD_DELAY)
1944
1945 static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
1946 int len)
1947 {
1948 struct ndmsg *ndm;
1949 struct interface *ifp;
1950 struct zebra_if *zif;
1951 struct zebra_vrf *zvrf;
1952 struct rtattr *tb[NDA_MAX + 1];
1953 struct interface *link_if;
1954 struct ethaddr mac;
1955 struct ipaddr ip;
1956 char buf[ETHER_ADDR_STRLEN];
1957 char buf2[INET6_ADDRSTRLEN];
1958 int mac_present = 0;
1959 u_char ext_learned;
1960
1961 ndm = NLMSG_DATA(h);
1962
1963 /* The interface should exist. */
1964 ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
1965 ndm->ndm_ifindex);
1966 if (!ifp)
1967 return 0;
1968
1969 /* Locate VRF corresponding to interface. We only process neigh
1970 * notifications
1971 * if EVPN is enabled on this VRF.
1972 */
1973 zvrf = vrf_info_lookup(ifp->vrf_id);
1974 if (!zvrf || !EVPN_ENABLED(zvrf))
1975 return 0;
1976 if (!ifp->info)
1977 return 0;
1978
1979 /* Drop "permanent" entries. */
1980 if (ndm->ndm_state & NUD_PERMANENT)
1981 return 0;
1982
1983 zif = (struct zebra_if *)ifp->info;
1984 /* The neighbor is present on an SVI. From this, we locate the
1985 * underlying
1986 * bridge because we're only interested in neighbors on a VxLAN bridge.
1987 * The bridge is located based on the nature of the SVI:
1988 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN
1989 * interface
1990 * and is linked to the bridge
1991 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge
1992 * inteface
1993 * itself
1994 */
1995 if (IS_ZEBRA_IF_VLAN(ifp)) {
1996 link_if = zif->link;
1997 if (!link_if)
1998 return 0;
1999 } else if (IS_ZEBRA_IF_BRIDGE(ifp))
2000 link_if = ifp;
2001 else
2002 return 0;
2003
2004 /* Parse attributes and extract fields of interest. */
2005 memset(tb, 0, sizeof tb);
2006 netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);
2007
2008 if (!tb[NDA_DST]) {
2009 zlog_warn("%s family %s IF %s(%u) - no DST",
2010 nl_msg_type_to_str(h->nlmsg_type),
2011 nl_family_to_str(ndm->ndm_family), ifp->name,
2012 ndm->ndm_ifindex);
2013 return 0;
2014 }
2015 memset(&mac, 0, sizeof(struct ethaddr));
2016 memset(&ip, 0, sizeof(struct ipaddr));
2017 ip.ipa_type = (ndm->ndm_family == AF_INET) ? IPADDR_V4 : IPADDR_V6;
2018 memcpy(&ip.ip.addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
2019
2020 if (h->nlmsg_type == RTM_NEWNEIGH) {
2021 if (tb[NDA_LLADDR]) {
2022 if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETHER_ADDR_LEN) {
2023 zlog_warn(
2024 "%s family %s IF %s(%u) - LLADDR is not MAC, len %ld",
2025 nl_msg_type_to_str(h->nlmsg_type),
2026 nl_family_to_str(ndm->ndm_family),
2027 ifp->name, ndm->ndm_ifindex,
2028 RTA_PAYLOAD(tb[NDA_LLADDR]));
2029 return 0;
2030 }
2031
2032 mac_present = 1;
2033 memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETHER_ADDR_LEN);
2034 }
2035
2036 ext_learned = (ndm->ndm_flags & NTF_EXT_LEARNED) ? 1 : 0;
2037
2038 if (IS_ZEBRA_DEBUG_KERNEL)
2039 zlog_debug(
2040 "Rx %s family %s IF %s(%u) IP %s MAC %s state 0x%x flags 0x%x",
2041 nl_msg_type_to_str(h->nlmsg_type),
2042 nl_family_to_str(ndm->ndm_family), ifp->name,
2043 ndm->ndm_ifindex,
2044 ipaddr2str(&ip, buf2, sizeof(buf2)),
2045 mac_present
2046 ? prefix_mac2str(&mac, buf, sizeof(buf))
2047 : "",
2048 ndm->ndm_state, ndm->ndm_flags);
2049
2050 /* If the neighbor state is valid for use, process as an add or
2051 * update
2052 * else process as a delete. Note that the delete handling may
2053 * result
2054 * in re-adding the neighbor if it is a valid "remote" neighbor.
2055 */
2056 if (ndm->ndm_state & NUD_VALID)
2057 return zebra_vxlan_local_neigh_add_update(
2058 ifp, link_if, &ip, &mac, ndm->ndm_state,
2059 ext_learned);
2060
2061 return zebra_vxlan_local_neigh_del(ifp, link_if, &ip);
2062 }
2063
2064 if (IS_ZEBRA_DEBUG_KERNEL)
2065 zlog_debug("Rx %s family %s IF %s(%u) IP %s",
2066 nl_msg_type_to_str(h->nlmsg_type),
2067 nl_family_to_str(ndm->ndm_family), ifp->name,
2068 ndm->ndm_ifindex,
2069 ipaddr2str(&ip, buf2, sizeof(buf2)));
2070
2071 /* Process the delete - it may result in re-adding the neighbor if it is
2072 * a valid "remote" neighbor.
2073 */
2074 return zebra_vxlan_local_neigh_del(ifp, link_if, &ip);
2075 }
2076
2077 static int netlink_neigh_table(struct sockaddr_nl *snl, struct nlmsghdr *h,
2078 ns_id_t ns_id, int startup)
2079 {
2080 int len;
2081 struct ndmsg *ndm;
2082
2083 if (h->nlmsg_type != RTM_NEWNEIGH)
2084 return 0;
2085
2086 /* Length validity. */
2087 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg));
2088 if (len < 0)
2089 return -1;
2090
2091 /* We are interested only in AF_INET or AF_INET6 notifications. */
2092 ndm = NLMSG_DATA(h);
2093 if (ndm->ndm_family != AF_INET && ndm->ndm_family != AF_INET6)
2094 return 0;
2095
2096 return netlink_neigh_change(snl, h, len);
2097 }
2098
2099 /* Request for IP neighbor information from the kernel */
2100 static int netlink_request_neigh(struct zebra_ns *zns, int family, int type,
2101 ifindex_t ifindex)
2102 {
2103 struct {
2104 struct nlmsghdr n;
2105 struct ndmsg ndm;
2106 char buf[256];
2107 } req;
2108
2109 /* Form the request, specifying filter (rtattr) if needed. */
2110 memset(&req, 0, sizeof(req));
2111 req.n.nlmsg_type = type;
2112 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
2113 req.ndm.ndm_family = family;
2114 if (ifindex)
2115 addattr32(&req.n, sizeof(req), NDA_IFINDEX, ifindex);
2116
2117 return netlink_request(&zns->netlink_cmd, &req.n);
2118 }
2119
2120 /*
2121 * IP Neighbor table read using netlink interface. This is invoked
2122 * at startup.
2123 */
2124 int netlink_neigh_read(struct zebra_ns *zns)
2125 {
2126 int ret;
2127
2128 /* Get IP neighbor table. */
2129 ret = netlink_request_neigh(zns, AF_UNSPEC, RTM_GETNEIGH, 0);
2130 if (ret < 0)
2131 return ret;
2132 ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, zns, 0,
2133 1);
2134
2135 return ret;
2136 }
2137
2138 /*
2139 * IP Neighbor table read using netlink interface. This is for a specific
2140 * VLAN device.
2141 */
2142 int netlink_neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if)
2143 {
2144 int ret = 0;
2145
2146 ret = netlink_request_neigh(zns, AF_UNSPEC, RTM_GETNEIGH,
2147 vlan_if->ifindex);
2148 if (ret < 0)
2149 return ret;
2150 ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, zns, 0,
2151 0);
2152
2153 return ret;
2154 }
2155
2156 int netlink_neigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
2157 ns_id_t ns_id)
2158 {
2159 int len;
2160 struct ndmsg *ndm;
2161
2162 if (!(h->nlmsg_type == RTM_NEWNEIGH || h->nlmsg_type == RTM_DELNEIGH))
2163 return 0;
2164
2165 /* Length validity. */
2166 len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg));
2167 if (len < 0)
2168 return -1;
2169
2170 /* Is this a notification for the MAC FDB or IP neighbor table? */
2171 ndm = NLMSG_DATA(h);
2172 if (ndm->ndm_family == AF_BRIDGE)
2173 return netlink_macfdb_change(snl, h, len);
2174
2175 if (ndm->ndm_type != RTN_UNICAST)
2176 return 0;
2177
2178 if (ndm->ndm_family == AF_INET || ndm->ndm_family == AF_INET6)
2179 return netlink_ipneigh_change(snl, h, len);
2180
2181 return 0;
2182 }
2183
2184 static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip,
2185 struct ethaddr *mac, u_int32_t flags, int cmd)
2186 {
2187 struct {
2188 struct nlmsghdr n;
2189 struct ndmsg ndm;
2190 char buf[256];
2191 } req;
2192 int ipa_len;
2193
2194 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
2195 char buf[INET6_ADDRSTRLEN];
2196 char buf2[ETHER_ADDR_STRLEN];
2197
2198 memset(&req.n, 0, sizeof(req.n));
2199 memset(&req.ndm, 0, sizeof(req.ndm));
2200
2201 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
2202 req.n.nlmsg_flags = NLM_F_REQUEST;
2203 if (cmd == RTM_NEWNEIGH)
2204 req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
2205 req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH
2206 req.ndm.ndm_family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6;
2207 req.ndm.ndm_state = flags;
2208 req.ndm.ndm_ifindex = ifp->ifindex;
2209 req.ndm.ndm_type = RTN_UNICAST;
2210 req.ndm.ndm_flags = NTF_EXT_LEARNED;
2211
2212
2213 ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN;
2214 addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
2215 if (mac)
2216 addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
2217
2218 if (IS_ZEBRA_DEBUG_KERNEL)
2219 zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s",
2220 nl_msg_type_to_str(cmd),
2221 nl_family_to_str(req.ndm.ndm_family), ifp->name,
2222 ifp->ifindex, ipaddr2str(ip, buf, sizeof(buf)),
2223 mac ? prefix_mac2str(mac, buf2, sizeof(buf2))
2224 : "null");
2225
2226 return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
2227 0);
2228 }
2229
2230 int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
2231 struct in_addr vtep_ip, u_char sticky)
2232 {
2233 return netlink_macfdb_update(ifp, vid, mac, vtep_ip, 0, RTM_NEWNEIGH,
2234 sticky);
2235 }
2236
2237 int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
2238 struct in_addr vtep_ip, int local)
2239 {
2240 return netlink_macfdb_update(ifp, vid, mac, vtep_ip, local,
2241 RTM_DELNEIGH, 0);
2242 }
2243
2244 int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
2245 struct ethaddr *mac)
2246 {
2247 return netlink_neigh_update2(ifp, ip, mac, NUD_REACHABLE, RTM_NEWNEIGH);
2248 }
2249
2250 int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip)
2251 {
2252 return netlink_neigh_update2(ifp, ip, NULL, 0, RTM_DELNEIGH);
2253 }
2254
2255 /*
2256 * MPLS label forwarding table change via netlink interface.
2257 */
2258 int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp)
2259 {
2260 mpls_lse_t lse;
2261 zebra_nhlfe_t *nhlfe;
2262 struct nexthop *nexthop = NULL;
2263 unsigned int nexthop_num;
2264 const char *routedesc;
2265 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
2266
2267 struct {
2268 struct nlmsghdr n;
2269 struct rtmsg r;
2270 char buf[NL_PKT_BUF_SIZE];
2271 } req;
2272
2273 memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE);
2274
2275
2276 /*
2277 * Count # nexthops so we can decide whether to use singlepath
2278 * or multipath case.
2279 */
2280 nexthop_num = 0;
2281 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
2282 nexthop = nhlfe->nexthop;
2283 if (!nexthop)
2284 continue;
2285 if (cmd == RTM_NEWROUTE) {
2286 /* Count all selected NHLFEs */
2287 if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
2288 && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
2289 nexthop_num++;
2290 } else /* DEL */
2291 {
2292 /* Count all installed NHLFEs */
2293 if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)
2294 && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
2295 nexthop_num++;
2296 }
2297 }
2298
2299 if (nexthop_num == 0) // unexpected
2300 return 0;
2301
2302 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
2303 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
2304 req.n.nlmsg_type = cmd;
2305 req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
2306
2307 req.r.rtm_family = AF_MPLS;
2308 req.r.rtm_table = RT_TABLE_MAIN;
2309 req.r.rtm_dst_len = MPLS_LABEL_LEN_BITS;
2310 req.r.rtm_protocol = RTPROT_ZEBRA;
2311 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
2312 req.r.rtm_type = RTN_UNICAST;
2313
2314 if (cmd == RTM_NEWROUTE)
2315 /* We do a replace to handle update. */
2316 req.n.nlmsg_flags |= NLM_F_REPLACE;
2317
2318 /* Fill destination */
2319 lse = mpls_lse_encode(lsp->ile.in_label, 0, 0, 1);
2320 addattr_l(&req.n, sizeof req, RTA_DST, &lse, sizeof(mpls_lse_t));
2321
2322 /* Fill nexthops (paths) based on single-path or multipath. The paths
2323 * chosen depend on the operation.
2324 */
2325 if (nexthop_num == 1 || multipath_num == 1) {
2326 routedesc = "single hop";
2327 _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc);
2328
2329 nexthop_num = 0;
2330 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
2331 nexthop = nhlfe->nexthop;
2332 if (!nexthop)
2333 continue;
2334
2335 if ((cmd == RTM_NEWROUTE
2336 && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
2337 && CHECK_FLAG(nexthop->flags,
2338 NEXTHOP_FLAG_ACTIVE)))
2339 || (cmd == RTM_DELROUTE
2340 && (CHECK_FLAG(nhlfe->flags,
2341 NHLFE_FLAG_INSTALLED)
2342 && CHECK_FLAG(nexthop->flags,
2343 NEXTHOP_FLAG_FIB)))) {
2344 /* Add the gateway */
2345 _netlink_mpls_build_singlepath(routedesc, nhlfe,
2346 &req.n, &req.r,
2347 sizeof req, cmd);
2348 if (cmd == RTM_NEWROUTE) {
2349 SET_FLAG(nhlfe->flags,
2350 NHLFE_FLAG_INSTALLED);
2351 SET_FLAG(nexthop->flags,
2352 NEXTHOP_FLAG_FIB);
2353 } else {
2354 UNSET_FLAG(nhlfe->flags,
2355 NHLFE_FLAG_INSTALLED);
2356 UNSET_FLAG(nexthop->flags,
2357 NEXTHOP_FLAG_FIB);
2358 }
2359 nexthop_num++;
2360 break;
2361 }
2362 }
2363 } else /* Multipath case */
2364 {
2365 char buf[NL_PKT_BUF_SIZE];
2366 struct rtattr *rta = (void *)buf;
2367 struct rtnexthop *rtnh;
2368 union g_addr *src1 = NULL;
2369
2370 rta->rta_type = RTA_MULTIPATH;
2371 rta->rta_len = RTA_LENGTH(0);
2372 rtnh = RTA_DATA(rta);
2373
2374 routedesc = "multihop";
2375 _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc);
2376
2377 nexthop_num = 0;
2378 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
2379 nexthop = nhlfe->nexthop;
2380 if (!nexthop)
2381 continue;
2382
2383 if (nexthop_num >= multipath_num)
2384 break;
2385
2386 if ((cmd == RTM_NEWROUTE
2387 && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
2388 && CHECK_FLAG(nexthop->flags,
2389 NEXTHOP_FLAG_ACTIVE)))
2390 || (cmd == RTM_DELROUTE
2391 && (CHECK_FLAG(nhlfe->flags,
2392 NHLFE_FLAG_INSTALLED)
2393 && CHECK_FLAG(nexthop->flags,
2394 NEXTHOP_FLAG_FIB)))) {
2395 nexthop_num++;
2396
2397 /* Build the multipath */
2398 _netlink_mpls_build_multipath(routedesc, nhlfe,
2399 rta, rtnh, &req.r,
2400 &src1);
2401 rtnh = RTNH_NEXT(rtnh);
2402
2403 if (cmd == RTM_NEWROUTE) {
2404 SET_FLAG(nhlfe->flags,
2405 NHLFE_FLAG_INSTALLED);
2406 SET_FLAG(nexthop->flags,
2407 NEXTHOP_FLAG_FIB);
2408 } else {
2409 UNSET_FLAG(nhlfe->flags,
2410 NHLFE_FLAG_INSTALLED);
2411 UNSET_FLAG(nexthop->flags,
2412 NEXTHOP_FLAG_FIB);
2413 }
2414 }
2415 }
2416
2417 /* Add the multipath */
2418 if (rta->rta_len > RTA_LENGTH(0))
2419 addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH,
2420 RTA_DATA(rta), RTA_PAYLOAD(rta));
2421 }
2422
2423 /* Talk to netlink socket. */
2424 return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
2425 0);
2426 }
2427
2428 /*
2429 * Handle failure in LSP install, clear flags for NHLFE.
2430 */
2431 void clear_nhlfe_installed(zebra_lsp_t *lsp)
2432 {
2433 zebra_nhlfe_t *nhlfe;
2434 struct nexthop *nexthop;
2435
2436 for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
2437 nexthop = nhlfe->nexthop;
2438 if (!nexthop)
2439 continue;
2440
2441 UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED);
2442 UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
2443 }
2444 }