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>
27 /* Hack for GNU libc version 2. */
29 #define MSG_TRUNC 0x20
30 #endif /* MSG_TRUNC */
36 #include "connected.h"
39 #include "zebra_memory.h"
49 #include "zebra/zserv.h"
50 #include "zebra/zebra_ns.h"
51 #include "zebra/zebra_vrf.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"
65 /* TODO - Temporary definitions, need to refine. */
78 #ifndef RTA_ENCAP_TYPE
79 #define RTA_ENCAP_TYPE 21
87 #define RTA_EXPIRES 23
90 #ifndef LWTUNNEL_ENCAP_MPLS
91 #define LWTUNNEL_ENCAP_MPLS 1
94 #ifndef MPLS_IPTUNNEL_DST
95 #define MPLS_IPTUNNEL_DST 1
103 #define NTF_MASTER 0x04
107 #define NTF_SELF 0x02
110 #ifndef NTF_EXT_LEARNED
111 #define NTF_EXT_LEARNED 0x10
115 #define NDA_IFINDEX 8
121 /* End of temporary definitions */
123 static vlanid_t filter_vlan
= 0;
131 char ipv4_ll_buf
[16] = "169.254.0.1";
132 struct in_addr ipv4_ll
;
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
140 void rt_netlink_init(void)
142 inet_pton(AF_INET
, ipv4_ll_buf
, &ipv4_ll
);
145 static inline int is_selfroute(int proto
)
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
)) {
159 static inline int zebra2proto(int proto
)
162 case ZEBRA_ROUTE_BABEL
:
163 proto
= RTPROT_BABEL
;
165 case ZEBRA_ROUTE_BGP
:
168 case ZEBRA_ROUTE_OSPF
:
169 case ZEBRA_ROUTE_OSPF6
:
172 case ZEBRA_ROUTE_STATIC
:
173 proto
= RTPROT_STATIC
;
175 case ZEBRA_ROUTE_ISIS
:
178 case ZEBRA_ROUTE_RIP
:
181 case ZEBRA_ROUTE_RIPNG
:
182 proto
= RTPROT_RIPNG
;
184 case ZEBRA_ROUTE_NHRP
:
187 case ZEBRA_ROUTE_EIGRP
:
188 proto
= RTPROT_EIGRP
;
190 case ZEBRA_ROUTE_LDP
:
194 proto
= RTPROT_ZEBRA
;
201 static inline int proto2zebra(int proto
, int family
)
205 proto
= ZEBRA_ROUTE_BABEL
;
208 proto
= ZEBRA_ROUTE_BGP
;
211 proto
= (family
== AFI_IP
) ?
212 ZEBRA_ROUTE_OSPF
: ZEBRA_ROUTE_OSPF6
;
215 proto
= ZEBRA_ROUTE_ISIS
;
218 proto
= ZEBRA_ROUTE_RIP
;
221 proto
= ZEBRA_ROUTE_RIPNG
;
224 proto
= ZEBRA_ROUTE_NHRP
;
227 proto
= ZEBRA_ROUTE_EIGRP
;
230 proto
= ZEBRA_ROUTE_LDP
;
233 proto
= ZEBRA_ROUTE_STATIC
;
236 proto
= ZEBRA_ROUTE_KERNEL
;
243 Pending: create an efficient table_id (in a tree/hash) based lookup)
245 static vrf_id_t
vrf_lookup_by_table(u_int32_t table_id
)
248 struct zebra_vrf
*zvrf
;
250 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
) {
251 if ((zvrf
= vrf
->info
) == NULL
|| (zvrf
->table_id
!= table_id
))
254 return zvrf_id(zvrf
);
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
,
267 struct rtattr
*tb
[RTA_MAX
+ 1];
270 struct prefix_ipv6 src_p
;
271 vrf_id_t vrf_id
= VRF_DEFAULT
;
273 char anyaddr
[16] = {0};
275 int proto
= ZEBRA_ROUTE_KERNEL
;
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
;
289 if (startup
&& h
->nlmsg_type
!= RTM_NEWROUTE
)
291 switch (rtm
->rtm_type
) {
295 bh_type
= BLACKHOLE_NULL
;
297 case RTN_UNREACHABLE
:
298 bh_type
= BLACKHOLE_REJECT
;
301 bh_type
= BLACKHOLE_ADMINPROHIB
;
307 len
= h
->nlmsg_len
- NLMSG_LENGTH(sizeof(struct rtmsg
));
311 memset(tb
, 0, sizeof tb
);
312 netlink_parse_rtattr(tb
, RTA_MAX
, RTM_RTA(rtm
), len
);
314 if (rtm
->rtm_flags
& RTM_F_CLONED
)
316 if (rtm
->rtm_protocol
== RTPROT_REDIRECT
)
318 if (rtm
->rtm_protocol
== RTPROT_KERNEL
)
321 if (!startup
&& is_selfroute(rtm
->rtm_protocol
)
322 && h
->nlmsg_type
== RTM_NEWROUTE
)
325 /* We don't care about change notifications for the MPLS table. */
326 /* TODO: Revisit this. */
327 if (rtm
->rtm_family
== AF_MPLS
)
330 /* Table corresponding to route. */
332 table
= *(int *)RTA_DATA(tb
[RTA_TABLE
]);
334 table
= rtm
->rtm_table
;
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
))
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
);
350 index
= *(int *)RTA_DATA(tb
[RTA_OIF
]);
353 dest
= RTA_DATA(tb
[RTA_DST
]);
358 src
= RTA_DATA(tb
[RTA_SRC
]);
363 prefsrc
= RTA_DATA(tb
[RTA_PREFSRC
]);
366 gate
= RTA_DATA(tb
[RTA_GATEWAY
]);
368 if (tb
[RTA_PRIORITY
])
369 metric
= *(int *)RTA_DATA(tb
[RTA_PRIORITY
]);
371 if (tb
[RTA_METRICS
]) {
372 struct rtattr
*mxrta
[RTAX_MAX
+ 1];
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
]));
380 mtu
= *(u_int32_t
*)RTA_DATA(mxrta
[RTAX_MTU
]);
383 if (rtm
->rtm_family
== AF_INET
) {
385 memcpy(&p
.u
.prefix4
, dest
, 4);
386 p
.prefixlen
= rtm
->rtm_dst_len
;
389 0; // Forces debug below to not display anything
390 } else if (rtm
->rtm_family
== AF_INET6
) {
392 memcpy(&p
.u
.prefix6
, dest
, 16);
393 p
.prefixlen
= rtm
->rtm_dst_len
;
395 src_p
.family
= AF_INET6
;
396 memcpy(&src_p
.prefix
, src
, 16);
397 src_p
.prefixlen
= rtm
->rtm_src_len
;
400 if (rtm
->rtm_src_len
!= 0) {
401 char buf
[PREFIX_STRLEN
];
403 "unsupported IPv[4|6] sourcedest route (dest %s vrf %u)",
404 prefix2str(&p
, buf
, sizeof(buf
)), vrf_id
);
408 if (IS_ZEBRA_DEBUG_KERNEL
) {
409 char buf
[PREFIX_STRLEN
];
410 char buf2
[PREFIX_STRLEN
];
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
))
421 if (rtm
->rtm_family
== AF_INET6
)
424 if (h
->nlmsg_type
== RTM_NEWROUTE
) {
425 if (!tb
[RTA_MULTIPATH
]) {
427 size_t sz
= (afi
== AFI_IP
) ? 4 : 16;
429 memset(&nh
, 0, sizeof(nh
));
431 if (bh_type
== BLACKHOLE_UNSPEC
) {
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
)
443 nh
.type
= NEXTHOP_TYPE_BLACKHOLE
;
444 nh
.bh_type
= bh_type
;
447 nh
.type
= NEXTHOP_TYPE_BLACKHOLE
;
448 nh
.bh_type
= bh_type
;
452 memcpy(&nh
.src
, prefsrc
, sz
);
454 memcpy(&nh
.gate
, gate
, sz
);
456 rib_add(afi
, SAFI_UNICAST
, vrf_id
, proto
,
457 0, flags
, &p
, NULL
, &nh
, table
, metric
, mtu
, 0);
459 /* This is a multipath route */
461 struct route_entry
*re
;
462 struct rtnexthop
*rtnh
=
463 (struct rtnexthop
*)RTA_DATA(tb
[RTA_MULTIPATH
]);
465 len
= RTA_PAYLOAD(tb
[RTA_MULTIPATH
]);
467 re
= XCALLOC(MTYPE_RE
, sizeof(struct route_entry
));
476 re
->uptime
= time(NULL
);
479 if (len
< (int)sizeof(*rtnh
)
480 || rtnh
->rtnh_len
> len
)
483 index
= rtnh
->rtnh_ifindex
;
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
));
496 if (rtm
->rtm_family
== AF_INET
) {
498 route_entry_nexthop_ipv4_ifindex_add(
502 route_entry_nexthop_ipv4_add(
505 } else if (rtm
->rtm_family
508 route_entry_nexthop_ipv6_ifindex_add(
512 route_entry_nexthop_ipv6_add(
516 route_entry_nexthop_ifindex_add(re
,
519 len
-= NLMSG_ALIGN(rtnh
->rtnh_len
);
520 rtnh
= RTNH_NEXT(rtnh
);
523 zserv_nexthop_num_warn(__func__
,
524 (const struct prefix
*)&p
,
526 if (re
->nexthop_num
== 0)
529 rib_add_multipath(AFI_IP
, SAFI_UNICAST
, &p
,
533 if (!tb
[RTA_MULTIPATH
]) {
535 size_t sz
= (afi
== AFI_IP
) ? 4 : 16;
537 memset(&nh
, 0, sizeof(nh
));
538 if (bh_type
== BLACKHOLE_UNSPEC
) {
540 nh
.type
= NEXTHOP_TYPE_IFINDEX
;
541 else if (index
&& gate
)
544 ? NEXTHOP_TYPE_IPV4_IFINDEX
545 : NEXTHOP_TYPE_IPV6_IFINDEX
;
546 else if (!index
&& gate
)
547 nh
.type
= (afi
== AFI_IP
)
551 nh
.type
= NEXTHOP_TYPE_BLACKHOLE
;
552 nh
.bh_type
= BLACKHOLE_UNSPEC
;
555 nh
.type
= NEXTHOP_TYPE_BLACKHOLE
;
556 nh
.bh_type
= bh_type
;
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);
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);
576 static struct mcast_route_data
*mroute
= NULL
;
578 static int netlink_route_change_read_multicast(struct sockaddr_nl
*snl
,
580 ns_id_t ns_id
, int startup
)
584 struct rtattr
*tb
[RTA_MAX
+ 1];
585 struct mcast_route_data
*m
;
586 struct mcast_route_data mr
;
593 char oif_list
[256] = "\0";
594 vrf_id_t vrf
= ns_id
;
600 memset(&mr
, 0, sizeof(mr
));
606 len
= h
->nlmsg_len
- NLMSG_LENGTH(sizeof(struct rtmsg
));
608 memset(tb
, 0, sizeof tb
);
609 netlink_parse_rtattr(tb
, RTA_MAX
, RTM_RTA(rtm
), len
);
612 table
= *(int *)RTA_DATA(tb
[RTA_TABLE
]);
614 table
= rtm
->rtm_table
;
616 vrf
= vrf_lookup_by_table(table
);
619 iif
= *(int *)RTA_DATA(tb
[RTA_IIF
]);
622 m
->sg
.src
= *(struct in_addr
*)RTA_DATA(tb
[RTA_SRC
]);
625 m
->sg
.grp
= *(struct in_addr
*)RTA_DATA(tb
[RTA_DST
]);
627 if ((RTA_EXPIRES
<= RTA_MAX
) && tb
[RTA_EXPIRES
])
628 m
->lastused
= *(unsigned long long *)RTA_DATA(tb
[RTA_EXPIRES
]);
630 if (tb
[RTA_MULTIPATH
]) {
631 struct rtnexthop
*rtnh
=
632 (struct rtnexthop
*)RTA_DATA(tb
[RTA_MULTIPATH
]);
634 len
= RTA_PAYLOAD(tb
[RTA_MULTIPATH
]);
636 if (len
< (int)sizeof(*rtnh
) || rtnh
->rtnh_len
> len
)
639 oif
[oif_count
] = rtnh
->rtnh_ifindex
;
642 len
-= NLMSG_ALIGN(rtnh
->rtnh_len
);
643 rtnh
= RTNH_NEXT(rtnh
);
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
);
655 sprintf(temp
, "%s ", ifp
->name
);
656 strcat(oif_list
, temp
);
658 struct zebra_vrf
*zvrf
= zebra_vrf_lookup_by_id(vrf
);
659 ifp
= if_lookup_by_index(iif
, vrf
);
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
);
668 int netlink_route_change(struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
669 ns_id_t ns_id
, int startup
)
672 vrf_id_t vrf_id
= ns_id
;
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
);
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
);
691 /* We don't care about change notifications for the MPLS table. */
692 /* TODO: Revisit this. */
693 if (rtm
->rtm_family
== AF_MPLS
)
696 len
= h
->nlmsg_len
- NLMSG_LENGTH(sizeof(struct rtmsg
));
700 if (rtm
->rtm_type
== RTN_MULTICAST
)
701 netlink_route_change_read_multicast(snl
, h
, ns_id
, startup
);
703 netlink_route_change_read_unicast(snl
, h
, ns_id
, startup
);
707 /* Request for specific route information from the kernel */
708 static int netlink_request_route(struct zebra_ns
*zns
, int family
, int type
)
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
;
721 return netlink_request(&zns
->netlink_cmd
, &req
.n
);
724 /* Routing table read function using netlink interface. Only called
726 int netlink_route_read(struct zebra_ns
*zns
)
730 /* Get IPv4 routing table. */
731 ret
= netlink_request_route(zns
, AF_INET
, RTM_GETROUTE
);
734 ret
= netlink_parse_info(netlink_route_change_read_unicast
,
735 &zns
->netlink_cmd
, zns
, 0, 1);
739 /* Get IPv6 routing table. */
740 ret
= netlink_request_route(zns
, AF_INET6
, RTM_GETROUTE
);
743 ret
= netlink_parse_info(netlink_route_change_read_unicast
,
744 &zns
->netlink_cmd
, zns
, 0, 1);
751 static void _netlink_route_nl_add_gateway_info(u_char route_family
,
753 struct nlmsghdr
*nlmsg
,
754 size_t req_size
, int bytelen
,
755 struct nexthop
*nexthop
)
757 if (route_family
== AF_MPLS
) {
758 struct gw_family_t gw_fam
;
760 gw_fam
.family
= gw_family
;
761 if (gw_family
== AF_INET
)
762 memcpy(&gw_fam
.gate
.ipv4
, &nexthop
->gate
.ipv4
, bytelen
);
764 memcpy(&gw_fam
.gate
.ipv6
, &nexthop
->gate
.ipv6
, bytelen
);
765 addattr_l(nlmsg
, req_size
, RTA_VIA
, &gw_fam
.family
,
768 if (gw_family
== AF_INET
)
769 addattr_l(nlmsg
, req_size
, RTA_GATEWAY
,
770 &nexthop
->gate
.ipv4
, bytelen
);
772 addattr_l(nlmsg
, req_size
, RTA_GATEWAY
,
773 &nexthop
->gate
.ipv6
, bytelen
);
777 static void _netlink_route_rta_add_gateway_info(u_char route_family
,
780 struct rtnexthop
*rtnh
,
781 size_t req_size
, int bytelen
,
782 struct nexthop
*nexthop
)
784 if (route_family
== AF_MPLS
) {
785 struct gw_family_t gw_fam
;
787 gw_fam
.family
= gw_family
;
788 if (gw_family
== AF_INET
)
789 memcpy(&gw_fam
.gate
.ipv4
, &nexthop
->gate
.ipv4
, bytelen
);
791 memcpy(&gw_fam
.gate
.ipv6
, &nexthop
->gate
.ipv6
, bytelen
);
792 rta_addattr_l(rta
, req_size
, RTA_VIA
, &gw_fam
.family
,
794 rtnh
->rtnh_len
+= RTA_LENGTH(bytelen
+ 2);
796 if (gw_family
== AF_INET
)
797 rta_addattr_l(rta
, req_size
, RTA_GATEWAY
,
798 &nexthop
->gate
.ipv4
, bytelen
);
800 rta_addattr_l(rta
, req_size
, RTA_GATEWAY
,
801 &nexthop
->gate
.ipv6
, bytelen
);
802 rtnh
->rtnh_len
+= sizeof(struct rtattr
) + bytelen
;
806 /* This function takes a nexthop as argument and adds
807 * the appropriate netlink attributes to an existing
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.
817 static void _netlink_route_build_singlepath(const char *routedesc
, int bytelen
,
818 struct nexthop
*nexthop
,
819 struct nlmsghdr
*nlmsg
,
821 size_t req_size
, int cmd
)
823 struct nexthop_label
*nh_label
;
824 mpls_lse_t out_lse
[MPLS_MAX_LABELS
];
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
834 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
835 * (in the case of LER)
837 nh_label
= nexthop
->nh_label
;
838 if (rtmsg
->rtm_family
== AF_MPLS
) {
840 assert(nh_label
->num_labels
== 1);
843 if (nh_label
&& nh_label
->num_labels
) {
844 int i
, num_labels
= 0;
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
852 out_lse
[i
] = mpls_lse_encode(nh_label
->label
[i
],
854 if (IS_ZEBRA_DEBUG_KERNEL
) {
856 sprintf(label_buf
, "label %d",
859 sprintf(label_buf1
, "/%d",
861 strcat(label_buf
, label_buf1
);
868 if (rtmsg
->rtm_family
== AF_MPLS
)
869 addattr_l(nlmsg
, req_size
, RTA_NEWDST
, &out_lse
,
870 num_labels
* sizeof(mpls_lse_t
));
873 u_int16_t encap
= LWTUNNEL_ENCAP_MPLS
;
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
,
880 num_labels
* sizeof(mpls_lse_t
));
881 addattr_nest_end(nlmsg
, nest
);
886 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
887 rtmsg
->rtm_flags
|= RTNH_F_ONLINK
;
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
);
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
);
903 if (IS_ZEBRA_DEBUG_KERNEL
)
905 " 5549: _netlink_route_build_singlepath() (%s): "
906 "nexthop via %s %s if %u",
907 routedesc
, ipv4_ll_buf
, label_buf
,
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
,
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
);
929 if (IS_ZEBRA_DEBUG_KERNEL
)
931 "netlink_route_multipath() (%s): "
932 "nexthop via %s %s if %u",
933 routedesc
, inet_ntoa(nexthop
->gate
.ipv4
),
934 label_buf
, nexthop
->ifindex
);
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
,
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
);
952 if (IS_ZEBRA_DEBUG_KERNEL
)
954 "netlink_route_multipath() (%s): "
955 "nexthop via %s %s if %u",
956 routedesc
, inet6_ntoa(nexthop
->gate
.ipv6
),
957 label_buf
, nexthop
->ifindex
);
959 if (nexthop
->type
== NEXTHOP_TYPE_IFINDEX
960 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
) {
961 addattr32(nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
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
);
972 if (IS_ZEBRA_DEBUG_KERNEL
)
974 "netlink_route_multipath() (%s): "
976 routedesc
, nexthop
->ifindex
);
979 if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
) {
980 addattr32(nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
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
);
991 if (IS_ZEBRA_DEBUG_KERNEL
)
993 "netlink_route_multipath() (%s): "
995 routedesc
, nexthop
->ifindex
);
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.
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.
1015 static void _netlink_route_build_multipath(const char *routedesc
, int bytelen
,
1016 struct nexthop
*nexthop
,
1018 struct rtnexthop
*rtnh
,
1019 struct rtmsg
*rtmsg
,
1022 struct nexthop_label
*nh_label
;
1023 mpls_lse_t out_lse
[MPLS_MAX_LABELS
];
1024 char label_buf
[100];
1026 rtnh
->rtnh_len
= sizeof(*rtnh
);
1027 rtnh
->rtnh_flags
= 0;
1028 rtnh
->rtnh_hops
= 0;
1029 rta
->rta_len
+= rtnh
->rtnh_len
;
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
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)
1041 nh_label
= nexthop
->nh_label
;
1042 if (rtmsg
->rtm_family
== AF_MPLS
) {
1044 assert(nh_label
->num_labels
== 1);
1047 if (nh_label
&& nh_label
->num_labels
) {
1048 int i
, num_labels
= 0;
1050 char label_buf1
[20];
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
1056 out_lse
[i
] = mpls_lse_encode(nh_label
->label
[i
],
1058 if (IS_ZEBRA_DEBUG_KERNEL
) {
1060 sprintf(label_buf
, "label %d",
1061 nh_label
->label
[i
]);
1063 sprintf(label_buf1
, "/%d",
1064 nh_label
->label
[i
]);
1065 strcat(label_buf
, label_buf1
);
1072 if (rtmsg
->rtm_family
== AF_MPLS
) {
1073 rta_addattr_l(rta
, NL_PKT_BUF_SIZE
, RTA_NEWDST
,
1075 num_labels
* sizeof(mpls_lse_t
));
1076 rtnh
->rtnh_len
+= RTA_LENGTH(
1077 num_labels
* sizeof(mpls_lse_t
));
1079 struct rtattr
*nest
;
1080 u_int16_t encap
= LWTUNNEL_ENCAP_MPLS
;
1081 int len
= rta
->rta_len
;
1083 rta_addattr_l(rta
, NL_PKT_BUF_SIZE
,
1084 RTA_ENCAP_TYPE
, &encap
,
1086 nest
= rta_nest(rta
, NL_PKT_BUF_SIZE
,
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
;
1097 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
1098 rtnh
->rtnh_flags
|= RTNH_F_ONLINK
;
1100 if (rtmsg
->rtm_family
== AF_INET
1101 && (nexthop
->type
== NEXTHOP_TYPE_IPV6
1102 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)) {
1104 rtnh
->rtnh_flags
|= RTNH_F_ONLINK
;
1105 rta_addattr_l(rta
, NL_PKT_BUF_SIZE
, RTA_GATEWAY
, &ipv4_ll
,
1107 rtnh
->rtnh_len
+= sizeof(struct rtattr
) + bytelen
;
1108 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
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
;
1115 if (IS_ZEBRA_DEBUG_KERNEL
)
1117 " 5549: netlink_route_build_multipath() (%s): "
1118 "nexthop via %s %s if %u",
1119 routedesc
, ipv4_ll_buf
, label_buf
,
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
,
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
;
1134 if (IS_ZEBRA_DEBUG_KERNEL
)
1136 "netlink_route_multipath() (%s): "
1137 "nexthop via %s %s if %u",
1138 routedesc
, inet_ntoa(nexthop
->gate
.ipv4
),
1139 label_buf
, nexthop
->ifindex
);
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
,
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
;
1152 if (IS_ZEBRA_DEBUG_KERNEL
)
1154 "netlink_route_multipath() (%s): "
1155 "nexthop via %s %s if %u",
1156 routedesc
, inet6_ntoa(nexthop
->gate
.ipv6
),
1157 label_buf
, nexthop
->ifindex
);
1160 if (nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
1161 || nexthop
->type
== NEXTHOP_TYPE_IFINDEX
) {
1162 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
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
;
1169 if (IS_ZEBRA_DEBUG_KERNEL
)
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
;
1177 if (IS_ZEBRA_DEBUG_KERNEL
)
1179 "netlink_route_multipath() (%s): "
1180 "nexthop via if %u",
1181 routedesc
, nexthop
->ifindex
);
1183 rtnh
->rtnh_ifindex
= 0;
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
)
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
);
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
)
1211 family
= NHLFE_FAMILY(nhlfe
);
1212 bytelen
= (family
== AF_INET
? 4 : 16);
1213 _netlink_route_build_multipath(routedesc
, bytelen
, nhlfe
->nexthop
, rta
,
1218 /* Log debug information for netlink_route_multipath
1219 * if debug logging is enabled.
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
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
)
1232 if (IS_ZEBRA_DEBUG_KERNEL
) {
1233 char buf
[PREFIX_STRLEN
];
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");
1242 static void _netlink_mpls_debug(int cmd
, u_int32_t label
, const char *routedesc
)
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
);
1249 static int netlink_neigh_update(int cmd
, int ifindex
, uint32_t addr
, char *lla
,
1258 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
1260 memset(&req
.n
, 0, sizeof(req
.n
));
1261 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
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
;
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
;
1273 addattr_l(&req
.n
, sizeof(req
), NDA_DST
, &addr
, 4);
1274 addattr_l(&req
.n
, sizeof(req
), NDA_LLADDR
, lla
, llalen
);
1276 return netlink_talk(netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
,
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
,
1287 struct sockaddr_nl snl
;
1288 struct nexthop
*nexthop
= NULL
;
1289 unsigned int nexthop_num
;
1291 int family
= PREFIX_FAMILY(p
);
1292 const char *routedesc
;
1299 char buf
[NL_PKT_BUF_SIZE
];
1302 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
1303 struct zebra_vrf
*zvrf
= vrf_info_lookup(re
->vrf_id
);
1305 memset(&req
, 0, sizeof req
- NL_PKT_BUF_SIZE
);
1307 bytelen
= (family
== AF_INET
? 4 : 16);
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
;
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
;
1323 addattr_l(&req
.n
, sizeof req
, RTA_DST
, &p
->u
.prefix
, bytelen
);
1325 addattr_l(&req
.n
, sizeof req
, RTA_SRC
, &src_p
->u
.prefix
,
1329 /* Hardcode the metric for all routes coming from zebra. Metric isn't
1331 * either by the kernel or by zebra. Its purely for calculating best
1333 * by the routing protocol and for communicating with protocol peers.
1335 addattr32(&req
.n
, sizeof req
, RTA_PRIORITY
, NL_DEFAULT_ROUTE_METRIC
);
1337 /* Table corresponding to this route. */
1338 if (re
->table
< 256)
1339 req
.r
.rtm_table
= re
->table
;
1341 req
.r
.rtm_table
= RT_TABLE_UNSPEC
;
1342 addattr32(&req
.n
, sizeof req
, RTA_TABLE
, re
->table
);
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
),
1361 /* Count overall nexthops so we can decide whether to use singlepath
1362 * or multipath case. */
1364 for (ALL_NEXTHOPS(re
->nexthop
, nexthop
)) {
1365 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1367 if (cmd
== RTM_NEWROUTE
1368 && !NEXTHOP_IS_ACTIVE(nexthop
->flags
))
1370 if (cmd
== RTM_DELROUTE
1371 && !CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
))
1377 /* Singlepath case. */
1378 if (nexthop_num
== 1 || multipath_num
== 1) {
1380 for (ALL_NEXTHOPS(re
->nexthop
, nexthop
)) {
1382 * So we want to cover 2 types of blackhole
1384 * 1) A normal blackhole route( ala from a static
1386 * 2) A recursively resolved blackhole route
1388 if (nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
) {
1389 switch (nexthop
->bh_type
) {
1390 case BLACKHOLE_ADMINPROHIB
:
1391 req
.r
.rtm_type
= RTN_PROHIBIT
;
1393 case BLACKHOLE_REJECT
:
1394 req
.r
.rtm_type
= RTN_UNREACHABLE
;
1397 req
.r
.rtm_type
= RTN_BLACKHOLE
;
1402 if (CHECK_FLAG(nexthop
->flags
,
1403 NEXTHOP_FLAG_RECURSIVE
)) {
1405 if (family
== AF_INET
) {
1406 if (nexthop
->rmap_src
.ipv4
1413 } else if (nexthop
->src
.ipv4
1421 } else if (family
== AF_INET6
) {
1422 if (!IN6_IS_ADDR_UNSPECIFIED(
1430 !IN6_IS_ADDR_UNSPECIFIED(
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"
1452 _netlink_route_debug(cmd
, p
, nexthop
, routedesc
,
1454 _netlink_route_build_singlepath(
1455 routedesc
, bytelen
, nexthop
, &req
.n
,
1456 &req
.r
, sizeof req
, cmd
);
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
);
1470 char buf
[NL_PKT_BUF_SIZE
];
1471 struct rtattr
*rta
= (void *)buf
;
1472 struct rtnexthop
*rtnh
;
1473 union g_addr
*src1
= NULL
;
1475 rta
->rta_type
= RTA_MULTIPATH
;
1476 rta
->rta_len
= RTA_LENGTH(0);
1477 rtnh
= RTA_DATA(rta
);
1480 for (ALL_NEXTHOPS(re
->nexthop
, nexthop
)) {
1481 if (nexthop_num
>= multipath_num
)
1484 if (CHECK_FLAG(nexthop
->flags
,
1485 NEXTHOP_FLAG_RECURSIVE
)) {
1486 /* This only works for IPv4 now */
1488 if (family
== AF_INET
) {
1489 if (nexthop
->rmap_src
.ipv4
1496 } else if (nexthop
->src
.ipv4
1504 } else if (family
== AF_INET6
) {
1505 if (!IN6_IS_ADDR_UNSPECIFIED(
1513 !IN6_IS_ADDR_UNSPECIFIED(
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"
1536 _netlink_route_debug(cmd
, p
, nexthop
, routedesc
,
1538 _netlink_route_build_multipath(
1539 routedesc
, bytelen
, nexthop
, rta
, rtnh
,
1541 rtnh
= RTNH_NEXT(rtnh
);
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
;
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");
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
));
1569 /* If there is no useful nexthop then return. */
1570 if (nexthop_num
== 0) {
1571 if (IS_ZEBRA_DEBUG_KERNEL
)
1573 "netlink_route_multipath(): No useful nexthop.");
1579 /* Destination netlink address. */
1580 memset(&snl
, 0, sizeof snl
);
1581 snl
.nl_family
= AF_NETLINK
;
1583 /* Talk to netlink socket. */
1584 return netlink_talk(netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
,
1588 int kernel_get_ipmr_sg_stats(struct zebra_vrf
*zvrf
, void *in
)
1591 struct mcast_route_data
*mr
= (struct mcast_route_data
*)in
;
1599 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
1601 memset(&req
.n
, 0, sizeof(req
.n
));
1602 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
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
;
1608 req
.ndm
.ndm_family
= RTNL_FAMILY_IPMR
;
1609 req
.n
.nlmsg_type
= RTM_GETROUTE
;
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);
1617 suc
= netlink_talk(netlink_route_change_read_multicast
, &req
.n
,
1618 &zns
->netlink_cmd
, zns
, 0);
1624 int kernel_route_rib(struct prefix
*p
, struct prefix
*src_p
,
1625 struct route_entry
*old
, struct route_entry
*new)
1630 return netlink_route_multipath(RTM_NEWROUTE
, p
, src_p
, new, 0);
1632 return netlink_route_multipath(RTM_DELROUTE
, p
, src_p
, old
, 0);
1634 return netlink_route_multipath(RTM_NEWROUTE
, p
, src_p
, new, 1);
1637 int kernel_neigh_update(int add
, int ifindex
, uint32_t addr
, char *lla
,
1640 return netlink_neigh_update(add
? RTM_NEWNEIGH
: RTM_DELNEIGH
, ifindex
,
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.
1648 static int netlink_vxlan_flood_list_update(struct interface
*ifp
,
1649 struct in_addr
*vtep_ip
, int cmd
)
1651 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
1657 u_char dst_mac
[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
1659 memset(&req
.n
, 0, sizeof(req
.n
));
1660 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
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"
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);
1676 return netlink_talk(netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
,
1681 * Add remote VTEP for this VxLAN interface (VNI). In Linux, this involves
1683 * a "flood" MAC FDB entry.
1685 int kernel_add_vtep(vni_t vni
, struct interface
*ifp
, struct in_addr
*vtep_ip
)
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
);
1691 return netlink_vxlan_flood_list_update(ifp
, vtep_ip
, RTM_NEWNEIGH
);
1695 * Remove remote VTEP for this VxLAN interface (VNI). In Linux, this involves
1696 * deleting the "flood" MAC FDB entry.
1698 int kernel_del_vtep(vni_t vni
, struct interface
*ifp
, struct in_addr
*vtep_ip
)
1700 if (IS_ZEBRA_DEBUG_VXLAN
)
1702 "Uninstall %s from flood list for VNI %u intf %s(%u)",
1703 inet_ntoa(*vtep_ip
), vni
, ifp
->name
, ifp
->ifindex
);
1705 return netlink_vxlan_flood_list_update(ifp
, vtep_ip
, RTM_DELNEIGH
);
1709 #define NDA_RTA(r) \
1710 ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
1713 static int netlink_macfdb_change(struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
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
;
1724 struct prefix vtep_ip
;
1725 int vid_present
= 0, dst_present
= 0;
1726 char buf
[ETHER_ADDR_STRLEN
];
1731 ndm
= NLMSG_DATA(h
);
1733 /* The interface should exist. */
1734 ifp
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
1739 /* Locate VRF corresponding to interface. We only process MAC
1741 * if EVPN is enabled on this VRF.
1743 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1744 if (!zvrf
|| !EVPN_ENABLED(zvrf
))
1749 /* The interface should be something we're interested in. */
1750 if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp
))
1753 /* Drop "permanent" entries. */
1754 if (ndm
->ndm_state
& NUD_PERMANENT
)
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
);
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
);
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
);
1778 if (RTA_PAYLOAD(tb
[NDA_LLADDR
]) != ETH_ALEN
) {
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
]));
1788 memcpy(&mac
, RTA_DATA(tb
[NDA_LLADDR
]), ETH_ALEN
);
1790 if ((NDA_VLAN
<= NDA_MAX
) && tb
[NDA_VLAN
]) {
1792 vid
= *(u_int16_t
*)RTA_DATA(tb
[NDA_VLAN
]);
1793 sprintf(vid_buf
, " VLAN %u", vid
);
1797 /* TODO: Only IPv4 supported now. */
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
]),
1803 sprintf(dst_buf
, " dst %s", inet_ntoa(vtep_ip
.u
.prefix4
));
1806 sticky
= (ndm
->ndm_state
& NUD_NOARP
) ? 1 : 0;
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
: "");
1817 if (filter_vlan
&& vid
!= filter_vlan
)
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
1823 * so perform an implicit delete of any local entry (if it exists).
1825 if (h
->nlmsg_type
== RTM_NEWNEIGH
) {
1826 /* Drop "permanent" entries. */
1827 if (ndm
->ndm_state
& NUD_PERMANENT
)
1830 if (IS_ZEBRA_IF_VXLAN(ifp
))
1831 return zebra_vxlan_check_del_local_mac(ifp
, br_if
, &mac
,
1834 return zebra_vxlan_local_mac_add_update(ifp
, br_if
, &mac
, vid
,
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
1843 * Ignore the notification from VxLan driver as it is also generated
1844 * when mac moves from remote to local.
1849 if (IS_ZEBRA_IF_VXLAN(ifp
))
1850 return zebra_vxlan_check_readd_remote_mac(ifp
, br_if
, &mac
,
1853 return zebra_vxlan_local_mac_del(ifp
, br_if
, &mac
, vid
);
1856 static int netlink_macfdb_table(struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
1857 ns_id_t ns_id
, int startup
)
1862 if (h
->nlmsg_type
!= RTM_NEWNEIGH
)
1865 /* Length validity. */
1866 len
= h
->nlmsg_len
- NLMSG_LENGTH(sizeof(struct ndmsg
));
1870 /* We are interested only in AF_BRIDGE notifications. */
1871 ndm
= NLMSG_DATA(h
);
1872 if (ndm
->ndm_family
!= AF_BRIDGE
)
1875 return netlink_macfdb_change(snl
, h
, len
);
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
)
1884 struct ifinfomsg ifm
;
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
;
1894 addattr32(&req
.n
, sizeof(req
), IFLA_MASTER
, master_ifindex
);
1896 return netlink_request(&zns
->netlink_cmd
, &req
.n
);
1900 * MAC forwarding database read using netlink interface. This is invoked
1903 int netlink_macfdb_read(struct zebra_ns
*zns
)
1907 /* Get bridge FDB table. */
1908 ret
= netlink_request_macs(zns
, AF_BRIDGE
, RTM_GETNEIGH
, 0);
1911 /* We are reading entire table. */
1913 ret
= netlink_parse_info(netlink_macfdb_table
, &zns
->netlink_cmd
, zns
,
1920 * MAC forwarding database read using netlink interface. This is for a
1921 * specific bridge and matching specific access VLAN (if VLAN-aware bridge).
1923 int netlink_macfdb_read_for_bridge(struct zebra_ns
*zns
, struct interface
*ifp
,
1924 struct interface
*br_if
)
1926 struct zebra_if
*br_zif
;
1927 struct zebra_if
*zif
;
1928 struct zebra_l2info_vxlan
*vxl
;
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
;
1939 /* Get bridge FDB table for specific bridge - we do the VLAN filtering.
1941 ret
= netlink_request_macs(zns
, AF_BRIDGE
, RTM_GETNEIGH
,
1945 ret
= netlink_parse_info(netlink_macfdb_table
, &zns
->netlink_cmd
, zns
,
1948 /* Reset VLAN filter. */
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
)
1957 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
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;
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
,
1980 memset(&req
.n
, 0, sizeof(req
.n
));
1981 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
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
;
1993 req
.ndm
.ndm_state
|= NUD_NOARP
;
1995 req
.ndm
.ndm_flags
|= NTF_EXT_LEARNED
;
1997 addattr_l(&req
.n
, sizeof(req
), NDA_LLADDR
, mac
, 6);
1998 req
.ndm
.ndm_ifindex
= ifp
->ifindex
;
2000 dst_alen
= 4; // TODO: hardcoded
2001 addattr_l(&req
.n
, sizeof(req
), NDA_DST
, &vtep_ip
, dst_alen
);
2003 sprintf(dst_buf
, " dst %s", inet_ntoa(vtep_ip
));
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
);
2009 sprintf(vid_buf
, " VLAN %u", vid
);
2011 addattr32(&req
.n
, sizeof(req
), NDA_MASTER
, br_if
->ifindex
);
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
: "");
2022 return netlink_talk(netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
,
2027 (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE | NUD_PROBE | NUD_STALE \
2030 static int netlink_ipneigh_change(struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
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
;
2041 char buf
[ETHER_ADDR_STRLEN
];
2042 char buf2
[INET6_ADDRSTRLEN
];
2043 int mac_present
= 0;
2046 ndm
= NLMSG_DATA(h
);
2048 /* The interface should exist. */
2049 ifp
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
2054 /* Locate VRF corresponding to interface. We only process neigh
2056 * if EVPN is enabled on this VRF.
2058 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
2059 if (!zvrf
|| !EVPN_ENABLED(zvrf
))
2064 /* Drop "permanent" entries. */
2065 if (ndm
->ndm_state
& NUD_PERMANENT
)
2068 zif
= (struct zebra_if
*)ifp
->info
;
2069 /* The neighbor is present on an SVI. From this, we locate the
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
2075 * and is linked to the bridge
2076 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge
2080 if (IS_ZEBRA_IF_VLAN(ifp
)) {
2081 link_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
2085 } else if (IS_ZEBRA_IF_BRIDGE(ifp
))
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
);
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
,
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
]));
2106 if (h
->nlmsg_type
== RTM_NEWNEIGH
) {
2107 if (tb
[NDA_LLADDR
]) {
2108 if (RTA_PAYLOAD(tb
[NDA_LLADDR
]) != ETH_ALEN
) {
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
]));
2119 memcpy(&mac
, RTA_DATA(tb
[NDA_LLADDR
]), ETH_ALEN
);
2122 ext_learned
= (ndm
->ndm_flags
& NTF_EXT_LEARNED
) ? 1 : 0;
2124 if (IS_ZEBRA_DEBUG_KERNEL
)
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
,
2130 ipaddr2str(&ip
, buf2
, sizeof(buf2
)),
2132 ? prefix_mac2str(&mac
, buf
, sizeof(buf
))
2134 ndm
->ndm_state
, ndm
->ndm_flags
);
2136 /* If the neighbor state is valid for use, process as an add or
2138 * else process as a delete. Note that the delete handling may
2140 * in re-adding the neighbor if it is a valid "remote" neighbor.
2142 if (ndm
->ndm_state
& NUD_VALID
)
2143 return zebra_vxlan_local_neigh_add_update(
2144 ifp
, link_if
, &ip
, &mac
, ndm
->ndm_state
,
2147 return zebra_vxlan_local_neigh_del(ifp
, link_if
, &ip
);
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
,
2155 ipaddr2str(&ip
, buf2
, sizeof(buf2
)));
2157 /* Process the delete - it may result in re-adding the neighbor if it is
2158 * a valid "remote" neighbor.
2160 return zebra_vxlan_local_neigh_del(ifp
, link_if
, &ip
);
2163 static int netlink_neigh_table(struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
2164 ns_id_t ns_id
, int startup
)
2169 if (h
->nlmsg_type
!= RTM_NEWNEIGH
)
2172 /* Length validity. */
2173 len
= h
->nlmsg_len
- NLMSG_LENGTH(sizeof(struct ndmsg
));
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
)
2182 return netlink_neigh_change(snl
, h
, len
);
2185 /* Request for IP neighbor information from the kernel */
2186 static int netlink_request_neigh(struct zebra_ns
*zns
, int family
, int type
,
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
;
2201 addattr32(&req
.n
, sizeof(req
), NDA_IFINDEX
, ifindex
);
2203 return netlink_request(&zns
->netlink_cmd
, &req
.n
);
2207 * IP Neighbor table read using netlink interface. This is invoked
2210 int netlink_neigh_read(struct zebra_ns
*zns
)
2214 /* Get IP neighbor table. */
2215 ret
= netlink_request_neigh(zns
, AF_UNSPEC
, RTM_GETNEIGH
, 0);
2218 ret
= netlink_parse_info(netlink_neigh_table
, &zns
->netlink_cmd
, zns
, 0,
2225 * IP Neighbor table read using netlink interface. This is for a specific
2228 int netlink_neigh_read_for_vlan(struct zebra_ns
*zns
, struct interface
*vlan_if
)
2232 ret
= netlink_request_neigh(zns
, AF_UNSPEC
, RTM_GETNEIGH
,
2236 ret
= netlink_parse_info(netlink_neigh_table
, &zns
->netlink_cmd
, zns
, 0,
2242 int netlink_neigh_change(struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
2248 if (!(h
->nlmsg_type
== RTM_NEWNEIGH
|| h
->nlmsg_type
== RTM_DELNEIGH
))
2251 /* Length validity. */
2252 len
= h
->nlmsg_len
- NLMSG_LENGTH(sizeof(struct ndmsg
));
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
);
2261 if (ndm
->ndm_type
!= RTN_UNICAST
)
2264 if (ndm
->ndm_family
== AF_INET
|| ndm
->ndm_family
== AF_INET6
)
2265 return netlink_ipneigh_change(snl
, h
, len
);
2270 static int netlink_neigh_update2(struct interface
*ifp
, struct ipaddr
*ip
,
2271 struct ethaddr
*mac
, u_int32_t flags
, int cmd
)
2280 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
2281 char buf
[INET6_ADDRSTRLEN
];
2282 char buf2
[ETHER_ADDR_STRLEN
];
2284 memset(&req
.n
, 0, sizeof(req
.n
));
2285 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
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
;
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
);
2302 addattr_l(&req
.n
, sizeof(req
), NDA_LLADDR
, mac
, 6);
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
))
2312 return netlink_talk(netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
,
2316 int kernel_add_mac(struct interface
*ifp
, vlanid_t vid
, struct ethaddr
*mac
,
2317 struct in_addr vtep_ip
, u_char sticky
)
2319 return netlink_macfdb_update(ifp
, vid
, mac
, vtep_ip
, 0, RTM_NEWNEIGH
,
2323 int kernel_del_mac(struct interface
*ifp
, vlanid_t vid
, struct ethaddr
*mac
,
2324 struct in_addr vtep_ip
, int local
)
2326 return netlink_macfdb_update(ifp
, vid
, mac
, vtep_ip
, local
,
2330 int kernel_add_neigh(struct interface
*ifp
, struct ipaddr
*ip
,
2331 struct ethaddr
*mac
)
2333 return netlink_neigh_update2(ifp
, ip
, mac
, NUD_REACHABLE
, RTM_NEWNEIGH
);
2336 int kernel_del_neigh(struct interface
*ifp
, struct ipaddr
*ip
)
2338 return netlink_neigh_update2(ifp
, ip
, NULL
, 0, RTM_DELNEIGH
);
2342 * MPLS label forwarding table change via netlink interface.
2344 int netlink_mpls_multipath(int cmd
, zebra_lsp_t
*lsp
)
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
);
2356 char buf
[NL_PKT_BUF_SIZE
];
2359 memset(&req
, 0, sizeof req
- NL_PKT_BUF_SIZE
);
2363 * Count # nexthops so we can decide whether to use singlepath
2364 * or multipath case.
2367 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
) {
2368 nexthop
= nhlfe
->nexthop
;
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
))
2378 /* Count all installed NHLFEs */
2379 if (CHECK_FLAG(nhlfe
->flags
, NHLFE_FLAG_INSTALLED
)
2380 && CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
))
2385 if (nexthop_num
== 0) // unexpected
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
;
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
;
2400 if (cmd
== RTM_NEWROUTE
)
2401 /* We do a replace to handle update. */
2402 req
.n
.nlmsg_flags
|= NLM_F_REPLACE
;
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
));
2408 /* Fill nexthops (paths) based on single-path or multipath. The paths
2409 * chosen depend on the operation.
2411 if (nexthop_num
== 1 || multipath_num
== 1) {
2412 routedesc
= "single hop";
2413 _netlink_mpls_debug(cmd
, lsp
->ile
.in_label
, routedesc
);
2416 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
) {
2417 nexthop
= nhlfe
->nexthop
;
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
,
2434 if (cmd
== RTM_NEWROUTE
) {
2435 SET_FLAG(nhlfe
->flags
,
2436 NHLFE_FLAG_INSTALLED
);
2437 SET_FLAG(nexthop
->flags
,
2440 UNSET_FLAG(nhlfe
->flags
,
2441 NHLFE_FLAG_INSTALLED
);
2442 UNSET_FLAG(nexthop
->flags
,
2449 } else /* Multipath case */
2451 char buf
[NL_PKT_BUF_SIZE
];
2452 struct rtattr
*rta
= (void *)buf
;
2453 struct rtnexthop
*rtnh
;
2454 union g_addr
*src1
= NULL
;
2456 rta
->rta_type
= RTA_MULTIPATH
;
2457 rta
->rta_len
= RTA_LENGTH(0);
2458 rtnh
= RTA_DATA(rta
);
2460 routedesc
= "multihop";
2461 _netlink_mpls_debug(cmd
, lsp
->ile
.in_label
, routedesc
);
2464 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
) {
2465 nexthop
= nhlfe
->nexthop
;
2469 if (nexthop_num
>= multipath_num
)
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
)))) {
2483 /* Build the multipath */
2484 _netlink_mpls_build_multipath(routedesc
, nhlfe
,
2487 rtnh
= RTNH_NEXT(rtnh
);
2489 if (cmd
== RTM_NEWROUTE
) {
2490 SET_FLAG(nhlfe
->flags
,
2491 NHLFE_FLAG_INSTALLED
);
2492 SET_FLAG(nexthop
->flags
,
2495 UNSET_FLAG(nhlfe
->flags
,
2496 NHLFE_FLAG_INSTALLED
);
2497 UNSET_FLAG(nexthop
->flags
,
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
));
2509 /* Talk to netlink socket. */
2510 return netlink_talk(netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
,
2515 * Handle failure in LSP install, clear flags for NHLFE.
2517 void clear_nhlfe_installed(zebra_lsp_t
*lsp
)
2519 zebra_nhlfe_t
*nhlfe
;
2520 struct nexthop
*nexthop
;
2522 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
) {
2523 nexthop
= nhlfe
->nexthop
;
2527 UNSET_FLAG(nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
2528 UNSET_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
);
2532 #endif /* HAVE_NETLINK */