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"
58 #include "zebra/zebra_mroute.h"
61 /* TODO - Temporary definitions, need to refine. */
74 #ifndef RTA_ENCAP_TYPE
75 #define RTA_ENCAP_TYPE 21
83 #define RTA_EXPIRES 23
86 #ifndef LWTUNNEL_ENCAP_MPLS
87 #define LWTUNNEL_ENCAP_MPLS 1
90 #ifndef MPLS_IPTUNNEL_DST
91 #define MPLS_IPTUNNEL_DST 1
97 /* End of temporary definitions */
107 Pending: create an efficient table_id (in a tree/hash) based lookup)
110 vrf_lookup_by_table (u_int32_t table_id
)
113 struct zebra_vrf
*zvrf
;
115 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
117 if ((zvrf
= vrf
->info
) == NULL
||
118 (zvrf
->table_id
!= table_id
))
121 return zvrf_id (zvrf
);
127 /* Looking up routing table by netlink interface. */
129 netlink_routing_table (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
134 struct rtattr
*tb
[RTA_MAX
+ 1];
137 struct prefix_ipv6 src_p
;
138 vrf_id_t vrf_id
= VRF_DEFAULT
;
140 char anyaddr
[16] = { 0 };
149 void *prefsrc
= NULL
; /* IPv4 preferred source host address */
150 void *src
= NULL
; /* IPv6 srcdest source prefix */
152 rtm
= NLMSG_DATA (h
);
154 if (h
->nlmsg_type
!= RTM_NEWROUTE
)
156 if (rtm
->rtm_type
!= RTN_UNICAST
)
159 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
163 memset (tb
, 0, sizeof tb
);
164 netlink_parse_rtattr (tb
, RTA_MAX
, RTM_RTA (rtm
), len
);
166 if (rtm
->rtm_flags
& RTM_F_CLONED
)
168 if (rtm
->rtm_protocol
== RTPROT_REDIRECT
)
170 if (rtm
->rtm_protocol
== RTPROT_KERNEL
)
173 /* We don't care about change notifications for the MPLS table. */
174 /* TODO: Revisit this. */
175 if (rtm
->rtm_family
== AF_MPLS
)
178 /* Table corresponding to route. */
180 table
= *(int *) RTA_DATA (tb
[RTA_TABLE
]);
182 table
= rtm
->rtm_table
;
185 vrf_id
= vrf_lookup_by_table(table
);
186 if (vrf_id
== VRF_DEFAULT
)
188 if (!is_zebra_valid_kernel_table(table
) &&
189 !is_zebra_main_routing_table(table
))
193 /* Route which inserted by Zebra. */
194 if (rtm
->rtm_protocol
== RTPROT_ZEBRA
)
195 flags
|= ZEBRA_FLAG_SELFROUTE
;
198 index
= *(int *) RTA_DATA (tb
[RTA_OIF
]);
201 dest
= RTA_DATA (tb
[RTA_DST
]);
206 src
= RTA_DATA (tb
[RTA_SRC
]);
211 prefsrc
= RTA_DATA (tb
[RTA_PREFSRC
]);
214 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
216 if (tb
[RTA_PRIORITY
])
217 metric
= *(int *) RTA_DATA(tb
[RTA_PRIORITY
]);
221 struct rtattr
*mxrta
[RTAX_MAX
+1];
223 memset (mxrta
, 0, sizeof mxrta
);
224 netlink_parse_rtattr (mxrta
, RTAX_MAX
, RTA_DATA(tb
[RTA_METRICS
]),
225 RTA_PAYLOAD(tb
[RTA_METRICS
]));
228 mtu
= *(u_int32_t
*) RTA_DATA(mxrta
[RTAX_MTU
]);
231 if (rtm
->rtm_family
== AF_INET
)
234 memcpy (&p
.u
.prefix4
, dest
, 4);
235 p
.prefixlen
= rtm
->rtm_dst_len
;
237 if (rtm
->rtm_src_len
!= 0)
240 if (!tb
[RTA_MULTIPATH
])
241 rib_add (AFI_IP
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
242 0, flags
, &p
, NULL
, gate
, prefsrc
, index
,
243 table
, metric
, mtu
, 0);
246 /* This is a multipath route */
249 struct rtnexthop
*rtnh
=
250 (struct rtnexthop
*) RTA_DATA (tb
[RTA_MULTIPATH
]);
252 len
= RTA_PAYLOAD (tb
[RTA_MULTIPATH
]);
254 rib
= XCALLOC (MTYPE_RIB
, sizeof (struct rib
));
255 rib
->type
= ZEBRA_ROUTE_KERNEL
;
258 rib
->metric
= metric
;
260 rib
->vrf_id
= vrf_id
;
262 rib
->nexthop_num
= 0;
263 rib
->uptime
= time (NULL
);
267 if (len
< (int) sizeof (*rtnh
) || rtnh
->rtnh_len
> len
)
270 index
= rtnh
->rtnh_ifindex
;
272 if (rtnh
->rtnh_len
> sizeof (*rtnh
))
274 memset (tb
, 0, sizeof (tb
));
275 netlink_parse_rtattr (tb
, RTA_MAX
, RTNH_DATA (rtnh
),
276 rtnh
->rtnh_len
- sizeof (*rtnh
));
278 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
284 rib_nexthop_ipv4_ifindex_add (rib
, gate
, prefsrc
, index
);
286 rib_nexthop_ipv4_add (rib
, gate
, prefsrc
);
289 rib_nexthop_ifindex_add (rib
, index
);
291 len
-= NLMSG_ALIGN(rtnh
->rtnh_len
);
292 rtnh
= RTNH_NEXT(rtnh
);
295 zserv_nexthop_num_warn(__func__
, (const struct prefix
*)&p
,
297 if (rib
->nexthop_num
== 0)
298 XFREE (MTYPE_RIB
, rib
);
300 rib_add_multipath (AFI_IP
, SAFI_UNICAST
, &p
, NULL
, rib
);
303 if (rtm
->rtm_family
== AF_INET6
)
306 memcpy (&p
.u
.prefix6
, dest
, 16);
307 p
.prefixlen
= rtm
->rtm_dst_len
;
309 src_p
.family
= AF_INET6
;
310 memcpy (&src_p
.prefix
, src
, 16);
311 src_p
.prefixlen
= rtm
->rtm_src_len
;
313 rib_add (AFI_IP6
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
314 0, flags
, &p
, &src_p
, gate
, prefsrc
, index
,
315 table
, metric
, mtu
, 0);
321 /* Routing information change from the kernel. */
323 netlink_route_change_read_unicast (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
328 struct rtattr
*tb
[RTA_MAX
+ 1];
329 u_char zebra_flags
= 0;
331 vrf_id_t vrf_id
= VRF_DEFAULT
;
332 char anyaddr
[16] = { 0 };
341 void *prefsrc
= NULL
; /* IPv4 preferred source host address */
342 void *src
= NULL
; /* IPv6 srcdest source prefix */
344 rtm
= NLMSG_DATA (h
);
346 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
348 memset (tb
, 0, sizeof tb
);
349 netlink_parse_rtattr (tb
, RTA_MAX
, RTM_RTA (rtm
), len
);
351 if (rtm
->rtm_flags
& RTM_F_CLONED
)
353 if (rtm
->rtm_protocol
== RTPROT_REDIRECT
)
355 if (rtm
->rtm_protocol
== RTPROT_KERNEL
)
358 if (rtm
->rtm_protocol
== RTPROT_ZEBRA
&& h
->nlmsg_type
== RTM_NEWROUTE
)
360 if (rtm
->rtm_protocol
== RTPROT_ZEBRA
)
361 SET_FLAG(zebra_flags
, ZEBRA_FLAG_SELFROUTE
);
363 /* Table corresponding to route. */
365 table
= *(int *) RTA_DATA (tb
[RTA_TABLE
]);
367 table
= rtm
->rtm_table
;
370 vrf_id
= vrf_lookup_by_table(table
);
371 if (vrf_id
== VRF_DEFAULT
)
373 if (!is_zebra_valid_kernel_table(table
) &&
374 !is_zebra_main_routing_table(table
))
379 index
= *(int *) RTA_DATA (tb
[RTA_OIF
]);
382 dest
= RTA_DATA (tb
[RTA_DST
]);
387 src
= RTA_DATA (tb
[RTA_SRC
]);
392 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
395 prefsrc
= RTA_DATA (tb
[RTA_PREFSRC
]);
397 if (h
->nlmsg_type
== RTM_NEWROUTE
)
399 if (tb
[RTA_PRIORITY
])
400 metric
= *(int *) RTA_DATA(tb
[RTA_PRIORITY
]);
404 struct rtattr
*mxrta
[RTAX_MAX
+1];
406 memset (mxrta
, 0, sizeof mxrta
);
407 netlink_parse_rtattr (mxrta
, RTAX_MAX
, RTA_DATA(tb
[RTA_METRICS
]),
408 RTA_PAYLOAD(tb
[RTA_METRICS
]));
411 mtu
= *(u_int32_t
*) RTA_DATA(mxrta
[RTAX_MTU
]);
415 if (rtm
->rtm_family
== AF_INET
)
418 memcpy (&p
.u
.prefix4
, dest
, 4);
419 p
.prefixlen
= rtm
->rtm_dst_len
;
421 if (rtm
->rtm_src_len
!= 0)
423 zlog_warn ("unsupported IPv4 sourcedest route (dest %s/%d)",
424 inet_ntoa (p
.u
.prefix4
), p
.prefixlen
);
428 if (IS_ZEBRA_DEBUG_KERNEL
)
430 char buf
[PREFIX_STRLEN
];
431 zlog_debug ("%s %s vrf %u",
432 nl_msg_type_to_str (h
->nlmsg_type
),
433 prefix2str (&p
, buf
, sizeof(buf
)), vrf_id
);
436 if (h
->nlmsg_type
== RTM_NEWROUTE
)
438 if (!tb
[RTA_MULTIPATH
])
439 rib_add (AFI_IP
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
440 0, 0, &p
, NULL
, gate
, prefsrc
, index
,
441 table
, metric
, mtu
, 0);
444 /* This is a multipath route */
447 struct rtnexthop
*rtnh
=
448 (struct rtnexthop
*) RTA_DATA (tb
[RTA_MULTIPATH
]);
450 len
= RTA_PAYLOAD (tb
[RTA_MULTIPATH
]);
452 rib
= XCALLOC (MTYPE_RIB
, sizeof (struct rib
));
453 rib
->type
= ZEBRA_ROUTE_KERNEL
;
456 rib
->metric
= metric
;
458 rib
->vrf_id
= vrf_id
;
460 rib
->nexthop_num
= 0;
461 rib
->uptime
= time (NULL
);
465 if (len
< (int) sizeof (*rtnh
) || rtnh
->rtnh_len
> len
)
468 index
= rtnh
->rtnh_ifindex
;
470 if (rtnh
->rtnh_len
> sizeof (*rtnh
))
472 memset (tb
, 0, sizeof (tb
));
473 netlink_parse_rtattr (tb
, RTA_MAX
, RTNH_DATA (rtnh
),
474 rtnh
->rtnh_len
- sizeof (*rtnh
));
476 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
482 rib_nexthop_ipv4_ifindex_add (rib
, gate
, prefsrc
, index
);
484 rib_nexthop_ipv4_add (rib
, gate
, prefsrc
);
487 rib_nexthop_ifindex_add (rib
, index
);
489 len
-= NLMSG_ALIGN(rtnh
->rtnh_len
);
490 rtnh
= RTNH_NEXT(rtnh
);
493 zserv_nexthop_num_warn(__func__
, (const struct prefix
*)&p
,
496 if (rib
->nexthop_num
== 0)
497 XFREE (MTYPE_RIB
, rib
);
499 rib_add_multipath (AFI_IP
, SAFI_UNICAST
, &p
, NULL
, rib
);
503 rib_delete (AFI_IP
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
, 0, zebra_flags
,
504 &p
, NULL
, gate
, index
, table
);
507 if (rtm
->rtm_family
== AF_INET6
)
510 struct prefix_ipv6 src_p
;
513 memcpy (&p
.u
.prefix6
, dest
, 16);
514 p
.prefixlen
= rtm
->rtm_dst_len
;
516 src_p
.family
= AF_INET6
;
517 memcpy (&src_p
.prefix
, src
, 16);
518 src_p
.prefixlen
= rtm
->rtm_src_len
;
520 if (IS_ZEBRA_DEBUG_KERNEL
)
522 char buf
[PREFIX_STRLEN
];
523 char buf2
[PREFIX_STRLEN
];
524 zlog_debug ("%s %s%s%s vrf %u",
525 nl_msg_type_to_str (h
->nlmsg_type
),
526 prefix2str (&p
, buf
, sizeof(buf
)),
527 src_p
.prefixlen
? " from " : "",
528 src_p
.prefixlen
? prefix2str(&src_p
, buf2
, sizeof(buf2
)) : "",
532 if (h
->nlmsg_type
== RTM_NEWROUTE
)
533 rib_add (AFI_IP6
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
534 0, 0, &p
, &src_p
, gate
, prefsrc
, index
,
535 table
, metric
, mtu
, 0);
537 rib_delete (AFI_IP6
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
538 0, zebra_flags
, &p
, &src_p
, gate
, index
, table
);
544 static struct mcast_route_data
*mroute
= NULL
;
547 netlink_route_change_read_multicast (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
552 struct rtattr
*tb
[RTA_MAX
+ 1];
553 struct mcast_route_data
*m
;
554 struct mcast_route_data mr
;
561 char oif_list
[256] = "\0";
562 vrf_id_t vrf
= ns_id
;
568 memset (&mr
, 0, sizeof (mr
));
572 rtm
= NLMSG_DATA (h
);
574 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
576 memset (tb
, 0, sizeof tb
);
577 netlink_parse_rtattr (tb
, RTA_MAX
, RTM_RTA (rtm
), len
);
580 iif
= *(int *)RTA_DATA (tb
[RTA_IIF
]);
583 m
->sg
.src
= *(struct in_addr
*)RTA_DATA (tb
[RTA_SRC
]);
586 m
->sg
.grp
= *(struct in_addr
*)RTA_DATA (tb
[RTA_DST
]);
588 if ((RTA_EXPIRES
<= RTA_MAX
) && tb
[RTA_EXPIRES
])
589 m
->lastused
= *(unsigned long long *)RTA_DATA (tb
[RTA_EXPIRES
]);
591 if (tb
[RTA_MULTIPATH
])
593 struct rtnexthop
*rtnh
=
594 (struct rtnexthop
*)RTA_DATA (tb
[RTA_MULTIPATH
]);
596 len
= RTA_PAYLOAD (tb
[RTA_MULTIPATH
]);
599 if (len
< (int) sizeof (*rtnh
) || rtnh
->rtnh_len
> len
)
602 oif
[oif_count
] = rtnh
->rtnh_ifindex
;
605 len
-= NLMSG_ALIGN (rtnh
->rtnh_len
);
606 rtnh
= RTNH_NEXT (rtnh
);
610 if (IS_ZEBRA_DEBUG_KERNEL
)
612 struct interface
*ifp
;
613 strcpy (sbuf
, inet_ntoa (m
->sg
.src
));
614 strcpy (gbuf
, inet_ntoa (m
->sg
.grp
));
615 for (count
= 0; count
< oif_count
; count
++)
617 ifp
= if_lookup_by_index_vrf (oif
[count
], vrf
);
620 sprintf (temp
, "%s ", ifp
->name
);
621 strcat (oif_list
, temp
);
623 ifp
= if_lookup_by_index_vrf (iif
, vrf
);
624 zlog_debug ("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld",
625 nl_msg_type_to_str(h
->nlmsg_type
), sbuf
, gbuf
, ifp
->name
, oif_list
, m
->lastused
);
631 netlink_route_change (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
635 vrf_id_t vrf_id
= ns_id
;
638 rtm
= NLMSG_DATA (h
);
640 if (!(h
->nlmsg_type
== RTM_NEWROUTE
|| h
->nlmsg_type
== RTM_DELROUTE
))
642 /* If this is not route add/delete message print warning. */
643 zlog_warn ("Kernel message: %d vrf %u\n", h
->nlmsg_type
, vrf_id
);
647 /* Connected route. */
648 if (IS_ZEBRA_DEBUG_KERNEL
)
649 zlog_debug ("%s %s %s proto %s vrf %u",
650 nl_msg_type_to_str (h
->nlmsg_type
),
651 nl_family_to_str (rtm
->rtm_family
),
652 nl_rttype_to_str (rtm
->rtm_type
),
653 nl_rtproto_to_str (rtm
->rtm_protocol
),
656 /* We don't care about change notifications for the MPLS table. */
657 /* TODO: Revisit this. */
658 if (rtm
->rtm_family
== AF_MPLS
)
661 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
665 switch (rtm
->rtm_type
)
668 netlink_route_change_read_unicast (snl
, h
, ns_id
);
671 netlink_route_change_read_multicast (snl
, h
, ns_id
);
681 /* Routing table read function using netlink interface. Only called
684 netlink_route_read (struct zebra_ns
*zns
)
688 /* Get IPv4 routing table. */
689 ret
= netlink_request (AF_INET
, RTM_GETROUTE
, &zns
->netlink_cmd
);
692 ret
= netlink_parse_info (netlink_routing_table
, &zns
->netlink_cmd
, zns
, 0);
696 /* Get IPv6 routing table. */
697 ret
= netlink_request (AF_INET6
, RTM_GETROUTE
, &zns
->netlink_cmd
);
700 ret
= netlink_parse_info (netlink_routing_table
, &zns
->netlink_cmd
, zns
, 0);
708 _netlink_route_nl_add_gateway_info (u_char route_family
, u_char gw_family
,
709 struct nlmsghdr
*nlmsg
,
710 size_t req_size
, int bytelen
,
711 struct nexthop
*nexthop
)
713 if (route_family
== AF_MPLS
)
715 struct gw_family_t gw_fam
;
717 gw_fam
.family
= gw_family
;
718 if (gw_family
== AF_INET
)
719 memcpy (&gw_fam
.gate
.ipv4
, &nexthop
->gate
.ipv4
, bytelen
);
721 memcpy (&gw_fam
.gate
.ipv6
, &nexthop
->gate
.ipv6
, bytelen
);
722 addattr_l (nlmsg
, req_size
, RTA_VIA
, &gw_fam
.family
, bytelen
+2);
726 if (gw_family
== AF_INET
)
727 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv4
, bytelen
);
729 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv6
, bytelen
);
734 _netlink_route_rta_add_gateway_info (u_char route_family
, u_char gw_family
,
735 struct rtattr
*rta
, struct rtnexthop
*rtnh
,
736 size_t req_size
, int bytelen
,
737 struct nexthop
*nexthop
)
739 if (route_family
== AF_MPLS
)
741 struct gw_family_t gw_fam
;
743 gw_fam
.family
= gw_family
;
744 if (gw_family
== AF_INET
)
745 memcpy (&gw_fam
.gate
.ipv4
, &nexthop
->gate
.ipv4
, bytelen
);
747 memcpy (&gw_fam
.gate
.ipv6
, &nexthop
->gate
.ipv6
, bytelen
);
748 rta_addattr_l (rta
, req_size
, RTA_VIA
, &gw_fam
.family
, bytelen
+2);
749 rtnh
->rtnh_len
+= RTA_LENGTH (bytelen
+ 2);
753 if (gw_family
== AF_INET
)
754 rta_addattr_l (rta
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv4
, bytelen
);
756 rta_addattr_l (rta
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv6
, bytelen
);
757 rtnh
->rtnh_len
+= sizeof (struct rtattr
) + bytelen
;
761 /* This function takes a nexthop as argument and adds
762 * the appropriate netlink attributes to an existing
765 * @param routedesc: Human readable description of route type
766 * (direct/recursive, single-/multipath)
767 * @param bytelen: Length of addresses in bytes.
768 * @param nexthop: Nexthop information
769 * @param nlmsg: nlmsghdr structure to fill in.
770 * @param req_size: The size allocated for the message.
773 _netlink_route_build_singlepath(
774 const char *routedesc
,
776 struct nexthop
*nexthop
,
777 struct nlmsghdr
*nlmsg
,
782 struct nexthop_label
*nh_label
;
783 mpls_lse_t out_lse
[MPLS_MAX_LABELS
];
786 if (rtmsg
->rtm_family
== AF_INET
&&
787 (nexthop
->type
== NEXTHOP_TYPE_IPV6
788 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
))
790 char buf
[16] = "169.254.0.1";
791 struct in_addr ipv4_ll
;
793 inet_pton (AF_INET
, buf
, &ipv4_ll
);
794 rtmsg
->rtm_flags
|= RTNH_F_ONLINK
;
795 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &ipv4_ll
, 4);
796 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
798 if (nexthop
->rmap_src
.ipv4
.s_addr
&& (cmd
== RTM_NEWROUTE
))
799 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
800 &nexthop
->rmap_src
.ipv4
, bytelen
);
801 else if (nexthop
->src
.ipv4
.s_addr
&& (cmd
== RTM_NEWROUTE
))
802 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
803 &nexthop
->src
.ipv4
, bytelen
);
805 if (IS_ZEBRA_DEBUG_KERNEL
)
806 zlog_debug(" 5549: _netlink_route_build_singlepath() (%s): "
807 "nexthop via %s if %u",
808 routedesc
, buf
, nexthop
->ifindex
);
813 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
814 * (in the case of LER)
816 nh_label
= nexthop
->nh_label
;
817 if (rtmsg
->rtm_family
== AF_MPLS
)
820 assert (nh_label
->num_labels
== 1);
823 if (nh_label
&& nh_label
->num_labels
)
825 int i
, num_labels
= 0;
829 for (i
= 0; i
< nh_label
->num_labels
; i
++)
831 if (nh_label
->label
[i
] != MPLS_IMP_NULL_LABEL
)
833 bos
= ((i
== (nh_label
->num_labels
- 1)) ? 1 : 0);
834 out_lse
[i
] = mpls_lse_encode (nh_label
->label
[i
], 0, 0, bos
);
836 sprintf (label_buf
, "label %d", nh_label
->label
[i
]);
839 sprintf (label_buf1
, "/%d", nh_label
->label
[i
]);
840 strcat (label_buf
, label_buf1
);
847 if (rtmsg
->rtm_family
== AF_MPLS
)
848 addattr_l (nlmsg
, req_size
, RTA_NEWDST
,
849 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
853 u_int16_t encap
= LWTUNNEL_ENCAP_MPLS
;
855 addattr_l(nlmsg
, req_size
, RTA_ENCAP_TYPE
,
856 &encap
, sizeof (u_int16_t
));
857 nest
= addattr_nest(nlmsg
, req_size
, RTA_ENCAP
);
858 addattr_l (nlmsg
, req_size
, MPLS_IPTUNNEL_DST
,
859 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
860 addattr_nest_end(nlmsg
, nest
);
865 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
866 rtmsg
->rtm_flags
|= RTNH_F_ONLINK
;
868 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
869 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
871 /* Send deletes to the kernel without specifying the next-hop */
872 if (cmd
!= RTM_DELROUTE
)
873 _netlink_route_nl_add_gateway_info (rtmsg
->rtm_family
, AF_INET
, nlmsg
,
874 req_size
, bytelen
, nexthop
);
876 if (cmd
== RTM_NEWROUTE
)
878 if (nexthop
->rmap_src
.ipv4
.s_addr
)
879 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
880 &nexthop
->rmap_src
.ipv4
, bytelen
);
881 else if (nexthop
->src
.ipv4
.s_addr
)
882 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
883 &nexthop
->src
.ipv4
, bytelen
);
886 if (IS_ZEBRA_DEBUG_KERNEL
)
887 zlog_debug("netlink_route_multipath() (%s): "
888 "nexthop via %s %s if %u",
890 inet_ntoa (nexthop
->gate
.ipv4
),
891 label_buf
, nexthop
->ifindex
);
893 if (nexthop
->type
== NEXTHOP_TYPE_IPV6
894 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
896 _netlink_route_nl_add_gateway_info (rtmsg
->rtm_family
, AF_INET6
, nlmsg
,
897 req_size
, bytelen
, nexthop
);
899 if (cmd
== RTM_NEWROUTE
)
901 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
902 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
903 &nexthop
->rmap_src
.ipv6
, bytelen
);
904 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
905 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
906 &nexthop
->src
.ipv6
, bytelen
);
909 if (IS_ZEBRA_DEBUG_KERNEL
)
910 zlog_debug("netlink_route_multipath() (%s): "
911 "nexthop via %s %s if %u",
913 inet6_ntoa (nexthop
->gate
.ipv6
),
914 label_buf
, nexthop
->ifindex
);
916 if (nexthop
->type
== NEXTHOP_TYPE_IFINDEX
917 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
919 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
921 if (cmd
== RTM_NEWROUTE
)
923 if (nexthop
->rmap_src
.ipv4
.s_addr
)
924 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
925 &nexthop
->rmap_src
.ipv4
, bytelen
);
926 else if (nexthop
->src
.ipv4
.s_addr
)
927 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
928 &nexthop
->src
.ipv4
, bytelen
);
931 if (IS_ZEBRA_DEBUG_KERNEL
)
932 zlog_debug("netlink_route_multipath() (%s): "
933 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
936 if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
938 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
940 if (cmd
== RTM_NEWROUTE
)
942 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
943 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
944 &nexthop
->rmap_src
.ipv6
, bytelen
);
945 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
946 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
947 &nexthop
->src
.ipv6
, bytelen
);
950 if (IS_ZEBRA_DEBUG_KERNEL
)
951 zlog_debug("netlink_route_multipath() (%s): "
952 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
956 /* This function takes a nexthop as argument and
957 * appends to the given rtattr/rtnexthop pair the
958 * representation of the nexthop. If the nexthop
959 * defines a preferred source, the src parameter
960 * will be modified to point to that src, otherwise
961 * it will be kept unmodified.
963 * @param routedesc: Human readable description of route type
964 * (direct/recursive, single-/multipath)
965 * @param bytelen: Length of addresses in bytes.
966 * @param nexthop: Nexthop information
967 * @param rta: rtnetlink attribute structure
968 * @param rtnh: pointer to an rtnetlink nexthop structure
969 * @param src: pointer pointing to a location where
970 * the prefsrc should be stored.
973 _netlink_route_build_multipath(
974 const char *routedesc
,
976 struct nexthop
*nexthop
,
978 struct rtnexthop
*rtnh
,
982 struct nexthop_label
*nh_label
;
983 mpls_lse_t out_lse
[MPLS_MAX_LABELS
];
986 rtnh
->rtnh_len
= sizeof (*rtnh
);
987 rtnh
->rtnh_flags
= 0;
989 rta
->rta_len
+= rtnh
->rtnh_len
;
991 if (rtmsg
->rtm_family
== AF_INET
&&
992 (nexthop
->type
== NEXTHOP_TYPE_IPV6
993 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
))
995 char buf
[16] = "169.254.0.1";
996 struct in_addr ipv4_ll
;
998 inet_pton (AF_INET
, buf
, &ipv4_ll
);
1000 rtnh
->rtnh_flags
|= RTNH_F_ONLINK
;
1001 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTA_GATEWAY
,
1003 rtnh
->rtnh_len
+= sizeof (struct rtattr
) + bytelen
;
1004 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
1006 if (nexthop
->rmap_src
.ipv4
.s_addr
)
1007 *src
= &nexthop
->rmap_src
;
1008 else if (nexthop
->src
.ipv4
.s_addr
)
1009 *src
= &nexthop
->src
;
1011 if (IS_ZEBRA_DEBUG_KERNEL
)
1012 zlog_debug(" 5549: netlink_route_build_multipath() (%s): "
1013 "nexthop via %s if %u",
1014 routedesc
, buf
, nexthop
->ifindex
);
1018 label_buf
[0] = '\0';
1019 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
1020 * (in the case of LER)
1022 nh_label
= nexthop
->nh_label
;
1023 if (rtmsg
->rtm_family
== AF_MPLS
)
1026 assert (nh_label
->num_labels
== 1);
1029 if (nh_label
&& nh_label
->num_labels
)
1031 int i
, num_labels
= 0;
1033 char label_buf1
[20];
1035 for (i
= 0; i
< nh_label
->num_labels
; i
++)
1037 if (nh_label
->label
[i
] != MPLS_IMP_NULL_LABEL
)
1039 bos
= ((i
== (nh_label
->num_labels
- 1)) ? 1 : 0);
1040 out_lse
[i
] = mpls_lse_encode (nh_label
->label
[i
], 0, 0, bos
);
1042 sprintf (label_buf
, "label %d", nh_label
->label
[i
]);
1045 sprintf (label_buf1
, "/%d", nh_label
->label
[i
]);
1046 strcat (label_buf
, label_buf1
);
1053 if (rtmsg
->rtm_family
== AF_MPLS
)
1055 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTA_NEWDST
,
1056 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
1057 rtnh
->rtnh_len
+= RTA_LENGTH (num_labels
* sizeof(mpls_lse_t
));
1061 struct rtattr
*nest
;
1062 u_int16_t encap
= LWTUNNEL_ENCAP_MPLS
;
1063 int len
= rta
->rta_len
;
1065 rta_addattr_l(rta
, NL_PKT_BUF_SIZE
, RTA_ENCAP_TYPE
,
1066 &encap
, sizeof (u_int16_t
));
1067 nest
= rta_nest(rta
, NL_PKT_BUF_SIZE
, RTA_ENCAP
);
1068 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, MPLS_IPTUNNEL_DST
,
1069 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
1070 rta_nest_end(rta
, nest
);
1071 rtnh
->rtnh_len
+= rta
->rta_len
- len
;
1076 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
1077 rtnh
->rtnh_flags
|= RTNH_F_ONLINK
;
1079 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
1080 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
1082 _netlink_route_rta_add_gateway_info (rtmsg
->rtm_family
, AF_INET
, rta
,
1083 rtnh
, NL_PKT_BUF_SIZE
, bytelen
, nexthop
);
1084 if (nexthop
->rmap_src
.ipv4
.s_addr
)
1085 *src
= &nexthop
->rmap_src
;
1086 else if (nexthop
->src
.ipv4
.s_addr
)
1087 *src
= &nexthop
->src
;
1089 if (IS_ZEBRA_DEBUG_KERNEL
)
1090 zlog_debug("netlink_route_multipath() (%s): "
1091 "nexthop via %s %s if %u",
1093 inet_ntoa (nexthop
->gate
.ipv4
),
1094 label_buf
, nexthop
->ifindex
);
1096 if (nexthop
->type
== NEXTHOP_TYPE_IPV6
1097 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
1099 _netlink_route_rta_add_gateway_info (rtmsg
->rtm_family
, AF_INET6
, rta
,
1100 rtnh
, NL_PKT_BUF_SIZE
, bytelen
, nexthop
);
1102 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
1103 *src
= &nexthop
->rmap_src
;
1104 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
1105 *src
= &nexthop
->src
;
1107 if (IS_ZEBRA_DEBUG_KERNEL
)
1108 zlog_debug("netlink_route_multipath() (%s): "
1109 "nexthop via %s %s if %u",
1111 inet6_ntoa (nexthop
->gate
.ipv6
),
1112 label_buf
, nexthop
->ifindex
);
1115 if (nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
1116 || nexthop
->type
== NEXTHOP_TYPE_IFINDEX
)
1118 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
1120 if (nexthop
->rmap_src
.ipv4
.s_addr
)
1121 *src
= &nexthop
->rmap_src
;
1122 else if (nexthop
->src
.ipv4
.s_addr
)
1123 *src
= &nexthop
->src
;
1125 if (IS_ZEBRA_DEBUG_KERNEL
)
1126 zlog_debug("netlink_route_multipath() (%s): "
1127 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
1129 else if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
1131 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
1133 if (IS_ZEBRA_DEBUG_KERNEL
)
1134 zlog_debug("netlink_route_multipath() (%s): "
1135 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
1139 rtnh
->rtnh_ifindex
= 0;
1144 _netlink_mpls_build_singlepath(
1145 const char *routedesc
,
1146 zebra_nhlfe_t
*nhlfe
,
1147 struct nlmsghdr
*nlmsg
,
1148 struct rtmsg
*rtmsg
,
1155 family
= NHLFE_FAMILY (nhlfe
);
1156 bytelen
= (family
== AF_INET
? 4 : 16);
1157 _netlink_route_build_singlepath(routedesc
, bytelen
, nhlfe
->nexthop
,
1158 nlmsg
, rtmsg
, req_size
, cmd
);
1163 _netlink_mpls_build_multipath(
1164 const char *routedesc
,
1165 zebra_nhlfe_t
*nhlfe
,
1167 struct rtnexthop
*rtnh
,
1168 struct rtmsg
*rtmsg
,
1174 family
= NHLFE_FAMILY (nhlfe
);
1175 bytelen
= (family
== AF_INET
? 4 : 16);
1176 _netlink_route_build_multipath(routedesc
, bytelen
, nhlfe
->nexthop
,
1177 rta
, rtnh
, rtmsg
, src
);
1181 /* Log debug information for netlink_route_multipath
1182 * if debug logging is enabled.
1184 * @param cmd: Netlink command which is to be processed
1185 * @param p: Prefix for which the change is due
1186 * @param nexthop: Nexthop which is currently processed
1187 * @param routedesc: Semantic annotation for nexthop
1188 * (recursive, multipath, etc.)
1189 * @param family: Address family which the change concerns
1192 _netlink_route_debug(
1195 struct nexthop
*nexthop
,
1196 const char *routedesc
,
1198 struct zebra_vrf
*zvrf
)
1200 if (IS_ZEBRA_DEBUG_KERNEL
)
1202 char buf
[PREFIX_STRLEN
];
1203 zlog_debug ("netlink_route_multipath() (%s): %s %s vrf %u type %s",
1205 nl_msg_type_to_str (cmd
),
1206 prefix2str (p
, buf
, sizeof(buf
)), zvrf_id (zvrf
),
1207 (nexthop
) ? nexthop_type_to_str (nexthop
->type
) : "UNK");
1212 _netlink_mpls_debug(
1215 const char *routedesc
)
1217 if (IS_ZEBRA_DEBUG_KERNEL
)
1218 zlog_debug ("netlink_mpls_multipath() (%s): %s %u/20",
1219 routedesc
, nl_msg_type_to_str (cmd
), label
);
1223 netlink_neigh_update (int cmd
, int ifindex
, uint32_t addr
, char *lla
, int llalen
)
1231 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1233 memset(&req
.n
, 0, sizeof(req
.n
));
1234 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
1236 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ndmsg
));
1237 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1238 req
.n
.nlmsg_type
= cmd
; //RTM_NEWNEIGH or RTM_DELNEIGH
1239 req
.ndm
.ndm_family
= AF_INET
;
1240 req
.ndm
.ndm_state
= NUD_PERMANENT
;
1241 req
.ndm
.ndm_ifindex
= ifindex
;
1242 req
.ndm
.ndm_type
= RTN_UNICAST
;
1244 addattr_l(&req
.n
, sizeof(req
), NDA_DST
, &addr
, 4);
1245 addattr_l(&req
.n
, sizeof(req
), NDA_LLADDR
, lla
, llalen
);
1247 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
);
1250 /* Routing table change via netlink interface. */
1251 /* Update flag indicates whether this is a "replace" or not. */
1253 netlink_route_multipath (int cmd
, struct prefix
*p
, struct prefix
*src_p
,
1254 struct rib
*rib
, int update
)
1257 struct sockaddr_nl snl
;
1258 struct nexthop
*nexthop
= NULL
, *tnexthop
;
1260 unsigned int nexthop_num
;
1262 int family
= PREFIX_FAMILY(p
);
1263 const char *routedesc
;
1271 char buf
[NL_PKT_BUF_SIZE
];
1274 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1275 struct zebra_vrf
*zvrf
= vrf_info_lookup (rib
->vrf_id
);
1277 memset (&req
, 0, sizeof req
- NL_PKT_BUF_SIZE
);
1279 bytelen
= (family
== AF_INET
? 4 : 16);
1281 req
.n
.nlmsg_len
= NLMSG_LENGTH (sizeof (struct rtmsg
));
1282 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1283 if ((cmd
== RTM_NEWROUTE
) && update
)
1284 req
.n
.nlmsg_flags
|= NLM_F_REPLACE
;
1285 req
.n
.nlmsg_type
= cmd
;
1286 req
.r
.rtm_family
= family
;
1287 req
.r
.rtm_dst_len
= p
->prefixlen
;
1288 req
.r
.rtm_src_len
= src_p
? src_p
->prefixlen
: 0;
1289 req
.r
.rtm_protocol
= RTPROT_ZEBRA
;
1290 req
.r
.rtm_scope
= RT_SCOPE_UNIVERSE
;
1292 if ((rib
->flags
& ZEBRA_FLAG_BLACKHOLE
) || (rib
->flags
& ZEBRA_FLAG_REJECT
))
1297 if (cmd
== RTM_NEWROUTE
)
1301 if (rib
->flags
& ZEBRA_FLAG_BLACKHOLE
)
1302 req
.r
.rtm_type
= RTN_BLACKHOLE
;
1303 else if (rib
->flags
& ZEBRA_FLAG_REJECT
)
1304 req
.r
.rtm_type
= RTN_UNREACHABLE
;
1306 assert (RTN_BLACKHOLE
!= RTN_UNREACHABLE
); /* false */
1309 req
.r
.rtm_type
= RTN_UNICAST
;
1312 addattr_l (&req
.n
, sizeof req
, RTA_DST
, &p
->u
.prefix
, bytelen
);
1314 addattr_l (&req
.n
, sizeof req
, RTA_SRC
, &src_p
->u
.prefix
, bytelen
);
1317 /* Hardcode the metric for all routes coming from zebra. Metric isn't used
1318 * either by the kernel or by zebra. Its purely for calculating best path(s)
1319 * by the routing protocol and for communicating with protocol peers.
1321 addattr32 (&req
.n
, sizeof req
, RTA_PRIORITY
, NL_DEFAULT_ROUTE_METRIC
);
1323 /* Table corresponding to this route. */
1324 if (rib
->table
< 256)
1325 req
.r
.rtm_table
= rib
->table
;
1328 req
.r
.rtm_table
= RT_TABLE_UNSPEC
;
1329 addattr32(&req
.n
, sizeof req
, RTA_TABLE
, rib
->table
);
1332 if (rib
->mtu
|| rib
->nexthop_mtu
)
1334 char buf
[NL_PKT_BUF_SIZE
];
1335 struct rtattr
*rta
= (void *) buf
;
1336 u_int32_t mtu
= rib
->mtu
;
1337 if (!mtu
|| (rib
->nexthop_mtu
&& rib
->nexthop_mtu
< mtu
))
1338 mtu
= rib
->nexthop_mtu
;
1339 rta
->rta_type
= RTA_METRICS
;
1340 rta
->rta_len
= RTA_LENGTH(0);
1341 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTAX_MTU
, &mtu
, sizeof mtu
);
1342 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_METRICS
, RTA_DATA (rta
),
1348 if (cmd
== RTM_NEWROUTE
)
1349 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1351 /* We shouldn't encounter recursive nexthops on discard routes,
1352 * but it is probably better to handle that case correctly anyway.
1354 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1360 /* Count overall nexthops so we can decide whether to use singlepath
1361 * or multipath case. */
1363 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1365 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1367 if (cmd
== RTM_NEWROUTE
&& !CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1369 if (cmd
== RTM_DELROUTE
&& !CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))
1375 /* Singlepath case. */
1376 if (nexthop_num
== 1 || multipath_num
== 1)
1379 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1381 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1385 if (family
== AF_INET
)
1387 if (nexthop
->rmap_src
.ipv4
.s_addr
!= 0)
1389 src
.ipv4
= nexthop
->rmap_src
.ipv4
;
1392 else if (nexthop
->src
.ipv4
.s_addr
!= 0)
1394 src
.ipv4
= nexthop
->src
.ipv4
;
1398 else if (family
== AF_INET6
)
1400 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
1402 src
.ipv6
= nexthop
->rmap_src
.ipv6
;
1405 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
1407 src
.ipv6
= nexthop
->src
.ipv6
;
1415 if ((cmd
== RTM_NEWROUTE
1416 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1417 || (cmd
== RTM_DELROUTE
1418 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
)))
1420 routedesc
= recursing
? "recursive, 1 hop" : "single hop";
1422 _netlink_route_debug(cmd
, p
, nexthop
, routedesc
, family
, zvrf
);
1423 _netlink_route_build_singlepath(routedesc
, bytelen
,
1424 nexthop
, &req
.n
, &req
.r
,
1430 if (setsrc
&& (cmd
== RTM_NEWROUTE
))
1432 if (family
== AF_INET
)
1433 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv4
, bytelen
);
1434 else if (family
== AF_INET6
)
1435 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv6
, bytelen
);
1440 char buf
[NL_PKT_BUF_SIZE
];
1441 struct rtattr
*rta
= (void *) buf
;
1442 struct rtnexthop
*rtnh
;
1443 union g_addr
*src1
= NULL
;
1445 rta
->rta_type
= RTA_MULTIPATH
;
1446 rta
->rta_len
= RTA_LENGTH (0);
1447 rtnh
= RTA_DATA (rta
);
1450 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1452 if (nexthop_num
>= multipath_num
)
1455 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1457 /* This only works for IPv4 now */
1460 if (family
== AF_INET
)
1462 if (nexthop
->rmap_src
.ipv4
.s_addr
!= 0)
1464 src
.ipv4
= nexthop
->rmap_src
.ipv4
;
1467 else if (nexthop
->src
.ipv4
.s_addr
!= 0)
1469 src
.ipv4
= nexthop
->src
.ipv4
;
1473 else if (family
== AF_INET6
)
1475 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
1477 src
.ipv6
= nexthop
->rmap_src
.ipv6
;
1480 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
1482 src
.ipv6
= nexthop
->src
.ipv6
;
1490 if ((cmd
== RTM_NEWROUTE
1491 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1492 || (cmd
== RTM_DELROUTE
1493 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
)))
1495 routedesc
= recursing
? "recursive, multihop" : "multihop";
1498 _netlink_route_debug(cmd
, p
, nexthop
,
1499 routedesc
, family
, zvrf
);
1500 _netlink_route_build_multipath(routedesc
, bytelen
,
1501 nexthop
, rta
, rtnh
, &req
.r
, &src1
);
1502 rtnh
= RTNH_NEXT (rtnh
);
1504 if (!setsrc
&& src1
)
1506 if (family
== AF_INET
)
1507 src
.ipv4
= src1
->ipv4
;
1508 else if (family
== AF_INET6
)
1509 src
.ipv6
= src1
->ipv6
;
1515 if (setsrc
&& (cmd
== RTM_NEWROUTE
))
1517 if (family
== AF_INET
)
1518 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv4
, bytelen
);
1519 else if (family
== AF_INET6
)
1520 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv6
, bytelen
);
1521 if (IS_ZEBRA_DEBUG_KERNEL
)
1522 zlog_debug("Setting source");
1525 if (rta
->rta_len
> RTA_LENGTH (0))
1526 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_MULTIPATH
, RTA_DATA (rta
),
1530 /* If there is no useful nexthop then return. */
1531 if (nexthop_num
== 0)
1533 if (IS_ZEBRA_DEBUG_KERNEL
)
1534 zlog_debug ("netlink_route_multipath(): No useful nexthop.");
1540 /* Destination netlink address. */
1541 memset (&snl
, 0, sizeof snl
);
1542 snl
.nl_family
= AF_NETLINK
;
1544 /* Talk to netlink socket. */
1545 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
);
1549 kernel_get_ipmr_sg_stats (void *in
)
1552 struct mcast_route_data
*mr
= (struct mcast_route_data
*)in
;
1560 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1562 memset(&req
.n
, 0, sizeof(req
.n
));
1563 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
1565 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ndmsg
));
1566 req
.n
.nlmsg_flags
= NLM_F_REQUEST
;
1567 req
.ndm
.ndm_family
= AF_INET
;
1568 req
.n
.nlmsg_type
= RTM_GETROUTE
;
1570 addattr_l (&req
.n
, sizeof (req
), RTA_IIF
, &mroute
->ifindex
, 4);
1571 addattr_l (&req
.n
, sizeof (req
), RTA_OIF
, &mroute
->ifindex
, 4);
1572 addattr_l (&req
.n
, sizeof (req
), RTA_SRC
, &mroute
->sg
.src
.s_addr
, 4);
1573 addattr_l (&req
.n
, sizeof (req
), RTA_DST
, &mroute
->sg
.grp
.s_addr
, 4);
1575 suc
= netlink_talk (netlink_route_change_read_multicast
, &req
.n
, &zns
->netlink_cmd
, zns
);
1582 kernel_route_rib (struct prefix
*p
, struct prefix
*src_p
,
1583 struct rib
*old
, struct rib
*new)
1586 return netlink_route_multipath (RTM_NEWROUTE
, p
, src_p
, new, 0);
1588 return netlink_route_multipath (RTM_DELROUTE
, p
, src_p
, old
, 0);
1590 return netlink_route_multipath (RTM_NEWROUTE
, p
, src_p
, new, 1);
1594 kernel_neigh_update (int add
, int ifindex
, uint32_t addr
, char *lla
, int llalen
)
1596 return netlink_neigh_update(add
? RTM_NEWNEIGH
: RTM_DELNEIGH
, ifindex
, addr
,
1601 * MPLS label forwarding table change via netlink interface.
1604 netlink_mpls_multipath (int cmd
, zebra_lsp_t
*lsp
)
1607 zebra_nhlfe_t
*nhlfe
;
1608 struct nexthop
*nexthop
= NULL
;
1609 unsigned int nexthop_num
;
1610 const char *routedesc
;
1611 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1617 char buf
[NL_PKT_BUF_SIZE
];
1620 memset (&req
, 0, sizeof req
- NL_PKT_BUF_SIZE
);
1624 * Count # nexthops so we can decide whether to use singlepath
1625 * or multipath case.
1628 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1630 nexthop
= nhlfe
->nexthop
;
1633 if (cmd
== RTM_NEWROUTE
)
1635 /* Count all selected NHLFEs */
1636 if (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
1637 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1642 /* Count all installed NHLFEs */
1643 if (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
1644 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))
1649 if (nexthop_num
== 0) // unexpected
1652 req
.n
.nlmsg_len
= NLMSG_LENGTH (sizeof (struct rtmsg
));
1653 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1654 req
.n
.nlmsg_type
= cmd
;
1655 req
.r
.rtm_family
= AF_MPLS
;
1656 req
.r
.rtm_table
= RT_TABLE_MAIN
;
1657 req
.r
.rtm_dst_len
= MPLS_LABEL_LEN_BITS
;
1658 req
.r
.rtm_protocol
= RTPROT_ZEBRA
;
1659 req
.r
.rtm_scope
= RT_SCOPE_UNIVERSE
;
1660 req
.r
.rtm_type
= RTN_UNICAST
;
1662 if (cmd
== RTM_NEWROUTE
)
1663 /* We do a replace to handle update. */
1664 req
.n
.nlmsg_flags
|= NLM_F_REPLACE
;
1666 /* Fill destination */
1667 lse
= mpls_lse_encode (lsp
->ile
.in_label
, 0, 0, 1);
1668 addattr_l (&req
.n
, sizeof req
, RTA_DST
, &lse
, sizeof(mpls_lse_t
));
1670 /* Fill nexthops (paths) based on single-path or multipath. The paths
1671 * chosen depend on the operation.
1673 if (nexthop_num
== 1 || multipath_num
== 1)
1675 routedesc
= "single hop";
1676 _netlink_mpls_debug(cmd
, lsp
->ile
.in_label
, routedesc
);
1679 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1681 nexthop
= nhlfe
->nexthop
;
1685 if ((cmd
== RTM_NEWROUTE
&&
1686 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
1687 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))) ||
1688 (cmd
== RTM_DELROUTE
&&
1689 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
1690 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))))
1692 /* Add the gateway */
1693 _netlink_mpls_build_singlepath(routedesc
, nhlfe
,
1694 &req
.n
, &req
.r
, sizeof req
, cmd
);
1695 if (cmd
== RTM_NEWROUTE
)
1697 SET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1698 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1702 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1703 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1710 else /* Multipath case */
1712 char buf
[NL_PKT_BUF_SIZE
];
1713 struct rtattr
*rta
= (void *) buf
;
1714 struct rtnexthop
*rtnh
;
1715 union g_addr
*src1
= NULL
;
1717 rta
->rta_type
= RTA_MULTIPATH
;
1718 rta
->rta_len
= RTA_LENGTH (0);
1719 rtnh
= RTA_DATA (rta
);
1721 routedesc
= "multihop";
1722 _netlink_mpls_debug(cmd
, lsp
->ile
.in_label
, routedesc
);
1725 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1727 nexthop
= nhlfe
->nexthop
;
1731 if (nexthop_num
>= multipath_num
)
1734 if ((cmd
== RTM_NEWROUTE
&&
1735 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
1736 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))) ||
1737 (cmd
== RTM_DELROUTE
&&
1738 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
1739 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))))
1743 /* Build the multipath */
1744 _netlink_mpls_build_multipath(routedesc
, nhlfe
, rta
,
1745 rtnh
, &req
.r
, &src1
);
1746 rtnh
= RTNH_NEXT (rtnh
);
1748 if (cmd
== RTM_NEWROUTE
)
1750 SET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1751 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1755 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1756 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1762 /* Add the multipath */
1763 if (rta
->rta_len
> RTA_LENGTH (0))
1764 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_MULTIPATH
, RTA_DATA (rta
),
1768 /* Talk to netlink socket. */
1769 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
);
1773 * Handle failure in LSP install, clear flags for NHLFE.
1776 clear_nhlfe_installed (zebra_lsp_t
*lsp
)
1778 zebra_nhlfe_t
*nhlfe
;
1779 struct nexthop
*nexthop
;
1781 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1783 nexthop
= nhlfe
->nexthop
;
1787 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1788 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);