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 vrf_id_t vrf_id
= VRF_DEFAULT
;
139 char anyaddr
[16] = { 0 };
150 rtm
= NLMSG_DATA (h
);
152 if (h
->nlmsg_type
!= RTM_NEWROUTE
)
154 if (rtm
->rtm_type
!= RTN_UNICAST
)
157 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
161 memset (tb
, 0, sizeof tb
);
162 netlink_parse_rtattr (tb
, RTA_MAX
, RTM_RTA (rtm
), len
);
164 if (rtm
->rtm_flags
& RTM_F_CLONED
)
166 if (rtm
->rtm_protocol
== RTPROT_REDIRECT
)
168 if (rtm
->rtm_protocol
== RTPROT_KERNEL
)
171 if (rtm
->rtm_src_len
!= 0)
174 /* We don't care about change notifications for the MPLS table. */
175 /* TODO: Revisit this. */
176 if (rtm
->rtm_family
== AF_MPLS
)
179 /* Table corresponding to route. */
181 table
= *(int *) RTA_DATA (tb
[RTA_TABLE
]);
183 table
= rtm
->rtm_table
;
186 vrf_id
= vrf_lookup_by_table(table
);
187 if (vrf_id
== VRF_DEFAULT
)
189 if (!is_zebra_valid_kernel_table(table
) &&
190 !is_zebra_main_routing_table(table
))
194 /* Route which inserted by Zebra. */
195 if (rtm
->rtm_protocol
== RTPROT_ZEBRA
)
196 flags
|= ZEBRA_FLAG_SELFROUTE
;
205 index
= *(int *) RTA_DATA (tb
[RTA_OIF
]);
208 dest
= RTA_DATA (tb
[RTA_DST
]);
213 src
= RTA_DATA (tb
[RTA_PREFSRC
]);
216 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
218 if (tb
[RTA_PRIORITY
])
219 metric
= *(int *) RTA_DATA(tb
[RTA_PRIORITY
]);
223 struct rtattr
*mxrta
[RTAX_MAX
+1];
225 memset (mxrta
, 0, sizeof mxrta
);
226 netlink_parse_rtattr (mxrta
, RTAX_MAX
, RTA_DATA(tb
[RTA_METRICS
]),
227 RTA_PAYLOAD(tb
[RTA_METRICS
]));
230 mtu
= *(u_int32_t
*) RTA_DATA(mxrta
[RTAX_MTU
]);
233 if (rtm
->rtm_family
== AF_INET
)
236 memcpy (&p
.u
.prefix4
, dest
, 4);
237 p
.prefixlen
= rtm
->rtm_dst_len
;
239 if (!tb
[RTA_MULTIPATH
])
240 rib_add (AFI_IP
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
241 0, flags
, &p
, gate
, src
, index
,
242 table
, metric
, mtu
, 0);
245 /* This is a multipath route */
248 struct rtnexthop
*rtnh
=
249 (struct rtnexthop
*) RTA_DATA (tb
[RTA_MULTIPATH
]);
251 len
= RTA_PAYLOAD (tb
[RTA_MULTIPATH
]);
253 rib
= XCALLOC (MTYPE_RIB
, sizeof (struct rib
));
254 rib
->type
= ZEBRA_ROUTE_KERNEL
;
257 rib
->metric
= metric
;
259 rib
->vrf_id
= vrf_id
;
261 rib
->nexthop_num
= 0;
262 rib
->uptime
= time (NULL
);
266 if (len
< (int) sizeof (*rtnh
) || rtnh
->rtnh_len
> len
)
269 index
= rtnh
->rtnh_ifindex
;
271 if (rtnh
->rtnh_len
> sizeof (*rtnh
))
273 memset (tb
, 0, sizeof (tb
));
274 netlink_parse_rtattr (tb
, RTA_MAX
, RTNH_DATA (rtnh
),
275 rtnh
->rtnh_len
- sizeof (*rtnh
));
277 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
283 rib_nexthop_ipv4_ifindex_add (rib
, gate
, src
, index
);
285 rib_nexthop_ipv4_add (rib
, gate
, src
);
288 rib_nexthop_ifindex_add (rib
, index
);
290 len
-= NLMSG_ALIGN(rtnh
->rtnh_len
);
291 rtnh
= RTNH_NEXT(rtnh
);
294 zserv_nexthop_num_warn(__func__
, (const struct prefix
*)&p
,
296 if (rib
->nexthop_num
== 0)
297 XFREE (MTYPE_RIB
, rib
);
299 rib_add_multipath (AFI_IP
, SAFI_UNICAST
, &p
, rib
);
302 if (rtm
->rtm_family
== AF_INET6
)
305 memcpy (&p
.u
.prefix6
, dest
, 16);
306 p
.prefixlen
= rtm
->rtm_dst_len
;
308 rib_add (AFI_IP6
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
309 0, flags
, &p
, gate
, src
, index
,
310 table
, metric
, mtu
, 0);
316 /* Routing information change from the kernel. */
318 netlink_route_change_read_unicast (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
323 struct rtattr
*tb
[RTA_MAX
+ 1];
324 u_char zebra_flags
= 0;
326 vrf_id_t vrf_id
= VRF_DEFAULT
;
327 char anyaddr
[16] = { 0 };
338 rtm
= NLMSG_DATA (h
);
340 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
342 memset (tb
, 0, sizeof tb
);
343 netlink_parse_rtattr (tb
, RTA_MAX
, RTM_RTA (rtm
), len
);
345 if (rtm
->rtm_flags
& RTM_F_CLONED
)
347 if (rtm
->rtm_protocol
== RTPROT_REDIRECT
)
349 if (rtm
->rtm_protocol
== RTPROT_KERNEL
)
352 if (rtm
->rtm_protocol
== RTPROT_ZEBRA
&& h
->nlmsg_type
== RTM_NEWROUTE
)
354 if (rtm
->rtm_protocol
== RTPROT_ZEBRA
)
355 SET_FLAG(zebra_flags
, ZEBRA_FLAG_SELFROUTE
);
357 if (rtm
->rtm_src_len
!= 0)
359 zlog_warn ("netlink_route_change(): no src len");
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
))
385 index
= *(int *) RTA_DATA (tb
[RTA_OIF
]);
388 dest
= RTA_DATA (tb
[RTA_DST
]);
393 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
396 src
= RTA_DATA (tb
[RTA_PREFSRC
]);
398 if (h
->nlmsg_type
== RTM_NEWROUTE
)
400 if (tb
[RTA_PRIORITY
])
401 metric
= *(int *) RTA_DATA(tb
[RTA_PRIORITY
]);
405 struct rtattr
*mxrta
[RTAX_MAX
+1];
407 memset (mxrta
, 0, sizeof mxrta
);
408 netlink_parse_rtattr (mxrta
, RTAX_MAX
, RTA_DATA(tb
[RTA_METRICS
]),
409 RTA_PAYLOAD(tb
[RTA_METRICS
]));
412 mtu
= *(u_int32_t
*) RTA_DATA(mxrta
[RTAX_MTU
]);
416 if (rtm
->rtm_family
== AF_INET
)
419 memcpy (&p
.u
.prefix4
, dest
, 4);
420 p
.prefixlen
= rtm
->rtm_dst_len
;
422 if (IS_ZEBRA_DEBUG_KERNEL
)
424 char buf
[PREFIX_STRLEN
];
425 zlog_debug ("%s %s vrf %u",
426 nl_msg_type_to_str (h
->nlmsg_type
),
427 prefix2str (&p
, buf
, sizeof(buf
)), vrf_id
);
430 if (h
->nlmsg_type
== RTM_NEWROUTE
)
432 if (!tb
[RTA_MULTIPATH
])
433 rib_add (AFI_IP
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
434 0, 0, &p
, gate
, src
, index
,
435 table
, metric
, mtu
, 0);
438 /* This is a multipath route */
441 struct rtnexthop
*rtnh
=
442 (struct rtnexthop
*) RTA_DATA (tb
[RTA_MULTIPATH
]);
444 len
= RTA_PAYLOAD (tb
[RTA_MULTIPATH
]);
446 rib
= XCALLOC (MTYPE_RIB
, sizeof (struct rib
));
447 rib
->type
= ZEBRA_ROUTE_KERNEL
;
450 rib
->metric
= metric
;
452 rib
->vrf_id
= vrf_id
;
454 rib
->nexthop_num
= 0;
455 rib
->uptime
= time (NULL
);
459 if (len
< (int) sizeof (*rtnh
) || rtnh
->rtnh_len
> len
)
462 index
= rtnh
->rtnh_ifindex
;
464 if (rtnh
->rtnh_len
> sizeof (*rtnh
))
466 memset (tb
, 0, sizeof (tb
));
467 netlink_parse_rtattr (tb
, RTA_MAX
, RTNH_DATA (rtnh
),
468 rtnh
->rtnh_len
- sizeof (*rtnh
));
470 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
476 rib_nexthop_ipv4_ifindex_add (rib
, gate
, src
, index
);
478 rib_nexthop_ipv4_add (rib
, gate
, src
);
481 rib_nexthop_ifindex_add (rib
, index
);
483 len
-= NLMSG_ALIGN(rtnh
->rtnh_len
);
484 rtnh
= RTNH_NEXT(rtnh
);
487 zserv_nexthop_num_warn(__func__
, (const struct prefix
*)&p
,
490 if (rib
->nexthop_num
== 0)
491 XFREE (MTYPE_RIB
, rib
);
493 rib_add_multipath (AFI_IP
, SAFI_UNICAST
, &p
, rib
);
497 rib_delete (AFI_IP
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
, 0, zebra_flags
,
498 &p
, gate
, index
, table
);
501 if (rtm
->rtm_family
== AF_INET6
)
506 memcpy (&p
.u
.prefix6
, dest
, 16);
507 p
.prefixlen
= rtm
->rtm_dst_len
;
509 if (IS_ZEBRA_DEBUG_KERNEL
)
511 char buf
[PREFIX_STRLEN
];
512 zlog_debug ("%s %s vrf %u",
513 nl_msg_type_to_str (h
->nlmsg_type
),
514 prefix2str (&p
, buf
, sizeof(buf
)), vrf_id
);
517 if (h
->nlmsg_type
== RTM_NEWROUTE
)
518 rib_add (AFI_IP6
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
519 0, 0, &p
, gate
, src
, index
,
520 table
, metric
, mtu
, 0);
522 rib_delete (AFI_IP6
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
523 0, zebra_flags
, &p
, gate
, index
, table
);
529 static struct mcast_route_data
*mroute
= NULL
;
532 netlink_route_change_read_multicast (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
537 struct rtattr
*tb
[RTA_MAX
+ 1];
538 struct mcast_route_data
*m
;
539 struct mcast_route_data mr
;
546 char oif_list
[256] = "\0";
547 vrf_id_t vrf
= ns_id
;
553 memset (&mr
, 0, sizeof (mr
));
557 rtm
= NLMSG_DATA (h
);
559 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
561 memset (tb
, 0, sizeof tb
);
562 netlink_parse_rtattr (tb
, RTA_MAX
, RTM_RTA (rtm
), len
);
565 iif
= *(int *)RTA_DATA (tb
[RTA_IIF
]);
568 m
->sg
.src
= *(struct in_addr
*)RTA_DATA (tb
[RTA_SRC
]);
571 m
->sg
.grp
= *(struct in_addr
*)RTA_DATA (tb
[RTA_DST
]);
573 if ((RTA_EXPIRES
<= RTA_MAX
) && tb
[RTA_EXPIRES
])
574 m
->lastused
= *(unsigned long long *)RTA_DATA (tb
[RTA_EXPIRES
]);
576 if (tb
[RTA_MULTIPATH
])
578 struct rtnexthop
*rtnh
=
579 (struct rtnexthop
*)RTA_DATA (tb
[RTA_MULTIPATH
]);
581 len
= RTA_PAYLOAD (tb
[RTA_MULTIPATH
]);
584 if (len
< (int) sizeof (*rtnh
) || rtnh
->rtnh_len
> len
)
587 oif
[oif_count
] = rtnh
->rtnh_ifindex
;
590 len
-= NLMSG_ALIGN (rtnh
->rtnh_len
);
591 rtnh
= RTNH_NEXT (rtnh
);
595 if (IS_ZEBRA_DEBUG_KERNEL
)
597 struct interface
*ifp
;
598 strcpy (sbuf
, inet_ntoa (m
->sg
.src
));
599 strcpy (gbuf
, inet_ntoa (m
->sg
.grp
));
600 for (count
= 0; count
< oif_count
; count
++)
602 ifp
= if_lookup_by_index_vrf (oif
[count
], vrf
);
605 sprintf (temp
, "%s ", ifp
->name
);
606 strcat (oif_list
, temp
);
608 ifp
= if_lookup_by_index_vrf (iif
, vrf
);
609 zlog_debug ("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld",
610 nl_msg_type_to_str(h
->nlmsg_type
), sbuf
, gbuf
, ifp
->name
, oif_list
, m
->lastused
);
616 netlink_route_change (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
620 vrf_id_t vrf_id
= ns_id
;
623 rtm
= NLMSG_DATA (h
);
625 if (!(h
->nlmsg_type
== RTM_NEWROUTE
|| h
->nlmsg_type
== RTM_DELROUTE
))
627 /* If this is not route add/delete message print warning. */
628 zlog_warn ("Kernel message: %d vrf %u\n", h
->nlmsg_type
, vrf_id
);
632 /* Connected route. */
633 if (IS_ZEBRA_DEBUG_KERNEL
)
634 zlog_debug ("%s %s %s proto %s vrf %u",
635 nl_msg_type_to_str (h
->nlmsg_type
),
636 nl_family_to_str (rtm
->rtm_family
),
637 nl_rttype_to_str (rtm
->rtm_type
),
638 nl_rtproto_to_str (rtm
->rtm_protocol
),
641 /* We don't care about change notifications for the MPLS table. */
642 /* TODO: Revisit this. */
643 if (rtm
->rtm_family
== AF_MPLS
)
646 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
650 switch (rtm
->rtm_type
)
653 netlink_route_change_read_unicast (snl
, h
, ns_id
);
656 netlink_route_change_read_multicast (snl
, h
, ns_id
);
666 /* Routing table read function using netlink interface. Only called
669 netlink_route_read (struct zebra_ns
*zns
)
673 /* Get IPv4 routing table. */
674 ret
= netlink_request (AF_INET
, RTM_GETROUTE
, &zns
->netlink_cmd
);
677 ret
= netlink_parse_info (netlink_routing_table
, &zns
->netlink_cmd
, zns
, 0);
681 /* Get IPv6 routing table. */
682 ret
= netlink_request (AF_INET6
, RTM_GETROUTE
, &zns
->netlink_cmd
);
685 ret
= netlink_parse_info (netlink_routing_table
, &zns
->netlink_cmd
, zns
, 0);
693 _netlink_route_nl_add_gateway_info (u_char route_family
, u_char gw_family
,
694 struct nlmsghdr
*nlmsg
,
695 size_t req_size
, int bytelen
,
696 struct nexthop
*nexthop
)
698 if (route_family
== AF_MPLS
)
700 struct gw_family_t gw_fam
;
702 gw_fam
.family
= gw_family
;
703 if (gw_family
== AF_INET
)
704 memcpy (&gw_fam
.gate
.ipv4
, &nexthop
->gate
.ipv4
, bytelen
);
706 memcpy (&gw_fam
.gate
.ipv6
, &nexthop
->gate
.ipv6
, bytelen
);
707 addattr_l (nlmsg
, req_size
, RTA_VIA
, &gw_fam
.family
, bytelen
+2);
711 if (gw_family
== AF_INET
)
712 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv4
, bytelen
);
714 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv6
, bytelen
);
719 _netlink_route_rta_add_gateway_info (u_char route_family
, u_char gw_family
,
720 struct rtattr
*rta
, struct rtnexthop
*rtnh
,
721 size_t req_size
, int bytelen
,
722 struct nexthop
*nexthop
)
724 if (route_family
== AF_MPLS
)
726 struct gw_family_t gw_fam
;
728 gw_fam
.family
= gw_family
;
729 if (gw_family
== AF_INET
)
730 memcpy (&gw_fam
.gate
.ipv4
, &nexthop
->gate
.ipv4
, bytelen
);
732 memcpy (&gw_fam
.gate
.ipv6
, &nexthop
->gate
.ipv6
, bytelen
);
733 rta_addattr_l (rta
, req_size
, RTA_VIA
, &gw_fam
.family
, bytelen
+2);
734 rtnh
->rtnh_len
+= RTA_LENGTH (bytelen
+ 2);
738 if (gw_family
== AF_INET
)
739 rta_addattr_l (rta
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv4
, bytelen
);
741 rta_addattr_l (rta
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv6
, bytelen
);
742 rtnh
->rtnh_len
+= sizeof (struct rtattr
) + bytelen
;
746 /* This function takes a nexthop as argument and adds
747 * the appropriate netlink attributes to an existing
750 * @param routedesc: Human readable description of route type
751 * (direct/recursive, single-/multipath)
752 * @param bytelen: Length of addresses in bytes.
753 * @param nexthop: Nexthop information
754 * @param nlmsg: nlmsghdr structure to fill in.
755 * @param req_size: The size allocated for the message.
758 _netlink_route_build_singlepath(
759 const char *routedesc
,
761 struct nexthop
*nexthop
,
762 struct nlmsghdr
*nlmsg
,
767 struct nexthop_label
*nh_label
;
768 mpls_lse_t out_lse
[MPLS_MAX_LABELS
];
771 if (rtmsg
->rtm_family
== AF_INET
&&
772 (nexthop
->type
== NEXTHOP_TYPE_IPV6
773 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
))
775 char buf
[16] = "169.254.0.1";
776 struct in_addr ipv4_ll
;
778 inet_pton (AF_INET
, buf
, &ipv4_ll
);
779 rtmsg
->rtm_flags
|= RTNH_F_ONLINK
;
780 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &ipv4_ll
, 4);
781 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
783 if (nexthop
->rmap_src
.ipv4
.s_addr
&& (cmd
== RTM_NEWROUTE
))
784 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
785 &nexthop
->rmap_src
.ipv4
, bytelen
);
786 else if (nexthop
->src
.ipv4
.s_addr
&& (cmd
== RTM_NEWROUTE
))
787 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
788 &nexthop
->src
.ipv4
, bytelen
);
790 if (IS_ZEBRA_DEBUG_KERNEL
)
791 zlog_debug(" 5549: _netlink_route_build_singlepath() (%s): "
792 "nexthop via %s if %u",
793 routedesc
, buf
, nexthop
->ifindex
);
798 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
799 * (in the case of LER)
801 nh_label
= nexthop
->nh_label
;
802 if (rtmsg
->rtm_family
== AF_MPLS
)
805 assert (nh_label
->num_labels
== 1);
808 if (nh_label
&& nh_label
->num_labels
)
810 int i
, num_labels
= 0;
814 for (i
= 0; i
< nh_label
->num_labels
; i
++)
816 if (nh_label
->label
[i
] != MPLS_IMP_NULL_LABEL
)
818 bos
= ((i
== (nh_label
->num_labels
- 1)) ? 1 : 0);
819 out_lse
[i
] = mpls_lse_encode (nh_label
->label
[i
], 0, 0, bos
);
821 sprintf (label_buf
, "label %d", nh_label
->label
[i
]);
824 sprintf (label_buf1
, "/%d", nh_label
->label
[i
]);
825 strcat (label_buf
, label_buf1
);
832 if (rtmsg
->rtm_family
== AF_MPLS
)
833 addattr_l (nlmsg
, req_size
, RTA_NEWDST
,
834 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
838 u_int16_t encap
= LWTUNNEL_ENCAP_MPLS
;
840 addattr_l(nlmsg
, req_size
, RTA_ENCAP_TYPE
,
841 &encap
, sizeof (u_int16_t
));
842 nest
= addattr_nest(nlmsg
, req_size
, RTA_ENCAP
);
843 addattr_l (nlmsg
, req_size
, MPLS_IPTUNNEL_DST
,
844 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
845 addattr_nest_end(nlmsg
, nest
);
850 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
851 rtmsg
->rtm_flags
|= RTNH_F_ONLINK
;
853 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
854 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
856 _netlink_route_nl_add_gateway_info (rtmsg
->rtm_family
, AF_INET
, nlmsg
,
857 req_size
, bytelen
, nexthop
);
859 if (cmd
== RTM_NEWROUTE
)
861 if (nexthop
->rmap_src
.ipv4
.s_addr
)
862 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
863 &nexthop
->rmap_src
.ipv4
, bytelen
);
864 else if (nexthop
->src
.ipv4
.s_addr
)
865 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
866 &nexthop
->src
.ipv4
, bytelen
);
869 if (IS_ZEBRA_DEBUG_KERNEL
)
870 zlog_debug("netlink_route_multipath() (%s): "
871 "nexthop via %s %s if %u",
873 inet_ntoa (nexthop
->gate
.ipv4
),
874 label_buf
, nexthop
->ifindex
);
876 if (nexthop
->type
== NEXTHOP_TYPE_IPV6
877 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
879 _netlink_route_nl_add_gateway_info (rtmsg
->rtm_family
, AF_INET6
, nlmsg
,
880 req_size
, bytelen
, nexthop
);
882 if (cmd
== RTM_NEWROUTE
)
884 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
885 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
886 &nexthop
->rmap_src
.ipv6
, bytelen
);
887 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
888 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
889 &nexthop
->src
.ipv6
, bytelen
);
892 if (IS_ZEBRA_DEBUG_KERNEL
)
893 zlog_debug("netlink_route_multipath() (%s): "
894 "nexthop via %s %s if %u",
896 inet6_ntoa (nexthop
->gate
.ipv6
),
897 label_buf
, nexthop
->ifindex
);
899 if (nexthop
->type
== NEXTHOP_TYPE_IFINDEX
900 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
902 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
904 if (cmd
== RTM_NEWROUTE
)
906 if (nexthop
->rmap_src
.ipv4
.s_addr
)
907 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
908 &nexthop
->rmap_src
.ipv4
, bytelen
);
909 else if (nexthop
->src
.ipv4
.s_addr
)
910 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
911 &nexthop
->src
.ipv4
, bytelen
);
914 if (IS_ZEBRA_DEBUG_KERNEL
)
915 zlog_debug("netlink_route_multipath() (%s): "
916 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
919 if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
921 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
923 if (cmd
== RTM_NEWROUTE
)
925 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
926 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
927 &nexthop
->rmap_src
.ipv6
, bytelen
);
928 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
929 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
930 &nexthop
->src
.ipv6
, bytelen
);
933 if (IS_ZEBRA_DEBUG_KERNEL
)
934 zlog_debug("netlink_route_multipath() (%s): "
935 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
939 /* This function takes a nexthop as argument and
940 * appends to the given rtattr/rtnexthop pair the
941 * representation of the nexthop. If the nexthop
942 * defines a preferred source, the src parameter
943 * will be modified to point to that src, otherwise
944 * it will be kept unmodified.
946 * @param routedesc: Human readable description of route type
947 * (direct/recursive, single-/multipath)
948 * @param bytelen: Length of addresses in bytes.
949 * @param nexthop: Nexthop information
950 * @param rta: rtnetlink attribute structure
951 * @param rtnh: pointer to an rtnetlink nexthop structure
952 * @param src: pointer pointing to a location where
953 * the prefsrc should be stored.
956 _netlink_route_build_multipath(
957 const char *routedesc
,
959 struct nexthop
*nexthop
,
961 struct rtnexthop
*rtnh
,
965 struct nexthop_label
*nh_label
;
966 mpls_lse_t out_lse
[MPLS_MAX_LABELS
];
969 rtnh
->rtnh_len
= sizeof (*rtnh
);
970 rtnh
->rtnh_flags
= 0;
972 rta
->rta_len
+= rtnh
->rtnh_len
;
974 if (rtmsg
->rtm_family
== AF_INET
&&
975 (nexthop
->type
== NEXTHOP_TYPE_IPV6
976 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
))
978 char buf
[16] = "169.254.0.1";
979 struct in_addr ipv4_ll
;
981 inet_pton (AF_INET
, buf
, &ipv4_ll
);
983 rtnh
->rtnh_flags
|= RTNH_F_ONLINK
;
984 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTA_GATEWAY
,
986 rtnh
->rtnh_len
+= sizeof (struct rtattr
) + bytelen
;
987 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
989 if (nexthop
->rmap_src
.ipv4
.s_addr
)
990 *src
= &nexthop
->rmap_src
;
991 else if (nexthop
->src
.ipv4
.s_addr
)
992 *src
= &nexthop
->src
;
994 if (IS_ZEBRA_DEBUG_KERNEL
)
995 zlog_debug(" 5549: netlink_route_build_multipath() (%s): "
996 "nexthop via %s if %u",
997 routedesc
, buf
, nexthop
->ifindex
);
1001 label_buf
[0] = '\0';
1002 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
1003 * (in the case of LER)
1005 nh_label
= nexthop
->nh_label
;
1006 if (rtmsg
->rtm_family
== AF_MPLS
)
1009 assert (nh_label
->num_labels
== 1);
1012 if (nh_label
&& nh_label
->num_labels
)
1014 int i
, num_labels
= 0;
1016 char label_buf1
[20];
1018 for (i
= 0; i
< nh_label
->num_labels
; i
++)
1020 if (nh_label
->label
[i
] != MPLS_IMP_NULL_LABEL
)
1022 bos
= ((i
== (nh_label
->num_labels
- 1)) ? 1 : 0);
1023 out_lse
[i
] = mpls_lse_encode (nh_label
->label
[i
], 0, 0, bos
);
1025 sprintf (label_buf
, "label %d", nh_label
->label
[i
]);
1028 sprintf (label_buf1
, "/%d", nh_label
->label
[i
]);
1029 strcat (label_buf
, label_buf1
);
1036 if (rtmsg
->rtm_family
== AF_MPLS
)
1038 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTA_NEWDST
,
1039 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
1040 rtnh
->rtnh_len
+= RTA_LENGTH (num_labels
* sizeof(mpls_lse_t
));
1044 struct rtattr
*nest
;
1045 u_int16_t encap
= LWTUNNEL_ENCAP_MPLS
;
1046 int len
= rta
->rta_len
;
1048 rta_addattr_l(rta
, NL_PKT_BUF_SIZE
, RTA_ENCAP_TYPE
,
1049 &encap
, sizeof (u_int16_t
));
1050 nest
= rta_nest(rta
, NL_PKT_BUF_SIZE
, RTA_ENCAP
);
1051 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, MPLS_IPTUNNEL_DST
,
1052 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
1053 rta_nest_end(rta
, nest
);
1054 rtnh
->rtnh_len
+= rta
->rta_len
- len
;
1059 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
1060 rtnh
->rtnh_flags
|= RTNH_F_ONLINK
;
1062 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
1063 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
1065 _netlink_route_rta_add_gateway_info (rtmsg
->rtm_family
, AF_INET
, rta
,
1066 rtnh
, NL_PKT_BUF_SIZE
, bytelen
, nexthop
);
1067 if (nexthop
->rmap_src
.ipv4
.s_addr
)
1068 *src
= &nexthop
->rmap_src
;
1069 else if (nexthop
->src
.ipv4
.s_addr
)
1070 *src
= &nexthop
->src
;
1072 if (IS_ZEBRA_DEBUG_KERNEL
)
1073 zlog_debug("netlink_route_multipath() (%s): "
1074 "nexthop via %s %s if %u",
1076 inet_ntoa (nexthop
->gate
.ipv4
),
1077 label_buf
, nexthop
->ifindex
);
1079 if (nexthop
->type
== NEXTHOP_TYPE_IPV6
1080 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
1082 _netlink_route_rta_add_gateway_info (rtmsg
->rtm_family
, AF_INET6
, rta
,
1083 rtnh
, NL_PKT_BUF_SIZE
, bytelen
, nexthop
);
1085 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
1086 *src
= &nexthop
->rmap_src
;
1087 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
1088 *src
= &nexthop
->src
;
1090 if (IS_ZEBRA_DEBUG_KERNEL
)
1091 zlog_debug("netlink_route_multipath() (%s): "
1092 "nexthop via %s %s if %u",
1094 inet6_ntoa (nexthop
->gate
.ipv6
),
1095 label_buf
, nexthop
->ifindex
);
1098 if (nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
1099 || nexthop
->type
== NEXTHOP_TYPE_IFINDEX
)
1101 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
1103 if (nexthop
->rmap_src
.ipv4
.s_addr
)
1104 *src
= &nexthop
->rmap_src
;
1105 else if (nexthop
->src
.ipv4
.s_addr
)
1106 *src
= &nexthop
->src
;
1108 if (IS_ZEBRA_DEBUG_KERNEL
)
1109 zlog_debug("netlink_route_multipath() (%s): "
1110 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
1112 else if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
1114 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
1116 if (IS_ZEBRA_DEBUG_KERNEL
)
1117 zlog_debug("netlink_route_multipath() (%s): "
1118 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
1122 rtnh
->rtnh_ifindex
= 0;
1127 _netlink_mpls_build_singlepath(
1128 const char *routedesc
,
1129 zebra_nhlfe_t
*nhlfe
,
1130 struct nlmsghdr
*nlmsg
,
1131 struct rtmsg
*rtmsg
,
1138 family
= NHLFE_FAMILY (nhlfe
);
1139 bytelen
= (family
== AF_INET
? 4 : 16);
1140 _netlink_route_build_singlepath(routedesc
, bytelen
, nhlfe
->nexthop
,
1141 nlmsg
, rtmsg
, req_size
, cmd
);
1146 _netlink_mpls_build_multipath(
1147 const char *routedesc
,
1148 zebra_nhlfe_t
*nhlfe
,
1150 struct rtnexthop
*rtnh
,
1151 struct rtmsg
*rtmsg
,
1157 family
= NHLFE_FAMILY (nhlfe
);
1158 bytelen
= (family
== AF_INET
? 4 : 16);
1159 _netlink_route_build_multipath(routedesc
, bytelen
, nhlfe
->nexthop
,
1160 rta
, rtnh
, rtmsg
, src
);
1164 /* Log debug information for netlink_route_multipath
1165 * if debug logging is enabled.
1167 * @param cmd: Netlink command which is to be processed
1168 * @param p: Prefix for which the change is due
1169 * @param nexthop: Nexthop which is currently processed
1170 * @param routedesc: Semantic annotation for nexthop
1171 * (recursive, multipath, etc.)
1172 * @param family: Address family which the change concerns
1175 _netlink_route_debug(
1178 struct nexthop
*nexthop
,
1179 const char *routedesc
,
1181 struct zebra_vrf
*zvrf
)
1183 if (IS_ZEBRA_DEBUG_KERNEL
)
1185 char buf
[PREFIX_STRLEN
];
1186 zlog_debug ("netlink_route_multipath() (%s): %s %s vrf %u type %s",
1188 nl_msg_type_to_str (cmd
),
1189 prefix2str (p
, buf
, sizeof(buf
)), zvrf_id (zvrf
),
1190 (nexthop
) ? nexthop_type_to_str (nexthop
->type
) : "UNK");
1195 _netlink_mpls_debug(
1198 const char *routedesc
)
1200 if (IS_ZEBRA_DEBUG_KERNEL
)
1201 zlog_debug ("netlink_mpls_multipath() (%s): %s %u/20",
1202 routedesc
, nl_msg_type_to_str (cmd
), label
);
1206 netlink_neigh_update (int cmd
, int ifindex
, uint32_t addr
, char *lla
, int llalen
)
1214 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1216 memset(&req
.n
, 0, sizeof(req
.n
));
1217 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
1219 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ndmsg
));
1220 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1221 req
.n
.nlmsg_type
= cmd
; //RTM_NEWNEIGH or RTM_DELNEIGH
1222 req
.ndm
.ndm_family
= AF_INET
;
1223 req
.ndm
.ndm_state
= NUD_PERMANENT
;
1224 req
.ndm
.ndm_ifindex
= ifindex
;
1225 req
.ndm
.ndm_type
= RTN_UNICAST
;
1227 addattr_l(&req
.n
, sizeof(req
), NDA_DST
, &addr
, 4);
1228 addattr_l(&req
.n
, sizeof(req
), NDA_LLADDR
, lla
, llalen
);
1230 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
);
1233 /* Routing table change via netlink interface. */
1234 /* Update flag indicates whether this is a "replace" or not. */
1236 netlink_route_multipath (int cmd
, struct prefix
*p
, struct rib
*rib
,
1240 struct sockaddr_nl snl
;
1241 struct nexthop
*nexthop
= NULL
, *tnexthop
;
1245 int family
= PREFIX_FAMILY(p
);
1246 const char *routedesc
;
1254 char buf
[NL_PKT_BUF_SIZE
];
1257 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1258 struct zebra_vrf
*zvrf
= vrf_info_lookup (rib
->vrf_id
);
1260 memset (&req
, 0, sizeof req
- NL_PKT_BUF_SIZE
);
1262 bytelen
= (family
== AF_INET
? 4 : 16);
1264 req
.n
.nlmsg_len
= NLMSG_LENGTH (sizeof (struct rtmsg
));
1265 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1266 if ((cmd
== RTM_NEWROUTE
) && update
)
1267 req
.n
.nlmsg_flags
|= NLM_F_REPLACE
;
1268 req
.n
.nlmsg_type
= cmd
;
1269 req
.r
.rtm_family
= family
;
1270 req
.r
.rtm_dst_len
= p
->prefixlen
;
1271 req
.r
.rtm_protocol
= RTPROT_ZEBRA
;
1272 req
.r
.rtm_scope
= RT_SCOPE_UNIVERSE
;
1274 if ((rib
->flags
& ZEBRA_FLAG_BLACKHOLE
) || (rib
->flags
& ZEBRA_FLAG_REJECT
))
1279 if (cmd
== RTM_NEWROUTE
)
1283 if (rib
->flags
& ZEBRA_FLAG_BLACKHOLE
)
1284 req
.r
.rtm_type
= RTN_BLACKHOLE
;
1285 else if (rib
->flags
& ZEBRA_FLAG_REJECT
)
1286 req
.r
.rtm_type
= RTN_UNREACHABLE
;
1288 assert (RTN_BLACKHOLE
!= RTN_UNREACHABLE
); /* false */
1291 req
.r
.rtm_type
= RTN_UNICAST
;
1294 addattr_l (&req
.n
, sizeof req
, RTA_DST
, &p
->u
.prefix
, bytelen
);
1297 /* Hardcode the metric for all routes coming from zebra. Metric isn't used
1298 * either by the kernel or by zebra. Its purely for calculating best path(s)
1299 * by the routing protocol and for communicating with protocol peers.
1301 addattr32 (&req
.n
, sizeof req
, RTA_PRIORITY
, NL_DEFAULT_ROUTE_METRIC
);
1303 /* Table corresponding to this route. */
1304 if (rib
->table
< 256)
1305 req
.r
.rtm_table
= rib
->table
;
1308 req
.r
.rtm_table
= RT_TABLE_UNSPEC
;
1309 addattr32(&req
.n
, sizeof req
, RTA_TABLE
, rib
->table
);
1312 if (rib
->mtu
|| rib
->nexthop_mtu
)
1314 char buf
[NL_PKT_BUF_SIZE
];
1315 struct rtattr
*rta
= (void *) buf
;
1316 u_int32_t mtu
= rib
->mtu
;
1317 if (!mtu
|| (rib
->nexthop_mtu
&& rib
->nexthop_mtu
< mtu
))
1318 mtu
= rib
->nexthop_mtu
;
1319 rta
->rta_type
= RTA_METRICS
;
1320 rta
->rta_len
= RTA_LENGTH(0);
1321 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTAX_MTU
, &mtu
, sizeof mtu
);
1322 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_METRICS
, RTA_DATA (rta
),
1328 if (cmd
== RTM_NEWROUTE
)
1329 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1331 /* We shouldn't encounter recursive nexthops on discard routes,
1332 * but it is probably better to handle that case correctly anyway.
1334 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1340 /* Count overall nexthops so we can decide whether to use singlepath
1341 * or multipath case. */
1343 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1345 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1347 if (cmd
== RTM_NEWROUTE
&& !CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1349 if (cmd
== RTM_DELROUTE
&& !CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))
1355 /* Singlepath case. */
1356 if (nexthop_num
== 1 || MULTIPATH_NUM
== 1)
1359 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1361 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1365 if (family
== AF_INET
)
1367 if (nexthop
->rmap_src
.ipv4
.s_addr
!= 0)
1369 src
.ipv4
= nexthop
->rmap_src
.ipv4
;
1372 else if (nexthop
->src
.ipv4
.s_addr
!= 0)
1374 src
.ipv4
= nexthop
->src
.ipv4
;
1378 else if (family
== AF_INET6
)
1380 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
1382 src
.ipv6
= nexthop
->rmap_src
.ipv6
;
1385 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
1387 src
.ipv6
= nexthop
->src
.ipv6
;
1395 if ((cmd
== RTM_NEWROUTE
1396 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1397 || (cmd
== RTM_DELROUTE
1398 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
)))
1400 routedesc
= recursing
? "recursive, 1 hop" : "single hop";
1402 _netlink_route_debug(cmd
, p
, nexthop
, routedesc
, family
, zvrf
);
1403 _netlink_route_build_singlepath(routedesc
, bytelen
,
1404 nexthop
, &req
.n
, &req
.r
,
1410 if (setsrc
&& (cmd
== RTM_NEWROUTE
))
1412 if (family
== AF_INET
)
1413 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv4
, bytelen
);
1414 else if (family
== AF_INET6
)
1415 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv6
, bytelen
);
1420 char buf
[NL_PKT_BUF_SIZE
];
1421 struct rtattr
*rta
= (void *) buf
;
1422 struct rtnexthop
*rtnh
;
1423 union g_addr
*src1
= NULL
;
1425 rta
->rta_type
= RTA_MULTIPATH
;
1426 rta
->rta_len
= RTA_LENGTH (0);
1427 rtnh
= RTA_DATA (rta
);
1430 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1432 if (nexthop_num
>= MULTIPATH_NUM
)
1435 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1437 /* This only works for IPv4 now */
1440 if (family
== AF_INET
)
1442 if (nexthop
->rmap_src
.ipv4
.s_addr
!= 0)
1444 src
.ipv4
= nexthop
->rmap_src
.ipv4
;
1447 else if (nexthop
->src
.ipv4
.s_addr
!= 0)
1449 src
.ipv4
= nexthop
->src
.ipv4
;
1453 else if (family
== AF_INET6
)
1455 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
1457 src
.ipv6
= nexthop
->rmap_src
.ipv6
;
1460 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
1462 src
.ipv6
= nexthop
->src
.ipv6
;
1470 if ((cmd
== RTM_NEWROUTE
1471 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1472 || (cmd
== RTM_DELROUTE
1473 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
)))
1475 routedesc
= recursing
? "recursive, multihop" : "multihop";
1478 _netlink_route_debug(cmd
, p
, nexthop
,
1479 routedesc
, family
, zvrf
);
1480 _netlink_route_build_multipath(routedesc
, bytelen
,
1481 nexthop
, rta
, rtnh
, &req
.r
, &src1
);
1482 rtnh
= RTNH_NEXT (rtnh
);
1484 if (!setsrc
&& src1
)
1486 if (family
== AF_INET
)
1487 src
.ipv4
= src1
->ipv4
;
1488 else if (family
== AF_INET6
)
1489 src
.ipv6
= src1
->ipv6
;
1495 if (setsrc
&& (cmd
== RTM_NEWROUTE
))
1497 if (family
== AF_INET
)
1498 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv4
, bytelen
);
1499 else if (family
== AF_INET6
)
1500 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv6
, bytelen
);
1501 if (IS_ZEBRA_DEBUG_KERNEL
)
1502 zlog_debug("Setting source");
1505 if (rta
->rta_len
> RTA_LENGTH (0))
1506 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_MULTIPATH
, RTA_DATA (rta
),
1510 /* If there is no useful nexthop then return. */
1511 if (nexthop_num
== 0)
1513 if (IS_ZEBRA_DEBUG_KERNEL
)
1514 zlog_debug ("netlink_route_multipath(): No useful nexthop.");
1520 /* Destination netlink address. */
1521 memset (&snl
, 0, sizeof snl
);
1522 snl
.nl_family
= AF_NETLINK
;
1524 /* Talk to netlink socket. */
1525 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
);
1529 kernel_get_ipmr_sg_stats (void *in
)
1532 struct mcast_route_data
*mr
= (struct mcast_route_data
*)in
;
1540 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1542 memset(&req
.n
, 0, sizeof(req
.n
));
1543 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
1545 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ndmsg
));
1546 req
.n
.nlmsg_flags
= NLM_F_REQUEST
;
1547 req
.ndm
.ndm_family
= AF_INET
;
1548 req
.n
.nlmsg_type
= RTM_GETROUTE
;
1550 addattr_l (&req
.n
, sizeof (req
), RTA_IIF
, &mroute
->ifindex
, 4);
1551 addattr_l (&req
.n
, sizeof (req
), RTA_OIF
, &mroute
->ifindex
, 4);
1552 addattr_l (&req
.n
, sizeof (req
), RTA_SRC
, &mroute
->sg
.src
.s_addr
, 4);
1553 addattr_l (&req
.n
, sizeof (req
), RTA_DST
, &mroute
->sg
.grp
.s_addr
, 4);
1555 suc
= netlink_talk (netlink_route_change_read_multicast
, &req
.n
, &zns
->netlink_cmd
, zns
);
1562 kernel_route_rib (struct prefix
*p
, struct rib
*old
, struct rib
*new)
1565 return netlink_route_multipath (RTM_NEWROUTE
, p
, new, 0);
1567 return netlink_route_multipath (RTM_DELROUTE
, p
, old
, 0);
1569 return netlink_route_multipath (RTM_NEWROUTE
, p
, new, 1);
1573 kernel_neigh_update (int add
, int ifindex
, uint32_t addr
, char *lla
, int llalen
)
1575 return netlink_neigh_update(add
? RTM_NEWNEIGH
: RTM_DELNEIGH
, ifindex
, addr
,
1580 * MPLS label forwarding table change via netlink interface.
1583 netlink_mpls_multipath (int cmd
, zebra_lsp_t
*lsp
)
1586 zebra_nhlfe_t
*nhlfe
;
1587 struct nexthop
*nexthop
= NULL
;
1589 const char *routedesc
;
1590 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1596 char buf
[NL_PKT_BUF_SIZE
];
1599 memset (&req
, 0, sizeof req
- NL_PKT_BUF_SIZE
);
1603 * Count # nexthops so we can decide whether to use singlepath
1604 * or multipath case.
1607 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1609 nexthop
= nhlfe
->nexthop
;
1612 if (cmd
== RTM_NEWROUTE
)
1614 /* Count all selected NHLFEs */
1615 if (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
1616 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1621 /* Count all installed NHLFEs */
1622 if (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
1623 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))
1628 if (nexthop_num
== 0) // unexpected
1631 req
.n
.nlmsg_len
= NLMSG_LENGTH (sizeof (struct rtmsg
));
1632 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1633 req
.n
.nlmsg_type
= cmd
;
1634 req
.r
.rtm_family
= AF_MPLS
;
1635 req
.r
.rtm_table
= RT_TABLE_MAIN
;
1636 req
.r
.rtm_dst_len
= MPLS_LABEL_LEN_BITS
;
1637 req
.r
.rtm_protocol
= RTPROT_ZEBRA
;
1638 req
.r
.rtm_scope
= RT_SCOPE_UNIVERSE
;
1639 req
.r
.rtm_type
= RTN_UNICAST
;
1641 if (cmd
== RTM_NEWROUTE
)
1642 /* We do a replace to handle update. */
1643 req
.n
.nlmsg_flags
|= NLM_F_REPLACE
;
1645 /* Fill destination */
1646 lse
= mpls_lse_encode (lsp
->ile
.in_label
, 0, 0, 1);
1647 addattr_l (&req
.n
, sizeof req
, RTA_DST
, &lse
, sizeof(mpls_lse_t
));
1649 /* Fill nexthops (paths) based on single-path or multipath. The paths
1650 * chosen depend on the operation.
1652 if (nexthop_num
== 1 || MULTIPATH_NUM
== 1)
1654 routedesc
= "single hop";
1655 _netlink_mpls_debug(cmd
, lsp
->ile
.in_label
, routedesc
);
1658 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1660 nexthop
= nhlfe
->nexthop
;
1664 if ((cmd
== RTM_NEWROUTE
&&
1665 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
1666 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))) ||
1667 (cmd
== RTM_DELROUTE
&&
1668 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
1669 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))))
1671 /* Add the gateway */
1672 _netlink_mpls_build_singlepath(routedesc
, nhlfe
,
1673 &req
.n
, &req
.r
, sizeof req
, cmd
);
1674 if (cmd
== RTM_NEWROUTE
)
1676 SET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1677 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1681 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1682 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1689 else /* Multipath case */
1691 char buf
[NL_PKT_BUF_SIZE
];
1692 struct rtattr
*rta
= (void *) buf
;
1693 struct rtnexthop
*rtnh
;
1694 union g_addr
*src1
= NULL
;
1696 rta
->rta_type
= RTA_MULTIPATH
;
1697 rta
->rta_len
= RTA_LENGTH (0);
1698 rtnh
= RTA_DATA (rta
);
1700 routedesc
= "multihop";
1701 _netlink_mpls_debug(cmd
, lsp
->ile
.in_label
, routedesc
);
1704 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1706 nexthop
= nhlfe
->nexthop
;
1710 if (MULTIPATH_NUM
!= 0 && nexthop_num
>= MULTIPATH_NUM
)
1713 if ((cmd
== RTM_NEWROUTE
&&
1714 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
1715 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))) ||
1716 (cmd
== RTM_DELROUTE
&&
1717 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
1718 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))))
1722 /* Build the multipath */
1723 _netlink_mpls_build_multipath(routedesc
, nhlfe
, rta
,
1724 rtnh
, &req
.r
, &src1
);
1725 rtnh
= RTNH_NEXT (rtnh
);
1727 if (cmd
== RTM_NEWROUTE
)
1729 SET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1730 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1734 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1735 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1741 /* Add the multipath */
1742 if (rta
->rta_len
> RTA_LENGTH (0))
1743 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_MULTIPATH
, RTA_DATA (rta
),
1747 /* Talk to netlink socket. */
1748 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
);
1752 * Handle failure in LSP install, clear flags for NHLFE.
1755 clear_nhlfe_installed (zebra_lsp_t
*lsp
)
1757 zebra_nhlfe_t
*nhlfe
;
1758 struct nexthop
*nexthop
;
1760 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1762 nexthop
= nhlfe
->nexthop
;
1766 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1767 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);