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
82 #ifndef LWTUNNEL_ENCAP_MPLS
83 #define LWTUNNEL_ENCAP_MPLS 1
86 #ifndef MPLS_IPTUNNEL_DST
87 #define MPLS_IPTUNNEL_DST 1
89 /* End of temporary definitions */
99 Pending: create an efficient table_id (in a tree/hash) based lookup)
102 vrf_lookup_by_table (u_int32_t table_id
)
105 struct zebra_vrf
*zvrf
;
107 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
109 if ((zvrf
= vrf
->info
) == NULL
||
110 (zvrf
->table_id
!= table_id
))
113 return zvrf_id (zvrf
);
119 /* Looking up routing table by netlink interface. */
121 netlink_routing_table (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
126 struct rtattr
*tb
[RTA_MAX
+ 1];
129 vrf_id_t vrf_id
= VRF_DEFAULT
;
131 char anyaddr
[16] = { 0 };
142 rtm
= NLMSG_DATA (h
);
144 if (h
->nlmsg_type
!= RTM_NEWROUTE
)
146 if (rtm
->rtm_type
!= RTN_UNICAST
)
149 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
153 memset (tb
, 0, sizeof tb
);
154 netlink_parse_rtattr (tb
, RTA_MAX
, RTM_RTA (rtm
), len
);
156 if (rtm
->rtm_flags
& RTM_F_CLONED
)
158 if (rtm
->rtm_protocol
== RTPROT_REDIRECT
)
160 if (rtm
->rtm_protocol
== RTPROT_KERNEL
)
163 if (rtm
->rtm_src_len
!= 0)
166 /* We don't care about change notifications for the MPLS table. */
167 /* TODO: Revisit this. */
168 if (rtm
->rtm_family
== AF_MPLS
)
171 /* Table corresponding to route. */
173 table
= *(int *) RTA_DATA (tb
[RTA_TABLE
]);
175 table
= rtm
->rtm_table
;
178 vrf_id
= vrf_lookup_by_table(table
);
179 if (vrf_id
== VRF_DEFAULT
)
181 if (!is_zebra_valid_kernel_table(table
) &&
182 !is_zebra_main_routing_table(table
))
186 /* Route which inserted by Zebra. */
187 if (rtm
->rtm_protocol
== RTPROT_ZEBRA
)
188 flags
|= ZEBRA_FLAG_SELFROUTE
;
197 index
= *(int *) RTA_DATA (tb
[RTA_OIF
]);
200 dest
= RTA_DATA (tb
[RTA_DST
]);
205 src
= RTA_DATA (tb
[RTA_PREFSRC
]);
208 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
210 if (tb
[RTA_PRIORITY
])
211 metric
= *(int *) RTA_DATA(tb
[RTA_PRIORITY
]);
215 struct rtattr
*mxrta
[RTAX_MAX
+1];
217 memset (mxrta
, 0, sizeof mxrta
);
218 netlink_parse_rtattr (mxrta
, RTAX_MAX
, RTA_DATA(tb
[RTA_METRICS
]),
219 RTA_PAYLOAD(tb
[RTA_METRICS
]));
222 mtu
= *(u_int32_t
*) RTA_DATA(mxrta
[RTAX_MTU
]);
225 if (rtm
->rtm_family
== AF_INET
)
228 memcpy (&p
.u
.prefix4
, dest
, 4);
229 p
.prefixlen
= rtm
->rtm_dst_len
;
231 if (!tb
[RTA_MULTIPATH
])
232 rib_add (AFI_IP
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
233 0, flags
, &p
, gate
, src
, index
,
234 table
, metric
, mtu
, 0);
237 /* This is a multipath route */
240 struct rtnexthop
*rtnh
=
241 (struct rtnexthop
*) RTA_DATA (tb
[RTA_MULTIPATH
]);
243 len
= RTA_PAYLOAD (tb
[RTA_MULTIPATH
]);
245 rib
= XCALLOC (MTYPE_RIB
, sizeof (struct rib
));
246 rib
->type
= ZEBRA_ROUTE_KERNEL
;
249 rib
->metric
= metric
;
251 rib
->vrf_id
= vrf_id
;
253 rib
->nexthop_num
= 0;
254 rib
->uptime
= time (NULL
);
258 if (len
< (int) sizeof (*rtnh
) || rtnh
->rtnh_len
> len
)
261 index
= rtnh
->rtnh_ifindex
;
263 if (rtnh
->rtnh_len
> sizeof (*rtnh
))
265 memset (tb
, 0, sizeof (tb
));
266 netlink_parse_rtattr (tb
, RTA_MAX
, RTNH_DATA (rtnh
),
267 rtnh
->rtnh_len
- sizeof (*rtnh
));
269 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
275 rib_nexthop_ipv4_ifindex_add (rib
, gate
, src
, index
);
277 rib_nexthop_ipv4_add (rib
, gate
, src
);
280 rib_nexthop_ifindex_add (rib
, index
);
282 len
-= NLMSG_ALIGN(rtnh
->rtnh_len
);
283 rtnh
= RTNH_NEXT(rtnh
);
286 zserv_nexthop_num_warn(__func__
, (const struct prefix
*)&p
,
288 if (rib
->nexthop_num
== 0)
289 XFREE (MTYPE_RIB
, rib
);
291 rib_add_multipath (AFI_IP
, SAFI_UNICAST
, &p
, rib
);
294 if (rtm
->rtm_family
== AF_INET6
)
297 memcpy (&p
.u
.prefix6
, dest
, 16);
298 p
.prefixlen
= rtm
->rtm_dst_len
;
300 rib_add (AFI_IP6
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
301 0, flags
, &p
, gate
, src
, index
,
302 table
, metric
, mtu
, 0);
308 /* Routing information change from the kernel. */
310 netlink_route_change_read_unicast (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
315 struct rtattr
*tb
[RTA_MAX
+ 1];
316 u_char zebra_flags
= 0;
318 vrf_id_t vrf_id
= VRF_DEFAULT
;
319 char anyaddr
[16] = { 0 };
330 rtm
= NLMSG_DATA (h
);
332 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
334 memset (tb
, 0, sizeof tb
);
335 netlink_parse_rtattr (tb
, RTA_MAX
, RTM_RTA (rtm
), len
);
337 if (rtm
->rtm_flags
& RTM_F_CLONED
)
339 if (rtm
->rtm_protocol
== RTPROT_REDIRECT
)
341 if (rtm
->rtm_protocol
== RTPROT_KERNEL
)
344 if (rtm
->rtm_protocol
== RTPROT_ZEBRA
&& h
->nlmsg_type
== RTM_NEWROUTE
)
346 if (rtm
->rtm_protocol
== RTPROT_ZEBRA
)
347 SET_FLAG(zebra_flags
, ZEBRA_FLAG_SELFROUTE
);
349 if (rtm
->rtm_src_len
!= 0)
351 zlog_warn ("netlink_route_change(): no src len");
355 /* Table corresponding to route. */
357 table
= *(int *) RTA_DATA (tb
[RTA_TABLE
]);
359 table
= rtm
->rtm_table
;
362 vrf_id
= vrf_lookup_by_table(table
);
363 if (vrf_id
== VRF_DEFAULT
)
365 if (!is_zebra_valid_kernel_table(table
) &&
366 !is_zebra_main_routing_table(table
))
377 index
= *(int *) RTA_DATA (tb
[RTA_OIF
]);
380 dest
= RTA_DATA (tb
[RTA_DST
]);
385 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
388 src
= RTA_DATA (tb
[RTA_PREFSRC
]);
390 if (h
->nlmsg_type
== RTM_NEWROUTE
)
392 if (tb
[RTA_PRIORITY
])
393 metric
= *(int *) RTA_DATA(tb
[RTA_PRIORITY
]);
397 struct rtattr
*mxrta
[RTAX_MAX
+1];
399 memset (mxrta
, 0, sizeof mxrta
);
400 netlink_parse_rtattr (mxrta
, RTAX_MAX
, RTA_DATA(tb
[RTA_METRICS
]),
401 RTA_PAYLOAD(tb
[RTA_METRICS
]));
404 mtu
= *(u_int32_t
*) RTA_DATA(mxrta
[RTAX_MTU
]);
408 if (rtm
->rtm_family
== AF_INET
)
411 memcpy (&p
.u
.prefix4
, dest
, 4);
412 p
.prefixlen
= rtm
->rtm_dst_len
;
414 if (IS_ZEBRA_DEBUG_KERNEL
)
416 char buf
[PREFIX_STRLEN
];
417 zlog_debug ("%s %s vrf %u",
418 nl_msg_type_to_str (h
->nlmsg_type
),
419 prefix2str (&p
, buf
, sizeof(buf
)), vrf_id
);
422 if (h
->nlmsg_type
== RTM_NEWROUTE
)
424 if (!tb
[RTA_MULTIPATH
])
425 rib_add (AFI_IP
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
426 0, 0, &p
, gate
, src
, index
,
427 table
, metric
, mtu
, 0);
430 /* This is a multipath route */
433 struct rtnexthop
*rtnh
=
434 (struct rtnexthop
*) RTA_DATA (tb
[RTA_MULTIPATH
]);
436 len
= RTA_PAYLOAD (tb
[RTA_MULTIPATH
]);
438 rib
= XCALLOC (MTYPE_RIB
, sizeof (struct rib
));
439 rib
->type
= ZEBRA_ROUTE_KERNEL
;
442 rib
->metric
= metric
;
444 rib
->vrf_id
= vrf_id
;
446 rib
->nexthop_num
= 0;
447 rib
->uptime
= time (NULL
);
451 if (len
< (int) sizeof (*rtnh
) || rtnh
->rtnh_len
> len
)
454 index
= rtnh
->rtnh_ifindex
;
456 if (rtnh
->rtnh_len
> sizeof (*rtnh
))
458 memset (tb
, 0, sizeof (tb
));
459 netlink_parse_rtattr (tb
, RTA_MAX
, RTNH_DATA (rtnh
),
460 rtnh
->rtnh_len
- sizeof (*rtnh
));
462 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
468 rib_nexthop_ipv4_ifindex_add (rib
, gate
, src
, index
);
470 rib_nexthop_ipv4_add (rib
, gate
, src
);
473 rib_nexthop_ifindex_add (rib
, index
);
475 len
-= NLMSG_ALIGN(rtnh
->rtnh_len
);
476 rtnh
= RTNH_NEXT(rtnh
);
479 zserv_nexthop_num_warn(__func__
, (const struct prefix
*)&p
,
482 if (rib
->nexthop_num
== 0)
483 XFREE (MTYPE_RIB
, rib
);
485 rib_add_multipath (AFI_IP
, SAFI_UNICAST
, &p
, rib
);
489 rib_delete (AFI_IP
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
, 0, zebra_flags
,
490 &p
, gate
, index
, table
);
493 if (rtm
->rtm_family
== AF_INET6
)
498 memcpy (&p
.u
.prefix6
, dest
, 16);
499 p
.prefixlen
= rtm
->rtm_dst_len
;
501 if (IS_ZEBRA_DEBUG_KERNEL
)
503 char buf
[PREFIX_STRLEN
];
504 zlog_debug ("%s %s vrf %u",
505 nl_msg_type_to_str (h
->nlmsg_type
),
506 prefix2str (&p
, buf
, sizeof(buf
)), vrf_id
);
509 if (h
->nlmsg_type
== RTM_NEWROUTE
)
510 rib_add (AFI_IP6
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
511 0, 0, &p
, gate
, src
, index
,
512 table
, metric
, mtu
, 0);
514 rib_delete (AFI_IP6
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
515 0, zebra_flags
, &p
, gate
, index
, table
);
521 static struct mcast_route_data
*mroute
= NULL
;
524 netlink_route_change_read_multicast (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
529 struct rtattr
*tb
[RTA_MAX
+ 1];
530 struct mcast_route_data
*m
;
531 struct mcast_route_data mr
;
538 char oif_list
[256] = "\0";
539 vrf_id_t vrf
= ns_id
;
545 memset (&mr
, 0, sizeof (mr
));
549 rtm
= NLMSG_DATA (h
);
551 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
553 memset (tb
, 0, sizeof tb
);
554 netlink_parse_rtattr (tb
, RTA_MAX
, RTM_RTA (rtm
), len
);
557 iif
= *(int *)RTA_DATA (tb
[RTA_IIF
]);
560 m
->sg
.src
= *(struct in_addr
*)RTA_DATA (tb
[RTA_SRC
]);
563 m
->sg
.grp
= *(struct in_addr
*)RTA_DATA (tb
[RTA_DST
]);
566 m
->lastused
= *(unsigned long long *)RTA_DATA (tb
[RTA_EXPIRES
]);
568 if (tb
[RTA_MULTIPATH
])
570 struct rtnexthop
*rtnh
=
571 (struct rtnexthop
*)RTA_DATA (tb
[RTA_MULTIPATH
]);
573 len
= RTA_PAYLOAD (tb
[RTA_MULTIPATH
]);
576 if (len
< (int) sizeof (*rtnh
) || rtnh
->rtnh_len
> len
)
579 oif
[oif_count
] = rtnh
->rtnh_ifindex
;
582 len
-= NLMSG_ALIGN (rtnh
->rtnh_len
);
583 rtnh
= RTNH_NEXT (rtnh
);
587 if (IS_ZEBRA_DEBUG_KERNEL
)
589 struct interface
*ifp
;
590 strcpy (sbuf
, inet_ntoa (m
->sg
.src
));
591 strcpy (gbuf
, inet_ntoa (m
->sg
.grp
));
592 for (count
= 0; count
< oif_count
; count
++)
594 ifp
= if_lookup_by_index_vrf (oif
[count
], vrf
);
597 sprintf (temp
, "%s ", ifp
->name
);
598 strcat (oif_list
, temp
);
600 ifp
= if_lookup_by_index_vrf (iif
, vrf
);
601 zlog_debug ("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld",
602 nl_msg_type_to_str(h
->nlmsg_type
), sbuf
, gbuf
, ifp
->name
, oif_list
, m
->lastused
);
608 netlink_route_change (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
612 vrf_id_t vrf_id
= ns_id
;
615 rtm
= NLMSG_DATA (h
);
617 if (!(h
->nlmsg_type
== RTM_NEWROUTE
|| h
->nlmsg_type
== RTM_DELROUTE
))
619 /* If this is not route add/delete message print warning. */
620 zlog_warn ("Kernel message: %d vrf %u\n", h
->nlmsg_type
, vrf_id
);
624 /* Connected route. */
625 if (IS_ZEBRA_DEBUG_KERNEL
)
626 zlog_debug ("%s %s %s proto %s vrf %u",
627 nl_msg_type_to_str (h
->nlmsg_type
),
628 nl_family_to_str (rtm
->rtm_family
),
629 nl_rttype_to_str (rtm
->rtm_type
),
630 nl_rtproto_to_str (rtm
->rtm_protocol
),
633 /* We don't care about change notifications for the MPLS table. */
634 /* TODO: Revisit this. */
635 if (rtm
->rtm_family
== AF_MPLS
)
638 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
642 switch (rtm
->rtm_type
)
645 netlink_route_change_read_unicast (snl
, h
, ns_id
);
648 netlink_route_change_read_multicast (snl
, h
, ns_id
);
658 /* Routing table read function using netlink interface. Only called
661 netlink_route_read (struct zebra_ns
*zns
)
665 /* Get IPv4 routing table. */
666 ret
= netlink_request (AF_INET
, RTM_GETROUTE
, &zns
->netlink_cmd
);
669 ret
= netlink_parse_info (netlink_routing_table
, &zns
->netlink_cmd
, zns
, 0);
674 /* Get IPv6 routing table. */
675 ret
= netlink_request (AF_INET6
, RTM_GETROUTE
, &zns
->netlink_cmd
);
678 ret
= netlink_parse_info (netlink_routing_table
, &zns
->netlink_cmd
, zns
, 0);
681 #endif /* HAVE_IPV6 */
687 _netlink_route_nl_add_gateway_info (u_char route_family
, u_char gw_family
,
688 struct nlmsghdr
*nlmsg
,
689 size_t req_size
, int bytelen
,
690 struct nexthop
*nexthop
)
692 if (route_family
== AF_MPLS
)
694 struct gw_family_t gw_fam
;
696 gw_fam
.family
= gw_family
;
697 if (gw_family
== AF_INET
)
698 memcpy (&gw_fam
.gate
.ipv4
, &nexthop
->gate
.ipv4
, bytelen
);
700 memcpy (&gw_fam
.gate
.ipv6
, &nexthop
->gate
.ipv6
, bytelen
);
701 addattr_l (nlmsg
, req_size
, RTA_VIA
, &gw_fam
.family
, bytelen
+2);
705 if (gw_family
== AF_INET
)
706 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv4
, bytelen
);
708 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv6
, bytelen
);
713 _netlink_route_rta_add_gateway_info (u_char route_family
, u_char gw_family
,
714 struct rtattr
*rta
, struct rtnexthop
*rtnh
,
715 size_t req_size
, int bytelen
,
716 struct nexthop
*nexthop
)
718 if (route_family
== AF_MPLS
)
720 struct gw_family_t gw_fam
;
722 gw_fam
.family
= gw_family
;
723 if (gw_family
== AF_INET
)
724 memcpy (&gw_fam
.gate
.ipv4
, &nexthop
->gate
.ipv4
, bytelen
);
726 memcpy (&gw_fam
.gate
.ipv6
, &nexthop
->gate
.ipv6
, bytelen
);
727 rta_addattr_l (rta
, req_size
, RTA_VIA
, &gw_fam
.family
, bytelen
+2);
728 rtnh
->rtnh_len
+= RTA_LENGTH (bytelen
+ 2);
732 if (gw_family
== AF_INET
)
733 rta_addattr_l (rta
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv4
, bytelen
);
735 rta_addattr_l (rta
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv6
, bytelen
);
736 rtnh
->rtnh_len
+= sizeof (struct rtattr
) + bytelen
;
740 /* This function takes a nexthop as argument and adds
741 * the appropriate netlink attributes to an existing
744 * @param routedesc: Human readable description of route type
745 * (direct/recursive, single-/multipath)
746 * @param bytelen: Length of addresses in bytes.
747 * @param nexthop: Nexthop information
748 * @param nlmsg: nlmsghdr structure to fill in.
749 * @param req_size: The size allocated for the message.
752 _netlink_route_build_singlepath(
753 const char *routedesc
,
755 struct nexthop
*nexthop
,
756 struct nlmsghdr
*nlmsg
,
761 struct nexthop_label
*nh_label
;
762 mpls_lse_t out_lse
[MPLS_MAX_LABELS
];
765 if (rtmsg
->rtm_family
== AF_INET
&&
766 (nexthop
->type
== NEXTHOP_TYPE_IPV6
767 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
))
769 char buf
[16] = "169.254.0.1";
770 struct in_addr ipv4_ll
;
772 inet_pton (AF_INET
, buf
, &ipv4_ll
);
773 rtmsg
->rtm_flags
|= RTNH_F_ONLINK
;
774 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &ipv4_ll
, 4);
775 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
777 if (nexthop
->rmap_src
.ipv4
.s_addr
&& (cmd
== RTM_NEWROUTE
))
778 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
779 &nexthop
->rmap_src
.ipv4
, bytelen
);
780 else if (nexthop
->src
.ipv4
.s_addr
&& (cmd
== RTM_NEWROUTE
))
781 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
782 &nexthop
->src
.ipv4
, bytelen
);
784 if (IS_ZEBRA_DEBUG_KERNEL
)
785 zlog_debug(" 5549: _netlink_route_build_singlepath() (%s): "
786 "nexthop via %s if %u",
787 routedesc
, buf
, nexthop
->ifindex
);
792 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
793 * (in the case of LER)
795 nh_label
= nexthop
->nh_label
;
796 if (rtmsg
->rtm_family
== AF_MPLS
)
799 assert (nh_label
->num_labels
== 1);
802 if (nh_label
&& nh_label
->num_labels
)
804 int i
, num_labels
= 0;
808 for (i
= 0; i
< nh_label
->num_labels
; i
++)
810 if (nh_label
->label
[i
] != MPLS_IMP_NULL_LABEL
)
812 bos
= ((i
== (nh_label
->num_labels
- 1)) ? 1 : 0);
813 out_lse
[i
] = mpls_lse_encode (nh_label
->label
[i
], 0, 0, bos
);
815 sprintf (label_buf
, "label %d", nh_label
->label
[i
]);
818 sprintf (label_buf1
, "/%d", nh_label
->label
[i
]);
819 strcat (label_buf
, label_buf1
);
826 if (rtmsg
->rtm_family
== AF_MPLS
)
827 addattr_l (nlmsg
, req_size
, RTA_NEWDST
,
828 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
832 u_int16_t encap
= LWTUNNEL_ENCAP_MPLS
;
834 addattr_l(nlmsg
, req_size
, RTA_ENCAP_TYPE
,
835 &encap
, sizeof (u_int16_t
));
836 nest
= addattr_nest(nlmsg
, req_size
, RTA_ENCAP
);
837 addattr_l (nlmsg
, req_size
, MPLS_IPTUNNEL_DST
,
838 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
839 addattr_nest_end(nlmsg
, nest
);
844 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
845 rtmsg
->rtm_flags
|= RTNH_F_ONLINK
;
847 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
848 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
850 _netlink_route_nl_add_gateway_info (rtmsg
->rtm_family
, AF_INET
, nlmsg
,
851 req_size
, bytelen
, nexthop
);
853 if (cmd
== RTM_NEWROUTE
)
855 if (nexthop
->rmap_src
.ipv4
.s_addr
)
856 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
857 &nexthop
->rmap_src
.ipv4
, bytelen
);
858 else if (nexthop
->src
.ipv4
.s_addr
)
859 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
860 &nexthop
->src
.ipv4
, bytelen
);
863 if (IS_ZEBRA_DEBUG_KERNEL
)
864 zlog_debug("netlink_route_multipath() (%s): "
865 "nexthop via %s %s if %u",
867 inet_ntoa (nexthop
->gate
.ipv4
),
868 label_buf
, nexthop
->ifindex
);
870 if (nexthop
->type
== NEXTHOP_TYPE_IPV6
871 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
873 _netlink_route_nl_add_gateway_info (rtmsg
->rtm_family
, AF_INET6
, nlmsg
,
874 req_size
, bytelen
, nexthop
);
876 if (cmd
== RTM_NEWROUTE
)
878 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
879 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
880 &nexthop
->rmap_src
.ipv6
, bytelen
);
881 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
882 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
883 &nexthop
->src
.ipv6
, bytelen
);
886 if (IS_ZEBRA_DEBUG_KERNEL
)
887 zlog_debug("netlink_route_multipath() (%s): "
888 "nexthop via %s %s if %u",
890 inet6_ntoa (nexthop
->gate
.ipv6
),
891 label_buf
, nexthop
->ifindex
);
893 if (nexthop
->type
== NEXTHOP_TYPE_IFINDEX
894 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
896 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
898 if (cmd
== RTM_NEWROUTE
)
900 if (nexthop
->rmap_src
.ipv4
.s_addr
)
901 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
902 &nexthop
->rmap_src
.ipv4
, bytelen
);
903 else if (nexthop
->src
.ipv4
.s_addr
)
904 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
905 &nexthop
->src
.ipv4
, bytelen
);
908 if (IS_ZEBRA_DEBUG_KERNEL
)
909 zlog_debug("netlink_route_multipath() (%s): "
910 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
913 if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
915 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
917 if (cmd
== RTM_NEWROUTE
)
919 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
920 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
921 &nexthop
->rmap_src
.ipv6
, bytelen
);
922 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
923 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
924 &nexthop
->src
.ipv6
, bytelen
);
927 if (IS_ZEBRA_DEBUG_KERNEL
)
928 zlog_debug("netlink_route_multipath() (%s): "
929 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
933 /* This function takes a nexthop as argument and
934 * appends to the given rtattr/rtnexthop pair the
935 * representation of the nexthop. If the nexthop
936 * defines a preferred source, the src parameter
937 * will be modified to point to that src, otherwise
938 * it will be kept unmodified.
940 * @param routedesc: Human readable description of route type
941 * (direct/recursive, single-/multipath)
942 * @param bytelen: Length of addresses in bytes.
943 * @param nexthop: Nexthop information
944 * @param rta: rtnetlink attribute structure
945 * @param rtnh: pointer to an rtnetlink nexthop structure
946 * @param src: pointer pointing to a location where
947 * the prefsrc should be stored.
950 _netlink_route_build_multipath(
951 const char *routedesc
,
953 struct nexthop
*nexthop
,
955 struct rtnexthop
*rtnh
,
959 struct nexthop_label
*nh_label
;
960 mpls_lse_t out_lse
[MPLS_MAX_LABELS
];
963 rtnh
->rtnh_len
= sizeof (*rtnh
);
964 rtnh
->rtnh_flags
= 0;
966 rta
->rta_len
+= rtnh
->rtnh_len
;
968 if (rtmsg
->rtm_family
== AF_INET
&&
969 (nexthop
->type
== NEXTHOP_TYPE_IPV6
970 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
))
972 char buf
[16] = "169.254.0.1";
973 struct in_addr ipv4_ll
;
975 inet_pton (AF_INET
, buf
, &ipv4_ll
);
977 rtnh
->rtnh_flags
|= RTNH_F_ONLINK
;
978 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTA_GATEWAY
,
980 rtnh
->rtnh_len
+= sizeof (struct rtattr
) + bytelen
;
981 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
983 if (nexthop
->rmap_src
.ipv4
.s_addr
)
984 *src
= &nexthop
->rmap_src
;
985 else if (nexthop
->src
.ipv4
.s_addr
)
986 *src
= &nexthop
->src
;
988 if (IS_ZEBRA_DEBUG_KERNEL
)
989 zlog_debug(" 5549: netlink_route_build_multipath() (%s): "
990 "nexthop via %s if %u",
991 routedesc
, buf
, nexthop
->ifindex
);
996 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
997 * (in the case of LER)
999 nh_label
= nexthop
->nh_label
;
1000 if (rtmsg
->rtm_family
== AF_MPLS
)
1003 assert (nh_label
->num_labels
== 1);
1006 if (nh_label
&& nh_label
->num_labels
)
1008 int i
, num_labels
= 0;
1010 char label_buf1
[20];
1012 for (i
= 0; i
< nh_label
->num_labels
; i
++)
1014 if (nh_label
->label
[i
] != MPLS_IMP_NULL_LABEL
)
1016 bos
= ((i
== (nh_label
->num_labels
- 1)) ? 1 : 0);
1017 out_lse
[i
] = mpls_lse_encode (nh_label
->label
[i
], 0, 0, bos
);
1019 sprintf (label_buf
, "label %d", nh_label
->label
[i
]);
1022 sprintf (label_buf1
, "/%d", nh_label
->label
[i
]);
1023 strcat (label_buf
, label_buf1
);
1030 if (rtmsg
->rtm_family
== AF_MPLS
)
1032 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTA_NEWDST
,
1033 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
1034 rtnh
->rtnh_len
+= RTA_LENGTH (num_labels
* sizeof(mpls_lse_t
));
1038 struct rtattr
*nest
;
1039 u_int16_t encap
= LWTUNNEL_ENCAP_MPLS
;
1040 int len
= rta
->rta_len
;
1042 rta_addattr_l(rta
, NL_PKT_BUF_SIZE
, RTA_ENCAP_TYPE
,
1043 &encap
, sizeof (u_int16_t
));
1044 nest
= rta_nest(rta
, NL_PKT_BUF_SIZE
, RTA_ENCAP
);
1045 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, MPLS_IPTUNNEL_DST
,
1046 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
1047 rta_nest_end(rta
, nest
);
1048 rtnh
->rtnh_len
+= rta
->rta_len
- len
;
1053 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
1054 rtnh
->rtnh_flags
|= RTNH_F_ONLINK
;
1056 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
1057 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
1059 _netlink_route_rta_add_gateway_info (rtmsg
->rtm_family
, AF_INET
, rta
,
1060 rtnh
, NL_PKT_BUF_SIZE
, bytelen
, nexthop
);
1061 if (nexthop
->rmap_src
.ipv4
.s_addr
)
1062 *src
= &nexthop
->rmap_src
;
1063 else if (nexthop
->src
.ipv4
.s_addr
)
1064 *src
= &nexthop
->src
;
1066 if (IS_ZEBRA_DEBUG_KERNEL
)
1067 zlog_debug("netlink_route_multipath() (%s): "
1068 "nexthop via %s %s if %u",
1070 inet_ntoa (nexthop
->gate
.ipv4
),
1071 label_buf
, nexthop
->ifindex
);
1073 if (nexthop
->type
== NEXTHOP_TYPE_IPV6
1074 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
1076 _netlink_route_rta_add_gateway_info (rtmsg
->rtm_family
, AF_INET6
, rta
,
1077 rtnh
, NL_PKT_BUF_SIZE
, bytelen
, nexthop
);
1079 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
1080 *src
= &nexthop
->rmap_src
;
1081 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
1082 *src
= &nexthop
->src
;
1084 if (IS_ZEBRA_DEBUG_KERNEL
)
1085 zlog_debug("netlink_route_multipath() (%s): "
1086 "nexthop via %s %s if %u",
1088 inet6_ntoa (nexthop
->gate
.ipv6
),
1089 label_buf
, nexthop
->ifindex
);
1092 if (nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
1093 || nexthop
->type
== NEXTHOP_TYPE_IFINDEX
)
1095 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
1097 if (nexthop
->rmap_src
.ipv4
.s_addr
)
1098 *src
= &nexthop
->rmap_src
;
1099 else if (nexthop
->src
.ipv4
.s_addr
)
1100 *src
= &nexthop
->src
;
1102 if (IS_ZEBRA_DEBUG_KERNEL
)
1103 zlog_debug("netlink_route_multipath() (%s): "
1104 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
1106 else if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
1108 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
1110 if (IS_ZEBRA_DEBUG_KERNEL
)
1111 zlog_debug("netlink_route_multipath() (%s): "
1112 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
1116 rtnh
->rtnh_ifindex
= 0;
1121 _netlink_mpls_build_singlepath(
1122 const char *routedesc
,
1123 zebra_nhlfe_t
*nhlfe
,
1124 struct nlmsghdr
*nlmsg
,
1125 struct rtmsg
*rtmsg
,
1132 family
= NHLFE_FAMILY (nhlfe
);
1133 bytelen
= (family
== AF_INET
? 4 : 16);
1134 _netlink_route_build_singlepath(routedesc
, bytelen
, nhlfe
->nexthop
,
1135 nlmsg
, rtmsg
, req_size
, cmd
);
1140 _netlink_mpls_build_multipath(
1141 const char *routedesc
,
1142 zebra_nhlfe_t
*nhlfe
,
1144 struct rtnexthop
*rtnh
,
1145 struct rtmsg
*rtmsg
,
1151 family
= NHLFE_FAMILY (nhlfe
);
1152 bytelen
= (family
== AF_INET
? 4 : 16);
1153 _netlink_route_build_multipath(routedesc
, bytelen
, nhlfe
->nexthop
,
1154 rta
, rtnh
, rtmsg
, src
);
1158 /* Log debug information for netlink_route_multipath
1159 * if debug logging is enabled.
1161 * @param cmd: Netlink command which is to be processed
1162 * @param p: Prefix for which the change is due
1163 * @param nexthop: Nexthop which is currently processed
1164 * @param routedesc: Semantic annotation for nexthop
1165 * (recursive, multipath, etc.)
1166 * @param family: Address family which the change concerns
1169 _netlink_route_debug(
1172 struct nexthop
*nexthop
,
1173 const char *routedesc
,
1175 struct zebra_vrf
*zvrf
)
1177 if (IS_ZEBRA_DEBUG_KERNEL
)
1179 char buf
[PREFIX_STRLEN
];
1180 zlog_debug ("netlink_route_multipath() (%s): %s %s vrf %u type %s",
1182 nl_msg_type_to_str (cmd
),
1183 prefix2str (p
, buf
, sizeof(buf
)), zvrf_id (zvrf
),
1184 (nexthop
) ? nexthop_type_to_str (nexthop
->type
) : "UNK");
1189 _netlink_mpls_debug(
1192 const char *routedesc
)
1194 if (IS_ZEBRA_DEBUG_KERNEL
)
1195 zlog_debug ("netlink_mpls_multipath() (%s): %s %u/20",
1196 routedesc
, nl_msg_type_to_str (cmd
), label
);
1200 netlink_neigh_update (int cmd
, int ifindex
, uint32_t addr
, char *lla
, int llalen
)
1208 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1210 memset(&req
.n
, 0, sizeof(req
.n
));
1211 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
1213 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ndmsg
));
1214 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1215 req
.n
.nlmsg_type
= cmd
; //RTM_NEWNEIGH or RTM_DELNEIGH
1216 req
.ndm
.ndm_family
= AF_INET
;
1217 req
.ndm
.ndm_state
= NUD_PERMANENT
;
1218 req
.ndm
.ndm_ifindex
= ifindex
;
1219 req
.ndm
.ndm_type
= RTN_UNICAST
;
1221 addattr_l(&req
.n
, sizeof(req
), NDA_DST
, &addr
, 4);
1222 addattr_l(&req
.n
, sizeof(req
), NDA_LLADDR
, lla
, llalen
);
1224 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
);
1227 /* Routing table change via netlink interface. */
1228 /* Update flag indicates whether this is a "replace" or not. */
1230 netlink_route_multipath (int cmd
, struct prefix
*p
, struct rib
*rib
,
1234 struct sockaddr_nl snl
;
1235 struct nexthop
*nexthop
= NULL
, *tnexthop
;
1239 int family
= PREFIX_FAMILY(p
);
1240 const char *routedesc
;
1248 char buf
[NL_PKT_BUF_SIZE
];
1251 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1252 struct zebra_vrf
*zvrf
= vrf_info_lookup (rib
->vrf_id
);
1254 memset (&req
, 0, sizeof req
- NL_PKT_BUF_SIZE
);
1256 bytelen
= (family
== AF_INET
? 4 : 16);
1258 req
.n
.nlmsg_len
= NLMSG_LENGTH (sizeof (struct rtmsg
));
1259 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1260 if ((cmd
== RTM_NEWROUTE
) && update
)
1261 req
.n
.nlmsg_flags
|= NLM_F_REPLACE
;
1262 req
.n
.nlmsg_type
= cmd
;
1263 req
.r
.rtm_family
= family
;
1264 req
.r
.rtm_dst_len
= p
->prefixlen
;
1265 req
.r
.rtm_protocol
= RTPROT_ZEBRA
;
1266 req
.r
.rtm_scope
= RT_SCOPE_UNIVERSE
;
1268 if ((rib
->flags
& ZEBRA_FLAG_BLACKHOLE
) || (rib
->flags
& ZEBRA_FLAG_REJECT
))
1273 if (cmd
== RTM_NEWROUTE
)
1277 if (rib
->flags
& ZEBRA_FLAG_BLACKHOLE
)
1278 req
.r
.rtm_type
= RTN_BLACKHOLE
;
1279 else if (rib
->flags
& ZEBRA_FLAG_REJECT
)
1280 req
.r
.rtm_type
= RTN_UNREACHABLE
;
1282 assert (RTN_BLACKHOLE
!= RTN_UNREACHABLE
); /* false */
1285 req
.r
.rtm_type
= RTN_UNICAST
;
1288 addattr_l (&req
.n
, sizeof req
, RTA_DST
, &p
->u
.prefix
, bytelen
);
1291 /* Hardcode the metric for all routes coming from zebra. Metric isn't used
1292 * either by the kernel or by zebra. Its purely for calculating best path(s)
1293 * by the routing protocol and for communicating with protocol peers.
1295 addattr32 (&req
.n
, sizeof req
, RTA_PRIORITY
, NL_DEFAULT_ROUTE_METRIC
);
1297 /* Table corresponding to this route. */
1298 if (rib
->table
< 256)
1299 req
.r
.rtm_table
= rib
->table
;
1302 req
.r
.rtm_table
= RT_TABLE_UNSPEC
;
1303 addattr32(&req
.n
, sizeof req
, RTA_TABLE
, rib
->table
);
1306 if (rib
->mtu
|| rib
->nexthop_mtu
)
1308 char buf
[NL_PKT_BUF_SIZE
];
1309 struct rtattr
*rta
= (void *) buf
;
1310 u_int32_t mtu
= rib
->mtu
;
1311 if (!mtu
|| (rib
->nexthop_mtu
&& rib
->nexthop_mtu
< mtu
))
1312 mtu
= rib
->nexthop_mtu
;
1313 rta
->rta_type
= RTA_METRICS
;
1314 rta
->rta_len
= RTA_LENGTH(0);
1315 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTAX_MTU
, &mtu
, sizeof mtu
);
1316 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_METRICS
, RTA_DATA (rta
),
1322 if (cmd
== RTM_NEWROUTE
)
1323 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1325 /* We shouldn't encounter recursive nexthops on discard routes,
1326 * but it is probably better to handle that case correctly anyway.
1328 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1334 /* Count overall nexthops so we can decide whether to use singlepath
1335 * or multipath case. */
1337 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1339 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1341 if (cmd
== RTM_NEWROUTE
&& !CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1343 if (cmd
== RTM_DELROUTE
&& !CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))
1349 /* Singlepath case. */
1350 if (nexthop_num
== 1 || MULTIPATH_NUM
== 1)
1353 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1355 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1359 if (family
== AF_INET
)
1361 if (nexthop
->rmap_src
.ipv4
.s_addr
!= 0)
1363 src
.ipv4
= nexthop
->rmap_src
.ipv4
;
1366 else if (nexthop
->src
.ipv4
.s_addr
!= 0)
1368 src
.ipv4
= nexthop
->src
.ipv4
;
1372 else if (family
== AF_INET6
)
1374 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
1376 src
.ipv6
= nexthop
->rmap_src
.ipv6
;
1379 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
1381 src
.ipv6
= nexthop
->src
.ipv6
;
1389 if ((cmd
== RTM_NEWROUTE
1390 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1391 || (cmd
== RTM_DELROUTE
1392 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
)))
1394 routedesc
= recursing
? "recursive, 1 hop" : "single hop";
1396 _netlink_route_debug(cmd
, p
, nexthop
, routedesc
, family
, zvrf
);
1397 _netlink_route_build_singlepath(routedesc
, bytelen
,
1398 nexthop
, &req
.n
, &req
.r
,
1404 if (setsrc
&& (cmd
== RTM_NEWROUTE
))
1406 if (family
== AF_INET
)
1407 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv4
, bytelen
);
1408 else if (family
== AF_INET6
)
1409 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv6
, bytelen
);
1414 char buf
[NL_PKT_BUF_SIZE
];
1415 struct rtattr
*rta
= (void *) buf
;
1416 struct rtnexthop
*rtnh
;
1417 union g_addr
*src1
= NULL
;
1419 rta
->rta_type
= RTA_MULTIPATH
;
1420 rta
->rta_len
= RTA_LENGTH (0);
1421 rtnh
= RTA_DATA (rta
);
1424 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1426 if (nexthop_num
>= MULTIPATH_NUM
)
1429 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1431 /* This only works for IPv4 now */
1434 if (family
== AF_INET
)
1436 if (nexthop
->rmap_src
.ipv4
.s_addr
!= 0)
1438 src
.ipv4
= nexthop
->rmap_src
.ipv4
;
1441 else if (nexthop
->src
.ipv4
.s_addr
!= 0)
1443 src
.ipv4
= nexthop
->src
.ipv4
;
1447 else if (family
== AF_INET6
)
1449 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
1451 src
.ipv6
= nexthop
->rmap_src
.ipv6
;
1454 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
1456 src
.ipv6
= nexthop
->src
.ipv6
;
1464 if ((cmd
== RTM_NEWROUTE
1465 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1466 || (cmd
== RTM_DELROUTE
1467 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
)))
1469 routedesc
= recursing
? "recursive, multihop" : "multihop";
1472 _netlink_route_debug(cmd
, p
, nexthop
,
1473 routedesc
, family
, zvrf
);
1474 _netlink_route_build_multipath(routedesc
, bytelen
,
1475 nexthop
, rta
, rtnh
, &req
.r
, &src1
);
1476 rtnh
= RTNH_NEXT (rtnh
);
1478 if (!setsrc
&& src1
)
1480 if (family
== AF_INET
)
1481 src
.ipv4
= src1
->ipv4
;
1482 else if (family
== AF_INET6
)
1483 src
.ipv6
= src1
->ipv6
;
1489 if (setsrc
&& (cmd
== RTM_NEWROUTE
))
1491 if (family
== AF_INET
)
1492 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv4
, bytelen
);
1493 else if (family
== AF_INET6
)
1494 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv6
, bytelen
);
1495 if (IS_ZEBRA_DEBUG_KERNEL
)
1496 zlog_debug("Setting source");
1499 if (rta
->rta_len
> RTA_LENGTH (0))
1500 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_MULTIPATH
, RTA_DATA (rta
),
1504 /* If there is no useful nexthop then return. */
1505 if (nexthop_num
== 0)
1507 if (IS_ZEBRA_DEBUG_KERNEL
)
1508 zlog_debug ("netlink_route_multipath(): No useful nexthop.");
1514 /* Destination netlink address. */
1515 memset (&snl
, 0, sizeof snl
);
1516 snl
.nl_family
= AF_NETLINK
;
1518 /* Talk to netlink socket. */
1519 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
);
1523 netlink_get_ipmr_sg_stats (void *in
)
1526 struct mcast_route_data
*mr
= (struct mcast_route_data
*)in
;
1534 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1536 memset(&req
.n
, 0, sizeof(req
.n
));
1537 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
1539 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ndmsg
));
1540 req
.n
.nlmsg_flags
= NLM_F_REQUEST
;
1541 req
.ndm
.ndm_family
= AF_INET
;
1542 req
.n
.nlmsg_type
= RTM_GETROUTE
;
1544 addattr_l (&req
.n
, sizeof (req
), RTA_IIF
, &mroute
->ifindex
, 4);
1545 addattr_l (&req
.n
, sizeof (req
), RTA_OIF
, &mroute
->ifindex
, 4);
1546 addattr_l (&req
.n
, sizeof (req
), RTA_SRC
, &mroute
->sg
.src
.s_addr
, 4);
1547 addattr_l (&req
.n
, sizeof (req
), RTA_DST
, &mroute
->sg
.grp
.s_addr
, 4);
1549 suc
= netlink_talk (netlink_route_change_read_multicast
, &req
.n
, &zns
->netlink_cmd
, zns
);
1556 kernel_route_rib (struct prefix
*p
, struct rib
*old
, struct rib
*new)
1559 return netlink_route_multipath (RTM_NEWROUTE
, p
, new, 0);
1561 return netlink_route_multipath (RTM_DELROUTE
, p
, old
, 0);
1563 return netlink_route_multipath (RTM_NEWROUTE
, p
, new, 1);
1567 kernel_neigh_update (int add
, int ifindex
, uint32_t addr
, char *lla
, int llalen
)
1569 return netlink_neigh_update(add
? RTM_NEWNEIGH
: RTM_DELNEIGH
, ifindex
, addr
,
1574 * MPLS label forwarding table change via netlink interface.
1577 netlink_mpls_multipath (int cmd
, zebra_lsp_t
*lsp
)
1580 zebra_nhlfe_t
*nhlfe
;
1581 struct nexthop
*nexthop
= NULL
;
1583 const char *routedesc
;
1584 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1590 char buf
[NL_PKT_BUF_SIZE
];
1593 memset (&req
, 0, sizeof req
- NL_PKT_BUF_SIZE
);
1597 * Count # nexthops so we can decide whether to use singlepath
1598 * or multipath case.
1601 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1603 nexthop
= nhlfe
->nexthop
;
1606 if (cmd
== RTM_NEWROUTE
)
1608 /* Count all selected NHLFEs */
1609 if (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
1610 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1615 /* Count all installed NHLFEs */
1616 if (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
1617 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))
1622 if (nexthop_num
== 0) // unexpected
1625 req
.n
.nlmsg_len
= NLMSG_LENGTH (sizeof (struct rtmsg
));
1626 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1627 req
.n
.nlmsg_type
= cmd
;
1628 req
.r
.rtm_family
= AF_MPLS
;
1629 req
.r
.rtm_table
= RT_TABLE_MAIN
;
1630 req
.r
.rtm_dst_len
= MPLS_LABEL_LEN_BITS
;
1631 req
.r
.rtm_protocol
= RTPROT_ZEBRA
;
1632 req
.r
.rtm_scope
= RT_SCOPE_UNIVERSE
;
1633 req
.r
.rtm_type
= RTN_UNICAST
;
1635 if (cmd
== RTM_NEWROUTE
)
1636 /* We do a replace to handle update. */
1637 req
.n
.nlmsg_flags
|= NLM_F_REPLACE
;
1639 /* Fill destination */
1640 lse
= mpls_lse_encode (lsp
->ile
.in_label
, 0, 0, 1);
1641 addattr_l (&req
.n
, sizeof req
, RTA_DST
, &lse
, sizeof(mpls_lse_t
));
1643 /* Fill nexthops (paths) based on single-path or multipath. The paths
1644 * chosen depend on the operation.
1646 if (nexthop_num
== 1 || MULTIPATH_NUM
== 1)
1648 routedesc
= "single hop";
1649 _netlink_mpls_debug(cmd
, lsp
->ile
.in_label
, routedesc
);
1652 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1654 nexthop
= nhlfe
->nexthop
;
1658 if ((cmd
== RTM_NEWROUTE
&&
1659 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
1660 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))) ||
1661 (cmd
== RTM_DELROUTE
&&
1662 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
1663 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))))
1665 /* Add the gateway */
1666 _netlink_mpls_build_singlepath(routedesc
, nhlfe
,
1667 &req
.n
, &req
.r
, sizeof req
, cmd
);
1668 if (cmd
== RTM_NEWROUTE
)
1670 SET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1671 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1675 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1676 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1683 else /* Multipath case */
1685 char buf
[NL_PKT_BUF_SIZE
];
1686 struct rtattr
*rta
= (void *) buf
;
1687 struct rtnexthop
*rtnh
;
1688 union g_addr
*src1
= NULL
;
1690 rta
->rta_type
= RTA_MULTIPATH
;
1691 rta
->rta_len
= RTA_LENGTH (0);
1692 rtnh
= RTA_DATA (rta
);
1694 routedesc
= "multihop";
1695 _netlink_mpls_debug(cmd
, lsp
->ile
.in_label
, routedesc
);
1698 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1700 nexthop
= nhlfe
->nexthop
;
1704 if (MULTIPATH_NUM
!= 0 && nexthop_num
>= MULTIPATH_NUM
)
1707 if ((cmd
== RTM_NEWROUTE
&&
1708 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
1709 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))) ||
1710 (cmd
== RTM_DELROUTE
&&
1711 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
1712 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))))
1716 /* Build the multipath */
1717 _netlink_mpls_build_multipath(routedesc
, nhlfe
, rta
,
1718 rtnh
, &req
.r
, &src1
);
1719 rtnh
= RTNH_NEXT (rtnh
);
1721 if (cmd
== RTM_NEWROUTE
)
1723 SET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1724 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1728 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1729 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1735 /* Add the multipath */
1736 if (rta
->rta_len
> RTA_LENGTH (0))
1737 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_MULTIPATH
, RTA_DATA (rta
),
1741 /* Talk to netlink socket. */
1742 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
);
1746 * Handle failure in LSP install, clear flags for NHLFE.
1749 clear_nhlfe_installed (zebra_lsp_t
*lsp
)
1751 zebra_nhlfe_t
*nhlfe
;
1752 struct nexthop
*nexthop
;
1754 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1756 nexthop
= nhlfe
->nexthop
;
1760 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1761 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);