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
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23 #include <net/if_arp.h>
25 /* Hack for GNU libc version 2. */
27 #define MSG_TRUNC 0x20
28 #endif /* MSG_TRUNC */
34 #include "connected.h"
37 #include "zebra_memory.h"
46 #include "zebra/zserv.h"
47 #include "zebra/zebra_ns.h"
48 #include "zebra/zebra_vrf.h"
50 #include "zebra/redistribute.h"
51 #include "zebra/interface.h"
52 #include "zebra/debug.h"
53 #include "zebra/rtadv.h"
54 #include "zebra/zebra_ptm.h"
55 #include "zebra/zebra_mpls.h"
56 #include "zebra/kernel_netlink.h"
57 #include "zebra/rt_netlink.h"
59 /* TODO - Temporary definitions, need to refine. */
72 #ifndef RTA_ENCAP_TYPE
73 #define RTA_ENCAP_TYPE 21
80 #ifndef LWTUNNEL_ENCAP_MPLS
81 #define LWTUNNEL_ENCAP_MPLS 1
84 #ifndef MPLS_IPTUNNEL_DST
85 #define MPLS_IPTUNNEL_DST 1
87 /* End of temporary definitions */
97 Pending: create an efficient table_id (in a tree/hash) based lookup)
100 vrf_lookup_by_table (u_int32_t table_id
)
103 struct zebra_vrf
*zvrf
;
105 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
107 if ((zvrf
= vrf
->info
) == NULL
||
108 (zvrf
->table_id
!= table_id
))
111 return zvrf_id (zvrf
);
117 /* Looking up routing table by netlink interface. */
119 netlink_routing_table (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
124 struct rtattr
*tb
[RTA_MAX
+ 1];
127 vrf_id_t vrf_id
= VRF_DEFAULT
;
129 char anyaddr
[16] = { 0 };
140 rtm
= NLMSG_DATA (h
);
142 if (h
->nlmsg_type
!= RTM_NEWROUTE
)
144 if (rtm
->rtm_type
!= RTN_UNICAST
)
147 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
151 memset (tb
, 0, sizeof tb
);
152 netlink_parse_rtattr (tb
, RTA_MAX
, RTM_RTA (rtm
), len
);
154 if (rtm
->rtm_flags
& RTM_F_CLONED
)
156 if (rtm
->rtm_protocol
== RTPROT_REDIRECT
)
158 if (rtm
->rtm_protocol
== RTPROT_KERNEL
)
161 if (rtm
->rtm_src_len
!= 0)
164 /* We don't care about change notifications for the MPLS table. */
165 /* TODO: Revisit this. */
166 if (rtm
->rtm_family
== AF_MPLS
)
169 /* Table corresponding to route. */
171 table
= *(int *) RTA_DATA (tb
[RTA_TABLE
]);
173 table
= rtm
->rtm_table
;
176 vrf_id
= vrf_lookup_by_table(table
);
177 if (vrf_id
== VRF_DEFAULT
)
179 if (!is_zebra_valid_kernel_table(table
) &&
180 !is_zebra_main_routing_table(table
))
184 /* Route which inserted by Zebra. */
185 if (rtm
->rtm_protocol
== RTPROT_ZEBRA
)
186 flags
|= ZEBRA_FLAG_SELFROUTE
;
195 index
= *(int *) RTA_DATA (tb
[RTA_OIF
]);
198 dest
= RTA_DATA (tb
[RTA_DST
]);
203 src
= RTA_DATA (tb
[RTA_PREFSRC
]);
206 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
208 if (tb
[RTA_PRIORITY
])
209 metric
= *(int *) RTA_DATA(tb
[RTA_PRIORITY
]);
213 struct rtattr
*mxrta
[RTAX_MAX
+1];
215 memset (mxrta
, 0, sizeof mxrta
);
216 netlink_parse_rtattr (mxrta
, RTAX_MAX
, RTA_DATA(tb
[RTA_METRICS
]),
217 RTA_PAYLOAD(tb
[RTA_METRICS
]));
220 mtu
= *(u_int32_t
*) RTA_DATA(mxrta
[RTAX_MTU
]);
223 if (rtm
->rtm_family
== AF_INET
)
226 memcpy (&p
.u
.prefix4
, dest
, 4);
227 p
.prefixlen
= rtm
->rtm_dst_len
;
229 if (!tb
[RTA_MULTIPATH
])
230 rib_add (AFI_IP
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
231 0, flags
, &p
, gate
, src
, index
,
232 table
, metric
, mtu
, 0);
235 /* This is a multipath route */
238 struct rtnexthop
*rtnh
=
239 (struct rtnexthop
*) RTA_DATA (tb
[RTA_MULTIPATH
]);
241 len
= RTA_PAYLOAD (tb
[RTA_MULTIPATH
]);
243 rib
= XCALLOC (MTYPE_RIB
, sizeof (struct rib
));
244 rib
->type
= ZEBRA_ROUTE_KERNEL
;
247 rib
->metric
= metric
;
249 rib
->vrf_id
= vrf_id
;
251 rib
->nexthop_num
= 0;
252 rib
->uptime
= time (NULL
);
256 if (len
< (int) sizeof (*rtnh
) || rtnh
->rtnh_len
> len
)
259 index
= rtnh
->rtnh_ifindex
;
261 if (rtnh
->rtnh_len
> sizeof (*rtnh
))
263 memset (tb
, 0, sizeof (tb
));
264 netlink_parse_rtattr (tb
, RTA_MAX
, RTNH_DATA (rtnh
),
265 rtnh
->rtnh_len
- sizeof (*rtnh
));
267 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
273 rib_nexthop_ipv4_ifindex_add (rib
, gate
, src
, index
);
275 rib_nexthop_ipv4_add (rib
, gate
, src
);
278 rib_nexthop_ifindex_add (rib
, index
);
280 len
-= NLMSG_ALIGN(rtnh
->rtnh_len
);
281 rtnh
= RTNH_NEXT(rtnh
);
284 zserv_nexthop_num_warn(__func__
, (const struct prefix
*)&p
,
286 if (rib
->nexthop_num
== 0)
287 XFREE (MTYPE_RIB
, rib
);
289 rib_add_multipath (AFI_IP
, SAFI_UNICAST
, &p
, rib
);
292 if (rtm
->rtm_family
== AF_INET6
)
295 memcpy (&p
.u
.prefix6
, dest
, 16);
296 p
.prefixlen
= rtm
->rtm_dst_len
;
298 rib_add (AFI_IP6
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
299 0, flags
, &p
, gate
, src
, index
,
300 table
, metric
, mtu
, 0);
306 static const struct message family_str
[] = {
309 {RTNL_FAMILY_IPMR
, "ipv4MR"},
310 {RTNL_FAMILY_IP6MR
, "ipv6MR"},
314 /* Routing information change from the kernel. */
316 netlink_route_change_read_unicast (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
321 struct rtattr
*tb
[RTA_MAX
+ 1];
322 u_char zebra_flags
= 0;
324 vrf_id_t vrf_id
= VRF_DEFAULT
;
325 char anyaddr
[16] = { 0 };
336 rtm
= NLMSG_DATA (h
);
338 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
340 memset (tb
, 0, sizeof tb
);
341 netlink_parse_rtattr (tb
, RTA_MAX
, RTM_RTA (rtm
), len
);
343 if (rtm
->rtm_flags
& RTM_F_CLONED
)
345 if (rtm
->rtm_protocol
== RTPROT_REDIRECT
)
347 if (rtm
->rtm_protocol
== RTPROT_KERNEL
)
350 if (rtm
->rtm_protocol
== RTPROT_ZEBRA
&& h
->nlmsg_type
== RTM_NEWROUTE
)
352 if (rtm
->rtm_protocol
== RTPROT_ZEBRA
)
353 SET_FLAG(zebra_flags
, ZEBRA_FLAG_SELFROUTE
);
355 if (rtm
->rtm_src_len
!= 0)
357 zlog_warn ("netlink_route_change(): no src len");
361 /* Table corresponding to route. */
363 table
= *(int *) RTA_DATA (tb
[RTA_TABLE
]);
365 table
= rtm
->rtm_table
;
368 vrf_id
= vrf_lookup_by_table(table
);
369 if (vrf_id
== VRF_DEFAULT
)
371 if (!is_zebra_valid_kernel_table(table
) &&
372 !is_zebra_main_routing_table(table
))
383 index
= *(int *) RTA_DATA (tb
[RTA_OIF
]);
386 dest
= RTA_DATA (tb
[RTA_DST
]);
391 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
394 src
= RTA_DATA (tb
[RTA_PREFSRC
]);
396 if (h
->nlmsg_type
== RTM_NEWROUTE
)
398 if (tb
[RTA_PRIORITY
])
399 metric
= *(int *) RTA_DATA(tb
[RTA_PRIORITY
]);
403 struct rtattr
*mxrta
[RTAX_MAX
+1];
405 memset (mxrta
, 0, sizeof mxrta
);
406 netlink_parse_rtattr (mxrta
, RTAX_MAX
, RTA_DATA(tb
[RTA_METRICS
]),
407 RTA_PAYLOAD(tb
[RTA_METRICS
]));
410 mtu
= *(u_int32_t
*) RTA_DATA(mxrta
[RTAX_MTU
]);
414 if (rtm
->rtm_family
== AF_INET
)
417 memcpy (&p
.u
.prefix4
, dest
, 4);
418 p
.prefixlen
= rtm
->rtm_dst_len
;
420 if (IS_ZEBRA_DEBUG_KERNEL
)
422 char buf
[PREFIX_STRLEN
];
423 zlog_debug ("%s %s vrf %u",
424 h
->nlmsg_type
== RTM_NEWROUTE
? "RTM_NEWROUTE" : "RTM_DELROUTE",
425 prefix2str (&p
, buf
, sizeof(buf
)), vrf_id
);
428 if (h
->nlmsg_type
== RTM_NEWROUTE
)
430 if (!tb
[RTA_MULTIPATH
])
431 rib_add (AFI_IP
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
432 0, 0, &p
, gate
, src
, index
,
433 table
, metric
, mtu
, 0);
436 /* This is a multipath route */
439 struct rtnexthop
*rtnh
=
440 (struct rtnexthop
*) RTA_DATA (tb
[RTA_MULTIPATH
]);
442 len
= RTA_PAYLOAD (tb
[RTA_MULTIPATH
]);
444 rib
= XCALLOC (MTYPE_RIB
, sizeof (struct rib
));
445 rib
->type
= ZEBRA_ROUTE_KERNEL
;
448 rib
->metric
= metric
;
450 rib
->vrf_id
= vrf_id
;
452 rib
->nexthop_num
= 0;
453 rib
->uptime
= time (NULL
);
457 if (len
< (int) sizeof (*rtnh
) || rtnh
->rtnh_len
> len
)
460 index
= rtnh
->rtnh_ifindex
;
462 if (rtnh
->rtnh_len
> sizeof (*rtnh
))
464 memset (tb
, 0, sizeof (tb
));
465 netlink_parse_rtattr (tb
, RTA_MAX
, RTNH_DATA (rtnh
),
466 rtnh
->rtnh_len
- sizeof (*rtnh
));
468 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
474 rib_nexthop_ipv4_ifindex_add (rib
, gate
, src
, index
);
476 rib_nexthop_ipv4_add (rib
, gate
, src
);
479 rib_nexthop_ifindex_add (rib
, index
);
481 len
-= NLMSG_ALIGN(rtnh
->rtnh_len
);
482 rtnh
= RTNH_NEXT(rtnh
);
485 zserv_nexthop_num_warn(__func__
, (const struct prefix
*)&p
,
488 if (rib
->nexthop_num
== 0)
489 XFREE (MTYPE_RIB
, rib
);
491 rib_add_multipath (AFI_IP
, SAFI_UNICAST
, &p
, rib
);
495 rib_delete (AFI_IP
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
, 0, zebra_flags
,
496 &p
, gate
, index
, table
);
499 if (rtm
->rtm_family
== AF_INET6
)
504 memcpy (&p
.u
.prefix6
, dest
, 16);
505 p
.prefixlen
= rtm
->rtm_dst_len
;
507 if (IS_ZEBRA_DEBUG_KERNEL
)
509 char buf
[PREFIX_STRLEN
];
510 zlog_debug ("%s %s vrf %u",
511 h
->nlmsg_type
== RTM_NEWROUTE
? "RTM_NEWROUTE" : "RTM_DELROUTE",
512 prefix2str (&p
, buf
, sizeof(buf
)), vrf_id
);
515 if (h
->nlmsg_type
== RTM_NEWROUTE
)
516 rib_add (AFI_IP6
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
517 0, 0, &p
, gate
, src
, index
,
518 table
, metric
, mtu
, 0);
520 rib_delete (AFI_IP6
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
521 0, zebra_flags
, &p
, gate
, index
, table
);
528 netlink_route_change_read_multicast (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
533 struct rtattr
*tb
[RTA_MAX
+ 1];
535 rtm
= NLMSG_DATA (h
);
537 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
539 memset (tb
, 0, sizeof tb
);
540 netlink_parse_rtattr (tb
, RTA_MAX
, RTM_RTA (rtm
), len
);
546 netlink_route_change (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
550 vrf_id_t vrf_id
= ns_id
;
553 rtm
= NLMSG_DATA (h
);
555 if (!(h
->nlmsg_type
== RTM_NEWROUTE
|| h
->nlmsg_type
== RTM_DELROUTE
))
557 /* If this is not route add/delete message print warning. */
558 zlog_warn ("Kernel message: %d vrf %u\n", h
->nlmsg_type
, vrf_id
);
562 /* Connected route. */
563 if (IS_ZEBRA_DEBUG_KERNEL
)
564 zlog_debug ("%s %s %s proto %s vrf %u",
566 RTM_NEWROUTE
? "RTM_NEWROUTE" : "RTM_DELROUTE",
567 lookup (family_str
, rtm
->rtm_family
),
568 rtm
->rtm_type
== RTN_UNICAST
? "unicast" : "multicast",
569 nl_rtproto_to_str (rtm
->rtm_protocol
),
572 /* We don't care about change notifications for the MPLS table. */
573 /* TODO: Revisit this. */
574 if (rtm
->rtm_family
== AF_MPLS
)
577 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
581 switch (rtm
->rtm_type
)
584 netlink_route_change_read_unicast (snl
, h
, ns_id
);
587 netlink_route_change_read_multicast (snl
, h
, ns_id
);
597 /* Routing table read function using netlink interface. Only called
600 netlink_route_read (struct zebra_ns
*zns
)
604 /* Get IPv4 routing table. */
605 ret
= netlink_request (AF_INET
, RTM_GETROUTE
, &zns
->netlink_cmd
);
608 ret
= netlink_parse_info (netlink_routing_table
, &zns
->netlink_cmd
, zns
, 0);
613 /* Get IPv6 routing table. */
614 ret
= netlink_request (AF_INET6
, RTM_GETROUTE
, &zns
->netlink_cmd
);
617 ret
= netlink_parse_info (netlink_routing_table
, &zns
->netlink_cmd
, zns
, 0);
620 #endif /* HAVE_IPV6 */
626 _netlink_route_nl_add_gateway_info (u_char route_family
, u_char gw_family
,
627 struct nlmsghdr
*nlmsg
,
628 size_t req_size
, int bytelen
,
629 struct nexthop
*nexthop
)
631 if (route_family
== AF_MPLS
)
633 struct gw_family_t gw_fam
;
635 gw_fam
.family
= gw_family
;
636 if (gw_family
== AF_INET
)
637 memcpy (&gw_fam
.gate
.ipv4
, &nexthop
->gate
.ipv4
, bytelen
);
639 memcpy (&gw_fam
.gate
.ipv6
, &nexthop
->gate
.ipv6
, bytelen
);
640 addattr_l (nlmsg
, req_size
, RTA_VIA
, &gw_fam
.family
, bytelen
+2);
644 if (gw_family
== AF_INET
)
645 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv4
, bytelen
);
647 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv6
, bytelen
);
652 _netlink_route_rta_add_gateway_info (u_char route_family
, u_char gw_family
,
653 struct rtattr
*rta
, struct rtnexthop
*rtnh
,
654 size_t req_size
, int bytelen
,
655 struct nexthop
*nexthop
)
657 if (route_family
== AF_MPLS
)
659 struct gw_family_t gw_fam
;
661 gw_fam
.family
= gw_family
;
662 if (gw_family
== AF_INET
)
663 memcpy (&gw_fam
.gate
.ipv4
, &nexthop
->gate
.ipv4
, bytelen
);
665 memcpy (&gw_fam
.gate
.ipv6
, &nexthop
->gate
.ipv6
, bytelen
);
666 rta_addattr_l (rta
, req_size
, RTA_VIA
, &gw_fam
.family
, bytelen
+2);
667 rtnh
->rtnh_len
+= RTA_LENGTH (bytelen
+ 2);
671 if (gw_family
== AF_INET
)
672 rta_addattr_l (rta
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv4
, bytelen
);
674 rta_addattr_l (rta
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv6
, bytelen
);
675 rtnh
->rtnh_len
+= sizeof (struct rtattr
) + bytelen
;
679 /* This function takes a nexthop as argument and adds
680 * the appropriate netlink attributes to an existing
683 * @param routedesc: Human readable description of route type
684 * (direct/recursive, single-/multipath)
685 * @param bytelen: Length of addresses in bytes.
686 * @param nexthop: Nexthop information
687 * @param nlmsg: nlmsghdr structure to fill in.
688 * @param req_size: The size allocated for the message.
691 _netlink_route_build_singlepath(
692 const char *routedesc
,
694 struct nexthop
*nexthop
,
695 struct nlmsghdr
*nlmsg
,
700 struct nexthop_label
*nh_label
;
701 mpls_lse_t out_lse
[MPLS_MAX_LABELS
];
704 if (rtmsg
->rtm_family
== AF_INET
&&
705 (nexthop
->type
== NEXTHOP_TYPE_IPV6
706 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
))
708 char buf
[16] = "169.254.0.1";
709 struct in_addr ipv4_ll
;
711 inet_pton (AF_INET
, buf
, &ipv4_ll
);
712 rtmsg
->rtm_flags
|= RTNH_F_ONLINK
;
713 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &ipv4_ll
, 4);
714 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
716 if (nexthop
->rmap_src
.ipv4
.s_addr
&& (cmd
== RTM_NEWROUTE
))
717 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
718 &nexthop
->rmap_src
.ipv4
, bytelen
);
719 else if (nexthop
->src
.ipv4
.s_addr
&& (cmd
== RTM_NEWROUTE
))
720 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
721 &nexthop
->src
.ipv4
, bytelen
);
723 if (IS_ZEBRA_DEBUG_KERNEL
)
724 zlog_debug(" 5549: _netlink_route_build_singlepath() (%s): "
725 "nexthop via %s if %u",
726 routedesc
, buf
, nexthop
->ifindex
);
731 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
732 * (in the case of LER)
734 nh_label
= nexthop
->nh_label
;
735 if (rtmsg
->rtm_family
== AF_MPLS
)
738 assert (nh_label
->num_labels
== 1);
741 if (nh_label
&& nh_label
->num_labels
)
743 int i
, num_labels
= 0;
747 for (i
= 0; i
< nh_label
->num_labels
; i
++)
749 if (nh_label
->label
[i
] != MPLS_IMP_NULL_LABEL
)
751 bos
= ((i
== (nh_label
->num_labels
- 1)) ? 1 : 0);
752 out_lse
[i
] = mpls_lse_encode (nh_label
->label
[i
], 0, 0, bos
);
754 sprintf (label_buf
, "label %d", nh_label
->label
[i
]);
757 sprintf (label_buf1
, "/%d", nh_label
->label
[i
]);
758 strcat (label_buf
, label_buf1
);
765 if (rtmsg
->rtm_family
== AF_MPLS
)
766 addattr_l (nlmsg
, req_size
, RTA_NEWDST
,
767 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
771 u_int16_t encap
= LWTUNNEL_ENCAP_MPLS
;
773 addattr_l(nlmsg
, req_size
, RTA_ENCAP_TYPE
,
774 &encap
, sizeof (u_int16_t
));
775 nest
= addattr_nest(nlmsg
, req_size
, RTA_ENCAP
);
776 addattr_l (nlmsg
, req_size
, MPLS_IPTUNNEL_DST
,
777 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
778 addattr_nest_end(nlmsg
, nest
);
783 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
784 rtmsg
->rtm_flags
|= RTNH_F_ONLINK
;
786 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
787 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
789 _netlink_route_nl_add_gateway_info (rtmsg
->rtm_family
, AF_INET
, nlmsg
,
790 req_size
, bytelen
, nexthop
);
792 if (cmd
== RTM_NEWROUTE
)
794 if (nexthop
->rmap_src
.ipv4
.s_addr
)
795 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
796 &nexthop
->rmap_src
.ipv4
, bytelen
);
797 else if (nexthop
->src
.ipv4
.s_addr
)
798 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
799 &nexthop
->src
.ipv4
, bytelen
);
802 if (IS_ZEBRA_DEBUG_KERNEL
)
803 zlog_debug("netlink_route_multipath() (%s): "
804 "nexthop via %s %s if %u",
806 inet_ntoa (nexthop
->gate
.ipv4
),
807 label_buf
, nexthop
->ifindex
);
809 if (nexthop
->type
== NEXTHOP_TYPE_IPV6
810 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
812 _netlink_route_nl_add_gateway_info (rtmsg
->rtm_family
, AF_INET6
, nlmsg
,
813 req_size
, bytelen
, nexthop
);
815 if (cmd
== RTM_NEWROUTE
)
817 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
818 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
819 &nexthop
->rmap_src
.ipv6
, bytelen
);
820 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
821 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
822 &nexthop
->src
.ipv6
, bytelen
);
825 if (IS_ZEBRA_DEBUG_KERNEL
)
826 zlog_debug("netlink_route_multipath() (%s): "
827 "nexthop via %s %s if %u",
829 inet6_ntoa (nexthop
->gate
.ipv6
),
830 label_buf
, nexthop
->ifindex
);
832 if (nexthop
->type
== NEXTHOP_TYPE_IFINDEX
833 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
835 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
837 if (cmd
== RTM_NEWROUTE
)
839 if (nexthop
->rmap_src
.ipv4
.s_addr
)
840 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
841 &nexthop
->rmap_src
.ipv4
, bytelen
);
842 else if (nexthop
->src
.ipv4
.s_addr
)
843 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
844 &nexthop
->src
.ipv4
, bytelen
);
847 if (IS_ZEBRA_DEBUG_KERNEL
)
848 zlog_debug("netlink_route_multipath() (%s): "
849 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
852 if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
854 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
856 if (cmd
== RTM_NEWROUTE
)
858 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
859 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
860 &nexthop
->rmap_src
.ipv6
, bytelen
);
861 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
862 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
863 &nexthop
->src
.ipv6
, bytelen
);
866 if (IS_ZEBRA_DEBUG_KERNEL
)
867 zlog_debug("netlink_route_multipath() (%s): "
868 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
872 /* This function takes a nexthop as argument and
873 * appends to the given rtattr/rtnexthop pair the
874 * representation of the nexthop. If the nexthop
875 * defines a preferred source, the src parameter
876 * will be modified to point to that src, otherwise
877 * it will be kept unmodified.
879 * @param routedesc: Human readable description of route type
880 * (direct/recursive, single-/multipath)
881 * @param bytelen: Length of addresses in bytes.
882 * @param nexthop: Nexthop information
883 * @param rta: rtnetlink attribute structure
884 * @param rtnh: pointer to an rtnetlink nexthop structure
885 * @param src: pointer pointing to a location where
886 * the prefsrc should be stored.
889 _netlink_route_build_multipath(
890 const char *routedesc
,
892 struct nexthop
*nexthop
,
894 struct rtnexthop
*rtnh
,
898 struct nexthop_label
*nh_label
;
899 mpls_lse_t out_lse
[MPLS_MAX_LABELS
];
902 rtnh
->rtnh_len
= sizeof (*rtnh
);
903 rtnh
->rtnh_flags
= 0;
905 rta
->rta_len
+= rtnh
->rtnh_len
;
907 if (rtmsg
->rtm_family
== AF_INET
&&
908 (nexthop
->type
== NEXTHOP_TYPE_IPV6
909 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
))
911 char buf
[16] = "169.254.0.1";
912 struct in_addr ipv4_ll
;
914 inet_pton (AF_INET
, buf
, &ipv4_ll
);
916 rtnh
->rtnh_flags
|= RTNH_F_ONLINK
;
917 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTA_GATEWAY
,
919 rtnh
->rtnh_len
+= sizeof (struct rtattr
) + bytelen
;
920 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
922 if (nexthop
->rmap_src
.ipv4
.s_addr
)
923 *src
= &nexthop
->rmap_src
;
924 else if (nexthop
->src
.ipv4
.s_addr
)
925 *src
= &nexthop
->src
;
927 if (IS_ZEBRA_DEBUG_KERNEL
)
928 zlog_debug(" 5549: netlink_route_build_multipath() (%s): "
929 "nexthop via %s if %u",
930 routedesc
, buf
, nexthop
->ifindex
);
935 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
936 * (in the case of LER)
938 nh_label
= nexthop
->nh_label
;
939 if (rtmsg
->rtm_family
== AF_MPLS
)
942 assert (nh_label
->num_labels
== 1);
945 if (nh_label
&& nh_label
->num_labels
)
947 int i
, num_labels
= 0;
951 for (i
= 0; i
< nh_label
->num_labels
; i
++)
953 if (nh_label
->label
[i
] != MPLS_IMP_NULL_LABEL
)
955 bos
= ((i
== (nh_label
->num_labels
- 1)) ? 1 : 0);
956 out_lse
[i
] = mpls_lse_encode (nh_label
->label
[i
], 0, 0, bos
);
958 sprintf (label_buf
, "label %d", nh_label
->label
[i
]);
961 sprintf (label_buf1
, "/%d", nh_label
->label
[i
]);
962 strcat (label_buf
, label_buf1
);
969 if (rtmsg
->rtm_family
== AF_MPLS
)
971 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTA_NEWDST
,
972 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
973 rtnh
->rtnh_len
+= RTA_LENGTH (num_labels
* sizeof(mpls_lse_t
));
978 u_int16_t encap
= LWTUNNEL_ENCAP_MPLS
;
979 int len
= rta
->rta_len
;
981 rta_addattr_l(rta
, NL_PKT_BUF_SIZE
, RTA_ENCAP_TYPE
,
982 &encap
, sizeof (u_int16_t
));
983 nest
= rta_nest(rta
, NL_PKT_BUF_SIZE
, RTA_ENCAP
);
984 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, MPLS_IPTUNNEL_DST
,
985 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
986 rta_nest_end(rta
, nest
);
987 rtnh
->rtnh_len
+= rta
->rta_len
- len
;
992 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
993 rtnh
->rtnh_flags
|= RTNH_F_ONLINK
;
995 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
996 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
998 _netlink_route_rta_add_gateway_info (rtmsg
->rtm_family
, AF_INET
, rta
,
999 rtnh
, NL_PKT_BUF_SIZE
, bytelen
, nexthop
);
1000 if (nexthop
->rmap_src
.ipv4
.s_addr
)
1001 *src
= &nexthop
->rmap_src
;
1002 else if (nexthop
->src
.ipv4
.s_addr
)
1003 *src
= &nexthop
->src
;
1005 if (IS_ZEBRA_DEBUG_KERNEL
)
1006 zlog_debug("netlink_route_multipath() (%s): "
1007 "nexthop via %s %s if %u",
1009 inet_ntoa (nexthop
->gate
.ipv4
),
1010 label_buf
, nexthop
->ifindex
);
1012 if (nexthop
->type
== NEXTHOP_TYPE_IPV6
1013 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
1015 _netlink_route_rta_add_gateway_info (rtmsg
->rtm_family
, AF_INET6
, rta
,
1016 rtnh
, NL_PKT_BUF_SIZE
, bytelen
, nexthop
);
1018 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
1019 *src
= &nexthop
->rmap_src
;
1020 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
1021 *src
= &nexthop
->src
;
1023 if (IS_ZEBRA_DEBUG_KERNEL
)
1024 zlog_debug("netlink_route_multipath() (%s): "
1025 "nexthop via %s %s if %u",
1027 inet6_ntoa (nexthop
->gate
.ipv6
),
1028 label_buf
, nexthop
->ifindex
);
1031 if (nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
1032 || nexthop
->type
== NEXTHOP_TYPE_IFINDEX
)
1034 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
1036 if (nexthop
->rmap_src
.ipv4
.s_addr
)
1037 *src
= &nexthop
->rmap_src
;
1038 else if (nexthop
->src
.ipv4
.s_addr
)
1039 *src
= &nexthop
->src
;
1041 if (IS_ZEBRA_DEBUG_KERNEL
)
1042 zlog_debug("netlink_route_multipath() (%s): "
1043 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
1045 else if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
1047 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
1049 if (IS_ZEBRA_DEBUG_KERNEL
)
1050 zlog_debug("netlink_route_multipath() (%s): "
1051 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
1055 rtnh
->rtnh_ifindex
= 0;
1060 _netlink_mpls_build_singlepath(
1061 const char *routedesc
,
1062 zebra_nhlfe_t
*nhlfe
,
1063 struct nlmsghdr
*nlmsg
,
1064 struct rtmsg
*rtmsg
,
1071 family
= NHLFE_FAMILY (nhlfe
);
1072 bytelen
= (family
== AF_INET
? 4 : 16);
1073 _netlink_route_build_singlepath(routedesc
, bytelen
, nhlfe
->nexthop
,
1074 nlmsg
, rtmsg
, req_size
, cmd
);
1079 _netlink_mpls_build_multipath(
1080 const char *routedesc
,
1081 zebra_nhlfe_t
*nhlfe
,
1083 struct rtnexthop
*rtnh
,
1084 struct rtmsg
*rtmsg
,
1090 family
= NHLFE_FAMILY (nhlfe
);
1091 bytelen
= (family
== AF_INET
? 4 : 16);
1092 _netlink_route_build_multipath(routedesc
, bytelen
, nhlfe
->nexthop
,
1093 rta
, rtnh
, rtmsg
, src
);
1097 /* Log debug information for netlink_route_multipath
1098 * if debug logging is enabled.
1100 * @param cmd: Netlink command which is to be processed
1101 * @param p: Prefix for which the change is due
1102 * @param nexthop: Nexthop which is currently processed
1103 * @param routedesc: Semantic annotation for nexthop
1104 * (recursive, multipath, etc.)
1105 * @param family: Address family which the change concerns
1108 _netlink_route_debug(
1111 struct nexthop
*nexthop
,
1112 const char *routedesc
,
1114 struct zebra_vrf
*zvrf
)
1116 if (IS_ZEBRA_DEBUG_KERNEL
)
1118 char buf
[PREFIX_STRLEN
];
1119 zlog_debug ("netlink_route_multipath() (%s): %s %s vrf %u type %s",
1121 nl_msg_type_to_str (cmd
),
1122 prefix2str (p
, buf
, sizeof(buf
)), zvrf_id (zvrf
),
1123 (nexthop
) ? nexthop_type_to_str (nexthop
->type
) : "UNK");
1128 _netlink_mpls_debug(
1131 const char *routedesc
)
1133 if (IS_ZEBRA_DEBUG_KERNEL
)
1134 zlog_debug ("netlink_mpls_multipath() (%s): %s %u/20",
1135 routedesc
, nl_msg_type_to_str (cmd
), label
);
1139 netlink_neigh_update (int cmd
, int ifindex
, uint32_t addr
, char *lla
, int llalen
)
1147 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1149 memset(&req
.n
, 0, sizeof(req
.n
));
1150 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
1152 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ndmsg
));
1153 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1154 req
.n
.nlmsg_type
= cmd
; //RTM_NEWNEIGH or RTM_DELNEIGH
1155 req
.ndm
.ndm_family
= AF_INET
;
1156 req
.ndm
.ndm_state
= NUD_PERMANENT
;
1157 req
.ndm
.ndm_ifindex
= ifindex
;
1158 req
.ndm
.ndm_type
= RTN_UNICAST
;
1160 addattr_l(&req
.n
, sizeof(req
), NDA_DST
, &addr
, 4);
1161 addattr_l(&req
.n
, sizeof(req
), NDA_LLADDR
, lla
, llalen
);
1163 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
);
1166 /* Routing table change via netlink interface. */
1167 /* Update flag indicates whether this is a "replace" or not. */
1169 netlink_route_multipath (int cmd
, struct prefix
*p
, struct rib
*rib
,
1173 struct sockaddr_nl snl
;
1174 struct nexthop
*nexthop
= NULL
, *tnexthop
;
1178 int family
= PREFIX_FAMILY(p
);
1179 const char *routedesc
;
1187 char buf
[NL_PKT_BUF_SIZE
];
1190 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1191 struct zebra_vrf
*zvrf
= vrf_info_lookup (rib
->vrf_id
);
1193 memset (&req
, 0, sizeof req
- NL_PKT_BUF_SIZE
);
1195 bytelen
= (family
== AF_INET
? 4 : 16);
1197 req
.n
.nlmsg_len
= NLMSG_LENGTH (sizeof (struct rtmsg
));
1198 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1199 if ((cmd
== RTM_NEWROUTE
) && update
)
1200 req
.n
.nlmsg_flags
|= NLM_F_REPLACE
;
1201 req
.n
.nlmsg_type
= cmd
;
1202 req
.r
.rtm_family
= family
;
1203 req
.r
.rtm_dst_len
= p
->prefixlen
;
1204 req
.r
.rtm_protocol
= RTPROT_ZEBRA
;
1205 req
.r
.rtm_scope
= RT_SCOPE_UNIVERSE
;
1207 if ((rib
->flags
& ZEBRA_FLAG_BLACKHOLE
) || (rib
->flags
& ZEBRA_FLAG_REJECT
))
1212 if (cmd
== RTM_NEWROUTE
)
1216 if (rib
->flags
& ZEBRA_FLAG_BLACKHOLE
)
1217 req
.r
.rtm_type
= RTN_BLACKHOLE
;
1218 else if (rib
->flags
& ZEBRA_FLAG_REJECT
)
1219 req
.r
.rtm_type
= RTN_UNREACHABLE
;
1221 assert (RTN_BLACKHOLE
!= RTN_UNREACHABLE
); /* false */
1224 req
.r
.rtm_type
= RTN_UNICAST
;
1227 addattr_l (&req
.n
, sizeof req
, RTA_DST
, &p
->u
.prefix
, bytelen
);
1230 /* Hardcode the metric for all routes coming from zebra. Metric isn't used
1231 * either by the kernel or by zebra. Its purely for calculating best path(s)
1232 * by the routing protocol and for communicating with protocol peers.
1234 addattr32 (&req
.n
, sizeof req
, RTA_PRIORITY
, NL_DEFAULT_ROUTE_METRIC
);
1236 /* Table corresponding to this route. */
1237 if (rib
->table
< 256)
1238 req
.r
.rtm_table
= rib
->table
;
1241 req
.r
.rtm_table
= RT_TABLE_UNSPEC
;
1242 addattr32(&req
.n
, sizeof req
, RTA_TABLE
, rib
->table
);
1245 if (rib
->mtu
|| rib
->nexthop_mtu
)
1247 char buf
[NL_PKT_BUF_SIZE
];
1248 struct rtattr
*rta
= (void *) buf
;
1249 u_int32_t mtu
= rib
->mtu
;
1250 if (!mtu
|| (rib
->nexthop_mtu
&& rib
->nexthop_mtu
< mtu
))
1251 mtu
= rib
->nexthop_mtu
;
1252 rta
->rta_type
= RTA_METRICS
;
1253 rta
->rta_len
= RTA_LENGTH(0);
1254 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTAX_MTU
, &mtu
, sizeof mtu
);
1255 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_METRICS
, RTA_DATA (rta
),
1261 if (cmd
== RTM_NEWROUTE
)
1262 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1264 /* We shouldn't encounter recursive nexthops on discard routes,
1265 * but it is probably better to handle that case correctly anyway.
1267 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1273 /* Count overall nexthops so we can decide whether to use singlepath
1274 * or multipath case. */
1276 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1278 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1280 if (cmd
== RTM_NEWROUTE
&& !CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1282 if (cmd
== RTM_DELROUTE
&& !CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))
1288 /* Singlepath case. */
1289 if (nexthop_num
== 1 || MULTIPATH_NUM
== 1)
1292 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1294 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1298 if (family
== AF_INET
)
1300 if (nexthop
->rmap_src
.ipv4
.s_addr
!= 0)
1302 src
.ipv4
= nexthop
->rmap_src
.ipv4
;
1305 else if (nexthop
->src
.ipv4
.s_addr
!= 0)
1307 src
.ipv4
= nexthop
->src
.ipv4
;
1311 else if (family
== AF_INET6
)
1313 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
1315 src
.ipv6
= nexthop
->rmap_src
.ipv6
;
1318 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
1320 src
.ipv6
= nexthop
->src
.ipv6
;
1328 if ((cmd
== RTM_NEWROUTE
1329 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1330 || (cmd
== RTM_DELROUTE
1331 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
)))
1333 routedesc
= recursing
? "recursive, 1 hop" : "single hop";
1335 _netlink_route_debug(cmd
, p
, nexthop
, routedesc
, family
, zvrf
);
1336 _netlink_route_build_singlepath(routedesc
, bytelen
,
1337 nexthop
, &req
.n
, &req
.r
,
1343 if (setsrc
&& (cmd
== RTM_NEWROUTE
))
1345 if (family
== AF_INET
)
1346 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv4
, bytelen
);
1347 else if (family
== AF_INET6
)
1348 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv6
, bytelen
);
1353 char buf
[NL_PKT_BUF_SIZE
];
1354 struct rtattr
*rta
= (void *) buf
;
1355 struct rtnexthop
*rtnh
;
1356 union g_addr
*src1
= NULL
;
1358 rta
->rta_type
= RTA_MULTIPATH
;
1359 rta
->rta_len
= RTA_LENGTH (0);
1360 rtnh
= RTA_DATA (rta
);
1363 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1365 if (nexthop_num
>= MULTIPATH_NUM
)
1368 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1370 /* This only works for IPv4 now */
1373 if (family
== AF_INET
)
1375 if (nexthop
->rmap_src
.ipv4
.s_addr
!= 0)
1377 src
.ipv4
= nexthop
->rmap_src
.ipv4
;
1380 else if (nexthop
->src
.ipv4
.s_addr
!= 0)
1382 src
.ipv4
= nexthop
->src
.ipv4
;
1386 else if (family
== AF_INET6
)
1388 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
1390 src
.ipv6
= nexthop
->rmap_src
.ipv6
;
1393 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
1395 src
.ipv6
= nexthop
->src
.ipv6
;
1403 if ((cmd
== RTM_NEWROUTE
1404 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1405 || (cmd
== RTM_DELROUTE
1406 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
)))
1408 routedesc
= recursing
? "recursive, multihop" : "multihop";
1411 _netlink_route_debug(cmd
, p
, nexthop
,
1412 routedesc
, family
, zvrf
);
1413 _netlink_route_build_multipath(routedesc
, bytelen
,
1414 nexthop
, rta
, rtnh
, &req
.r
, &src1
);
1415 rtnh
= RTNH_NEXT (rtnh
);
1417 if (!setsrc
&& src1
)
1419 if (family
== AF_INET
)
1420 src
.ipv4
= src1
->ipv4
;
1421 else if (family
== AF_INET6
)
1422 src
.ipv6
= src1
->ipv6
;
1428 if (setsrc
&& (cmd
== RTM_NEWROUTE
))
1430 if (family
== AF_INET
)
1431 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv4
, bytelen
);
1432 else if (family
== AF_INET6
)
1433 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv6
, bytelen
);
1434 if (IS_ZEBRA_DEBUG_KERNEL
)
1435 zlog_debug("Setting source");
1438 if (rta
->rta_len
> RTA_LENGTH (0))
1439 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_MULTIPATH
, RTA_DATA (rta
),
1443 /* If there is no useful nexthop then return. */
1444 if (nexthop_num
== 0)
1446 if (IS_ZEBRA_DEBUG_KERNEL
)
1447 zlog_debug ("netlink_route_multipath(): No useful nexthop.");
1453 /* Destination netlink address. */
1454 memset (&snl
, 0, sizeof snl
);
1455 snl
.nl_family
= AF_NETLINK
;
1457 /* Talk to netlink socket. */
1458 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
);
1462 kernel_route_rib (struct prefix
*p
, struct rib
*old
, struct rib
*new)
1465 return netlink_route_multipath (RTM_NEWROUTE
, p
, new, 0);
1467 return netlink_route_multipath (RTM_DELROUTE
, p
, old
, 0);
1469 return netlink_route_multipath (RTM_NEWROUTE
, p
, new, 1);
1473 kernel_neigh_update (int add
, int ifindex
, uint32_t addr
, char *lla
, int llalen
)
1475 return netlink_neigh_update(add
? RTM_NEWNEIGH
: RTM_DELNEIGH
, ifindex
, addr
,
1480 * MPLS label forwarding table change via netlink interface.
1483 netlink_mpls_multipath (int cmd
, zebra_lsp_t
*lsp
)
1486 zebra_nhlfe_t
*nhlfe
;
1487 struct nexthop
*nexthop
= NULL
;
1489 const char *routedesc
;
1490 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1496 char buf
[NL_PKT_BUF_SIZE
];
1499 memset (&req
, 0, sizeof req
- NL_PKT_BUF_SIZE
);
1503 * Count # nexthops so we can decide whether to use singlepath
1504 * or multipath case.
1507 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1509 nexthop
= nhlfe
->nexthop
;
1512 if (cmd
== RTM_NEWROUTE
)
1514 /* Count all selected NHLFEs */
1515 if (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
1516 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1521 /* Count all installed NHLFEs */
1522 if (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
1523 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))
1528 if (nexthop_num
== 0) // unexpected
1531 req
.n
.nlmsg_len
= NLMSG_LENGTH (sizeof (struct rtmsg
));
1532 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1533 req
.n
.nlmsg_type
= cmd
;
1534 req
.r
.rtm_family
= AF_MPLS
;
1535 req
.r
.rtm_table
= RT_TABLE_MAIN
;
1536 req
.r
.rtm_dst_len
= MPLS_LABEL_LEN_BITS
;
1537 req
.r
.rtm_protocol
= RTPROT_ZEBRA
;
1538 req
.r
.rtm_scope
= RT_SCOPE_UNIVERSE
;
1539 req
.r
.rtm_type
= RTN_UNICAST
;
1541 if (cmd
== RTM_NEWROUTE
)
1542 /* We do a replace to handle update. */
1543 req
.n
.nlmsg_flags
|= NLM_F_REPLACE
;
1545 /* Fill destination */
1546 lse
= mpls_lse_encode (lsp
->ile
.in_label
, 0, 0, 1);
1547 addattr_l (&req
.n
, sizeof req
, RTA_DST
, &lse
, sizeof(mpls_lse_t
));
1549 /* Fill nexthops (paths) based on single-path or multipath. The paths
1550 * chosen depend on the operation.
1552 if (nexthop_num
== 1 || MULTIPATH_NUM
== 1)
1554 routedesc
= "single hop";
1555 _netlink_mpls_debug(cmd
, lsp
->ile
.in_label
, routedesc
);
1558 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1560 nexthop
= nhlfe
->nexthop
;
1564 if ((cmd
== RTM_NEWROUTE
&&
1565 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
1566 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))) ||
1567 (cmd
== RTM_DELROUTE
&&
1568 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
1569 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))))
1571 /* Add the gateway */
1572 _netlink_mpls_build_singlepath(routedesc
, nhlfe
,
1573 &req
.n
, &req
.r
, sizeof req
, cmd
);
1574 if (cmd
== RTM_NEWROUTE
)
1576 SET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1577 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1581 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1582 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1589 else /* Multipath case */
1591 char buf
[NL_PKT_BUF_SIZE
];
1592 struct rtattr
*rta
= (void *) buf
;
1593 struct rtnexthop
*rtnh
;
1594 union g_addr
*src1
= NULL
;
1596 rta
->rta_type
= RTA_MULTIPATH
;
1597 rta
->rta_len
= RTA_LENGTH (0);
1598 rtnh
= RTA_DATA (rta
);
1600 routedesc
= "multihop";
1601 _netlink_mpls_debug(cmd
, lsp
->ile
.in_label
, routedesc
);
1604 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1606 nexthop
= nhlfe
->nexthop
;
1610 if (MULTIPATH_NUM
!= 0 && nexthop_num
>= MULTIPATH_NUM
)
1613 if ((cmd
== RTM_NEWROUTE
&&
1614 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
1615 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))) ||
1616 (cmd
== RTM_DELROUTE
&&
1617 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
1618 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))))
1622 /* Build the multipath */
1623 _netlink_mpls_build_multipath(routedesc
, nhlfe
, rta
,
1624 rtnh
, &req
.r
, &src1
);
1625 rtnh
= RTNH_NEXT (rtnh
);
1627 if (cmd
== RTM_NEWROUTE
)
1629 SET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1630 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1634 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1635 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1641 /* Add the multipath */
1642 if (rta
->rta_len
> RTA_LENGTH (0))
1643 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_MULTIPATH
, RTA_DATA (rta
),
1647 /* Talk to netlink socket. */
1648 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
);
1652 * Handle failure in LSP install, clear flags for NHLFE.
1655 clear_nhlfe_installed (zebra_lsp_t
*lsp
)
1657 zebra_nhlfe_t
*nhlfe
;
1658 struct nexthop
*nexthop
;
1660 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1662 nexthop
= nhlfe
->nexthop
;
1666 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1667 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);