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