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
22 #include <net/if_arp.h>
24 /* Hack for GNU libc version 2. */
26 #define MSG_TRUNC 0x20
27 #endif /* MSG_TRUNC */
33 #include "connected.h"
36 #include "zebra_memory.h"
45 #include "zebra/zserv.h"
46 #include "zebra/zebra_ns.h"
47 #include "zebra/zebra_vrf.h"
49 #include "zebra/redistribute.h"
50 #include "zebra/interface.h"
51 #include "zebra/debug.h"
52 #include "zebra/rtadv.h"
53 #include "zebra/zebra_ptm.h"
54 #include "zebra/zebra_mpls.h"
55 #include "zebra/kernel_netlink.h"
56 #include "zebra/rt_netlink.h"
57 #include "zebra/zebra_mroute.h"
60 /* TODO - Temporary definitions, need to refine. */
73 #ifndef RTA_ENCAP_TYPE
74 #define RTA_ENCAP_TYPE 21
82 #define RTA_EXPIRES 23
85 #ifndef LWTUNNEL_ENCAP_MPLS
86 #define LWTUNNEL_ENCAP_MPLS 1
89 #ifndef MPLS_IPTUNNEL_DST
90 #define MPLS_IPTUNNEL_DST 1
96 /* End of temporary definitions */
105 char ipv4_ll_buf
[16] = "169.254.0.1";
106 struct in_addr ipv4_ll
;
109 * The ipv4_ll data structure is used for all 5549
110 * additions to the kernel. Let's figure out the
111 * correct value one time instead for every
112 * install/remove of a 5549 type route
115 rt_netlink_init (void)
117 inet_pton (AF_INET
, ipv4_ll_buf
, &ipv4_ll
);
120 static inline int is_selfroute(int proto
)
122 if ((proto
== RTPROT_BGP
) || (proto
== RTPROT_OSPF
) ||
123 (proto
== RTPROT_STATIC
) || (proto
== RTPROT_ZEBRA
) ||
124 (proto
== RTPROT_ISIS
) || (proto
== RTPROT_RIPNG
) ||
125 (proto
== RTPROT_NHRP
) || (proto
== RTPROT_EIGRP
) ||
126 (proto
== RTPROT_LDP
) || (proto
== RTPROT_BABEL
)) {
133 static inline int get_rt_proto(int proto
)
136 case ZEBRA_ROUTE_BABEL
:
137 proto
= RTPROT_BABEL
;
139 case ZEBRA_ROUTE_BGP
:
142 case ZEBRA_ROUTE_OSPF
:
143 case ZEBRA_ROUTE_OSPF6
:
146 case ZEBRA_ROUTE_STATIC
:
147 proto
= RTPROT_STATIC
;
149 case ZEBRA_ROUTE_ISIS
:
152 case ZEBRA_ROUTE_RIP
:
155 case ZEBRA_ROUTE_RIPNG
:
156 proto
= RTPROT_RIPNG
;
158 case ZEBRA_ROUTE_NHRP
:
161 case ZEBRA_ROUTE_EIGRP
:
162 proto
= RTPROT_EIGRP
;
164 case ZEBRA_ROUTE_LDP
:
168 proto
= RTPROT_ZEBRA
;
176 Pending: create an efficient table_id (in a tree/hash) based lookup)
179 vrf_lookup_by_table (u_int32_t table_id
)
182 struct zebra_vrf
*zvrf
;
184 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
186 if ((zvrf
= vrf
->info
) == NULL
||
187 (zvrf
->table_id
!= table_id
))
190 return zvrf_id (zvrf
);
196 /* Looking up routing table by netlink interface. */
198 netlink_route_change_read_unicast (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
199 ns_id_t ns_id
, int startup
)
203 struct rtattr
*tb
[RTA_MAX
+ 1];
206 struct prefix_ipv6 src_p
;
207 vrf_id_t vrf_id
= VRF_DEFAULT
;
209 char anyaddr
[16] = { 0 };
218 void *prefsrc
= NULL
; /* IPv4 preferred source host address */
219 void *src
= NULL
; /* IPv6 srcdest source prefix */
221 rtm
= NLMSG_DATA (h
);
223 if (startup
&& h
->nlmsg_type
!= RTM_NEWROUTE
)
225 if (startup
&& rtm
->rtm_type
!= RTN_UNICAST
)
228 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
232 memset (tb
, 0, sizeof tb
);
233 netlink_parse_rtattr (tb
, RTA_MAX
, RTM_RTA (rtm
), len
);
235 if (rtm
->rtm_flags
& RTM_F_CLONED
)
237 if (rtm
->rtm_protocol
== RTPROT_REDIRECT
)
239 if (rtm
->rtm_protocol
== RTPROT_KERNEL
)
243 is_selfroute (rtm
->rtm_protocol
) &&
244 h
->nlmsg_type
== RTM_NEWROUTE
)
247 /* We don't care about change notifications for the MPLS table. */
248 /* TODO: Revisit this. */
249 if (rtm
->rtm_family
== AF_MPLS
)
252 /* Table corresponding to route. */
254 table
= *(int *) RTA_DATA (tb
[RTA_TABLE
]);
256 table
= rtm
->rtm_table
;
259 vrf_id
= vrf_lookup_by_table(table
);
260 if (vrf_id
== VRF_DEFAULT
)
262 if (!is_zebra_valid_kernel_table(table
) &&
263 !is_zebra_main_routing_table(table
))
267 /* Route which inserted by Zebra. */
268 if (is_selfroute(rtm
->rtm_protocol
))
269 flags
|= ZEBRA_FLAG_SELFROUTE
;
272 index
= *(int *) RTA_DATA (tb
[RTA_OIF
]);
275 dest
= RTA_DATA (tb
[RTA_DST
]);
280 src
= RTA_DATA (tb
[RTA_SRC
]);
285 prefsrc
= RTA_DATA (tb
[RTA_PREFSRC
]);
288 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
290 if (h
->nlmsg_type
== RTM_NEWROUTE
)
292 if (tb
[RTA_PRIORITY
])
293 metric
= *(int *) RTA_DATA(tb
[RTA_PRIORITY
]);
297 struct rtattr
*mxrta
[RTAX_MAX
+1];
299 memset (mxrta
, 0, sizeof mxrta
);
300 netlink_parse_rtattr (mxrta
, RTAX_MAX
, RTA_DATA(tb
[RTA_METRICS
]),
301 RTA_PAYLOAD(tb
[RTA_METRICS
]));
304 mtu
= *(u_int32_t
*) RTA_DATA(mxrta
[RTAX_MTU
]);
308 if (rtm
->rtm_family
== AF_INET
)
311 memcpy (&p
.u
.prefix4
, dest
, 4);
312 p
.prefixlen
= rtm
->rtm_dst_len
;
314 src_p
.prefixlen
= 0; // Forces debug below to not display anything
316 else if (rtm
->rtm_family
== AF_INET6
)
319 memcpy (&p
.u
.prefix6
, dest
, 16);
320 p
.prefixlen
= rtm
->rtm_dst_len
;
322 src_p
.family
= AF_INET6
;
323 memcpy (&src_p
.prefix
, src
, 16);
324 src_p
.prefixlen
= rtm
->rtm_src_len
;
327 if (rtm
->rtm_src_len
!= 0)
329 char buf
[PREFIX_STRLEN
];
330 zlog_warn ("unsupported IPv[4|6] sourcedest route (dest %s vrf %u)",
331 prefix2str (&p
, buf
, sizeof(buf
)), vrf_id
);
335 if (IS_ZEBRA_DEBUG_KERNEL
)
337 char buf
[PREFIX_STRLEN
];
338 char buf2
[PREFIX_STRLEN
];
339 zlog_debug ("%s %s%s%s vrf %u",
340 nl_msg_type_to_str (h
->nlmsg_type
),
341 prefix2str (&p
, buf
, sizeof(buf
)),
342 src_p
.prefixlen
? " from " : "",
343 src_p
.prefixlen
? prefix2str(&src_p
, buf2
, sizeof(buf2
)) : "",
348 if (rtm
->rtm_family
== AF_INET6
)
351 if (h
->nlmsg_type
== RTM_NEWROUTE
)
353 if (!tb
[RTA_MULTIPATH
])
354 rib_add (afi
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
355 0, flags
, &p
, NULL
, gate
, prefsrc
, index
,
356 table
, metric
, mtu
, 0);
359 /* This is a multipath route */
361 struct route_entry
*re
;
362 struct rtnexthop
*rtnh
=
363 (struct rtnexthop
*) RTA_DATA (tb
[RTA_MULTIPATH
]);
365 len
= RTA_PAYLOAD (tb
[RTA_MULTIPATH
]);
367 re
= XCALLOC (MTYPE_RE
, sizeof (struct route_entry
));
368 re
->type
= ZEBRA_ROUTE_KERNEL
;
376 re
->uptime
= time (NULL
);
380 if (len
< (int) sizeof (*rtnh
) || rtnh
->rtnh_len
> len
)
383 index
= rtnh
->rtnh_ifindex
;
385 if (rtnh
->rtnh_len
> sizeof (*rtnh
))
387 memset (tb
, 0, sizeof (tb
));
388 netlink_parse_rtattr (tb
, RTA_MAX
, RTNH_DATA (rtnh
),
389 rtnh
->rtnh_len
- sizeof (*rtnh
));
391 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
396 if (rtm
->rtm_family
== AF_INET
)
399 route_entry_nexthop_ipv4_ifindex_add (re
, gate
, prefsrc
, index
);
401 route_entry_nexthop_ipv4_add (re
, gate
, prefsrc
);
403 else if (rtm
->rtm_family
== AF_INET6
)
406 route_entry_nexthop_ipv6_ifindex_add (re
, gate
, index
);
408 route_entry_nexthop_ipv6_add (re
,gate
);
412 route_entry_nexthop_ifindex_add (re
, index
);
414 len
-= NLMSG_ALIGN(rtnh
->rtnh_len
);
415 rtnh
= RTNH_NEXT(rtnh
);
418 zserv_nexthop_num_warn(__func__
, (const struct prefix
*)&p
,
420 if (re
->nexthop_num
== 0)
421 XFREE (MTYPE_RE
, re
);
423 rib_add_multipath (AFI_IP
, SAFI_UNICAST
, &p
, NULL
, re
);
428 if (!tb
[RTA_MULTIPATH
])
429 rib_delete (afi
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
, 0, flags
,
430 &p
, NULL
, gate
, index
, table
);
433 struct rtnexthop
*rtnh
=
434 (struct rtnexthop
*) RTA_DATA (tb
[RTA_MULTIPATH
]);
436 len
= RTA_PAYLOAD (tb
[RTA_MULTIPATH
]);
440 if (len
< (int) sizeof (*rtnh
) || rtnh
->rtnh_len
> len
)
444 if (rtnh
->rtnh_len
> sizeof (*rtnh
))
446 memset (tb
, 0, sizeof (tb
));
447 netlink_parse_rtattr (tb
, RTA_MAX
, RTNH_DATA (rtnh
),
448 rtnh
->rtnh_len
- sizeof (*rtnh
));
450 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
454 rib_delete (afi
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
, 0, flags
,
455 &p
, NULL
, gate
, index
, table
);
457 len
-= NLMSG_ALIGN(rtnh
->rtnh_len
);
458 rtnh
= RTNH_NEXT(rtnh
);
466 static struct mcast_route_data
*mroute
= NULL
;
469 netlink_route_change_read_multicast (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
470 ns_id_t ns_id
, int startup
)
474 struct rtattr
*tb
[RTA_MAX
+ 1];
475 struct mcast_route_data
*m
;
476 struct mcast_route_data mr
;
483 char oif_list
[256] = "\0";
484 vrf_id_t vrf
= ns_id
;
490 memset (&mr
, 0, sizeof (mr
));
494 rtm
= NLMSG_DATA (h
);
496 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
498 memset (tb
, 0, sizeof tb
);
499 netlink_parse_rtattr (tb
, RTA_MAX
, RTM_RTA (rtm
), len
);
502 iif
= *(int *)RTA_DATA (tb
[RTA_IIF
]);
505 m
->sg
.src
= *(struct in_addr
*)RTA_DATA (tb
[RTA_SRC
]);
508 m
->sg
.grp
= *(struct in_addr
*)RTA_DATA (tb
[RTA_DST
]);
510 if ((RTA_EXPIRES
<= RTA_MAX
) && tb
[RTA_EXPIRES
])
511 m
->lastused
= *(unsigned long long *)RTA_DATA (tb
[RTA_EXPIRES
]);
513 if (tb
[RTA_MULTIPATH
])
515 struct rtnexthop
*rtnh
=
516 (struct rtnexthop
*)RTA_DATA (tb
[RTA_MULTIPATH
]);
518 len
= RTA_PAYLOAD (tb
[RTA_MULTIPATH
]);
521 if (len
< (int) sizeof (*rtnh
) || rtnh
->rtnh_len
> len
)
524 oif
[oif_count
] = rtnh
->rtnh_ifindex
;
527 len
-= NLMSG_ALIGN (rtnh
->rtnh_len
);
528 rtnh
= RTNH_NEXT (rtnh
);
532 if (IS_ZEBRA_DEBUG_KERNEL
)
534 struct interface
*ifp
;
535 strcpy (sbuf
, inet_ntoa (m
->sg
.src
));
536 strcpy (gbuf
, inet_ntoa (m
->sg
.grp
));
537 for (count
= 0; count
< oif_count
; count
++)
539 ifp
= if_lookup_by_index (oif
[count
], vrf
);
542 sprintf (temp
, "%s ", ifp
->name
);
543 strcat (oif_list
, temp
);
545 ifp
= if_lookup_by_index (iif
, vrf
);
546 zlog_debug ("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld",
547 nl_msg_type_to_str(h
->nlmsg_type
), sbuf
, gbuf
, ifp
->name
, oif_list
, m
->lastused
);
553 netlink_route_change (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
554 ns_id_t ns_id
, int startup
)
557 vrf_id_t vrf_id
= ns_id
;
560 rtm
= NLMSG_DATA (h
);
562 if (!(h
->nlmsg_type
== RTM_NEWROUTE
|| h
->nlmsg_type
== RTM_DELROUTE
))
564 /* If this is not route add/delete message print warning. */
565 zlog_warn ("Kernel message: %d vrf %u\n", h
->nlmsg_type
, vrf_id
);
569 /* Connected route. */
570 if (IS_ZEBRA_DEBUG_KERNEL
)
571 zlog_debug ("%s %s %s proto %s vrf %u",
572 nl_msg_type_to_str (h
->nlmsg_type
),
573 nl_family_to_str (rtm
->rtm_family
),
574 nl_rttype_to_str (rtm
->rtm_type
),
575 nl_rtproto_to_str (rtm
->rtm_protocol
),
578 /* We don't care about change notifications for the MPLS table. */
579 /* TODO: Revisit this. */
580 if (rtm
->rtm_family
== AF_MPLS
)
583 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
587 switch (rtm
->rtm_type
)
590 netlink_route_change_read_unicast (snl
, h
, ns_id
, startup
);
593 netlink_route_change_read_multicast (snl
, h
, ns_id
, startup
);
603 /* Routing table read function using netlink interface. Only called
606 netlink_route_read (struct zebra_ns
*zns
)
610 /* Get IPv4 routing table. */
611 ret
= netlink_request (AF_INET
, RTM_GETROUTE
, &zns
->netlink_cmd
);
614 ret
= netlink_parse_info (netlink_route_change_read_unicast
, &zns
->netlink_cmd
, zns
, 0, 1);
618 /* Get IPv6 routing table. */
619 ret
= netlink_request (AF_INET6
, RTM_GETROUTE
, &zns
->netlink_cmd
);
622 ret
= netlink_parse_info (netlink_route_change_read_unicast
, &zns
->netlink_cmd
, zns
, 0, 1);
630 _netlink_route_nl_add_gateway_info (u_char route_family
, u_char gw_family
,
631 struct nlmsghdr
*nlmsg
,
632 size_t req_size
, int bytelen
,
633 struct nexthop
*nexthop
)
635 if (route_family
== AF_MPLS
)
637 struct gw_family_t gw_fam
;
639 gw_fam
.family
= gw_family
;
640 if (gw_family
== AF_INET
)
641 memcpy (&gw_fam
.gate
.ipv4
, &nexthop
->gate
.ipv4
, bytelen
);
643 memcpy (&gw_fam
.gate
.ipv6
, &nexthop
->gate
.ipv6
, bytelen
);
644 addattr_l (nlmsg
, req_size
, RTA_VIA
, &gw_fam
.family
, bytelen
+2);
648 if (gw_family
== AF_INET
)
649 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv4
, bytelen
);
651 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv6
, bytelen
);
656 _netlink_route_rta_add_gateway_info (u_char route_family
, u_char gw_family
,
657 struct rtattr
*rta
, struct rtnexthop
*rtnh
,
658 size_t req_size
, int bytelen
,
659 struct nexthop
*nexthop
)
661 if (route_family
== AF_MPLS
)
663 struct gw_family_t gw_fam
;
665 gw_fam
.family
= gw_family
;
666 if (gw_family
== AF_INET
)
667 memcpy (&gw_fam
.gate
.ipv4
, &nexthop
->gate
.ipv4
, bytelen
);
669 memcpy (&gw_fam
.gate
.ipv6
, &nexthop
->gate
.ipv6
, bytelen
);
670 rta_addattr_l (rta
, req_size
, RTA_VIA
, &gw_fam
.family
, bytelen
+2);
671 rtnh
->rtnh_len
+= RTA_LENGTH (bytelen
+ 2);
675 if (gw_family
== AF_INET
)
676 rta_addattr_l (rta
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv4
, bytelen
);
678 rta_addattr_l (rta
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv6
, bytelen
);
679 rtnh
->rtnh_len
+= sizeof (struct rtattr
) + bytelen
;
683 /* This function takes a nexthop as argument and adds
684 * the appropriate netlink attributes to an existing
687 * @param routedesc: Human readable description of route type
688 * (direct/recursive, single-/multipath)
689 * @param bytelen: Length of addresses in bytes.
690 * @param nexthop: Nexthop information
691 * @param nlmsg: nlmsghdr structure to fill in.
692 * @param req_size: The size allocated for the message.
695 _netlink_route_build_singlepath(
696 const char *routedesc
,
698 struct nexthop
*nexthop
,
699 struct nlmsghdr
*nlmsg
,
704 struct nexthop_label
*nh_label
;
705 mpls_lse_t out_lse
[MPLS_MAX_LABELS
];
709 * label_buf is *only* currently used within debugging.
710 * As such when we assign it we are guarding it inside
711 * a debug test. If you want to change this make sure
712 * you fix this assumption
715 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
716 * (in the case of LER)
718 nh_label
= nexthop
->nh_label
;
719 if (rtmsg
->rtm_family
== AF_MPLS
)
722 assert (nh_label
->num_labels
== 1);
725 if (nh_label
&& nh_label
->num_labels
)
727 int i
, num_labels
= 0;
731 for (i
= 0; i
< nh_label
->num_labels
; i
++)
733 if (nh_label
->label
[i
] != MPLS_IMP_NULL_LABEL
)
735 bos
= ((i
== (nh_label
->num_labels
- 1)) ? 1 : 0);
736 out_lse
[i
] = mpls_lse_encode (nh_label
->label
[i
], 0, 0, bos
);
737 if (IS_ZEBRA_DEBUG_KERNEL
)
740 sprintf (label_buf
, "label %d", nh_label
->label
[i
]);
743 sprintf (label_buf1
, "/%d", nh_label
->label
[i
]);
744 strcat (label_buf
, label_buf1
);
752 if (rtmsg
->rtm_family
== AF_MPLS
)
753 addattr_l (nlmsg
, req_size
, RTA_NEWDST
,
754 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
758 u_int16_t encap
= LWTUNNEL_ENCAP_MPLS
;
760 addattr_l(nlmsg
, req_size
, RTA_ENCAP_TYPE
,
761 &encap
, sizeof (u_int16_t
));
762 nest
= addattr_nest(nlmsg
, req_size
, RTA_ENCAP
);
763 addattr_l (nlmsg
, req_size
, MPLS_IPTUNNEL_DST
,
764 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
765 addattr_nest_end(nlmsg
, nest
);
770 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
771 rtmsg
->rtm_flags
|= RTNH_F_ONLINK
;
773 if (rtmsg
->rtm_family
== AF_INET
&&
774 (nexthop
->type
== NEXTHOP_TYPE_IPV6
775 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
))
777 rtmsg
->rtm_flags
|= RTNH_F_ONLINK
;
778 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &ipv4_ll
, 4);
779 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
781 if (nexthop
->rmap_src
.ipv4
.s_addr
&& (cmd
== RTM_NEWROUTE
))
782 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
783 &nexthop
->rmap_src
.ipv4
, bytelen
);
784 else if (nexthop
->src
.ipv4
.s_addr
&& (cmd
== RTM_NEWROUTE
))
785 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
786 &nexthop
->src
.ipv4
, bytelen
);
788 if (IS_ZEBRA_DEBUG_KERNEL
)
789 zlog_debug(" 5549: _netlink_route_build_singlepath() (%s): "
790 "nexthop via %s %s if %u",
791 routedesc
, ipv4_ll_buf
, label_buf
, nexthop
->ifindex
);
795 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
796 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
798 /* Send deletes to the kernel without specifying the next-hop */
799 if (cmd
!= RTM_DELROUTE
)
800 _netlink_route_nl_add_gateway_info (rtmsg
->rtm_family
, AF_INET
, nlmsg
,
801 req_size
, bytelen
, nexthop
);
803 if (cmd
== RTM_NEWROUTE
)
805 if (nexthop
->rmap_src
.ipv4
.s_addr
)
806 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
807 &nexthop
->rmap_src
.ipv4
, bytelen
);
808 else if (nexthop
->src
.ipv4
.s_addr
)
809 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
810 &nexthop
->src
.ipv4
, bytelen
);
813 if (IS_ZEBRA_DEBUG_KERNEL
)
814 zlog_debug("netlink_route_multipath() (%s): "
815 "nexthop via %s %s if %u",
817 inet_ntoa (nexthop
->gate
.ipv4
),
818 label_buf
, nexthop
->ifindex
);
821 if (nexthop
->type
== NEXTHOP_TYPE_IPV6
822 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
824 _netlink_route_nl_add_gateway_info (rtmsg
->rtm_family
, AF_INET6
, nlmsg
,
825 req_size
, bytelen
, nexthop
);
827 if (cmd
== RTM_NEWROUTE
)
829 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
830 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
831 &nexthop
->rmap_src
.ipv6
, bytelen
);
832 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
833 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
834 &nexthop
->src
.ipv6
, bytelen
);
837 if (IS_ZEBRA_DEBUG_KERNEL
)
838 zlog_debug("netlink_route_multipath() (%s): "
839 "nexthop via %s %s if %u",
841 inet6_ntoa (nexthop
->gate
.ipv6
),
842 label_buf
, nexthop
->ifindex
);
844 if (nexthop
->type
== NEXTHOP_TYPE_IFINDEX
845 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
847 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
849 if (cmd
== RTM_NEWROUTE
)
851 if (nexthop
->rmap_src
.ipv4
.s_addr
)
852 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
853 &nexthop
->rmap_src
.ipv4
, bytelen
);
854 else if (nexthop
->src
.ipv4
.s_addr
)
855 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
856 &nexthop
->src
.ipv4
, bytelen
);
859 if (IS_ZEBRA_DEBUG_KERNEL
)
860 zlog_debug("netlink_route_multipath() (%s): "
861 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
864 if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
866 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
868 if (cmd
== RTM_NEWROUTE
)
870 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
871 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
872 &nexthop
->rmap_src
.ipv6
, bytelen
);
873 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
874 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
875 &nexthop
->src
.ipv6
, bytelen
);
878 if (IS_ZEBRA_DEBUG_KERNEL
)
879 zlog_debug("netlink_route_multipath() (%s): "
880 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
884 /* This function takes a nexthop as argument and
885 * appends to the given rtattr/rtnexthop pair the
886 * representation of the nexthop. If the nexthop
887 * defines a preferred source, the src parameter
888 * will be modified to point to that src, otherwise
889 * it will be kept unmodified.
891 * @param routedesc: Human readable description of route type
892 * (direct/recursive, single-/multipath)
893 * @param bytelen: Length of addresses in bytes.
894 * @param nexthop: Nexthop information
895 * @param rta: rtnetlink attribute structure
896 * @param rtnh: pointer to an rtnetlink nexthop structure
897 * @param src: pointer pointing to a location where
898 * the prefsrc should be stored.
901 _netlink_route_build_multipath(
902 const char *routedesc
,
904 struct nexthop
*nexthop
,
906 struct rtnexthop
*rtnh
,
910 struct nexthop_label
*nh_label
;
911 mpls_lse_t out_lse
[MPLS_MAX_LABELS
];
914 rtnh
->rtnh_len
= sizeof (*rtnh
);
915 rtnh
->rtnh_flags
= 0;
917 rta
->rta_len
+= rtnh
->rtnh_len
;
920 * label_buf is *only* currently used within debugging.
921 * As such when we assign it we are guarding it inside
922 * a debug test. If you want to change this make sure
923 * you fix this assumption
926 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
927 * (in the case of LER)
929 nh_label
= nexthop
->nh_label
;
930 if (rtmsg
->rtm_family
== AF_MPLS
)
933 assert (nh_label
->num_labels
== 1);
936 if (nh_label
&& nh_label
->num_labels
)
938 int i
, num_labels
= 0;
942 for (i
= 0; i
< nh_label
->num_labels
; i
++)
944 if (nh_label
->label
[i
] != MPLS_IMP_NULL_LABEL
)
946 bos
= ((i
== (nh_label
->num_labels
- 1)) ? 1 : 0);
947 out_lse
[i
] = mpls_lse_encode (nh_label
->label
[i
], 0, 0, bos
);
948 if (IS_ZEBRA_DEBUG_KERNEL
)
951 sprintf (label_buf
, "label %d", nh_label
->label
[i
]);
954 sprintf (label_buf1
, "/%d", nh_label
->label
[i
]);
955 strcat (label_buf
, label_buf1
);
963 if (rtmsg
->rtm_family
== AF_MPLS
)
965 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTA_NEWDST
,
966 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
967 rtnh
->rtnh_len
+= RTA_LENGTH (num_labels
* sizeof(mpls_lse_t
));
972 u_int16_t encap
= LWTUNNEL_ENCAP_MPLS
;
973 int len
= rta
->rta_len
;
975 rta_addattr_l(rta
, NL_PKT_BUF_SIZE
, RTA_ENCAP_TYPE
,
976 &encap
, sizeof (u_int16_t
));
977 nest
= rta_nest(rta
, NL_PKT_BUF_SIZE
, RTA_ENCAP
);
978 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, MPLS_IPTUNNEL_DST
,
979 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
980 rta_nest_end(rta
, nest
);
981 rtnh
->rtnh_len
+= rta
->rta_len
- len
;
986 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
987 rtnh
->rtnh_flags
|= RTNH_F_ONLINK
;
989 if (rtmsg
->rtm_family
== AF_INET
&&
990 (nexthop
->type
== NEXTHOP_TYPE_IPV6
991 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
))
994 rtnh
->rtnh_flags
|= RTNH_F_ONLINK
;
995 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTA_GATEWAY
,
997 rtnh
->rtnh_len
+= sizeof (struct rtattr
) + bytelen
;
998 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
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(" 5549: netlink_route_build_multipath() (%s): "
1007 "nexthop via %s %s if %u",
1008 routedesc
, ipv4_ll_buf
, label_buf
, nexthop
->ifindex
);
1012 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
1013 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
1015 _netlink_route_rta_add_gateway_info (rtmsg
->rtm_family
, AF_INET
, rta
,
1016 rtnh
, NL_PKT_BUF_SIZE
, bytelen
, nexthop
);
1017 if (nexthop
->rmap_src
.ipv4
.s_addr
)
1018 *src
= &nexthop
->rmap_src
;
1019 else if (nexthop
->src
.ipv4
.s_addr
)
1020 *src
= &nexthop
->src
;
1022 if (IS_ZEBRA_DEBUG_KERNEL
)
1023 zlog_debug("netlink_route_multipath() (%s): "
1024 "nexthop via %s %s if %u",
1026 inet_ntoa (nexthop
->gate
.ipv4
),
1027 label_buf
, nexthop
->ifindex
);
1029 if (nexthop
->type
== NEXTHOP_TYPE_IPV6
1030 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
1032 _netlink_route_rta_add_gateway_info (rtmsg
->rtm_family
, AF_INET6
, rta
,
1033 rtnh
, NL_PKT_BUF_SIZE
, bytelen
, nexthop
);
1035 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
1036 *src
= &nexthop
->rmap_src
;
1037 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
1038 *src
= &nexthop
->src
;
1040 if (IS_ZEBRA_DEBUG_KERNEL
)
1041 zlog_debug("netlink_route_multipath() (%s): "
1042 "nexthop via %s %s if %u",
1044 inet6_ntoa (nexthop
->gate
.ipv6
),
1045 label_buf
, nexthop
->ifindex
);
1048 if (nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
1049 || nexthop
->type
== NEXTHOP_TYPE_IFINDEX
)
1051 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
1053 if (nexthop
->rmap_src
.ipv4
.s_addr
)
1054 *src
= &nexthop
->rmap_src
;
1055 else if (nexthop
->src
.ipv4
.s_addr
)
1056 *src
= &nexthop
->src
;
1058 if (IS_ZEBRA_DEBUG_KERNEL
)
1059 zlog_debug("netlink_route_multipath() (%s): "
1060 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
1062 else if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
1064 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
1066 if (IS_ZEBRA_DEBUG_KERNEL
)
1067 zlog_debug("netlink_route_multipath() (%s): "
1068 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
1072 rtnh
->rtnh_ifindex
= 0;
1077 _netlink_mpls_build_singlepath(
1078 const char *routedesc
,
1079 zebra_nhlfe_t
*nhlfe
,
1080 struct nlmsghdr
*nlmsg
,
1081 struct rtmsg
*rtmsg
,
1088 family
= NHLFE_FAMILY (nhlfe
);
1089 bytelen
= (family
== AF_INET
? 4 : 16);
1090 _netlink_route_build_singlepath(routedesc
, bytelen
, nhlfe
->nexthop
,
1091 nlmsg
, rtmsg
, req_size
, cmd
);
1096 _netlink_mpls_build_multipath(
1097 const char *routedesc
,
1098 zebra_nhlfe_t
*nhlfe
,
1100 struct rtnexthop
*rtnh
,
1101 struct rtmsg
*rtmsg
,
1107 family
= NHLFE_FAMILY (nhlfe
);
1108 bytelen
= (family
== AF_INET
? 4 : 16);
1109 _netlink_route_build_multipath(routedesc
, bytelen
, nhlfe
->nexthop
,
1110 rta
, rtnh
, rtmsg
, src
);
1114 /* Log debug information for netlink_route_multipath
1115 * if debug logging is enabled.
1117 * @param cmd: Netlink command which is to be processed
1118 * @param p: Prefix for which the change is due
1119 * @param nexthop: Nexthop which is currently processed
1120 * @param routedesc: Semantic annotation for nexthop
1121 * (recursive, multipath, etc.)
1122 * @param family: Address family which the change concerns
1125 _netlink_route_debug(
1128 struct nexthop
*nexthop
,
1129 const char *routedesc
,
1131 struct zebra_vrf
*zvrf
)
1133 if (IS_ZEBRA_DEBUG_KERNEL
)
1135 char buf
[PREFIX_STRLEN
];
1136 zlog_debug ("netlink_route_multipath() (%s): %s %s vrf %u type %s",
1138 nl_msg_type_to_str (cmd
),
1139 prefix2str (p
, buf
, sizeof(buf
)), zvrf_id (zvrf
),
1140 (nexthop
) ? nexthop_type_to_str (nexthop
->type
) : "UNK");
1145 _netlink_mpls_debug(
1148 const char *routedesc
)
1150 if (IS_ZEBRA_DEBUG_KERNEL
)
1151 zlog_debug ("netlink_mpls_multipath() (%s): %s %u/20",
1152 routedesc
, nl_msg_type_to_str (cmd
), label
);
1156 netlink_neigh_update (int cmd
, int ifindex
, uint32_t addr
, char *lla
, int llalen
)
1164 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1166 memset(&req
.n
, 0, sizeof(req
.n
));
1167 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
1169 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ndmsg
));
1170 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1171 req
.n
.nlmsg_type
= cmd
; //RTM_NEWNEIGH or RTM_DELNEIGH
1172 req
.n
.nlmsg_pid
= zns
->netlink_cmd
.snl
.nl_pid
;
1174 req
.ndm
.ndm_family
= AF_INET
;
1175 req
.ndm
.ndm_state
= NUD_PERMANENT
;
1176 req
.ndm
.ndm_ifindex
= ifindex
;
1177 req
.ndm
.ndm_type
= RTN_UNICAST
;
1179 addattr_l(&req
.n
, sizeof(req
), NDA_DST
, &addr
, 4);
1180 addattr_l(&req
.n
, sizeof(req
), NDA_LLADDR
, lla
, llalen
);
1182 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
, 0);
1185 /* Routing table change via netlink interface. */
1186 /* Update flag indicates whether this is a "replace" or not. */
1188 netlink_route_multipath (int cmd
, struct prefix
*p
, struct prefix
*src_p
,
1189 struct route_entry
*re
, int update
)
1192 struct sockaddr_nl snl
;
1193 struct nexthop
*nexthop
= NULL
, *tnexthop
;
1195 unsigned int nexthop_num
;
1197 int family
= PREFIX_FAMILY(p
);
1198 const char *routedesc
;
1206 char buf
[NL_PKT_BUF_SIZE
];
1209 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1210 struct zebra_vrf
*zvrf
= vrf_info_lookup (re
->vrf_id
);
1212 memset (&req
, 0, sizeof req
- NL_PKT_BUF_SIZE
);
1214 bytelen
= (family
== AF_INET
? 4 : 16);
1216 req
.n
.nlmsg_len
= NLMSG_LENGTH (sizeof (struct rtmsg
));
1217 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1218 if ((cmd
== RTM_NEWROUTE
) && update
)
1219 req
.n
.nlmsg_flags
|= NLM_F_REPLACE
;
1220 req
.n
.nlmsg_type
= cmd
;
1221 req
.n
.nlmsg_pid
= zns
->netlink_cmd
.snl
.nl_pid
;
1223 req
.r
.rtm_family
= family
;
1224 req
.r
.rtm_dst_len
= p
->prefixlen
;
1225 req
.r
.rtm_src_len
= src_p
? src_p
->prefixlen
: 0;
1226 req
.r
.rtm_protocol
= get_rt_proto(re
->type
);
1227 req
.r
.rtm_scope
= RT_SCOPE_UNIVERSE
;
1229 if ((re
->flags
& ZEBRA_FLAG_BLACKHOLE
) || (re
->flags
& ZEBRA_FLAG_REJECT
))
1234 if (cmd
== RTM_NEWROUTE
)
1238 if (re
->flags
& ZEBRA_FLAG_BLACKHOLE
)
1239 req
.r
.rtm_type
= RTN_BLACKHOLE
;
1240 else if (re
->flags
& ZEBRA_FLAG_REJECT
)
1241 req
.r
.rtm_type
= RTN_UNREACHABLE
;
1243 assert (RTN_BLACKHOLE
!= RTN_UNREACHABLE
); /* false */
1246 req
.r
.rtm_type
= RTN_UNICAST
;
1249 addattr_l (&req
.n
, sizeof req
, RTA_DST
, &p
->u
.prefix
, bytelen
);
1251 addattr_l (&req
.n
, sizeof req
, RTA_SRC
, &src_p
->u
.prefix
, bytelen
);
1254 /* Hardcode the metric for all routes coming from zebra. Metric isn't used
1255 * either by the kernel or by zebra. Its purely for calculating best path(s)
1256 * by the routing protocol and for communicating with protocol peers.
1258 addattr32 (&req
.n
, sizeof req
, RTA_PRIORITY
, NL_DEFAULT_ROUTE_METRIC
);
1260 /* Table corresponding to this route. */
1261 if (re
->table
< 256)
1262 req
.r
.rtm_table
= re
->table
;
1265 req
.r
.rtm_table
= RT_TABLE_UNSPEC
;
1266 addattr32(&req
.n
, sizeof req
, RTA_TABLE
, re
->table
);
1269 if (re
->mtu
|| re
->nexthop_mtu
)
1271 char buf
[NL_PKT_BUF_SIZE
];
1272 struct rtattr
*rta
= (void *) buf
;
1273 u_int32_t mtu
= re
->mtu
;
1274 if (!mtu
|| (re
->nexthop_mtu
&& re
->nexthop_mtu
< mtu
))
1275 mtu
= re
->nexthop_mtu
;
1276 rta
->rta_type
= RTA_METRICS
;
1277 rta
->rta_len
= RTA_LENGTH(0);
1278 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTAX_MTU
, &mtu
, sizeof mtu
);
1279 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_METRICS
, RTA_DATA (rta
),
1285 if (cmd
== RTM_NEWROUTE
)
1286 for (ALL_NEXTHOPS_RO(re
->nexthop
, nexthop
, tnexthop
, recursing
))
1288 /* We shouldn't encounter recursive nexthops on discard routes,
1289 * but it is probably better to handle that case correctly anyway.
1291 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1297 /* Count overall nexthops so we can decide whether to use singlepath
1298 * or multipath case. */
1300 for (ALL_NEXTHOPS_RO(re
->nexthop
, nexthop
, tnexthop
, recursing
))
1302 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1304 if (cmd
== RTM_NEWROUTE
&& !CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1306 if (cmd
== RTM_DELROUTE
&& !CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))
1312 /* Singlepath case. */
1313 if (nexthop_num
== 1 || multipath_num
== 1)
1316 for (ALL_NEXTHOPS_RO(re
->nexthop
, nexthop
, tnexthop
, recursing
))
1318 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1322 if (family
== AF_INET
)
1324 if (nexthop
->rmap_src
.ipv4
.s_addr
!= 0)
1326 src
.ipv4
= nexthop
->rmap_src
.ipv4
;
1329 else if (nexthop
->src
.ipv4
.s_addr
!= 0)
1331 src
.ipv4
= nexthop
->src
.ipv4
;
1335 else if (family
== AF_INET6
)
1337 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
1339 src
.ipv6
= nexthop
->rmap_src
.ipv6
;
1342 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
1344 src
.ipv6
= nexthop
->src
.ipv6
;
1352 if ((cmd
== RTM_NEWROUTE
1353 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1354 || (cmd
== RTM_DELROUTE
1355 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
)))
1357 routedesc
= recursing
? "recursive, 1 hop" : "single hop";
1359 _netlink_route_debug(cmd
, p
, nexthop
, routedesc
, family
, zvrf
);
1360 _netlink_route_build_singlepath(routedesc
, bytelen
,
1361 nexthop
, &req
.n
, &req
.r
,
1367 if (setsrc
&& (cmd
== RTM_NEWROUTE
))
1369 if (family
== AF_INET
)
1370 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv4
, bytelen
);
1371 else if (family
== AF_INET6
)
1372 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv6
, bytelen
);
1377 char buf
[NL_PKT_BUF_SIZE
];
1378 struct rtattr
*rta
= (void *) buf
;
1379 struct rtnexthop
*rtnh
;
1380 union g_addr
*src1
= NULL
;
1382 rta
->rta_type
= RTA_MULTIPATH
;
1383 rta
->rta_len
= RTA_LENGTH (0);
1384 rtnh
= RTA_DATA (rta
);
1387 for (ALL_NEXTHOPS_RO(re
->nexthop
, nexthop
, tnexthop
, recursing
))
1389 if (nexthop_num
>= multipath_num
)
1392 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1394 /* This only works for IPv4 now */
1397 if (family
== AF_INET
)
1399 if (nexthop
->rmap_src
.ipv4
.s_addr
!= 0)
1401 src
.ipv4
= nexthop
->rmap_src
.ipv4
;
1404 else if (nexthop
->src
.ipv4
.s_addr
!= 0)
1406 src
.ipv4
= nexthop
->src
.ipv4
;
1410 else if (family
== AF_INET6
)
1412 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
1414 src
.ipv6
= nexthop
->rmap_src
.ipv6
;
1417 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
1419 src
.ipv6
= nexthop
->src
.ipv6
;
1427 if ((cmd
== RTM_NEWROUTE
1428 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1429 || (cmd
== RTM_DELROUTE
1430 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
)))
1432 routedesc
= recursing
? "recursive, multihop" : "multihop";
1435 _netlink_route_debug(cmd
, p
, nexthop
,
1436 routedesc
, family
, zvrf
);
1437 _netlink_route_build_multipath(routedesc
, bytelen
,
1438 nexthop
, rta
, rtnh
, &req
.r
, &src1
);
1439 rtnh
= RTNH_NEXT (rtnh
);
1441 if (!setsrc
&& src1
)
1443 if (family
== AF_INET
)
1444 src
.ipv4
= src1
->ipv4
;
1445 else if (family
== AF_INET6
)
1446 src
.ipv6
= src1
->ipv6
;
1452 if (setsrc
&& (cmd
== RTM_NEWROUTE
))
1454 if (family
== AF_INET
)
1455 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv4
, bytelen
);
1456 else if (family
== AF_INET6
)
1457 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv6
, bytelen
);
1458 if (IS_ZEBRA_DEBUG_KERNEL
)
1459 zlog_debug("Setting source");
1462 if (rta
->rta_len
> RTA_LENGTH (0))
1463 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_MULTIPATH
, RTA_DATA (rta
),
1467 /* If there is no useful nexthop then return. */
1468 if (nexthop_num
== 0)
1470 if (IS_ZEBRA_DEBUG_KERNEL
)
1471 zlog_debug ("netlink_route_multipath(): No useful nexthop.");
1477 /* Destination netlink address. */
1478 memset (&snl
, 0, sizeof snl
);
1479 snl
.nl_family
= AF_NETLINK
;
1481 /* Talk to netlink socket. */
1482 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
, 0);
1486 kernel_get_ipmr_sg_stats (void *in
)
1489 struct mcast_route_data
*mr
= (struct mcast_route_data
*)in
;
1497 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1499 memset(&req
.n
, 0, sizeof(req
.n
));
1500 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
1502 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ndmsg
));
1503 req
.n
.nlmsg_flags
= NLM_F_REQUEST
;
1504 req
.n
.nlmsg_pid
= zns
->netlink_cmd
.snl
.nl_pid
;
1506 req
.ndm
.ndm_family
= AF_INET
;
1507 req
.n
.nlmsg_type
= RTM_GETROUTE
;
1509 addattr_l (&req
.n
, sizeof (req
), RTA_IIF
, &mroute
->ifindex
, 4);
1510 addattr_l (&req
.n
, sizeof (req
), RTA_OIF
, &mroute
->ifindex
, 4);
1511 addattr_l (&req
.n
, sizeof (req
), RTA_SRC
, &mroute
->sg
.src
.s_addr
, 4);
1512 addattr_l (&req
.n
, sizeof (req
), RTA_DST
, &mroute
->sg
.grp
.s_addr
, 4);
1514 suc
= netlink_talk (netlink_route_change_read_multicast
, &req
.n
, &zns
->netlink_cmd
, zns
, 0);
1521 kernel_route_rib (struct prefix
*p
, struct prefix
*src_p
,
1522 struct route_entry
*old
, struct route_entry
*new)
1525 return netlink_route_multipath (RTM_NEWROUTE
, p
, src_p
, new, 0);
1527 return netlink_route_multipath (RTM_DELROUTE
, p
, src_p
, old
, 0);
1529 return netlink_route_multipath (RTM_NEWROUTE
, p
, src_p
, new, 1);
1533 kernel_neigh_update (int add
, int ifindex
, uint32_t addr
, char *lla
, int llalen
)
1535 return netlink_neigh_update(add
? RTM_NEWNEIGH
: RTM_DELNEIGH
, ifindex
, addr
,
1540 * MPLS label forwarding table change via netlink interface.
1543 netlink_mpls_multipath (int cmd
, zebra_lsp_t
*lsp
)
1546 zebra_nhlfe_t
*nhlfe
;
1547 struct nexthop
*nexthop
= NULL
;
1548 unsigned int nexthop_num
;
1549 const char *routedesc
;
1550 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1556 char buf
[NL_PKT_BUF_SIZE
];
1559 memset (&req
, 0, sizeof req
- NL_PKT_BUF_SIZE
);
1563 * Count # nexthops so we can decide whether to use singlepath
1564 * or multipath case.
1567 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1569 nexthop
= nhlfe
->nexthop
;
1572 if (cmd
== RTM_NEWROUTE
)
1574 /* Count all selected NHLFEs */
1575 if (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
1576 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1581 /* Count all installed NHLFEs */
1582 if (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
1583 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))
1588 if (nexthop_num
== 0) // unexpected
1591 req
.n
.nlmsg_len
= NLMSG_LENGTH (sizeof (struct rtmsg
));
1592 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1593 req
.n
.nlmsg_type
= cmd
;
1594 req
.n
.nlmsg_pid
= zns
->netlink_cmd
.snl
.nl_pid
;
1596 req
.r
.rtm_family
= AF_MPLS
;
1597 req
.r
.rtm_table
= RT_TABLE_MAIN
;
1598 req
.r
.rtm_dst_len
= MPLS_LABEL_LEN_BITS
;
1599 req
.r
.rtm_protocol
= RTPROT_ZEBRA
;
1600 req
.r
.rtm_scope
= RT_SCOPE_UNIVERSE
;
1601 req
.r
.rtm_type
= RTN_UNICAST
;
1603 if (cmd
== RTM_NEWROUTE
)
1604 /* We do a replace to handle update. */
1605 req
.n
.nlmsg_flags
|= NLM_F_REPLACE
;
1607 /* Fill destination */
1608 lse
= mpls_lse_encode (lsp
->ile
.in_label
, 0, 0, 1);
1609 addattr_l (&req
.n
, sizeof req
, RTA_DST
, &lse
, sizeof(mpls_lse_t
));
1611 /* Fill nexthops (paths) based on single-path or multipath. The paths
1612 * chosen depend on the operation.
1614 if (nexthop_num
== 1 || multipath_num
== 1)
1616 routedesc
= "single hop";
1617 _netlink_mpls_debug(cmd
, lsp
->ile
.in_label
, routedesc
);
1620 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1622 nexthop
= nhlfe
->nexthop
;
1626 if ((cmd
== RTM_NEWROUTE
&&
1627 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
1628 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))) ||
1629 (cmd
== RTM_DELROUTE
&&
1630 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
1631 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))))
1633 /* Add the gateway */
1634 _netlink_mpls_build_singlepath(routedesc
, nhlfe
,
1635 &req
.n
, &req
.r
, sizeof req
, cmd
);
1636 if (cmd
== RTM_NEWROUTE
)
1638 SET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1639 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1643 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1644 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1651 else /* Multipath case */
1653 char buf
[NL_PKT_BUF_SIZE
];
1654 struct rtattr
*rta
= (void *) buf
;
1655 struct rtnexthop
*rtnh
;
1656 union g_addr
*src1
= NULL
;
1658 rta
->rta_type
= RTA_MULTIPATH
;
1659 rta
->rta_len
= RTA_LENGTH (0);
1660 rtnh
= RTA_DATA (rta
);
1662 routedesc
= "multihop";
1663 _netlink_mpls_debug(cmd
, lsp
->ile
.in_label
, routedesc
);
1666 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1668 nexthop
= nhlfe
->nexthop
;
1672 if (nexthop_num
>= multipath_num
)
1675 if ((cmd
== RTM_NEWROUTE
&&
1676 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
1677 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))) ||
1678 (cmd
== RTM_DELROUTE
&&
1679 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
1680 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))))
1684 /* Build the multipath */
1685 _netlink_mpls_build_multipath(routedesc
, nhlfe
, rta
,
1686 rtnh
, &req
.r
, &src1
);
1687 rtnh
= RTNH_NEXT (rtnh
);
1689 if (cmd
== RTM_NEWROUTE
)
1691 SET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1692 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1696 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1697 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1703 /* Add the multipath */
1704 if (rta
->rta_len
> RTA_LENGTH (0))
1705 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_MULTIPATH
, RTA_DATA (rta
),
1709 /* Talk to netlink socket. */
1710 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
, 0);
1714 * Handle failure in LSP install, clear flags for NHLFE.
1717 clear_nhlfe_installed (zebra_lsp_t
*lsp
)
1719 zebra_nhlfe_t
*nhlfe
;
1720 struct nexthop
*nexthop
;
1722 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1724 nexthop
= nhlfe
->nexthop
;
1728 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1729 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);