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 */
106 static inline int is_selfroute(int proto
)
108 if ((proto
== RTPROT_BGP
) || (proto
== RTPROT_OSPF
) ||
109 (proto
== RTPROT_STATIC
) || (proto
== RTPROT_ZEBRA
) ||
110 (proto
== RTPROT_ISIS
) || (proto
== RTPROT_RIPNG
)) {
117 static inline int get_rt_proto(int proto
)
120 case ZEBRA_ROUTE_BGP
:
123 case ZEBRA_ROUTE_OSPF
:
124 case ZEBRA_ROUTE_OSPF6
:
127 case ZEBRA_ROUTE_STATIC
:
128 proto
= RTPROT_STATIC
;
130 case ZEBRA_ROUTE_ISIS
:
133 case ZEBRA_ROUTE_RIP
:
136 case ZEBRA_ROUTE_RIPNG
:
137 proto
= RTPROT_RIPNG
;
140 proto
= RTPROT_ZEBRA
;
148 Pending: create an efficient table_id (in a tree/hash) based lookup)
151 vrf_lookup_by_table (u_int32_t table_id
)
154 struct zebra_vrf
*zvrf
;
156 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
)
158 if ((zvrf
= vrf
->info
) == NULL
||
159 (zvrf
->table_id
!= table_id
))
162 return zvrf_id (zvrf
);
168 /* Looking up routing table by netlink interface. */
170 netlink_route_change_read_unicast (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
171 ns_id_t ns_id
, int startup
)
175 struct rtattr
*tb
[RTA_MAX
+ 1];
178 struct prefix_ipv6 src_p
;
179 vrf_id_t vrf_id
= VRF_DEFAULT
;
181 char anyaddr
[16] = { 0 };
190 void *prefsrc
= NULL
; /* IPv4 preferred source host address */
191 void *src
= NULL
; /* IPv6 srcdest source prefix */
193 rtm
= NLMSG_DATA (h
);
195 if (startup
&& h
->nlmsg_type
!= RTM_NEWROUTE
)
197 if (startup
&& rtm
->rtm_type
!= RTN_UNICAST
)
200 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
204 memset (tb
, 0, sizeof tb
);
205 netlink_parse_rtattr (tb
, RTA_MAX
, RTM_RTA (rtm
), len
);
207 if (rtm
->rtm_flags
& RTM_F_CLONED
)
209 if (rtm
->rtm_protocol
== RTPROT_REDIRECT
)
211 if (rtm
->rtm_protocol
== RTPROT_KERNEL
)
215 is_selfroute (rtm
->rtm_protocol
) &&
216 h
->nlmsg_type
== RTM_NEWROUTE
)
219 /* We don't care about change notifications for the MPLS table. */
220 /* TODO: Revisit this. */
221 if (rtm
->rtm_family
== AF_MPLS
)
224 /* Table corresponding to route. */
226 table
= *(int *) RTA_DATA (tb
[RTA_TABLE
]);
228 table
= rtm
->rtm_table
;
231 vrf_id
= vrf_lookup_by_table(table
);
232 if (vrf_id
== VRF_DEFAULT
)
234 if (!is_zebra_valid_kernel_table(table
) &&
235 !is_zebra_main_routing_table(table
))
239 /* Route which inserted by Zebra. */
240 if (is_selfroute(rtm
->rtm_protocol
))
241 flags
|= ZEBRA_FLAG_SELFROUTE
;
244 index
= *(int *) RTA_DATA (tb
[RTA_OIF
]);
247 dest
= RTA_DATA (tb
[RTA_DST
]);
252 src
= RTA_DATA (tb
[RTA_SRC
]);
257 prefsrc
= RTA_DATA (tb
[RTA_PREFSRC
]);
260 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
262 if (h
->nlmsg_type
== RTM_NEWROUTE
)
264 if (tb
[RTA_PRIORITY
])
265 metric
= *(int *) RTA_DATA(tb
[RTA_PRIORITY
]);
269 struct rtattr
*mxrta
[RTAX_MAX
+1];
271 memset (mxrta
, 0, sizeof mxrta
);
272 netlink_parse_rtattr (mxrta
, RTAX_MAX
, RTA_DATA(tb
[RTA_METRICS
]),
273 RTA_PAYLOAD(tb
[RTA_METRICS
]));
276 mtu
= *(u_int32_t
*) RTA_DATA(mxrta
[RTAX_MTU
]);
280 if (rtm
->rtm_family
== AF_INET
)
283 memcpy (&p
.u
.prefix4
, dest
, 4);
284 p
.prefixlen
= rtm
->rtm_dst_len
;
286 else if (rtm
->rtm_family
== AF_INET6
)
289 memcpy (&p
.u
.prefix6
, dest
, 16);
290 p
.prefixlen
= rtm
->rtm_dst_len
;
292 src_p
.family
= AF_INET6
;
293 memcpy (&src_p
.prefix
, src
, 16);
294 src_p
.prefixlen
= rtm
->rtm_src_len
;
297 if (rtm
->rtm_src_len
!= 0)
299 char buf
[PREFIX_STRLEN
];
300 zlog_warn ("unsupported IPv[4|6] sourcedest route (dest %s vrf %u)",
301 prefix2str (&p
, buf
, sizeof(buf
)), vrf_id
);
305 if (IS_ZEBRA_DEBUG_KERNEL
)
307 char buf
[PREFIX_STRLEN
];
308 char buf2
[PREFIX_STRLEN
];
309 zlog_debug ("%s %s%s%s vrf %u",
310 nl_msg_type_to_str (h
->nlmsg_type
),
311 prefix2str (&p
, buf
, sizeof(buf
)),
312 src_p
.prefixlen
? " from " : "",
313 src_p
.prefixlen
? prefix2str(&src_p
, buf2
, sizeof(buf2
)) : "",
318 if (rtm
->rtm_family
== AF_INET6
)
321 if (h
->nlmsg_type
== RTM_NEWROUTE
)
323 if (!tb
[RTA_MULTIPATH
])
324 rib_add (afi
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
325 0, flags
, &p
, NULL
, gate
, prefsrc
, index
,
326 table
, metric
, mtu
, 0);
329 /* This is a multipath route */
332 struct rtnexthop
*rtnh
=
333 (struct rtnexthop
*) RTA_DATA (tb
[RTA_MULTIPATH
]);
335 len
= RTA_PAYLOAD (tb
[RTA_MULTIPATH
]);
337 rib
= XCALLOC (MTYPE_RIB
, sizeof (struct rib
));
338 rib
->type
= ZEBRA_ROUTE_KERNEL
;
341 rib
->metric
= metric
;
343 rib
->vrf_id
= vrf_id
;
345 rib
->nexthop_num
= 0;
346 rib
->uptime
= time (NULL
);
350 if (len
< (int) sizeof (*rtnh
) || rtnh
->rtnh_len
> len
)
353 index
= rtnh
->rtnh_ifindex
;
355 if (rtnh
->rtnh_len
> sizeof (*rtnh
))
357 memset (tb
, 0, sizeof (tb
));
358 netlink_parse_rtattr (tb
, RTA_MAX
, RTNH_DATA (rtnh
),
359 rtnh
->rtnh_len
- sizeof (*rtnh
));
361 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
366 if (rtm
->rtm_family
== AF_INET
)
369 rib_nexthop_ipv4_ifindex_add (rib
, gate
, prefsrc
, index
);
371 rib_nexthop_ipv4_add (rib
, gate
, prefsrc
);
373 else if (rtm
->rtm_family
== AF_INET6
)
376 rib_nexthop_ipv6_ifindex_add (rib
, gate
, index
);
378 rib_nexthop_ipv6_add (rib
,gate
);
382 rib_nexthop_ifindex_add (rib
, index
);
384 len
-= NLMSG_ALIGN(rtnh
->rtnh_len
);
385 rtnh
= RTNH_NEXT(rtnh
);
388 zserv_nexthop_num_warn(__func__
, (const struct prefix
*)&p
,
390 if (rib
->nexthop_num
== 0)
391 XFREE (MTYPE_RIB
, rib
);
393 rib_add_multipath (AFI_IP
, SAFI_UNICAST
, &p
, NULL
, rib
);
398 if (!tb
[RTA_MULTIPATH
])
399 rib_delete (afi
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
, 0, flags
,
400 &p
, NULL
, gate
, index
, table
);
403 struct rtnexthop
*rtnh
=
404 (struct rtnexthop
*) RTA_DATA (tb
[RTA_MULTIPATH
]);
406 len
= RTA_PAYLOAD (tb
[RTA_MULTIPATH
]);
410 if (len
< (int) sizeof (*rtnh
) || rtnh
->rtnh_len
> len
)
414 if (rtnh
->rtnh_len
> sizeof (*rtnh
))
416 memset (tb
, 0, sizeof (tb
));
417 netlink_parse_rtattr (tb
, RTA_MAX
, RTNH_DATA (rtnh
),
418 rtnh
->rtnh_len
- sizeof (*rtnh
));
420 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
424 rib_delete (afi
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
, 0, flags
,
425 &p
, NULL
, gate
, index
, table
);
427 len
-= NLMSG_ALIGN(rtnh
->rtnh_len
);
428 rtnh
= RTNH_NEXT(rtnh
);
436 static struct mcast_route_data
*mroute
= NULL
;
439 netlink_route_change_read_multicast (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
440 ns_id_t ns_id
, int startup
)
444 struct rtattr
*tb
[RTA_MAX
+ 1];
445 struct mcast_route_data
*m
;
446 struct mcast_route_data mr
;
453 char oif_list
[256] = "\0";
454 vrf_id_t vrf
= ns_id
;
460 memset (&mr
, 0, sizeof (mr
));
464 rtm
= NLMSG_DATA (h
);
466 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
468 memset (tb
, 0, sizeof tb
);
469 netlink_parse_rtattr (tb
, RTA_MAX
, RTM_RTA (rtm
), len
);
472 iif
= *(int *)RTA_DATA (tb
[RTA_IIF
]);
475 m
->sg
.src
= *(struct in_addr
*)RTA_DATA (tb
[RTA_SRC
]);
478 m
->sg
.grp
= *(struct in_addr
*)RTA_DATA (tb
[RTA_DST
]);
480 if ((RTA_EXPIRES
<= RTA_MAX
) && tb
[RTA_EXPIRES
])
481 m
->lastused
= *(unsigned long long *)RTA_DATA (tb
[RTA_EXPIRES
]);
483 if (tb
[RTA_MULTIPATH
])
485 struct rtnexthop
*rtnh
=
486 (struct rtnexthop
*)RTA_DATA (tb
[RTA_MULTIPATH
]);
488 len
= RTA_PAYLOAD (tb
[RTA_MULTIPATH
]);
491 if (len
< (int) sizeof (*rtnh
) || rtnh
->rtnh_len
> len
)
494 oif
[oif_count
] = rtnh
->rtnh_ifindex
;
497 len
-= NLMSG_ALIGN (rtnh
->rtnh_len
);
498 rtnh
= RTNH_NEXT (rtnh
);
502 if (IS_ZEBRA_DEBUG_KERNEL
)
504 struct interface
*ifp
;
505 strcpy (sbuf
, inet_ntoa (m
->sg
.src
));
506 strcpy (gbuf
, inet_ntoa (m
->sg
.grp
));
507 for (count
= 0; count
< oif_count
; count
++)
509 ifp
= if_lookup_by_index (oif
[count
], vrf
);
512 sprintf (temp
, "%s ", ifp
->name
);
513 strcat (oif_list
, temp
);
515 ifp
= if_lookup_by_index (iif
, vrf
);
516 zlog_debug ("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld",
517 nl_msg_type_to_str(h
->nlmsg_type
), sbuf
, gbuf
, ifp
->name
, oif_list
, m
->lastused
);
523 netlink_route_change (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
524 ns_id_t ns_id
, int startup
)
527 vrf_id_t vrf_id
= ns_id
;
530 rtm
= NLMSG_DATA (h
);
532 if (!(h
->nlmsg_type
== RTM_NEWROUTE
|| h
->nlmsg_type
== RTM_DELROUTE
))
534 /* If this is not route add/delete message print warning. */
535 zlog_warn ("Kernel message: %d vrf %u\n", h
->nlmsg_type
, vrf_id
);
539 /* Connected route. */
540 if (IS_ZEBRA_DEBUG_KERNEL
)
541 zlog_debug ("%s %s %s proto %s vrf %u",
542 nl_msg_type_to_str (h
->nlmsg_type
),
543 nl_family_to_str (rtm
->rtm_family
),
544 nl_rttype_to_str (rtm
->rtm_type
),
545 nl_rtproto_to_str (rtm
->rtm_protocol
),
548 /* We don't care about change notifications for the MPLS table. */
549 /* TODO: Revisit this. */
550 if (rtm
->rtm_family
== AF_MPLS
)
553 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
557 switch (rtm
->rtm_type
)
560 netlink_route_change_read_unicast (snl
, h
, ns_id
, startup
);
563 netlink_route_change_read_multicast (snl
, h
, ns_id
, startup
);
573 /* Routing table read function using netlink interface. Only called
576 netlink_route_read (struct zebra_ns
*zns
)
580 /* Get IPv4 routing table. */
581 ret
= netlink_request (AF_INET
, RTM_GETROUTE
, &zns
->netlink_cmd
);
584 ret
= netlink_parse_info (netlink_route_change_read_unicast
, &zns
->netlink_cmd
, zns
, 0, 1);
588 /* Get IPv6 routing table. */
589 ret
= netlink_request (AF_INET6
, RTM_GETROUTE
, &zns
->netlink_cmd
);
592 ret
= netlink_parse_info (netlink_route_change_read_unicast
, &zns
->netlink_cmd
, zns
, 0, 1);
600 _netlink_route_nl_add_gateway_info (u_char route_family
, u_char gw_family
,
601 struct nlmsghdr
*nlmsg
,
602 size_t req_size
, int bytelen
,
603 struct nexthop
*nexthop
)
605 if (route_family
== AF_MPLS
)
607 struct gw_family_t gw_fam
;
609 gw_fam
.family
= gw_family
;
610 if (gw_family
== AF_INET
)
611 memcpy (&gw_fam
.gate
.ipv4
, &nexthop
->gate
.ipv4
, bytelen
);
613 memcpy (&gw_fam
.gate
.ipv6
, &nexthop
->gate
.ipv6
, bytelen
);
614 addattr_l (nlmsg
, req_size
, RTA_VIA
, &gw_fam
.family
, bytelen
+2);
618 if (gw_family
== AF_INET
)
619 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv4
, bytelen
);
621 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv6
, bytelen
);
626 _netlink_route_rta_add_gateway_info (u_char route_family
, u_char gw_family
,
627 struct rtattr
*rta
, struct rtnexthop
*rtnh
,
628 size_t req_size
, int bytelen
,
629 struct nexthop
*nexthop
)
631 if (route_family
== AF_MPLS
)
633 struct gw_family_t gw_fam
;
635 gw_fam
.family
= gw_family
;
636 if (gw_family
== AF_INET
)
637 memcpy (&gw_fam
.gate
.ipv4
, &nexthop
->gate
.ipv4
, bytelen
);
639 memcpy (&gw_fam
.gate
.ipv6
, &nexthop
->gate
.ipv6
, bytelen
);
640 rta_addattr_l (rta
, req_size
, RTA_VIA
, &gw_fam
.family
, bytelen
+2);
641 rtnh
->rtnh_len
+= RTA_LENGTH (bytelen
+ 2);
645 if (gw_family
== AF_INET
)
646 rta_addattr_l (rta
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv4
, bytelen
);
648 rta_addattr_l (rta
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv6
, bytelen
);
649 rtnh
->rtnh_len
+= sizeof (struct rtattr
) + bytelen
;
653 /* This function takes a nexthop as argument and adds
654 * the appropriate netlink attributes to an existing
657 * @param routedesc: Human readable description of route type
658 * (direct/recursive, single-/multipath)
659 * @param bytelen: Length of addresses in bytes.
660 * @param nexthop: Nexthop information
661 * @param nlmsg: nlmsghdr structure to fill in.
662 * @param req_size: The size allocated for the message.
665 _netlink_route_build_singlepath(
666 const char *routedesc
,
668 struct nexthop
*nexthop
,
669 struct nlmsghdr
*nlmsg
,
674 struct nexthop_label
*nh_label
;
675 mpls_lse_t out_lse
[MPLS_MAX_LABELS
];
678 if (rtmsg
->rtm_family
== AF_INET
&&
679 (nexthop
->type
== NEXTHOP_TYPE_IPV6
680 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
))
682 char buf
[16] = "169.254.0.1";
683 struct in_addr ipv4_ll
;
685 inet_pton (AF_INET
, buf
, &ipv4_ll
);
686 rtmsg
->rtm_flags
|= RTNH_F_ONLINK
;
687 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &ipv4_ll
, 4);
688 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
690 if (nexthop
->rmap_src
.ipv4
.s_addr
&& (cmd
== RTM_NEWROUTE
))
691 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
692 &nexthop
->rmap_src
.ipv4
, bytelen
);
693 else if (nexthop
->src
.ipv4
.s_addr
&& (cmd
== RTM_NEWROUTE
))
694 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
695 &nexthop
->src
.ipv4
, bytelen
);
697 if (IS_ZEBRA_DEBUG_KERNEL
)
698 zlog_debug(" 5549: _netlink_route_build_singlepath() (%s): "
699 "nexthop via %s if %u",
700 routedesc
, buf
, nexthop
->ifindex
);
705 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
706 * (in the case of LER)
708 nh_label
= nexthop
->nh_label
;
709 if (rtmsg
->rtm_family
== AF_MPLS
)
712 assert (nh_label
->num_labels
== 1);
715 if (nh_label
&& nh_label
->num_labels
)
717 int i
, num_labels
= 0;
721 for (i
= 0; i
< nh_label
->num_labels
; i
++)
723 if (nh_label
->label
[i
] != MPLS_IMP_NULL_LABEL
)
725 bos
= ((i
== (nh_label
->num_labels
- 1)) ? 1 : 0);
726 out_lse
[i
] = mpls_lse_encode (nh_label
->label
[i
], 0, 0, bos
);
728 sprintf (label_buf
, "label %d", nh_label
->label
[i
]);
731 sprintf (label_buf1
, "/%d", nh_label
->label
[i
]);
732 strcat (label_buf
, label_buf1
);
739 if (rtmsg
->rtm_family
== AF_MPLS
)
740 addattr_l (nlmsg
, req_size
, RTA_NEWDST
,
741 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
745 u_int16_t encap
= LWTUNNEL_ENCAP_MPLS
;
747 addattr_l(nlmsg
, req_size
, RTA_ENCAP_TYPE
,
748 &encap
, sizeof (u_int16_t
));
749 nest
= addattr_nest(nlmsg
, req_size
, RTA_ENCAP
);
750 addattr_l (nlmsg
, req_size
, MPLS_IPTUNNEL_DST
,
751 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
752 addattr_nest_end(nlmsg
, nest
);
757 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
758 rtmsg
->rtm_flags
|= RTNH_F_ONLINK
;
760 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
761 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
763 /* Send deletes to the kernel without specifying the next-hop */
764 if (cmd
!= RTM_DELROUTE
)
765 _netlink_route_nl_add_gateway_info (rtmsg
->rtm_family
, AF_INET
, nlmsg
,
766 req_size
, bytelen
, nexthop
);
768 if (cmd
== RTM_NEWROUTE
)
770 if (nexthop
->rmap_src
.ipv4
.s_addr
)
771 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
772 &nexthop
->rmap_src
.ipv4
, bytelen
);
773 else if (nexthop
->src
.ipv4
.s_addr
)
774 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
775 &nexthop
->src
.ipv4
, bytelen
);
778 if (IS_ZEBRA_DEBUG_KERNEL
)
779 zlog_debug("netlink_route_multipath() (%s): "
780 "nexthop via %s %s if %u",
782 inet_ntoa (nexthop
->gate
.ipv4
),
783 label_buf
, nexthop
->ifindex
);
785 if (nexthop
->type
== NEXTHOP_TYPE_IPV6
786 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
788 _netlink_route_nl_add_gateway_info (rtmsg
->rtm_family
, AF_INET6
, nlmsg
,
789 req_size
, bytelen
, nexthop
);
791 if (cmd
== RTM_NEWROUTE
)
793 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
794 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
795 &nexthop
->rmap_src
.ipv6
, bytelen
);
796 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
797 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
798 &nexthop
->src
.ipv6
, bytelen
);
801 if (IS_ZEBRA_DEBUG_KERNEL
)
802 zlog_debug("netlink_route_multipath() (%s): "
803 "nexthop via %s %s if %u",
805 inet6_ntoa (nexthop
->gate
.ipv6
),
806 label_buf
, nexthop
->ifindex
);
808 if (nexthop
->type
== NEXTHOP_TYPE_IFINDEX
809 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
811 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
813 if (cmd
== RTM_NEWROUTE
)
815 if (nexthop
->rmap_src
.ipv4
.s_addr
)
816 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
817 &nexthop
->rmap_src
.ipv4
, bytelen
);
818 else if (nexthop
->src
.ipv4
.s_addr
)
819 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
820 &nexthop
->src
.ipv4
, bytelen
);
823 if (IS_ZEBRA_DEBUG_KERNEL
)
824 zlog_debug("netlink_route_multipath() (%s): "
825 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
828 if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
830 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
832 if (cmd
== RTM_NEWROUTE
)
834 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
835 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
836 &nexthop
->rmap_src
.ipv6
, bytelen
);
837 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
838 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
839 &nexthop
->src
.ipv6
, bytelen
);
842 if (IS_ZEBRA_DEBUG_KERNEL
)
843 zlog_debug("netlink_route_multipath() (%s): "
844 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
848 /* This function takes a nexthop as argument and
849 * appends to the given rtattr/rtnexthop pair the
850 * representation of the nexthop. If the nexthop
851 * defines a preferred source, the src parameter
852 * will be modified to point to that src, otherwise
853 * it will be kept unmodified.
855 * @param routedesc: Human readable description of route type
856 * (direct/recursive, single-/multipath)
857 * @param bytelen: Length of addresses in bytes.
858 * @param nexthop: Nexthop information
859 * @param rta: rtnetlink attribute structure
860 * @param rtnh: pointer to an rtnetlink nexthop structure
861 * @param src: pointer pointing to a location where
862 * the prefsrc should be stored.
865 _netlink_route_build_multipath(
866 const char *routedesc
,
868 struct nexthop
*nexthop
,
870 struct rtnexthop
*rtnh
,
874 struct nexthop_label
*nh_label
;
875 mpls_lse_t out_lse
[MPLS_MAX_LABELS
];
878 rtnh
->rtnh_len
= sizeof (*rtnh
);
879 rtnh
->rtnh_flags
= 0;
881 rta
->rta_len
+= rtnh
->rtnh_len
;
883 if (rtmsg
->rtm_family
== AF_INET
&&
884 (nexthop
->type
== NEXTHOP_TYPE_IPV6
885 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
))
887 char buf
[16] = "169.254.0.1";
888 struct in_addr ipv4_ll
;
890 inet_pton (AF_INET
, buf
, &ipv4_ll
);
892 rtnh
->rtnh_flags
|= RTNH_F_ONLINK
;
893 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTA_GATEWAY
,
895 rtnh
->rtnh_len
+= sizeof (struct rtattr
) + bytelen
;
896 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
898 if (nexthop
->rmap_src
.ipv4
.s_addr
)
899 *src
= &nexthop
->rmap_src
;
900 else if (nexthop
->src
.ipv4
.s_addr
)
901 *src
= &nexthop
->src
;
903 if (IS_ZEBRA_DEBUG_KERNEL
)
904 zlog_debug(" 5549: netlink_route_build_multipath() (%s): "
905 "nexthop via %s if %u",
906 routedesc
, buf
, nexthop
->ifindex
);
911 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
912 * (in the case of LER)
914 nh_label
= nexthop
->nh_label
;
915 if (rtmsg
->rtm_family
== AF_MPLS
)
918 assert (nh_label
->num_labels
== 1);
921 if (nh_label
&& nh_label
->num_labels
)
923 int i
, num_labels
= 0;
927 for (i
= 0; i
< nh_label
->num_labels
; i
++)
929 if (nh_label
->label
[i
] != MPLS_IMP_NULL_LABEL
)
931 bos
= ((i
== (nh_label
->num_labels
- 1)) ? 1 : 0);
932 out_lse
[i
] = mpls_lse_encode (nh_label
->label
[i
], 0, 0, bos
);
934 sprintf (label_buf
, "label %d", nh_label
->label
[i
]);
937 sprintf (label_buf1
, "/%d", nh_label
->label
[i
]);
938 strcat (label_buf
, label_buf1
);
945 if (rtmsg
->rtm_family
== AF_MPLS
)
947 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTA_NEWDST
,
948 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
949 rtnh
->rtnh_len
+= RTA_LENGTH (num_labels
* sizeof(mpls_lse_t
));
954 u_int16_t encap
= LWTUNNEL_ENCAP_MPLS
;
955 int len
= rta
->rta_len
;
957 rta_addattr_l(rta
, NL_PKT_BUF_SIZE
, RTA_ENCAP_TYPE
,
958 &encap
, sizeof (u_int16_t
));
959 nest
= rta_nest(rta
, NL_PKT_BUF_SIZE
, RTA_ENCAP
);
960 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, MPLS_IPTUNNEL_DST
,
961 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
962 rta_nest_end(rta
, nest
);
963 rtnh
->rtnh_len
+= rta
->rta_len
- len
;
968 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
969 rtnh
->rtnh_flags
|= RTNH_F_ONLINK
;
971 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
972 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
974 _netlink_route_rta_add_gateway_info (rtmsg
->rtm_family
, AF_INET
, rta
,
975 rtnh
, NL_PKT_BUF_SIZE
, bytelen
, nexthop
);
976 if (nexthop
->rmap_src
.ipv4
.s_addr
)
977 *src
= &nexthop
->rmap_src
;
978 else if (nexthop
->src
.ipv4
.s_addr
)
979 *src
= &nexthop
->src
;
981 if (IS_ZEBRA_DEBUG_KERNEL
)
982 zlog_debug("netlink_route_multipath() (%s): "
983 "nexthop via %s %s if %u",
985 inet_ntoa (nexthop
->gate
.ipv4
),
986 label_buf
, nexthop
->ifindex
);
988 if (nexthop
->type
== NEXTHOP_TYPE_IPV6
989 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
991 _netlink_route_rta_add_gateway_info (rtmsg
->rtm_family
, AF_INET6
, rta
,
992 rtnh
, NL_PKT_BUF_SIZE
, bytelen
, nexthop
);
994 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
995 *src
= &nexthop
->rmap_src
;
996 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
997 *src
= &nexthop
->src
;
999 if (IS_ZEBRA_DEBUG_KERNEL
)
1000 zlog_debug("netlink_route_multipath() (%s): "
1001 "nexthop via %s %s if %u",
1003 inet6_ntoa (nexthop
->gate
.ipv6
),
1004 label_buf
, nexthop
->ifindex
);
1007 if (nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
1008 || nexthop
->type
== NEXTHOP_TYPE_IFINDEX
)
1010 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
1012 if (nexthop
->rmap_src
.ipv4
.s_addr
)
1013 *src
= &nexthop
->rmap_src
;
1014 else if (nexthop
->src
.ipv4
.s_addr
)
1015 *src
= &nexthop
->src
;
1017 if (IS_ZEBRA_DEBUG_KERNEL
)
1018 zlog_debug("netlink_route_multipath() (%s): "
1019 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
1021 else if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
1023 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
1025 if (IS_ZEBRA_DEBUG_KERNEL
)
1026 zlog_debug("netlink_route_multipath() (%s): "
1027 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
1031 rtnh
->rtnh_ifindex
= 0;
1036 _netlink_mpls_build_singlepath(
1037 const char *routedesc
,
1038 zebra_nhlfe_t
*nhlfe
,
1039 struct nlmsghdr
*nlmsg
,
1040 struct rtmsg
*rtmsg
,
1047 family
= NHLFE_FAMILY (nhlfe
);
1048 bytelen
= (family
== AF_INET
? 4 : 16);
1049 _netlink_route_build_singlepath(routedesc
, bytelen
, nhlfe
->nexthop
,
1050 nlmsg
, rtmsg
, req_size
, cmd
);
1055 _netlink_mpls_build_multipath(
1056 const char *routedesc
,
1057 zebra_nhlfe_t
*nhlfe
,
1059 struct rtnexthop
*rtnh
,
1060 struct rtmsg
*rtmsg
,
1066 family
= NHLFE_FAMILY (nhlfe
);
1067 bytelen
= (family
== AF_INET
? 4 : 16);
1068 _netlink_route_build_multipath(routedesc
, bytelen
, nhlfe
->nexthop
,
1069 rta
, rtnh
, rtmsg
, src
);
1073 /* Log debug information for netlink_route_multipath
1074 * if debug logging is enabled.
1076 * @param cmd: Netlink command which is to be processed
1077 * @param p: Prefix for which the change is due
1078 * @param nexthop: Nexthop which is currently processed
1079 * @param routedesc: Semantic annotation for nexthop
1080 * (recursive, multipath, etc.)
1081 * @param family: Address family which the change concerns
1084 _netlink_route_debug(
1087 struct nexthop
*nexthop
,
1088 const char *routedesc
,
1090 struct zebra_vrf
*zvrf
)
1092 if (IS_ZEBRA_DEBUG_KERNEL
)
1094 char buf
[PREFIX_STRLEN
];
1095 zlog_debug ("netlink_route_multipath() (%s): %s %s vrf %u type %s",
1097 nl_msg_type_to_str (cmd
),
1098 prefix2str (p
, buf
, sizeof(buf
)), zvrf_id (zvrf
),
1099 (nexthop
) ? nexthop_type_to_str (nexthop
->type
) : "UNK");
1104 _netlink_mpls_debug(
1107 const char *routedesc
)
1109 if (IS_ZEBRA_DEBUG_KERNEL
)
1110 zlog_debug ("netlink_mpls_multipath() (%s): %s %u/20",
1111 routedesc
, nl_msg_type_to_str (cmd
), label
);
1115 netlink_neigh_update (int cmd
, int ifindex
, uint32_t addr
, char *lla
, int llalen
)
1123 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1125 memset(&req
.n
, 0, sizeof(req
.n
));
1126 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
1128 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ndmsg
));
1129 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1130 req
.n
.nlmsg_type
= cmd
; //RTM_NEWNEIGH or RTM_DELNEIGH
1131 req
.ndm
.ndm_family
= AF_INET
;
1132 req
.ndm
.ndm_state
= NUD_PERMANENT
;
1133 req
.ndm
.ndm_ifindex
= ifindex
;
1134 req
.ndm
.ndm_type
= RTN_UNICAST
;
1136 addattr_l(&req
.n
, sizeof(req
), NDA_DST
, &addr
, 4);
1137 addattr_l(&req
.n
, sizeof(req
), NDA_LLADDR
, lla
, llalen
);
1139 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
, 0);
1142 /* Routing table change via netlink interface. */
1143 /* Update flag indicates whether this is a "replace" or not. */
1145 netlink_route_multipath (int cmd
, struct prefix
*p
, struct prefix
*src_p
,
1146 struct rib
*rib
, int update
)
1149 struct sockaddr_nl snl
;
1150 struct nexthop
*nexthop
= NULL
, *tnexthop
;
1152 unsigned int nexthop_num
;
1154 int family
= PREFIX_FAMILY(p
);
1155 const char *routedesc
;
1163 char buf
[NL_PKT_BUF_SIZE
];
1166 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1167 struct zebra_vrf
*zvrf
= vrf_info_lookup (rib
->vrf_id
);
1169 memset (&req
, 0, sizeof req
- NL_PKT_BUF_SIZE
);
1171 bytelen
= (family
== AF_INET
? 4 : 16);
1173 req
.n
.nlmsg_len
= NLMSG_LENGTH (sizeof (struct rtmsg
));
1174 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1175 if ((cmd
== RTM_NEWROUTE
) && update
)
1176 req
.n
.nlmsg_flags
|= NLM_F_REPLACE
;
1177 req
.n
.nlmsg_type
= cmd
;
1178 req
.r
.rtm_family
= family
;
1179 req
.r
.rtm_dst_len
= p
->prefixlen
;
1180 req
.r
.rtm_src_len
= src_p
? src_p
->prefixlen
: 0;
1181 req
.r
.rtm_protocol
= get_rt_proto(rib
->type
);
1182 req
.r
.rtm_scope
= RT_SCOPE_UNIVERSE
;
1184 if ((rib
->flags
& ZEBRA_FLAG_BLACKHOLE
) || (rib
->flags
& ZEBRA_FLAG_REJECT
))
1189 if (cmd
== RTM_NEWROUTE
)
1193 if (rib
->flags
& ZEBRA_FLAG_BLACKHOLE
)
1194 req
.r
.rtm_type
= RTN_BLACKHOLE
;
1195 else if (rib
->flags
& ZEBRA_FLAG_REJECT
)
1196 req
.r
.rtm_type
= RTN_UNREACHABLE
;
1198 assert (RTN_BLACKHOLE
!= RTN_UNREACHABLE
); /* false */
1201 req
.r
.rtm_type
= RTN_UNICAST
;
1204 addattr_l (&req
.n
, sizeof req
, RTA_DST
, &p
->u
.prefix
, bytelen
);
1206 addattr_l (&req
.n
, sizeof req
, RTA_SRC
, &src_p
->u
.prefix
, bytelen
);
1209 /* Hardcode the metric for all routes coming from zebra. Metric isn't used
1210 * either by the kernel or by zebra. Its purely for calculating best path(s)
1211 * by the routing protocol and for communicating with protocol peers.
1213 addattr32 (&req
.n
, sizeof req
, RTA_PRIORITY
, NL_DEFAULT_ROUTE_METRIC
);
1215 /* Table corresponding to this route. */
1216 if (rib
->table
< 256)
1217 req
.r
.rtm_table
= rib
->table
;
1220 req
.r
.rtm_table
= RT_TABLE_UNSPEC
;
1221 addattr32(&req
.n
, sizeof req
, RTA_TABLE
, rib
->table
);
1224 if (rib
->mtu
|| rib
->nexthop_mtu
)
1226 char buf
[NL_PKT_BUF_SIZE
];
1227 struct rtattr
*rta
= (void *) buf
;
1228 u_int32_t mtu
= rib
->mtu
;
1229 if (!mtu
|| (rib
->nexthop_mtu
&& rib
->nexthop_mtu
< mtu
))
1230 mtu
= rib
->nexthop_mtu
;
1231 rta
->rta_type
= RTA_METRICS
;
1232 rta
->rta_len
= RTA_LENGTH(0);
1233 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTAX_MTU
, &mtu
, sizeof mtu
);
1234 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_METRICS
, RTA_DATA (rta
),
1240 if (cmd
== RTM_NEWROUTE
)
1241 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1243 /* We shouldn't encounter recursive nexthops on discard routes,
1244 * but it is probably better to handle that case correctly anyway.
1246 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1252 /* Count overall nexthops so we can decide whether to use singlepath
1253 * or multipath case. */
1255 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1257 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1259 if (cmd
== RTM_NEWROUTE
&& !CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1261 if (cmd
== RTM_DELROUTE
&& !CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))
1267 /* Singlepath case. */
1268 if (nexthop_num
== 1 || multipath_num
== 1)
1271 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1273 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1277 if (family
== AF_INET
)
1279 if (nexthop
->rmap_src
.ipv4
.s_addr
!= 0)
1281 src
.ipv4
= nexthop
->rmap_src
.ipv4
;
1284 else if (nexthop
->src
.ipv4
.s_addr
!= 0)
1286 src
.ipv4
= nexthop
->src
.ipv4
;
1290 else if (family
== AF_INET6
)
1292 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
1294 src
.ipv6
= nexthop
->rmap_src
.ipv6
;
1297 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
1299 src
.ipv6
= nexthop
->src
.ipv6
;
1307 if ((cmd
== RTM_NEWROUTE
1308 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1309 || (cmd
== RTM_DELROUTE
1310 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
)))
1312 routedesc
= recursing
? "recursive, 1 hop" : "single hop";
1314 _netlink_route_debug(cmd
, p
, nexthop
, routedesc
, family
, zvrf
);
1315 _netlink_route_build_singlepath(routedesc
, bytelen
,
1316 nexthop
, &req
.n
, &req
.r
,
1322 if (setsrc
&& (cmd
== RTM_NEWROUTE
))
1324 if (family
== AF_INET
)
1325 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv4
, bytelen
);
1326 else if (family
== AF_INET6
)
1327 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv6
, bytelen
);
1332 char buf
[NL_PKT_BUF_SIZE
];
1333 struct rtattr
*rta
= (void *) buf
;
1334 struct rtnexthop
*rtnh
;
1335 union g_addr
*src1
= NULL
;
1337 rta
->rta_type
= RTA_MULTIPATH
;
1338 rta
->rta_len
= RTA_LENGTH (0);
1339 rtnh
= RTA_DATA (rta
);
1342 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1344 if (nexthop_num
>= multipath_num
)
1347 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1349 /* This only works for IPv4 now */
1352 if (family
== AF_INET
)
1354 if (nexthop
->rmap_src
.ipv4
.s_addr
!= 0)
1356 src
.ipv4
= nexthop
->rmap_src
.ipv4
;
1359 else if (nexthop
->src
.ipv4
.s_addr
!= 0)
1361 src
.ipv4
= nexthop
->src
.ipv4
;
1365 else if (family
== AF_INET6
)
1367 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
1369 src
.ipv6
= nexthop
->rmap_src
.ipv6
;
1372 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
1374 src
.ipv6
= nexthop
->src
.ipv6
;
1382 if ((cmd
== RTM_NEWROUTE
1383 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1384 || (cmd
== RTM_DELROUTE
1385 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
)))
1387 routedesc
= recursing
? "recursive, multihop" : "multihop";
1390 _netlink_route_debug(cmd
, p
, nexthop
,
1391 routedesc
, family
, zvrf
);
1392 _netlink_route_build_multipath(routedesc
, bytelen
,
1393 nexthop
, rta
, rtnh
, &req
.r
, &src1
);
1394 rtnh
= RTNH_NEXT (rtnh
);
1396 if (!setsrc
&& src1
)
1398 if (family
== AF_INET
)
1399 src
.ipv4
= src1
->ipv4
;
1400 else if (family
== AF_INET6
)
1401 src
.ipv6
= src1
->ipv6
;
1407 if (setsrc
&& (cmd
== RTM_NEWROUTE
))
1409 if (family
== AF_INET
)
1410 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv4
, bytelen
);
1411 else if (family
== AF_INET6
)
1412 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv6
, bytelen
);
1413 if (IS_ZEBRA_DEBUG_KERNEL
)
1414 zlog_debug("Setting source");
1417 if (rta
->rta_len
> RTA_LENGTH (0))
1418 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_MULTIPATH
, RTA_DATA (rta
),
1422 /* If there is no useful nexthop then return. */
1423 if (nexthop_num
== 0)
1425 if (IS_ZEBRA_DEBUG_KERNEL
)
1426 zlog_debug ("netlink_route_multipath(): No useful nexthop.");
1432 /* Destination netlink address. */
1433 memset (&snl
, 0, sizeof snl
);
1434 snl
.nl_family
= AF_NETLINK
;
1436 /* Talk to netlink socket. */
1437 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
, 0);
1441 kernel_get_ipmr_sg_stats (void *in
)
1444 struct mcast_route_data
*mr
= (struct mcast_route_data
*)in
;
1452 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1454 memset(&req
.n
, 0, sizeof(req
.n
));
1455 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
1457 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ndmsg
));
1458 req
.n
.nlmsg_flags
= NLM_F_REQUEST
;
1459 req
.ndm
.ndm_family
= AF_INET
;
1460 req
.n
.nlmsg_type
= RTM_GETROUTE
;
1462 addattr_l (&req
.n
, sizeof (req
), RTA_IIF
, &mroute
->ifindex
, 4);
1463 addattr_l (&req
.n
, sizeof (req
), RTA_OIF
, &mroute
->ifindex
, 4);
1464 addattr_l (&req
.n
, sizeof (req
), RTA_SRC
, &mroute
->sg
.src
.s_addr
, 4);
1465 addattr_l (&req
.n
, sizeof (req
), RTA_DST
, &mroute
->sg
.grp
.s_addr
, 4);
1467 suc
= netlink_talk (netlink_route_change_read_multicast
, &req
.n
, &zns
->netlink_cmd
, zns
, 0);
1474 kernel_route_rib (struct prefix
*p
, struct prefix
*src_p
,
1475 struct rib
*old
, struct rib
*new)
1478 return netlink_route_multipath (RTM_NEWROUTE
, p
, src_p
, new, 0);
1480 return netlink_route_multipath (RTM_DELROUTE
, p
, src_p
, old
, 0);
1482 return netlink_route_multipath (RTM_NEWROUTE
, p
, src_p
, new, 1);
1486 kernel_neigh_update (int add
, int ifindex
, uint32_t addr
, char *lla
, int llalen
)
1488 return netlink_neigh_update(add
? RTM_NEWNEIGH
: RTM_DELNEIGH
, ifindex
, addr
,
1493 * MPLS label forwarding table change via netlink interface.
1496 netlink_mpls_multipath (int cmd
, zebra_lsp_t
*lsp
)
1499 zebra_nhlfe_t
*nhlfe
;
1500 struct nexthop
*nexthop
= NULL
;
1501 unsigned int nexthop_num
;
1502 const char *routedesc
;
1503 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1509 char buf
[NL_PKT_BUF_SIZE
];
1512 memset (&req
, 0, sizeof req
- NL_PKT_BUF_SIZE
);
1516 * Count # nexthops so we can decide whether to use singlepath
1517 * or multipath case.
1520 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1522 nexthop
= nhlfe
->nexthop
;
1525 if (cmd
== RTM_NEWROUTE
)
1527 /* Count all selected NHLFEs */
1528 if (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
1529 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1534 /* Count all installed NHLFEs */
1535 if (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
1536 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))
1541 if (nexthop_num
== 0) // unexpected
1544 req
.n
.nlmsg_len
= NLMSG_LENGTH (sizeof (struct rtmsg
));
1545 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1546 req
.n
.nlmsg_type
= cmd
;
1547 req
.r
.rtm_family
= AF_MPLS
;
1548 req
.r
.rtm_table
= RT_TABLE_MAIN
;
1549 req
.r
.rtm_dst_len
= MPLS_LABEL_LEN_BITS
;
1550 req
.r
.rtm_protocol
= RTPROT_ZEBRA
;
1551 req
.r
.rtm_scope
= RT_SCOPE_UNIVERSE
;
1552 req
.r
.rtm_type
= RTN_UNICAST
;
1554 if (cmd
== RTM_NEWROUTE
)
1555 /* We do a replace to handle update. */
1556 req
.n
.nlmsg_flags
|= NLM_F_REPLACE
;
1558 /* Fill destination */
1559 lse
= mpls_lse_encode (lsp
->ile
.in_label
, 0, 0, 1);
1560 addattr_l (&req
.n
, sizeof req
, RTA_DST
, &lse
, sizeof(mpls_lse_t
));
1562 /* Fill nexthops (paths) based on single-path or multipath. The paths
1563 * chosen depend on the operation.
1565 if (nexthop_num
== 1 || multipath_num
== 1)
1567 routedesc
= "single hop";
1568 _netlink_mpls_debug(cmd
, lsp
->ile
.in_label
, routedesc
);
1571 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1573 nexthop
= nhlfe
->nexthop
;
1577 if ((cmd
== RTM_NEWROUTE
&&
1578 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
1579 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))) ||
1580 (cmd
== RTM_DELROUTE
&&
1581 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
1582 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))))
1584 /* Add the gateway */
1585 _netlink_mpls_build_singlepath(routedesc
, nhlfe
,
1586 &req
.n
, &req
.r
, sizeof req
, cmd
);
1587 if (cmd
== RTM_NEWROUTE
)
1589 SET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1590 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1594 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1595 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1602 else /* Multipath case */
1604 char buf
[NL_PKT_BUF_SIZE
];
1605 struct rtattr
*rta
= (void *) buf
;
1606 struct rtnexthop
*rtnh
;
1607 union g_addr
*src1
= NULL
;
1609 rta
->rta_type
= RTA_MULTIPATH
;
1610 rta
->rta_len
= RTA_LENGTH (0);
1611 rtnh
= RTA_DATA (rta
);
1613 routedesc
= "multihop";
1614 _netlink_mpls_debug(cmd
, lsp
->ile
.in_label
, routedesc
);
1617 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1619 nexthop
= nhlfe
->nexthop
;
1623 if (nexthop_num
>= multipath_num
)
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
))))
1635 /* Build the multipath */
1636 _netlink_mpls_build_multipath(routedesc
, nhlfe
, rta
,
1637 rtnh
, &req
.r
, &src1
);
1638 rtnh
= RTNH_NEXT (rtnh
);
1640 if (cmd
== RTM_NEWROUTE
)
1642 SET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1643 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1647 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1648 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1654 /* Add the multipath */
1655 if (rta
->rta_len
> RTA_LENGTH (0))
1656 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_MULTIPATH
, RTA_DATA (rta
),
1660 /* Talk to netlink socket. */
1661 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
, 0);
1665 * Handle failure in LSP install, clear flags for NHLFE.
1668 clear_nhlfe_installed (zebra_lsp_t
*lsp
)
1670 zebra_nhlfe_t
*nhlfe
;
1671 struct nexthop
*nexthop
;
1673 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1675 nexthop
= nhlfe
->nexthop
;
1679 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1680 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);