1 /* Kernel routing table updates using netlink over GNU/Linux system.
2 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
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
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.
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
25 #include <net/if_arp.h>
26 #include <linux/lwtunnel.h>
27 #include <linux/mpls_iptunnel.h>
28 #include <linux/neighbour.h>
29 #include <linux/rtnetlink.h>
31 /* Hack for GNU libc version 2. */
33 #define MSG_TRUNC 0x20
34 #endif /* MSG_TRUNC */
40 #include "connected.h"
43 #include "zebra_memory.h"
53 #include "zebra/zserv.h"
54 #include "zebra/zebra_ns.h"
55 #include "zebra/zebra_vrf.h"
57 #include "zebra/redistribute.h"
58 #include "zebra/interface.h"
59 #include "zebra/debug.h"
60 #include "zebra/rtadv.h"
61 #include "zebra/zebra_ptm.h"
62 #include "zebra/zebra_mpls.h"
63 #include "zebra/kernel_netlink.h"
64 #include "zebra/rt_netlink.h"
65 #include "zebra/zebra_mroute.h"
66 #include "zebra/zebra_vxlan.h"
72 static vlanid_t filter_vlan
= 0;
80 char ipv4_ll_buf
[16] = "169.254.0.1";
81 struct in_addr ipv4_ll
;
84 * The ipv4_ll data structure is used for all 5549
85 * additions to the kernel. Let's figure out the
86 * correct value one time instead for every
87 * install/remove of a 5549 type route
89 void rt_netlink_init(void)
91 inet_pton(AF_INET
, ipv4_ll_buf
, &ipv4_ll
);
94 static inline int is_selfroute(int proto
)
96 if ((proto
== RTPROT_BGP
) || (proto
== RTPROT_OSPF
)
97 || (proto
== RTPROT_STATIC
) || (proto
== RTPROT_ZEBRA
)
98 || (proto
== RTPROT_ISIS
) || (proto
== RTPROT_RIPNG
)
99 || (proto
== RTPROT_NHRP
) || (proto
== RTPROT_EIGRP
)
100 || (proto
== RTPROT_LDP
) || (proto
== RTPROT_BABEL
)
101 || (proto
== RTPROT_RIP
) || (proto
== RTPROT_SHARP
)) {
108 static inline int zebra2proto(int proto
)
111 case ZEBRA_ROUTE_BABEL
:
112 proto
= RTPROT_BABEL
;
114 case ZEBRA_ROUTE_BGP
:
117 case ZEBRA_ROUTE_OSPF
:
118 case ZEBRA_ROUTE_OSPF6
:
121 case ZEBRA_ROUTE_STATIC
:
122 proto
= RTPROT_STATIC
;
124 case ZEBRA_ROUTE_ISIS
:
127 case ZEBRA_ROUTE_RIP
:
130 case ZEBRA_ROUTE_RIPNG
:
131 proto
= RTPROT_RIPNG
;
133 case ZEBRA_ROUTE_NHRP
:
136 case ZEBRA_ROUTE_EIGRP
:
137 proto
= RTPROT_EIGRP
;
139 case ZEBRA_ROUTE_LDP
:
142 case ZEBRA_ROUTE_SHARP
:
143 proto
= RTPROT_SHARP
;
146 proto
= RTPROT_ZEBRA
;
153 static inline int proto2zebra(int proto
, int family
)
157 proto
= ZEBRA_ROUTE_BABEL
;
160 proto
= ZEBRA_ROUTE_BGP
;
163 proto
= (family
== AFI_IP
) ?
164 ZEBRA_ROUTE_OSPF
: ZEBRA_ROUTE_OSPF6
;
167 proto
= ZEBRA_ROUTE_ISIS
;
170 proto
= ZEBRA_ROUTE_RIP
;
173 proto
= ZEBRA_ROUTE_RIPNG
;
176 proto
= ZEBRA_ROUTE_NHRP
;
179 proto
= ZEBRA_ROUTE_EIGRP
;
182 proto
= ZEBRA_ROUTE_LDP
;
185 proto
= ZEBRA_ROUTE_STATIC
;
188 proto
= ZEBRA_ROUTE_KERNEL
;
195 Pending: create an efficient table_id (in a tree/hash) based lookup)
197 static vrf_id_t
vrf_lookup_by_table(u_int32_t table_id
)
200 struct zebra_vrf
*zvrf
;
202 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
) {
203 if ((zvrf
= vrf
->info
) == NULL
|| (zvrf
->table_id
!= table_id
))
206 return zvrf_id(zvrf
);
212 /* Looking up routing table by netlink interface. */
213 static int netlink_route_change_read_unicast(struct sockaddr_nl
*snl
,
214 struct nlmsghdr
*h
, ns_id_t ns_id
,
219 struct rtattr
*tb
[RTA_MAX
+ 1];
222 struct prefix_ipv6 src_p
= {};
223 vrf_id_t vrf_id
= VRF_DEFAULT
;
225 char anyaddr
[16] = {0};
227 int proto
= ZEBRA_ROUTE_KERNEL
;
232 uint8_t distance
= 0;
237 void *prefsrc
= NULL
; /* IPv4 preferred source host address */
238 void *src
= NULL
; /* IPv6 srcdest source prefix */
239 enum blackhole_type bh_type
= BLACKHOLE_UNSPEC
;
243 if (startup
&& h
->nlmsg_type
!= RTM_NEWROUTE
)
245 switch (rtm
->rtm_type
) {
249 bh_type
= BLACKHOLE_NULL
;
251 case RTN_UNREACHABLE
:
252 bh_type
= BLACKHOLE_REJECT
;
255 bh_type
= BLACKHOLE_ADMINPROHIB
;
261 len
= h
->nlmsg_len
- NLMSG_LENGTH(sizeof(struct rtmsg
));
265 memset(tb
, 0, sizeof tb
);
266 netlink_parse_rtattr(tb
, RTA_MAX
, RTM_RTA(rtm
), len
);
268 if (rtm
->rtm_flags
& RTM_F_CLONED
)
270 if (rtm
->rtm_protocol
== RTPROT_REDIRECT
)
272 if (rtm
->rtm_protocol
== RTPROT_KERNEL
)
275 if (!startup
&& is_selfroute(rtm
->rtm_protocol
)
276 && h
->nlmsg_type
== RTM_NEWROUTE
)
279 /* We don't care about change notifications for the MPLS table. */
280 /* TODO: Revisit this. */
281 if (rtm
->rtm_family
== AF_MPLS
)
284 /* Table corresponding to route. */
286 table
= *(int *)RTA_DATA(tb
[RTA_TABLE
]);
288 table
= rtm
->rtm_table
;
291 vrf_id
= vrf_lookup_by_table(table
);
292 if (vrf_id
== VRF_DEFAULT
) {
293 if (!is_zebra_valid_kernel_table(table
)
294 && !is_zebra_main_routing_table(table
))
298 /* Route which inserted by Zebra. */
299 if (is_selfroute(rtm
->rtm_protocol
)) {
300 flags
|= ZEBRA_FLAG_SELFROUTE
;
301 proto
= proto2zebra(rtm
->rtm_protocol
, rtm
->rtm_family
);
304 index
= *(int *)RTA_DATA(tb
[RTA_OIF
]);
307 dest
= RTA_DATA(tb
[RTA_DST
]);
312 src
= RTA_DATA(tb
[RTA_SRC
]);
317 prefsrc
= RTA_DATA(tb
[RTA_PREFSRC
]);
320 gate
= RTA_DATA(tb
[RTA_GATEWAY
]);
322 if (tb
[RTA_PRIORITY
])
323 metric
= *(int *)RTA_DATA(tb
[RTA_PRIORITY
]);
325 #if defined(SUPPORT_REALMS)
327 tag
= *(uint32_t *)RTA_DATA(tb
[RTA_FLOW
]);
330 if (tb
[RTA_METRICS
]) {
331 struct rtattr
*mxrta
[RTAX_MAX
+ 1];
333 memset(mxrta
, 0, sizeof mxrta
);
334 netlink_parse_rtattr(mxrta
, RTAX_MAX
,
335 RTA_DATA(tb
[RTA_METRICS
]),
336 RTA_PAYLOAD(tb
[RTA_METRICS
]));
339 mtu
= *(u_int32_t
*)RTA_DATA(mxrta
[RTAX_MTU
]);
342 if (rtm
->rtm_family
== AF_INET
) {
344 memcpy(&p
.u
.prefix4
, dest
, 4);
345 p
.prefixlen
= rtm
->rtm_dst_len
;
348 0; // Forces debug below to not display anything
349 } else if (rtm
->rtm_family
== AF_INET6
) {
351 memcpy(&p
.u
.prefix6
, dest
, 16);
352 p
.prefixlen
= rtm
->rtm_dst_len
;
354 src_p
.family
= AF_INET6
;
355 memcpy(&src_p
.prefix
, src
, 16);
356 src_p
.prefixlen
= rtm
->rtm_src_len
;
359 if (rtm
->rtm_src_len
!= 0) {
360 char buf
[PREFIX_STRLEN
];
362 "unsupported IPv[4|6] sourcedest route (dest %s vrf %u)",
363 prefix2str(&p
, buf
, sizeof(buf
)), vrf_id
);
368 * For ZEBRA_ROUTE_KERNEL types:
370 * The metric/priority of the route received from the kernel
371 * is a 32 bit number. We are going to interpret the high
372 * order byte as the Admin Distance and the low order 3 bytes
375 * This will allow us to do two things:
376 * 1) Allow the creation of kernel routes that can be
377 * overridden by zebra.
378 * 2) Allow the old behavior for 'most' kernel route types
379 * if a user enters 'ip route ...' v4 routes get a metric
380 * of 0 and v6 routes get a metric of 1024. Both of these
381 * values will end up with a admin distance of 0, which
382 * will cause them to win for the purposes of zebra.
384 if (proto
== ZEBRA_ROUTE_KERNEL
) {
385 distance
= (metric
>> 24) & 0xFF;
386 metric
= (metric
& 0x00FFFFFF);
389 if (IS_ZEBRA_DEBUG_KERNEL
) {
390 char buf
[PREFIX_STRLEN
];
391 char buf2
[PREFIX_STRLEN
];
393 "%s %s%s%s vrf %u metric: %d Admin Distance: %d", nl_msg_type_to_str(h
->nlmsg_type
),
394 prefix2str(&p
, buf
, sizeof(buf
)),
395 src_p
.prefixlen
? " from " : "",
396 src_p
.prefixlen
? prefix2str(&src_p
, buf2
, sizeof(buf2
))
398 vrf_id
, metric
, distance
);
402 if (rtm
->rtm_family
== AF_INET6
)
405 if (h
->nlmsg_type
== RTM_NEWROUTE
) {
406 if (!tb
[RTA_MULTIPATH
]) {
408 size_t sz
= (afi
== AFI_IP
) ? 4 : 16;
410 memset(&nh
, 0, sizeof(nh
));
412 if (bh_type
== BLACKHOLE_UNSPEC
) {
414 nh
.type
= NEXTHOP_TYPE_IFINDEX
;
415 else if (index
&& gate
)
416 nh
.type
= (afi
== AFI_IP
)
417 ? NEXTHOP_TYPE_IPV4_IFINDEX
418 : NEXTHOP_TYPE_IPV6_IFINDEX
;
419 else if (!index
&& gate
)
420 nh
.type
= (afi
== AFI_IP
)
424 nh
.type
= NEXTHOP_TYPE_BLACKHOLE
;
425 nh
.bh_type
= bh_type
;
428 nh
.type
= NEXTHOP_TYPE_BLACKHOLE
;
429 nh
.bh_type
= bh_type
;
433 memcpy(&nh
.src
, prefsrc
, sz
);
435 memcpy(&nh
.gate
, gate
, sz
);
437 rib_add(afi
, SAFI_UNICAST
, vrf_id
, proto
,
438 0, flags
, &p
, NULL
, &nh
, table
, metric
,
441 /* This is a multipath route */
443 struct route_entry
*re
;
444 struct rtnexthop
*rtnh
=
445 (struct rtnexthop
*)RTA_DATA(tb
[RTA_MULTIPATH
]);
447 len
= RTA_PAYLOAD(tb
[RTA_MULTIPATH
]);
449 re
= XCALLOC(MTYPE_RE
, sizeof(struct route_entry
));
451 re
->distance
= distance
;
458 re
->uptime
= time(NULL
);
462 if (len
< (int)sizeof(*rtnh
)
463 || rtnh
->rtnh_len
> len
)
466 index
= rtnh
->rtnh_ifindex
;
468 if (rtnh
->rtnh_len
> sizeof(*rtnh
)) {
469 memset(tb
, 0, sizeof(tb
));
470 netlink_parse_rtattr(
471 tb
, RTA_MAX
, RTNH_DATA(rtnh
),
472 rtnh
->rtnh_len
- sizeof(*rtnh
));
479 if (rtm
->rtm_family
== AF_INET
) {
481 route_entry_nexthop_ipv4_ifindex_add(
485 route_entry_nexthop_ipv4_add(
488 } else if (rtm
->rtm_family
491 route_entry_nexthop_ipv6_ifindex_add(
495 route_entry_nexthop_ipv6_add(
499 route_entry_nexthop_ifindex_add(re
,
502 len
-= NLMSG_ALIGN(rtnh
->rtnh_len
);
503 rtnh
= RTNH_NEXT(rtnh
);
506 zserv_nexthop_num_warn(__func__
,
507 (const struct prefix
*)&p
,
509 if (re
->nexthop_num
== 0)
512 rib_add_multipath(afi
, SAFI_UNICAST
, &p
,
516 if (!tb
[RTA_MULTIPATH
]) {
518 size_t sz
= (afi
== AFI_IP
) ? 4 : 16;
520 memset(&nh
, 0, sizeof(nh
));
521 if (bh_type
== BLACKHOLE_UNSPEC
) {
523 nh
.type
= NEXTHOP_TYPE_IFINDEX
;
524 else if (index
&& gate
)
527 ? NEXTHOP_TYPE_IPV4_IFINDEX
528 : NEXTHOP_TYPE_IPV6_IFINDEX
;
529 else if (!index
&& gate
)
530 nh
.type
= (afi
== AFI_IP
)
534 nh
.type
= NEXTHOP_TYPE_BLACKHOLE
;
535 nh
.bh_type
= BLACKHOLE_UNSPEC
;
538 nh
.type
= NEXTHOP_TYPE_BLACKHOLE
;
539 nh
.bh_type
= bh_type
;
543 memcpy(&nh
.gate
, gate
, sz
);
544 rib_delete(afi
, SAFI_UNICAST
, vrf_id
,
545 proto
, 0, flags
, &p
, NULL
, &nh
,
546 table
, metric
, true, NULL
);
548 /* XXX: need to compare the entire list of nexthops
549 * here for NLM_F_APPEND stupidity */
550 rib_delete(afi
, SAFI_UNICAST
, vrf_id
,
551 proto
, 0, flags
, &p
, NULL
, NULL
,
552 table
, metric
, true, NULL
);
559 static struct mcast_route_data
*mroute
= NULL
;
561 static int netlink_route_change_read_multicast(struct sockaddr_nl
*snl
,
563 ns_id_t ns_id
, int startup
)
567 struct rtattr
*tb
[RTA_MAX
+ 1];
568 struct mcast_route_data
*m
;
569 struct mcast_route_data mr
;
576 char oif_list
[256] = "\0";
577 vrf_id_t vrf
= ns_id
;
583 memset(&mr
, 0, sizeof(mr
));
589 len
= h
->nlmsg_len
- NLMSG_LENGTH(sizeof(struct rtmsg
));
591 memset(tb
, 0, sizeof tb
);
592 netlink_parse_rtattr(tb
, RTA_MAX
, RTM_RTA(rtm
), len
);
595 table
= *(int *)RTA_DATA(tb
[RTA_TABLE
]);
597 table
= rtm
->rtm_table
;
599 vrf
= vrf_lookup_by_table(table
);
602 iif
= *(int *)RTA_DATA(tb
[RTA_IIF
]);
605 m
->sg
.src
= *(struct in_addr
*)RTA_DATA(tb
[RTA_SRC
]);
608 m
->sg
.grp
= *(struct in_addr
*)RTA_DATA(tb
[RTA_DST
]);
610 if ((RTA_EXPIRES
<= RTA_MAX
) && tb
[RTA_EXPIRES
])
611 m
->lastused
= *(unsigned long long *)RTA_DATA(tb
[RTA_EXPIRES
]);
613 if (tb
[RTA_MULTIPATH
]) {
614 struct rtnexthop
*rtnh
=
615 (struct rtnexthop
*)RTA_DATA(tb
[RTA_MULTIPATH
]);
617 len
= RTA_PAYLOAD(tb
[RTA_MULTIPATH
]);
619 if (len
< (int)sizeof(*rtnh
) || rtnh
->rtnh_len
> len
)
622 oif
[oif_count
] = rtnh
->rtnh_ifindex
;
625 len
-= NLMSG_ALIGN(rtnh
->rtnh_len
);
626 rtnh
= RTNH_NEXT(rtnh
);
630 if (IS_ZEBRA_DEBUG_KERNEL
) {
631 struct interface
*ifp
;
632 strlcpy(sbuf
, inet_ntoa(m
->sg
.src
), sizeof(sbuf
));
633 strlcpy(gbuf
, inet_ntoa(m
->sg
.grp
), sizeof(gbuf
));
634 for (count
= 0; count
< oif_count
; count
++) {
635 ifp
= if_lookup_by_index(oif
[count
], vrf
);
638 sprintf(temp
, "%s ", ifp
->name
);
639 strcat(oif_list
, temp
);
641 struct zebra_vrf
*zvrf
= zebra_vrf_lookup_by_id(vrf
);
642 ifp
= if_lookup_by_index(iif
, vrf
);
644 "MCAST VRF: %s(%d) %s (%s,%s) IIF: %s OIF: %s jiffies: %lld",
645 zvrf
->vrf
->name
, vrf
, nl_msg_type_to_str(h
->nlmsg_type
),
646 sbuf
, gbuf
, ifp
->name
, oif_list
, m
->lastused
);
651 int netlink_route_change(struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
652 ns_id_t ns_id
, int startup
)
655 vrf_id_t vrf_id
= ns_id
;
660 if (!(h
->nlmsg_type
== RTM_NEWROUTE
|| h
->nlmsg_type
== RTM_DELROUTE
)) {
661 /* If this is not route add/delete message print warning. */
662 zlog_warn("Kernel message: %d vrf %u\n", h
->nlmsg_type
, vrf_id
);
666 /* Connected route. */
667 if (IS_ZEBRA_DEBUG_KERNEL
)
668 zlog_debug("%s %s %s proto %s vrf %u",
669 nl_msg_type_to_str(h
->nlmsg_type
),
670 nl_family_to_str(rtm
->rtm_family
),
671 nl_rttype_to_str(rtm
->rtm_type
),
672 nl_rtproto_to_str(rtm
->rtm_protocol
), vrf_id
);
674 /* We don't care about change notifications for the MPLS table. */
675 /* TODO: Revisit this. */
676 if (rtm
->rtm_family
== AF_MPLS
)
679 len
= h
->nlmsg_len
- NLMSG_LENGTH(sizeof(struct rtmsg
));
683 if (rtm
->rtm_type
== RTN_MULTICAST
)
684 netlink_route_change_read_multicast(snl
, h
, ns_id
, startup
);
686 netlink_route_change_read_unicast(snl
, h
, ns_id
, startup
);
690 /* Request for specific route information from the kernel */
691 static int netlink_request_route(struct zebra_ns
*zns
, int family
, int type
)
698 /* Form the request, specifying filter (rtattr) if needed. */
699 memset(&req
, 0, sizeof(req
));
700 req
.n
.nlmsg_type
= type
;
701 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct rtmsg
));
702 req
.rtm
.rtm_family
= family
;
704 return netlink_request(&zns
->netlink_cmd
, &req
.n
);
707 /* Routing table read function using netlink interface. Only called
709 int netlink_route_read(struct zebra_ns
*zns
)
713 /* Get IPv4 routing table. */
714 ret
= netlink_request_route(zns
, AF_INET
, RTM_GETROUTE
);
717 ret
= netlink_parse_info(netlink_route_change_read_unicast
,
718 &zns
->netlink_cmd
, zns
, 0, 1);
722 /* Get IPv6 routing table. */
723 ret
= netlink_request_route(zns
, AF_INET6
, RTM_GETROUTE
);
726 ret
= netlink_parse_info(netlink_route_change_read_unicast
,
727 &zns
->netlink_cmd
, zns
, 0, 1);
734 static void _netlink_route_nl_add_gateway_info(u_char route_family
,
736 struct nlmsghdr
*nlmsg
,
737 size_t req_size
, int bytelen
,
738 struct nexthop
*nexthop
)
740 if (route_family
== AF_MPLS
) {
741 struct gw_family_t gw_fam
;
743 gw_fam
.family
= gw_family
;
744 if (gw_family
== AF_INET
)
745 memcpy(&gw_fam
.gate
.ipv4
, &nexthop
->gate
.ipv4
, bytelen
);
747 memcpy(&gw_fam
.gate
.ipv6
, &nexthop
->gate
.ipv6
, bytelen
);
748 addattr_l(nlmsg
, req_size
, RTA_VIA
, &gw_fam
.family
,
751 if (gw_family
== AF_INET
)
752 addattr_l(nlmsg
, req_size
, RTA_GATEWAY
,
753 &nexthop
->gate
.ipv4
, bytelen
);
755 addattr_l(nlmsg
, req_size
, RTA_GATEWAY
,
756 &nexthop
->gate
.ipv6
, bytelen
);
760 static void _netlink_route_rta_add_gateway_info(u_char route_family
,
763 struct rtnexthop
*rtnh
,
764 size_t req_size
, int bytelen
,
765 struct nexthop
*nexthop
)
767 if (route_family
== AF_MPLS
) {
768 struct gw_family_t gw_fam
;
770 gw_fam
.family
= gw_family
;
771 if (gw_family
== AF_INET
)
772 memcpy(&gw_fam
.gate
.ipv4
, &nexthop
->gate
.ipv4
, bytelen
);
774 memcpy(&gw_fam
.gate
.ipv6
, &nexthop
->gate
.ipv6
, bytelen
);
775 rta_addattr_l(rta
, req_size
, RTA_VIA
, &gw_fam
.family
,
777 rtnh
->rtnh_len
+= RTA_LENGTH(bytelen
+ 2);
779 if (gw_family
== AF_INET
)
780 rta_addattr_l(rta
, req_size
, RTA_GATEWAY
,
781 &nexthop
->gate
.ipv4
, bytelen
);
783 rta_addattr_l(rta
, req_size
, RTA_GATEWAY
,
784 &nexthop
->gate
.ipv6
, bytelen
);
785 rtnh
->rtnh_len
+= sizeof(struct rtattr
) + bytelen
;
789 /* This function takes a nexthop as argument and adds
790 * the appropriate netlink attributes to an existing
793 * @param routedesc: Human readable description of route type
794 * (direct/recursive, single-/multipath)
795 * @param bytelen: Length of addresses in bytes.
796 * @param nexthop: Nexthop information
797 * @param nlmsg: nlmsghdr structure to fill in.
798 * @param req_size: The size allocated for the message.
800 static void _netlink_route_build_singlepath(const char *routedesc
, int bytelen
,
801 struct nexthop
*nexthop
,
802 struct nlmsghdr
*nlmsg
,
804 size_t req_size
, int cmd
)
806 struct mpls_label_stack
*nh_label
;
807 mpls_lse_t out_lse
[MPLS_MAX_LABELS
];
811 * label_buf is *only* currently used within debugging.
812 * As such when we assign it we are guarding it inside
813 * a debug test. If you want to change this make sure
814 * you fix this assumption
817 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
818 * (in the case of LER)
820 nh_label
= nexthop
->nh_label
;
821 if (rtmsg
->rtm_family
== AF_MPLS
) {
823 assert(nh_label
->num_labels
== 1);
826 if (nh_label
&& nh_label
->num_labels
) {
827 int i
, num_labels
= 0;
831 for (i
= 0; i
< nh_label
->num_labels
; i
++) {
832 if (nh_label
->label
[i
] != MPLS_IMP_NULL_LABEL
) {
833 bos
= ((i
== (nh_label
->num_labels
- 1)) ? 1
835 out_lse
[i
] = mpls_lse_encode(nh_label
->label
[i
],
837 if (IS_ZEBRA_DEBUG_KERNEL
) {
839 sprintf(label_buf
, "label %u",
842 sprintf(label_buf1
, "/%u",
844 strlcat(label_buf
, label_buf1
,
852 if (rtmsg
->rtm_family
== AF_MPLS
)
853 addattr_l(nlmsg
, req_size
, RTA_NEWDST
, &out_lse
,
854 num_labels
* sizeof(mpls_lse_t
));
857 u_int16_t encap
= LWTUNNEL_ENCAP_MPLS
;
859 addattr_l(nlmsg
, req_size
, RTA_ENCAP_TYPE
,
860 &encap
, sizeof(u_int16_t
));
861 nest
= addattr_nest(nlmsg
, req_size
, RTA_ENCAP
);
862 addattr_l(nlmsg
, req_size
, MPLS_IPTUNNEL_DST
,
864 num_labels
* sizeof(mpls_lse_t
));
865 addattr_nest_end(nlmsg
, nest
);
870 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
871 rtmsg
->rtm_flags
|= RTNH_F_ONLINK
;
873 if (rtmsg
->rtm_family
== AF_INET
874 && (nexthop
->type
== NEXTHOP_TYPE_IPV6
875 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)) {
876 rtmsg
->rtm_flags
|= RTNH_F_ONLINK
;
877 addattr_l(nlmsg
, req_size
, RTA_GATEWAY
, &ipv4_ll
, 4);
878 addattr32(nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
880 if (nexthop
->rmap_src
.ipv4
.s_addr
&& (cmd
== RTM_NEWROUTE
))
881 addattr_l(nlmsg
, req_size
, RTA_PREFSRC
,
882 &nexthop
->rmap_src
.ipv4
, bytelen
);
883 else if (nexthop
->src
.ipv4
.s_addr
&& (cmd
== RTM_NEWROUTE
))
884 addattr_l(nlmsg
, req_size
, RTA_PREFSRC
,
885 &nexthop
->src
.ipv4
, bytelen
);
887 if (IS_ZEBRA_DEBUG_KERNEL
)
889 " 5549: _netlink_route_build_singlepath() (%s): "
890 "nexthop via %s %s if %u",
891 routedesc
, ipv4_ll_buf
, label_buf
,
896 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
897 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
) {
898 /* Send deletes to the kernel without specifying the next-hop */
899 if (cmd
!= RTM_DELROUTE
)
900 _netlink_route_nl_add_gateway_info(
901 rtmsg
->rtm_family
, AF_INET
, nlmsg
, req_size
,
904 if (cmd
== RTM_NEWROUTE
) {
905 if (nexthop
->rmap_src
.ipv4
.s_addr
)
906 addattr_l(nlmsg
, req_size
, RTA_PREFSRC
,
907 &nexthop
->rmap_src
.ipv4
, bytelen
);
908 else if (nexthop
->src
.ipv4
.s_addr
)
909 addattr_l(nlmsg
, req_size
, RTA_PREFSRC
,
910 &nexthop
->src
.ipv4
, bytelen
);
913 if (IS_ZEBRA_DEBUG_KERNEL
)
915 "netlink_route_multipath() (%s): "
916 "nexthop via %s %s if %u",
917 routedesc
, inet_ntoa(nexthop
->gate
.ipv4
),
918 label_buf
, nexthop
->ifindex
);
921 if (nexthop
->type
== NEXTHOP_TYPE_IPV6
922 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
) {
923 _netlink_route_nl_add_gateway_info(rtmsg
->rtm_family
, AF_INET6
,
924 nlmsg
, req_size
, bytelen
,
927 if (cmd
== RTM_NEWROUTE
) {
928 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
929 addattr_l(nlmsg
, req_size
, RTA_PREFSRC
,
930 &nexthop
->rmap_src
.ipv6
, bytelen
);
931 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
932 addattr_l(nlmsg
, req_size
, RTA_PREFSRC
,
933 &nexthop
->src
.ipv6
, bytelen
);
936 if (IS_ZEBRA_DEBUG_KERNEL
)
938 "netlink_route_multipath() (%s): "
939 "nexthop via %s %s if %u",
940 routedesc
, inet6_ntoa(nexthop
->gate
.ipv6
),
941 label_buf
, nexthop
->ifindex
);
943 if (nexthop
->type
== NEXTHOP_TYPE_IFINDEX
944 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
) {
945 addattr32(nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
947 if (cmd
== RTM_NEWROUTE
) {
948 if (nexthop
->rmap_src
.ipv4
.s_addr
)
949 addattr_l(nlmsg
, req_size
, RTA_PREFSRC
,
950 &nexthop
->rmap_src
.ipv4
, bytelen
);
951 else if (nexthop
->src
.ipv4
.s_addr
)
952 addattr_l(nlmsg
, req_size
, RTA_PREFSRC
,
953 &nexthop
->src
.ipv4
, bytelen
);
956 if (IS_ZEBRA_DEBUG_KERNEL
)
958 "netlink_route_multipath() (%s): "
960 routedesc
, nexthop
->ifindex
);
963 if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
) {
964 addattr32(nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
966 if (cmd
== RTM_NEWROUTE
) {
967 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
968 addattr_l(nlmsg
, req_size
, RTA_PREFSRC
,
969 &nexthop
->rmap_src
.ipv6
, bytelen
);
970 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
971 addattr_l(nlmsg
, req_size
, RTA_PREFSRC
,
972 &nexthop
->src
.ipv6
, bytelen
);
975 if (IS_ZEBRA_DEBUG_KERNEL
)
977 "netlink_route_multipath() (%s): "
979 routedesc
, nexthop
->ifindex
);
983 /* This function takes a nexthop as argument and
984 * appends to the given rtattr/rtnexthop pair the
985 * representation of the nexthop. If the nexthop
986 * defines a preferred source, the src parameter
987 * will be modified to point to that src, otherwise
988 * it will be kept unmodified.
990 * @param routedesc: Human readable description of route type
991 * (direct/recursive, single-/multipath)
992 * @param bytelen: Length of addresses in bytes.
993 * @param nexthop: Nexthop information
994 * @param rta: rtnetlink attribute structure
995 * @param rtnh: pointer to an rtnetlink nexthop structure
996 * @param src: pointer pointing to a location where
997 * the prefsrc should be stored.
999 static void _netlink_route_build_multipath(const char *routedesc
, int bytelen
,
1000 struct nexthop
*nexthop
,
1002 struct rtnexthop
*rtnh
,
1003 struct rtmsg
*rtmsg
,
1006 struct mpls_label_stack
*nh_label
;
1007 mpls_lse_t out_lse
[MPLS_MAX_LABELS
];
1008 char label_buf
[256];
1010 rtnh
->rtnh_len
= sizeof(*rtnh
);
1011 rtnh
->rtnh_flags
= 0;
1012 rtnh
->rtnh_hops
= 0;
1013 rta
->rta_len
+= rtnh
->rtnh_len
;
1016 * label_buf is *only* currently used within debugging.
1017 * As such when we assign it we are guarding it inside
1018 * a debug test. If you want to change this make sure
1019 * you fix this assumption
1021 label_buf
[0] = '\0';
1022 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
1023 * (in the case of LER)
1025 nh_label
= nexthop
->nh_label
;
1026 if (rtmsg
->rtm_family
== AF_MPLS
) {
1028 assert(nh_label
->num_labels
== 1);
1031 if (nh_label
&& nh_label
->num_labels
) {
1032 int i
, num_labels
= 0;
1034 char label_buf1
[20];
1036 for (i
= 0; i
< nh_label
->num_labels
; i
++) {
1037 if (nh_label
->label
[i
] != MPLS_IMP_NULL_LABEL
) {
1038 bos
= ((i
== (nh_label
->num_labels
- 1)) ? 1
1040 out_lse
[i
] = mpls_lse_encode(nh_label
->label
[i
],
1042 if (IS_ZEBRA_DEBUG_KERNEL
) {
1044 sprintf(label_buf
, "label %u",
1045 nh_label
->label
[i
]);
1047 sprintf(label_buf1
, "/%u",
1048 nh_label
->label
[i
]);
1049 strlcat(label_buf
, label_buf1
,
1057 if (rtmsg
->rtm_family
== AF_MPLS
) {
1058 rta_addattr_l(rta
, NL_PKT_BUF_SIZE
, RTA_NEWDST
,
1060 num_labels
* sizeof(mpls_lse_t
));
1061 rtnh
->rtnh_len
+= RTA_LENGTH(
1062 num_labels
* sizeof(mpls_lse_t
));
1064 struct rtattr
*nest
;
1065 u_int16_t encap
= LWTUNNEL_ENCAP_MPLS
;
1066 int len
= rta
->rta_len
;
1068 rta_addattr_l(rta
, NL_PKT_BUF_SIZE
,
1069 RTA_ENCAP_TYPE
, &encap
,
1071 nest
= rta_nest(rta
, NL_PKT_BUF_SIZE
,
1073 rta_addattr_l(rta
, NL_PKT_BUF_SIZE
,
1074 MPLS_IPTUNNEL_DST
, &out_lse
,
1075 num_labels
* sizeof(mpls_lse_t
));
1076 rta_nest_end(rta
, nest
);
1077 rtnh
->rtnh_len
+= rta
->rta_len
- len
;
1082 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
1083 rtnh
->rtnh_flags
|= RTNH_F_ONLINK
;
1085 if (rtmsg
->rtm_family
== AF_INET
1086 && (nexthop
->type
== NEXTHOP_TYPE_IPV6
1087 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)) {
1089 rtnh
->rtnh_flags
|= RTNH_F_ONLINK
;
1090 rta_addattr_l(rta
, NL_PKT_BUF_SIZE
, RTA_GATEWAY
, &ipv4_ll
,
1092 rtnh
->rtnh_len
+= sizeof(struct rtattr
) + bytelen
;
1093 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
1095 if (nexthop
->rmap_src
.ipv4
.s_addr
)
1096 *src
= &nexthop
->rmap_src
;
1097 else if (nexthop
->src
.ipv4
.s_addr
)
1098 *src
= &nexthop
->src
;
1100 if (IS_ZEBRA_DEBUG_KERNEL
)
1102 " 5549: netlink_route_build_multipath() (%s): "
1103 "nexthop via %s %s if %u",
1104 routedesc
, ipv4_ll_buf
, label_buf
,
1109 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
1110 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
) {
1111 _netlink_route_rta_add_gateway_info(rtmsg
->rtm_family
, AF_INET
,
1112 rta
, rtnh
, NL_PKT_BUF_SIZE
,
1114 if (nexthop
->rmap_src
.ipv4
.s_addr
)
1115 *src
= &nexthop
->rmap_src
;
1116 else if (nexthop
->src
.ipv4
.s_addr
)
1117 *src
= &nexthop
->src
;
1119 if (IS_ZEBRA_DEBUG_KERNEL
)
1121 "netlink_route_multipath() (%s): "
1122 "nexthop via %s %s if %u",
1123 routedesc
, inet_ntoa(nexthop
->gate
.ipv4
),
1124 label_buf
, nexthop
->ifindex
);
1126 if (nexthop
->type
== NEXTHOP_TYPE_IPV6
1127 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
) {
1128 _netlink_route_rta_add_gateway_info(rtmsg
->rtm_family
, AF_INET6
,
1129 rta
, rtnh
, NL_PKT_BUF_SIZE
,
1132 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
1133 *src
= &nexthop
->rmap_src
;
1134 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
1135 *src
= &nexthop
->src
;
1137 if (IS_ZEBRA_DEBUG_KERNEL
)
1139 "netlink_route_multipath() (%s): "
1140 "nexthop via %s %s if %u",
1141 routedesc
, inet6_ntoa(nexthop
->gate
.ipv6
),
1142 label_buf
, nexthop
->ifindex
);
1145 if (nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
1146 || nexthop
->type
== NEXTHOP_TYPE_IFINDEX
) {
1147 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
1149 if (nexthop
->rmap_src
.ipv4
.s_addr
)
1150 *src
= &nexthop
->rmap_src
;
1151 else if (nexthop
->src
.ipv4
.s_addr
)
1152 *src
= &nexthop
->src
;
1154 if (IS_ZEBRA_DEBUG_KERNEL
)
1156 "netlink_route_multipath() (%s): "
1157 "nexthop via if %u",
1158 routedesc
, nexthop
->ifindex
);
1159 } else if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
) {
1160 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
1162 if (IS_ZEBRA_DEBUG_KERNEL
)
1164 "netlink_route_multipath() (%s): "
1165 "nexthop via if %u",
1166 routedesc
, nexthop
->ifindex
);
1168 rtnh
->rtnh_ifindex
= 0;
1172 static inline void _netlink_mpls_build_singlepath(const char *routedesc
,
1173 zebra_nhlfe_t
*nhlfe
,
1174 struct nlmsghdr
*nlmsg
,
1175 struct rtmsg
*rtmsg
,
1176 size_t req_size
, int cmd
)
1181 family
= NHLFE_FAMILY(nhlfe
);
1182 bytelen
= (family
== AF_INET
? 4 : 16);
1183 _netlink_route_build_singlepath(routedesc
, bytelen
, nhlfe
->nexthop
,
1184 nlmsg
, rtmsg
, req_size
, cmd
);
1189 _netlink_mpls_build_multipath(const char *routedesc
, zebra_nhlfe_t
*nhlfe
,
1190 struct rtattr
*rta
, struct rtnexthop
*rtnh
,
1191 struct rtmsg
*rtmsg
, union g_addr
**src
)
1196 family
= NHLFE_FAMILY(nhlfe
);
1197 bytelen
= (family
== AF_INET
? 4 : 16);
1198 _netlink_route_build_multipath(routedesc
, bytelen
, nhlfe
->nexthop
, rta
,
1203 /* Log debug information for netlink_route_multipath
1204 * if debug logging is enabled.
1206 * @param cmd: Netlink command which is to be processed
1207 * @param p: Prefix for which the change is due
1208 * @param nexthop: Nexthop which is currently processed
1209 * @param routedesc: Semantic annotation for nexthop
1210 * (recursive, multipath, etc.)
1211 * @param family: Address family which the change concerns
1213 static void _netlink_route_debug(int cmd
, struct prefix
*p
,
1214 struct nexthop
*nexthop
, const char *routedesc
,
1215 int family
, struct zebra_vrf
*zvrf
)
1217 if (IS_ZEBRA_DEBUG_KERNEL
) {
1218 char buf
[PREFIX_STRLEN
];
1220 "netlink_route_multipath() (%s): %s %s vrf %u type %s",
1221 routedesc
, nl_msg_type_to_str(cmd
),
1222 prefix2str(p
, buf
, sizeof(buf
)), zvrf_id(zvrf
),
1223 (nexthop
) ? nexthop_type_to_str(nexthop
->type
) : "UNK");
1227 static void _netlink_mpls_debug(int cmd
, u_int32_t label
, const char *routedesc
)
1229 if (IS_ZEBRA_DEBUG_KERNEL
)
1230 zlog_debug("netlink_mpls_multipath() (%s): %s %u/20", routedesc
,
1231 nl_msg_type_to_str(cmd
), label
);
1234 static int netlink_neigh_update(int cmd
, int ifindex
, uint32_t addr
, char *lla
,
1243 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
1245 memset(&req
.n
, 0, sizeof(req
.n
));
1246 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
1248 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ndmsg
));
1249 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1250 req
.n
.nlmsg_type
= cmd
; // RTM_NEWNEIGH or RTM_DELNEIGH
1251 req
.n
.nlmsg_pid
= zns
->netlink_cmd
.snl
.nl_pid
;
1253 req
.ndm
.ndm_family
= AF_INET
;
1254 req
.ndm
.ndm_state
= NUD_PERMANENT
;
1255 req
.ndm
.ndm_ifindex
= ifindex
;
1256 req
.ndm
.ndm_type
= RTN_UNICAST
;
1258 addattr_l(&req
.n
, sizeof(req
), NDA_DST
, &addr
, 4);
1259 addattr_l(&req
.n
, sizeof(req
), NDA_LLADDR
, lla
, llalen
);
1261 return netlink_talk(netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
,
1265 /* Routing table change via netlink interface. */
1266 /* Update flag indicates whether this is a "replace" or not. */
1267 static int netlink_route_multipath(int cmd
, struct prefix
*p
,
1268 struct prefix
*src_p
, struct route_entry
*re
,
1272 struct sockaddr_nl snl
;
1273 struct nexthop
*nexthop
= NULL
;
1274 unsigned int nexthop_num
;
1276 int family
= PREFIX_FAMILY(p
);
1277 const char *routedesc
;
1284 char buf
[NL_PKT_BUF_SIZE
];
1287 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
1288 struct zebra_vrf
*zvrf
= vrf_info_lookup(re
->vrf_id
);
1290 memset(&req
, 0, sizeof req
- NL_PKT_BUF_SIZE
);
1292 bytelen
= (family
== AF_INET
? 4 : 16);
1294 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct rtmsg
));
1295 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1296 if ((cmd
== RTM_NEWROUTE
) && update
)
1297 req
.n
.nlmsg_flags
|= NLM_F_REPLACE
;
1298 req
.n
.nlmsg_type
= cmd
;
1299 req
.n
.nlmsg_pid
= zns
->netlink_cmd
.snl
.nl_pid
;
1301 req
.r
.rtm_family
= family
;
1302 req
.r
.rtm_dst_len
= p
->prefixlen
;
1303 req
.r
.rtm_src_len
= src_p
? src_p
->prefixlen
: 0;
1304 req
.r
.rtm_protocol
= zebra2proto(re
->type
);
1305 req
.r
.rtm_scope
= RT_SCOPE_UNIVERSE
;
1306 req
.r
.rtm_type
= RTN_UNICAST
;
1308 addattr_l(&req
.n
, sizeof req
, RTA_DST
, &p
->u
.prefix
, bytelen
);
1310 addattr_l(&req
.n
, sizeof req
, RTA_SRC
, &src_p
->u
.prefix
,
1314 /* Hardcode the metric for all routes coming from zebra. Metric isn't
1316 * either by the kernel or by zebra. Its purely for calculating best
1318 * by the routing protocol and for communicating with protocol peers.
1320 addattr32(&req
.n
, sizeof req
, RTA_PRIORITY
, NL_DEFAULT_ROUTE_METRIC
);
1321 #if defined(SUPPORT_REALMS)
1322 if (re
->tag
> 0 && re
->tag
<= 255)
1323 addattr32(&req
.n
, sizeof req
, RTA_FLOW
, re
->tag
);
1325 /* Table corresponding to this route. */
1326 if (re
->table
< 256)
1327 req
.r
.rtm_table
= re
->table
;
1329 req
.r
.rtm_table
= RT_TABLE_UNSPEC
;
1330 addattr32(&req
.n
, sizeof req
, RTA_TABLE
, re
->table
);
1336 if (re
->mtu
|| re
->nexthop_mtu
) {
1337 char buf
[NL_PKT_BUF_SIZE
];
1338 struct rtattr
*rta
= (void *)buf
;
1339 u_int32_t mtu
= re
->mtu
;
1340 if (!mtu
|| (re
->nexthop_mtu
&& re
->nexthop_mtu
< mtu
))
1341 mtu
= re
->nexthop_mtu
;
1342 rta
->rta_type
= RTA_METRICS
;
1343 rta
->rta_len
= RTA_LENGTH(0);
1344 rta_addattr_l(rta
, NL_PKT_BUF_SIZE
, RTAX_MTU
, &mtu
, sizeof mtu
);
1345 addattr_l(&req
.n
, NL_PKT_BUF_SIZE
, RTA_METRICS
, RTA_DATA(rta
),
1349 /* Count overall nexthops so we can decide whether to use singlepath
1350 * or multipath case. */
1352 for (ALL_NEXTHOPS(re
->nexthop
, nexthop
)) {
1353 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1355 if (cmd
== RTM_NEWROUTE
1356 && !NEXTHOP_IS_ACTIVE(nexthop
->flags
))
1358 if (cmd
== RTM_DELROUTE
1359 && !CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
))
1365 /* Singlepath case. */
1366 if (nexthop_num
== 1 || multipath_num
== 1) {
1368 for (ALL_NEXTHOPS(re
->nexthop
, nexthop
)) {
1370 * So we want to cover 2 types of blackhole
1372 * 1) A normal blackhole route( ala from a static
1374 * 2) A recursively resolved blackhole route
1376 if (nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
) {
1377 switch (nexthop
->bh_type
) {
1378 case BLACKHOLE_ADMINPROHIB
:
1379 req
.r
.rtm_type
= RTN_PROHIBIT
;
1381 case BLACKHOLE_REJECT
:
1382 req
.r
.rtm_type
= RTN_UNREACHABLE
;
1385 req
.r
.rtm_type
= RTN_BLACKHOLE
;
1390 if (CHECK_FLAG(nexthop
->flags
,
1391 NEXTHOP_FLAG_RECURSIVE
)) {
1393 if (family
== AF_INET
) {
1394 if (nexthop
->rmap_src
.ipv4
1401 } else if (nexthop
->src
.ipv4
1409 } else if (family
== AF_INET6
) {
1410 if (!IN6_IS_ADDR_UNSPECIFIED(
1418 !IN6_IS_ADDR_UNSPECIFIED(
1431 if ((cmd
== RTM_NEWROUTE
1432 && NEXTHOP_IS_ACTIVE(nexthop
->flags
))
1433 || (cmd
== RTM_DELROUTE
1434 && CHECK_FLAG(nexthop
->flags
,
1435 NEXTHOP_FLAG_FIB
))) {
1436 routedesc
= nexthop
->rparent
1437 ? "recursive, single-path"
1440 _netlink_route_debug(cmd
, p
, nexthop
, routedesc
,
1442 _netlink_route_build_singlepath(
1443 routedesc
, bytelen
, nexthop
, &req
.n
,
1444 &req
.r
, sizeof req
, cmd
);
1449 if (setsrc
&& (cmd
== RTM_NEWROUTE
)) {
1450 if (family
== AF_INET
)
1451 addattr_l(&req
.n
, sizeof req
, RTA_PREFSRC
,
1452 &src
.ipv4
, bytelen
);
1453 else if (family
== AF_INET6
)
1454 addattr_l(&req
.n
, sizeof req
, RTA_PREFSRC
,
1455 &src
.ipv6
, bytelen
);
1458 char buf
[NL_PKT_BUF_SIZE
];
1459 struct rtattr
*rta
= (void *)buf
;
1460 struct rtnexthop
*rtnh
;
1461 union g_addr
*src1
= NULL
;
1463 rta
->rta_type
= RTA_MULTIPATH
;
1464 rta
->rta_len
= RTA_LENGTH(0);
1465 rtnh
= RTA_DATA(rta
);
1468 for (ALL_NEXTHOPS(re
->nexthop
, nexthop
)) {
1469 if (nexthop_num
>= multipath_num
)
1472 if (CHECK_FLAG(nexthop
->flags
,
1473 NEXTHOP_FLAG_RECURSIVE
)) {
1474 /* This only works for IPv4 now */
1476 if (family
== AF_INET
) {
1477 if (nexthop
->rmap_src
.ipv4
1484 } else if (nexthop
->src
.ipv4
1492 } else if (family
== AF_INET6
) {
1493 if (!IN6_IS_ADDR_UNSPECIFIED(
1501 !IN6_IS_ADDR_UNSPECIFIED(
1514 if ((cmd
== RTM_NEWROUTE
1515 && NEXTHOP_IS_ACTIVE(nexthop
->flags
))
1516 || (cmd
== RTM_DELROUTE
1517 && CHECK_FLAG(nexthop
->flags
,
1518 NEXTHOP_FLAG_FIB
))) {
1519 routedesc
= nexthop
->rparent
1520 ? "recursive, multipath"
1524 _netlink_route_debug(cmd
, p
, nexthop
, routedesc
,
1526 _netlink_route_build_multipath(
1527 routedesc
, bytelen
, nexthop
, rta
, rtnh
,
1529 rtnh
= RTNH_NEXT(rtnh
);
1531 if (!setsrc
&& src1
) {
1532 if (family
== AF_INET
)
1533 src
.ipv4
= src1
->ipv4
;
1534 else if (family
== AF_INET6
)
1535 src
.ipv6
= src1
->ipv6
;
1541 if (setsrc
&& (cmd
== RTM_NEWROUTE
)) {
1542 if (family
== AF_INET
)
1543 addattr_l(&req
.n
, sizeof req
, RTA_PREFSRC
,
1544 &src
.ipv4
, bytelen
);
1545 else if (family
== AF_INET6
)
1546 addattr_l(&req
.n
, sizeof req
, RTA_PREFSRC
,
1547 &src
.ipv6
, bytelen
);
1548 if (IS_ZEBRA_DEBUG_KERNEL
)
1549 zlog_debug("Setting source");
1552 if (rta
->rta_len
> RTA_LENGTH(0))
1553 addattr_l(&req
.n
, NL_PKT_BUF_SIZE
, RTA_MULTIPATH
,
1554 RTA_DATA(rta
), RTA_PAYLOAD(rta
));
1557 /* If there is no useful nexthop then return. */
1558 if (nexthop_num
== 0) {
1559 if (IS_ZEBRA_DEBUG_KERNEL
)
1561 "netlink_route_multipath(): No useful nexthop.");
1567 /* Destination netlink address. */
1568 memset(&snl
, 0, sizeof snl
);
1569 snl
.nl_family
= AF_NETLINK
;
1571 /* Talk to netlink socket. */
1572 return netlink_talk(netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
,
1576 int kernel_get_ipmr_sg_stats(struct zebra_vrf
*zvrf
, void *in
)
1579 struct mcast_route_data
*mr
= (struct mcast_route_data
*)in
;
1587 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
1589 memset(&req
.n
, 0, sizeof(req
.n
));
1590 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
1592 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ndmsg
));
1593 req
.n
.nlmsg_flags
= NLM_F_REQUEST
;
1594 req
.n
.nlmsg_pid
= zns
->netlink_cmd
.snl
.nl_pid
;
1596 req
.ndm
.ndm_family
= RTNL_FAMILY_IPMR
;
1597 req
.n
.nlmsg_type
= RTM_GETROUTE
;
1599 addattr_l(&req
.n
, sizeof(req
), RTA_IIF
, &mroute
->ifindex
, 4);
1600 addattr_l(&req
.n
, sizeof(req
), RTA_OIF
, &mroute
->ifindex
, 4);
1601 addattr_l(&req
.n
, sizeof(req
), RTA_SRC
, &mroute
->sg
.src
.s_addr
, 4);
1602 addattr_l(&req
.n
, sizeof(req
), RTA_DST
, &mroute
->sg
.grp
.s_addr
, 4);
1603 addattr_l(&req
.n
, sizeof(req
), RTA_TABLE
, &zvrf
->table_id
, 4);
1605 suc
= netlink_talk(netlink_route_change_read_multicast
, &req
.n
,
1606 &zns
->netlink_cmd
, zns
, 0);
1612 void kernel_route_rib(struct prefix
*p
, struct prefix
*src_p
,
1613 struct route_entry
*old
, struct route_entry
*new)
1620 if (p
->family
== AF_INET
)
1621 ret
= netlink_route_multipath(RTM_NEWROUTE
, p
, src_p
,
1622 new, (old
) ? 1 : 0);
1625 * So v6 route replace semantics are not in
1626 * the kernel at this point as I understand it.
1627 * So let's do a delete than an add.
1628 * In the future once v6 route replace semantics
1629 * are in we can figure out what to do here to
1630 * allow working with old and new kernels.
1632 * I'm also intentionally ignoring the failure case
1633 * of the route delete. If that happens yeah we're
1637 netlink_route_multipath(RTM_DELROUTE
, p
,
1639 ret
= netlink_route_multipath(RTM_NEWROUTE
, p
,
1642 kernel_route_rib_pass_fail(p
, new,
1644 SOUTHBOUND_INSTALL_SUCCESS
:
1645 SOUTHBOUND_INSTALL_FAILURE
);
1650 ret
= netlink_route_multipath(RTM_DELROUTE
, p
, src_p
, old
, 0);
1652 kernel_route_rib_pass_fail(p
, old
,
1654 SOUTHBOUND_DELETE_SUCCESS
:
1655 SOUTHBOUND_DELETE_FAILURE
);
1659 int kernel_neigh_update(int add
, int ifindex
, uint32_t addr
, char *lla
,
1662 return netlink_neigh_update(add
? RTM_NEWNEIGH
: RTM_DELNEIGH
, ifindex
,
1667 * Add remote VTEP to the flood list for this VxLAN interface (VNI). This
1668 * is done by adding an FDB entry with a MAC of 00:00:00:00:00:00.
1670 static int netlink_vxlan_flood_list_update(struct interface
*ifp
,
1671 struct in_addr
*vtep_ip
, int cmd
)
1673 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
1679 u_char dst_mac
[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
1681 memset(&req
.n
, 0, sizeof(req
.n
));
1682 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
1684 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ndmsg
));
1685 req
.n
.nlmsg_flags
= NLM_F_REQUEST
;
1686 if (cmd
== RTM_NEWNEIGH
)
1687 req
.n
.nlmsg_flags
|= (NLM_F_CREATE
| NLM_F_APPEND
);
1688 req
.n
.nlmsg_type
= cmd
;
1689 req
.ndm
.ndm_family
= PF_BRIDGE
;
1690 req
.ndm
.ndm_state
= NUD_NOARP
| NUD_PERMANENT
;
1691 req
.ndm
.ndm_flags
|= NTF_SELF
; // Handle by "self", not "master"
1694 addattr_l(&req
.n
, sizeof(req
), NDA_LLADDR
, &dst_mac
, 6);
1695 req
.ndm
.ndm_ifindex
= ifp
->ifindex
;
1696 addattr_l(&req
.n
, sizeof(req
), NDA_DST
, &vtep_ip
->s_addr
, 4);
1698 return netlink_talk(netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
,
1703 * Add remote VTEP for this VxLAN interface (VNI). In Linux, this involves
1705 * a "flood" MAC FDB entry.
1707 int kernel_add_vtep(vni_t vni
, struct interface
*ifp
, struct in_addr
*vtep_ip
)
1709 if (IS_ZEBRA_DEBUG_VXLAN
)
1710 zlog_debug("Install %s into flood list for VNI %u intf %s(%u)",
1711 inet_ntoa(*vtep_ip
), vni
, ifp
->name
, ifp
->ifindex
);
1713 return netlink_vxlan_flood_list_update(ifp
, vtep_ip
, RTM_NEWNEIGH
);
1717 * Remove remote VTEP for this VxLAN interface (VNI). In Linux, this involves
1718 * deleting the "flood" MAC FDB entry.
1720 int kernel_del_vtep(vni_t vni
, struct interface
*ifp
, struct in_addr
*vtep_ip
)
1722 if (IS_ZEBRA_DEBUG_VXLAN
)
1724 "Uninstall %s from flood list for VNI %u intf %s(%u)",
1725 inet_ntoa(*vtep_ip
), vni
, ifp
->name
, ifp
->ifindex
);
1727 return netlink_vxlan_flood_list_update(ifp
, vtep_ip
, RTM_DELNEIGH
);
1731 #define NDA_RTA(r) \
1732 ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
1735 static int netlink_macfdb_change(struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
1739 struct interface
*ifp
;
1740 struct zebra_if
*zif
;
1741 struct rtattr
*tb
[NDA_MAX
+ 1];
1742 struct interface
*br_if
;
1745 struct prefix vtep_ip
;
1746 int vid_present
= 0, dst_present
= 0;
1747 char buf
[ETHER_ADDR_STRLEN
];
1752 ndm
= NLMSG_DATA(h
);
1754 /* We only process macfdb notifications if EVPN is enabled */
1755 if (!is_evpn_enabled())
1758 /* The interface should exist. */
1759 ifp
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
1761 if (!ifp
|| !ifp
->info
)
1764 /* The interface should be something we're interested in. */
1765 if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp
))
1768 /* Drop "permanent" entries. */
1769 if (ndm
->ndm_state
& NUD_PERMANENT
)
1772 zif
= (struct zebra_if
*)ifp
->info
;
1773 if ((br_if
= zif
->brslave_info
.br_if
) == NULL
) {
1774 zlog_warn("%s family %s IF %s(%u) brIF %u - no bridge master",
1775 nl_msg_type_to_str(h
->nlmsg_type
),
1776 nl_family_to_str(ndm
->ndm_family
), ifp
->name
,
1777 ndm
->ndm_ifindex
, zif
->brslave_info
.bridge_ifindex
);
1781 /* Parse attributes and extract fields of interest. */
1782 memset(tb
, 0, sizeof tb
);
1783 netlink_parse_rtattr(tb
, NDA_MAX
, NDA_RTA(ndm
), len
);
1785 if (!tb
[NDA_LLADDR
]) {
1786 zlog_warn("%s family %s IF %s(%u) brIF %u - no LLADDR",
1787 nl_msg_type_to_str(h
->nlmsg_type
),
1788 nl_family_to_str(ndm
->ndm_family
), ifp
->name
,
1789 ndm
->ndm_ifindex
, zif
->brslave_info
.bridge_ifindex
);
1793 if (RTA_PAYLOAD(tb
[NDA_LLADDR
]) != ETH_ALEN
) {
1795 "%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %lu",
1796 nl_msg_type_to_str(h
->nlmsg_type
),
1797 nl_family_to_str(ndm
->ndm_family
), ifp
->name
,
1798 ndm
->ndm_ifindex
, zif
->brslave_info
.bridge_ifindex
,
1799 (unsigned long)RTA_PAYLOAD(tb
[NDA_LLADDR
]));
1803 memcpy(&mac
, RTA_DATA(tb
[NDA_LLADDR
]), ETH_ALEN
);
1805 if ((NDA_VLAN
<= NDA_MAX
) && tb
[NDA_VLAN
]) {
1807 vid
= *(u_int16_t
*)RTA_DATA(tb
[NDA_VLAN
]);
1808 sprintf(vid_buf
, " VLAN %u", vid
);
1812 /* TODO: Only IPv4 supported now. */
1814 vtep_ip
.family
= AF_INET
;
1815 vtep_ip
.prefixlen
= IPV4_MAX_BITLEN
;
1816 memcpy(&(vtep_ip
.u
.prefix4
.s_addr
), RTA_DATA(tb
[NDA_DST
]),
1818 sprintf(dst_buf
, " dst %s", inet_ntoa(vtep_ip
.u
.prefix4
));
1821 sticky
= (ndm
->ndm_state
& NUD_NOARP
) ? 1 : 0;
1823 if (IS_ZEBRA_DEBUG_KERNEL
)
1824 zlog_debug("Rx %s family %s IF %s(%u)%s %sMAC %s%s",
1825 nl_msg_type_to_str(h
->nlmsg_type
),
1826 nl_family_to_str(ndm
->ndm_family
), ifp
->name
,
1827 ndm
->ndm_ifindex
, vid_present
? vid_buf
: "",
1828 sticky
? "sticky " : "",
1829 prefix_mac2str(&mac
, buf
, sizeof(buf
)),
1830 dst_present
? dst_buf
: "");
1832 if (filter_vlan
&& vid
!= filter_vlan
)
1835 /* If add or update, do accordingly if learnt on a "local" interface; if
1836 * the notification is over VxLAN, this has to be related to
1838 * so perform an implicit delete of any local entry (if it exists).
1840 if (h
->nlmsg_type
== RTM_NEWNEIGH
) {
1841 /* Drop "permanent" entries. */
1842 if (ndm
->ndm_state
& NUD_PERMANENT
)
1845 if (IS_ZEBRA_IF_VXLAN(ifp
))
1846 return zebra_vxlan_check_del_local_mac(ifp
, br_if
, &mac
,
1849 return zebra_vxlan_local_mac_add_update(ifp
, br_if
, &mac
, vid
,
1853 /* This is a delete notification.
1854 * 1. For a MAC over VxLan, check if it needs to be refreshed(readded)
1855 * 2. For a MAC over "local" interface, delete the mac
1856 * Note: We will get notifications from both bridge driver and VxLAN
1858 * Ignore the notification from VxLan driver as it is also generated
1859 * when mac moves from remote to local.
1864 if (IS_ZEBRA_IF_VXLAN(ifp
))
1865 return zebra_vxlan_check_readd_remote_mac(ifp
, br_if
, &mac
,
1868 return zebra_vxlan_local_mac_del(ifp
, br_if
, &mac
, vid
);
1871 static int netlink_macfdb_table(struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
1872 ns_id_t ns_id
, int startup
)
1877 if (h
->nlmsg_type
!= RTM_NEWNEIGH
)
1880 /* Length validity. */
1881 len
= h
->nlmsg_len
- NLMSG_LENGTH(sizeof(struct ndmsg
));
1885 /* We are interested only in AF_BRIDGE notifications. */
1886 ndm
= NLMSG_DATA(h
);
1887 if (ndm
->ndm_family
!= AF_BRIDGE
)
1890 return netlink_macfdb_change(snl
, h
, len
);
1893 /* Request for MAC FDB information from the kernel */
1894 static int netlink_request_macs(struct zebra_ns
*zns
, int family
, int type
,
1895 ifindex_t master_ifindex
)
1899 struct ifinfomsg ifm
;
1903 /* Form the request, specifying filter (rtattr) if needed. */
1904 memset(&req
, 0, sizeof(req
));
1905 req
.n
.nlmsg_type
= type
;
1906 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
1907 req
.ifm
.ifi_family
= family
;
1909 addattr32(&req
.n
, sizeof(req
), IFLA_MASTER
, master_ifindex
);
1911 return netlink_request(&zns
->netlink_cmd
, &req
.n
);
1915 * MAC forwarding database read using netlink interface. This is invoked
1918 int netlink_macfdb_read(struct zebra_ns
*zns
)
1922 /* Get bridge FDB table. */
1923 ret
= netlink_request_macs(zns
, AF_BRIDGE
, RTM_GETNEIGH
, 0);
1926 /* We are reading entire table. */
1928 ret
= netlink_parse_info(netlink_macfdb_table
, &zns
->netlink_cmd
, zns
,
1935 * MAC forwarding database read using netlink interface. This is for a
1936 * specific bridge and matching specific access VLAN (if VLAN-aware bridge).
1938 int netlink_macfdb_read_for_bridge(struct zebra_ns
*zns
, struct interface
*ifp
,
1939 struct interface
*br_if
)
1941 struct zebra_if
*br_zif
;
1942 struct zebra_if
*zif
;
1943 struct zebra_l2info_vxlan
*vxl
;
1947 /* Save VLAN we're filtering on, if needed. */
1948 br_zif
= (struct zebra_if
*)br_if
->info
;
1949 zif
= (struct zebra_if
*)ifp
->info
;
1950 vxl
= &zif
->l2info
.vxl
;
1951 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
1952 filter_vlan
= vxl
->access_vlan
;
1954 /* Get bridge FDB table for specific bridge - we do the VLAN filtering.
1956 ret
= netlink_request_macs(zns
, AF_BRIDGE
, RTM_GETNEIGH
,
1960 ret
= netlink_parse_info(netlink_macfdb_table
, &zns
->netlink_cmd
, zns
,
1963 /* Reset VLAN filter. */
1968 static int netlink_macfdb_update(struct interface
*ifp
, vlanid_t vid
,
1969 struct ethaddr
*mac
, struct in_addr vtep_ip
,
1970 int local
, int cmd
, u_char sticky
)
1972 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
1979 struct zebra_if
*zif
;
1980 struct interface
*br_if
;
1981 struct zebra_if
*br_zif
;
1982 char buf
[ETHER_ADDR_STRLEN
];
1983 int vid_present
= 0, dst_present
= 0;
1988 if ((br_if
= zif
->brslave_info
.br_if
) == NULL
) {
1989 zlog_warn("MAC %s on IF %s(%u) - no mapping to bridge",
1990 (cmd
== RTM_NEWNEIGH
) ? "add" : "del", ifp
->name
,
1995 memset(&req
.n
, 0, sizeof(req
.n
));
1996 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
1998 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ndmsg
));
1999 req
.n
.nlmsg_flags
= NLM_F_REQUEST
;
2000 if (cmd
== RTM_NEWNEIGH
)
2001 req
.n
.nlmsg_flags
|= (NLM_F_CREATE
| NLM_F_REPLACE
);
2002 req
.n
.nlmsg_type
= cmd
;
2003 req
.ndm
.ndm_family
= AF_BRIDGE
;
2004 req
.ndm
.ndm_flags
|= NTF_SELF
| NTF_MASTER
;
2005 req
.ndm
.ndm_state
= NUD_REACHABLE
;
2008 req
.ndm
.ndm_state
|= NUD_NOARP
;
2010 req
.ndm
.ndm_flags
|= NTF_EXT_LEARNED
;
2012 addattr_l(&req
.n
, sizeof(req
), NDA_LLADDR
, mac
, 6);
2013 req
.ndm
.ndm_ifindex
= ifp
->ifindex
;
2015 dst_alen
= 4; // TODO: hardcoded
2016 addattr_l(&req
.n
, sizeof(req
), NDA_DST
, &vtep_ip
, dst_alen
);
2018 sprintf(dst_buf
, " dst %s", inet_ntoa(vtep_ip
));
2020 br_zif
= (struct zebra_if
*)br_if
->info
;
2021 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
) && vid
> 0) {
2022 addattr16(&req
.n
, sizeof(req
), NDA_VLAN
, vid
);
2024 sprintf(vid_buf
, " VLAN %u", vid
);
2026 addattr32(&req
.n
, sizeof(req
), NDA_MASTER
, br_if
->ifindex
);
2028 if (IS_ZEBRA_DEBUG_KERNEL
)
2029 zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s%s",
2030 nl_msg_type_to_str(cmd
),
2031 nl_family_to_str(req
.ndm
.ndm_family
), ifp
->name
,
2032 ifp
->ifindex
, vid_present
? vid_buf
: "",
2033 sticky
? "sticky " : "",
2034 prefix_mac2str(mac
, buf
, sizeof(buf
)),
2035 dst_present
? dst_buf
: "");
2037 return netlink_talk(netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
,
2042 (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE | NUD_PROBE | NUD_STALE \
2045 static int netlink_ipneigh_change(struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
2049 struct interface
*ifp
;
2050 struct zebra_if
*zif
;
2051 struct rtattr
*tb
[NDA_MAX
+ 1];
2052 struct interface
*link_if
;
2055 char buf
[ETHER_ADDR_STRLEN
];
2056 char buf2
[INET6_ADDRSTRLEN
];
2057 int mac_present
= 0;
2060 ndm
= NLMSG_DATA(h
);
2062 /* We only process neigh notifications if EVPN is enabled */
2063 if (!is_evpn_enabled())
2066 /* The interface should exist. */
2067 ifp
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
2069 if (!ifp
|| !ifp
->info
)
2072 /* Drop "permanent" entries. */
2073 if (ndm
->ndm_state
& NUD_PERMANENT
)
2076 zif
= (struct zebra_if
*)ifp
->info
;
2077 /* The neighbor is present on an SVI. From this, we locate the
2079 * bridge because we're only interested in neighbors on a VxLAN bridge.
2080 * The bridge is located based on the nature of the SVI:
2081 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN
2083 * and is linked to the bridge
2084 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge
2088 if (IS_ZEBRA_IF_VLAN(ifp
)) {
2089 link_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
2093 } else if (IS_ZEBRA_IF_BRIDGE(ifp
))
2098 /* Parse attributes and extract fields of interest. */
2099 memset(tb
, 0, sizeof tb
);
2100 netlink_parse_rtattr(tb
, NDA_MAX
, NDA_RTA(ndm
), len
);
2103 zlog_warn("%s family %s IF %s(%u) - no DST",
2104 nl_msg_type_to_str(h
->nlmsg_type
),
2105 nl_family_to_str(ndm
->ndm_family
), ifp
->name
,
2109 memset(&mac
, 0, sizeof(struct ethaddr
));
2110 memset(&ip
, 0, sizeof(struct ipaddr
));
2111 ip
.ipa_type
= (ndm
->ndm_family
== AF_INET
) ? IPADDR_V4
: IPADDR_V6
;
2112 memcpy(&ip
.ip
.addr
, RTA_DATA(tb
[NDA_DST
]), RTA_PAYLOAD(tb
[NDA_DST
]));
2114 if (h
->nlmsg_type
== RTM_NEWNEIGH
) {
2115 if (tb
[NDA_LLADDR
]) {
2116 if (RTA_PAYLOAD(tb
[NDA_LLADDR
]) != ETH_ALEN
) {
2118 "%s family %s IF %s(%u) - LLADDR is not MAC, len %lu",
2119 nl_msg_type_to_str(h
->nlmsg_type
),
2120 nl_family_to_str(ndm
->ndm_family
),
2121 ifp
->name
, ndm
->ndm_ifindex
,
2122 (unsigned long)RTA_PAYLOAD(tb
[NDA_LLADDR
]));
2127 memcpy(&mac
, RTA_DATA(tb
[NDA_LLADDR
]), ETH_ALEN
);
2130 ext_learned
= (ndm
->ndm_flags
& NTF_EXT_LEARNED
) ? 1 : 0;
2132 if (IS_ZEBRA_DEBUG_KERNEL
)
2134 "Rx %s family %s IF %s(%u) IP %s MAC %s state 0x%x flags 0x%x",
2135 nl_msg_type_to_str(h
->nlmsg_type
),
2136 nl_family_to_str(ndm
->ndm_family
), ifp
->name
,
2138 ipaddr2str(&ip
, buf2
, sizeof(buf2
)),
2140 ? prefix_mac2str(&mac
, buf
, sizeof(buf
))
2142 ndm
->ndm_state
, ndm
->ndm_flags
);
2144 /* If the neighbor state is valid for use, process as an add or
2146 * else process as a delete. Note that the delete handling may
2148 * in re-adding the neighbor if it is a valid "remote" neighbor.
2150 if (ndm
->ndm_state
& NUD_VALID
)
2151 return zebra_vxlan_local_neigh_add_update(
2152 ifp
, link_if
, &ip
, &mac
, ndm
->ndm_state
,
2155 return zebra_vxlan_local_neigh_del(ifp
, link_if
, &ip
);
2158 if (IS_ZEBRA_DEBUG_KERNEL
)
2159 zlog_debug("Rx %s family %s IF %s(%u) IP %s",
2160 nl_msg_type_to_str(h
->nlmsg_type
),
2161 nl_family_to_str(ndm
->ndm_family
), ifp
->name
,
2163 ipaddr2str(&ip
, buf2
, sizeof(buf2
)));
2165 /* Process the delete - it may result in re-adding the neighbor if it is
2166 * a valid "remote" neighbor.
2168 return zebra_vxlan_local_neigh_del(ifp
, link_if
, &ip
);
2171 static int netlink_neigh_table(struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
2172 ns_id_t ns_id
, int startup
)
2177 if (h
->nlmsg_type
!= RTM_NEWNEIGH
)
2180 /* Length validity. */
2181 len
= h
->nlmsg_len
- NLMSG_LENGTH(sizeof(struct ndmsg
));
2185 /* We are interested only in AF_INET or AF_INET6 notifications. */
2186 ndm
= NLMSG_DATA(h
);
2187 if (ndm
->ndm_family
!= AF_INET
&& ndm
->ndm_family
!= AF_INET6
)
2190 return netlink_neigh_change(snl
, h
, len
);
2193 /* Request for IP neighbor information from the kernel */
2194 static int netlink_request_neigh(struct zebra_ns
*zns
, int family
, int type
,
2203 /* Form the request, specifying filter (rtattr) if needed. */
2204 memset(&req
, 0, sizeof(req
));
2205 req
.n
.nlmsg_type
= type
;
2206 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ndmsg
));
2207 req
.ndm
.ndm_family
= family
;
2209 addattr32(&req
.n
, sizeof(req
), NDA_IFINDEX
, ifindex
);
2211 return netlink_request(&zns
->netlink_cmd
, &req
.n
);
2215 * IP Neighbor table read using netlink interface. This is invoked
2218 int netlink_neigh_read(struct zebra_ns
*zns
)
2222 /* Get IP neighbor table. */
2223 ret
= netlink_request_neigh(zns
, AF_UNSPEC
, RTM_GETNEIGH
, 0);
2226 ret
= netlink_parse_info(netlink_neigh_table
, &zns
->netlink_cmd
, zns
, 0,
2233 * IP Neighbor table read using netlink interface. This is for a specific
2236 int netlink_neigh_read_for_vlan(struct zebra_ns
*zns
, struct interface
*vlan_if
)
2240 ret
= netlink_request_neigh(zns
, AF_UNSPEC
, RTM_GETNEIGH
,
2244 ret
= netlink_parse_info(netlink_neigh_table
, &zns
->netlink_cmd
, zns
, 0,
2250 int netlink_neigh_change(struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
2256 if (!(h
->nlmsg_type
== RTM_NEWNEIGH
|| h
->nlmsg_type
== RTM_DELNEIGH
))
2259 /* Length validity. */
2260 len
= h
->nlmsg_len
- NLMSG_LENGTH(sizeof(struct ndmsg
));
2264 /* Is this a notification for the MAC FDB or IP neighbor table? */
2265 ndm
= NLMSG_DATA(h
);
2266 if (ndm
->ndm_family
== AF_BRIDGE
)
2267 return netlink_macfdb_change(snl
, h
, len
);
2269 if (ndm
->ndm_type
!= RTN_UNICAST
)
2272 if (ndm
->ndm_family
== AF_INET
|| ndm
->ndm_family
== AF_INET6
)
2273 return netlink_ipneigh_change(snl
, h
, len
);
2278 static int netlink_neigh_update2(struct interface
*ifp
, struct ipaddr
*ip
,
2279 struct ethaddr
*mac
, u_int32_t flags
, int cmd
)
2288 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
2289 char buf
[INET6_ADDRSTRLEN
];
2290 char buf2
[ETHER_ADDR_STRLEN
];
2292 memset(&req
.n
, 0, sizeof(req
.n
));
2293 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
2295 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ndmsg
));
2296 req
.n
.nlmsg_flags
= NLM_F_REQUEST
;
2297 if (cmd
== RTM_NEWNEIGH
)
2298 req
.n
.nlmsg_flags
|= (NLM_F_CREATE
| NLM_F_REPLACE
);
2299 req
.n
.nlmsg_type
= cmd
; // RTM_NEWNEIGH or RTM_DELNEIGH
2300 req
.ndm
.ndm_family
= IS_IPADDR_V4(ip
) ? AF_INET
: AF_INET6
;
2301 req
.ndm
.ndm_state
= flags
;
2302 req
.ndm
.ndm_ifindex
= ifp
->ifindex
;
2303 req
.ndm
.ndm_type
= RTN_UNICAST
;
2304 req
.ndm
.ndm_flags
= NTF_EXT_LEARNED
;
2307 ipa_len
= IS_IPADDR_V4(ip
) ? IPV4_MAX_BYTELEN
: IPV6_MAX_BYTELEN
;
2308 addattr_l(&req
.n
, sizeof(req
), NDA_DST
, &ip
->ip
.addr
, ipa_len
);
2310 addattr_l(&req
.n
, sizeof(req
), NDA_LLADDR
, mac
, 6);
2312 if (IS_ZEBRA_DEBUG_KERNEL
)
2313 zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s",
2314 nl_msg_type_to_str(cmd
),
2315 nl_family_to_str(req
.ndm
.ndm_family
), ifp
->name
,
2316 ifp
->ifindex
, ipaddr2str(ip
, buf
, sizeof(buf
)),
2317 mac
? prefix_mac2str(mac
, buf2
, sizeof(buf2
))
2320 return netlink_talk(netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
,
2324 int kernel_add_mac(struct interface
*ifp
, vlanid_t vid
, struct ethaddr
*mac
,
2325 struct in_addr vtep_ip
, u_char sticky
)
2327 return netlink_macfdb_update(ifp
, vid
, mac
, vtep_ip
, 0, RTM_NEWNEIGH
,
2331 int kernel_del_mac(struct interface
*ifp
, vlanid_t vid
, struct ethaddr
*mac
,
2332 struct in_addr vtep_ip
, int local
)
2334 return netlink_macfdb_update(ifp
, vid
, mac
, vtep_ip
, local
,
2338 int kernel_add_neigh(struct interface
*ifp
, struct ipaddr
*ip
,
2339 struct ethaddr
*mac
)
2341 return netlink_neigh_update2(ifp
, ip
, mac
, NUD_REACHABLE
, RTM_NEWNEIGH
);
2344 int kernel_del_neigh(struct interface
*ifp
, struct ipaddr
*ip
)
2346 return netlink_neigh_update2(ifp
, ip
, NULL
, 0, RTM_DELNEIGH
);
2350 * MPLS label forwarding table change via netlink interface.
2352 int netlink_mpls_multipath(int cmd
, zebra_lsp_t
*lsp
)
2355 zebra_nhlfe_t
*nhlfe
;
2356 struct nexthop
*nexthop
= NULL
;
2357 unsigned int nexthop_num
;
2358 const char *routedesc
;
2359 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
2365 char buf
[NL_PKT_BUF_SIZE
];
2368 memset(&req
, 0, sizeof req
- NL_PKT_BUF_SIZE
);
2371 * Count # nexthops so we can decide whether to use singlepath
2372 * or multipath case.
2375 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
) {
2376 nexthop
= nhlfe
->nexthop
;
2379 if (cmd
== RTM_NEWROUTE
) {
2380 /* Count all selected NHLFEs */
2381 if (CHECK_FLAG(nhlfe
->flags
, NHLFE_FLAG_SELECTED
)
2382 && CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
2386 /* Count all installed NHLFEs */
2387 if (CHECK_FLAG(nhlfe
->flags
, NHLFE_FLAG_INSTALLED
)
2388 && CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
))
2393 if ((nexthop_num
== 0) || (!lsp
->best_nhlfe
&& (cmd
!= RTM_DELROUTE
)))
2396 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct rtmsg
));
2397 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
2398 req
.n
.nlmsg_type
= cmd
;
2399 req
.n
.nlmsg_pid
= zns
->netlink_cmd
.snl
.nl_pid
;
2401 req
.r
.rtm_family
= AF_MPLS
;
2402 req
.r
.rtm_table
= RT_TABLE_MAIN
;
2403 req
.r
.rtm_dst_len
= MPLS_LABEL_LEN_BITS
;
2404 req
.r
.rtm_scope
= RT_SCOPE_UNIVERSE
;
2405 req
.r
.rtm_type
= RTN_UNICAST
;
2407 if (cmd
== RTM_NEWROUTE
) {
2408 /* We do a replace to handle update. */
2409 req
.n
.nlmsg_flags
|= NLM_F_REPLACE
;
2411 /* set the protocol value if installing */
2412 route_type
= re_type_from_lsp_type(lsp
->best_nhlfe
->type
);
2413 req
.r
.rtm_protocol
= zebra2proto(route_type
);
2416 /* Fill destination */
2417 lse
= mpls_lse_encode(lsp
->ile
.in_label
, 0, 0, 1);
2418 addattr_l(&req
.n
, sizeof req
, RTA_DST
, &lse
, sizeof(mpls_lse_t
));
2420 /* Fill nexthops (paths) based on single-path or multipath. The paths
2421 * chosen depend on the operation.
2423 if (nexthop_num
== 1 || multipath_num
== 1) {
2424 routedesc
= "single-path";
2425 _netlink_mpls_debug(cmd
, lsp
->ile
.in_label
, routedesc
);
2428 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
) {
2429 nexthop
= nhlfe
->nexthop
;
2433 if ((cmd
== RTM_NEWROUTE
2434 && (CHECK_FLAG(nhlfe
->flags
, NHLFE_FLAG_SELECTED
)
2435 && CHECK_FLAG(nexthop
->flags
,
2436 NEXTHOP_FLAG_ACTIVE
)))
2437 || (cmd
== RTM_DELROUTE
2438 && (CHECK_FLAG(nhlfe
->flags
,
2439 NHLFE_FLAG_INSTALLED
)
2440 && CHECK_FLAG(nexthop
->flags
,
2441 NEXTHOP_FLAG_FIB
)))) {
2442 /* Add the gateway */
2443 _netlink_mpls_build_singlepath(routedesc
, nhlfe
,
2450 } else /* Multipath case */
2452 char buf
[NL_PKT_BUF_SIZE
];
2453 struct rtattr
*rta
= (void *)buf
;
2454 struct rtnexthop
*rtnh
;
2455 union g_addr
*src1
= NULL
;
2457 rta
->rta_type
= RTA_MULTIPATH
;
2458 rta
->rta_len
= RTA_LENGTH(0);
2459 rtnh
= RTA_DATA(rta
);
2461 routedesc
= "multipath";
2462 _netlink_mpls_debug(cmd
, lsp
->ile
.in_label
, routedesc
);
2465 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
) {
2466 nexthop
= nhlfe
->nexthop
;
2470 if (nexthop_num
>= multipath_num
)
2473 if ((cmd
== RTM_NEWROUTE
2474 && (CHECK_FLAG(nhlfe
->flags
, NHLFE_FLAG_SELECTED
)
2475 && CHECK_FLAG(nexthop
->flags
,
2476 NEXTHOP_FLAG_ACTIVE
)))
2477 || (cmd
== RTM_DELROUTE
2478 && (CHECK_FLAG(nhlfe
->flags
,
2479 NHLFE_FLAG_INSTALLED
)
2480 && CHECK_FLAG(nexthop
->flags
,
2481 NEXTHOP_FLAG_FIB
)))) {
2484 /* Build the multipath */
2485 _netlink_mpls_build_multipath(routedesc
, nhlfe
,
2488 rtnh
= RTNH_NEXT(rtnh
);
2492 /* Add the multipath */
2493 if (rta
->rta_len
> RTA_LENGTH(0))
2494 addattr_l(&req
.n
, NL_PKT_BUF_SIZE
, RTA_MULTIPATH
,
2495 RTA_DATA(rta
), RTA_PAYLOAD(rta
));
2498 /* Talk to netlink socket. */
2499 return netlink_talk(netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
,
2502 #endif /* HAVE_NETLINK */