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_route_change_read_unicast (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
130 ns_id_t ns_id
, int startup
)
134 struct rtattr
*tb
[RTA_MAX
+ 1];
137 struct prefix_ipv6 src_p
;
138 vrf_id_t vrf_id
= VRF_DEFAULT
;
140 char anyaddr
[16] = { 0 };
149 void *prefsrc
= NULL
; /* IPv4 preferred source host address */
150 void *src
= NULL
; /* IPv6 srcdest source prefix */
152 rtm
= NLMSG_DATA (h
);
154 if (startup
&& h
->nlmsg_type
!= RTM_NEWROUTE
)
156 if (startup
&& rtm
->rtm_type
!= RTN_UNICAST
)
159 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
163 memset (tb
, 0, sizeof tb
);
164 netlink_parse_rtattr (tb
, RTA_MAX
, RTM_RTA (rtm
), len
);
166 if (rtm
->rtm_flags
& RTM_F_CLONED
)
168 if (rtm
->rtm_protocol
== RTPROT_REDIRECT
)
170 if (rtm
->rtm_protocol
== RTPROT_KERNEL
)
174 rtm
->rtm_protocol
== RTPROT_ZEBRA
&&
175 h
->nlmsg_type
== RTM_NEWROUTE
)
178 /* We don't care about change notifications for the MPLS table. */
179 /* TODO: Revisit this. */
180 if (rtm
->rtm_family
== AF_MPLS
)
183 /* Table corresponding to route. */
185 table
= *(int *) RTA_DATA (tb
[RTA_TABLE
]);
187 table
= rtm
->rtm_table
;
190 vrf_id
= vrf_lookup_by_table(table
);
191 if (vrf_id
== VRF_DEFAULT
)
193 if (!is_zebra_valid_kernel_table(table
) &&
194 !is_zebra_main_routing_table(table
))
198 /* Route which inserted by Zebra. */
199 if (rtm
->rtm_protocol
== RTPROT_ZEBRA
)
200 flags
|= ZEBRA_FLAG_SELFROUTE
;
203 index
= *(int *) RTA_DATA (tb
[RTA_OIF
]);
206 dest
= RTA_DATA (tb
[RTA_DST
]);
211 src
= RTA_DATA (tb
[RTA_SRC
]);
216 prefsrc
= RTA_DATA (tb
[RTA_PREFSRC
]);
219 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
221 if (h
->nlmsg_type
== RTM_NEWROUTE
)
223 if (tb
[RTA_PRIORITY
])
224 metric
= *(int *) RTA_DATA(tb
[RTA_PRIORITY
]);
228 struct rtattr
*mxrta
[RTAX_MAX
+1];
230 memset (mxrta
, 0, sizeof mxrta
);
231 netlink_parse_rtattr (mxrta
, RTAX_MAX
, RTA_DATA(tb
[RTA_METRICS
]),
232 RTA_PAYLOAD(tb
[RTA_METRICS
]));
235 mtu
= *(u_int32_t
*) RTA_DATA(mxrta
[RTAX_MTU
]);
239 if (rtm
->rtm_family
== AF_INET
)
242 memcpy (&p
.u
.prefix4
, dest
, 4);
243 p
.prefixlen
= rtm
->rtm_dst_len
;
245 else if (rtm
->rtm_family
== AF_INET6
)
248 memcpy (&p
.u
.prefix6
, dest
, 16);
249 p
.prefixlen
= rtm
->rtm_dst_len
;
251 src_p
.family
= AF_INET6
;
252 memcpy (&src_p
.prefix
, src
, 16);
253 src_p
.prefixlen
= rtm
->rtm_src_len
;
256 if (rtm
->rtm_src_len
!= 0)
258 char buf
[PREFIX_STRLEN
];
259 zlog_warn ("unsupported IPv[4|6] sourcedest route (dest %s vrf %u)",
260 prefix2str (&p
, buf
, sizeof(buf
)), vrf_id
);
264 if (IS_ZEBRA_DEBUG_KERNEL
)
266 char buf
[PREFIX_STRLEN
];
267 char buf2
[PREFIX_STRLEN
];
268 zlog_debug ("%s %s%s%s vrf %u",
269 nl_msg_type_to_str (h
->nlmsg_type
),
270 prefix2str (&p
, buf
, sizeof(buf
)),
271 src_p
.prefixlen
? " from " : "",
272 src_p
.prefixlen
? prefix2str(&src_p
, buf2
, sizeof(buf2
)) : "",
277 if (rtm
->rtm_family
== AF_INET6
)
280 if (h
->nlmsg_type
== RTM_NEWROUTE
)
282 if (!tb
[RTA_MULTIPATH
])
283 rib_add (afi
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
,
284 0, flags
, &p
, NULL
, gate
, prefsrc
, index
,
285 table
, metric
, mtu
, 0);
288 /* This is a multipath route */
291 struct rtnexthop
*rtnh
=
292 (struct rtnexthop
*) RTA_DATA (tb
[RTA_MULTIPATH
]);
294 len
= RTA_PAYLOAD (tb
[RTA_MULTIPATH
]);
296 rib
= XCALLOC (MTYPE_RIB
, sizeof (struct rib
));
297 rib
->type
= ZEBRA_ROUTE_KERNEL
;
300 rib
->metric
= metric
;
302 rib
->vrf_id
= vrf_id
;
304 rib
->nexthop_num
= 0;
305 rib
->uptime
= time (NULL
);
309 if (len
< (int) sizeof (*rtnh
) || rtnh
->rtnh_len
> len
)
312 index
= rtnh
->rtnh_ifindex
;
314 if (rtnh
->rtnh_len
> sizeof (*rtnh
))
316 memset (tb
, 0, sizeof (tb
));
317 netlink_parse_rtattr (tb
, RTA_MAX
, RTNH_DATA (rtnh
),
318 rtnh
->rtnh_len
- sizeof (*rtnh
));
320 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
325 if (rtm
->rtm_family
== AF_INET
)
328 rib_nexthop_ipv4_ifindex_add (rib
, gate
, prefsrc
, index
);
330 rib_nexthop_ipv4_add (rib
, gate
, prefsrc
);
332 else if (rtm
->rtm_family
== AF_INET6
)
335 rib_nexthop_ipv6_ifindex_add (rib
, gate
, index
);
337 rib_nexthop_ipv6_add (rib
,gate
);
341 rib_nexthop_ifindex_add (rib
, index
);
343 len
-= NLMSG_ALIGN(rtnh
->rtnh_len
);
344 rtnh
= RTNH_NEXT(rtnh
);
347 zserv_nexthop_num_warn(__func__
, (const struct prefix
*)&p
,
349 if (rib
->nexthop_num
== 0)
350 XFREE (MTYPE_RIB
, rib
);
352 rib_add_multipath (AFI_IP
, SAFI_UNICAST
, &p
, NULL
, rib
);
357 if (!tb
[RTA_MULTIPATH
])
358 rib_delete (afi
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
, 0, flags
,
359 &p
, NULL
, gate
, index
, table
);
362 struct rtnexthop
*rtnh
=
363 (struct rtnexthop
*) RTA_DATA (tb
[RTA_MULTIPATH
]);
365 len
= RTA_PAYLOAD (tb
[RTA_MULTIPATH
]);
369 if (len
< (int) sizeof (*rtnh
) || rtnh
->rtnh_len
> len
)
373 if (rtnh
->rtnh_len
> sizeof (*rtnh
))
375 memset (tb
, 0, sizeof (tb
));
376 netlink_parse_rtattr (tb
, RTA_MAX
, RTNH_DATA (rtnh
),
377 rtnh
->rtnh_len
- sizeof (*rtnh
));
379 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
383 rib_delete (afi
, SAFI_UNICAST
, vrf_id
, ZEBRA_ROUTE_KERNEL
, 0, flags
,
384 &p
, NULL
, gate
, index
, table
);
386 len
-= NLMSG_ALIGN(rtnh
->rtnh_len
);
387 rtnh
= RTNH_NEXT(rtnh
);
395 static struct mcast_route_data
*mroute
= NULL
;
398 netlink_route_change_read_multicast (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
399 ns_id_t ns_id
, int startup
)
403 struct rtattr
*tb
[RTA_MAX
+ 1];
404 struct mcast_route_data
*m
;
405 struct mcast_route_data mr
;
412 char oif_list
[256] = "\0";
413 vrf_id_t vrf
= ns_id
;
419 memset (&mr
, 0, sizeof (mr
));
423 rtm
= NLMSG_DATA (h
);
425 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
427 memset (tb
, 0, sizeof tb
);
428 netlink_parse_rtattr (tb
, RTA_MAX
, RTM_RTA (rtm
), len
);
431 iif
= *(int *)RTA_DATA (tb
[RTA_IIF
]);
434 m
->sg
.src
= *(struct in_addr
*)RTA_DATA (tb
[RTA_SRC
]);
437 m
->sg
.grp
= *(struct in_addr
*)RTA_DATA (tb
[RTA_DST
]);
439 if ((RTA_EXPIRES
<= RTA_MAX
) && tb
[RTA_EXPIRES
])
440 m
->lastused
= *(unsigned long long *)RTA_DATA (tb
[RTA_EXPIRES
]);
442 if (tb
[RTA_MULTIPATH
])
444 struct rtnexthop
*rtnh
=
445 (struct rtnexthop
*)RTA_DATA (tb
[RTA_MULTIPATH
]);
447 len
= RTA_PAYLOAD (tb
[RTA_MULTIPATH
]);
450 if (len
< (int) sizeof (*rtnh
) || rtnh
->rtnh_len
> len
)
453 oif
[oif_count
] = rtnh
->rtnh_ifindex
;
456 len
-= NLMSG_ALIGN (rtnh
->rtnh_len
);
457 rtnh
= RTNH_NEXT (rtnh
);
461 if (IS_ZEBRA_DEBUG_KERNEL
)
463 struct interface
*ifp
;
464 strcpy (sbuf
, inet_ntoa (m
->sg
.src
));
465 strcpy (gbuf
, inet_ntoa (m
->sg
.grp
));
466 for (count
= 0; count
< oif_count
; count
++)
468 ifp
= if_lookup_by_index (oif
[count
], vrf
);
471 sprintf (temp
, "%s ", ifp
->name
);
472 strcat (oif_list
, temp
);
474 ifp
= if_lookup_by_index (iif
, vrf
);
475 zlog_debug ("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld",
476 nl_msg_type_to_str(h
->nlmsg_type
), sbuf
, gbuf
, ifp
->name
, oif_list
, m
->lastused
);
482 netlink_route_change (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
,
483 ns_id_t ns_id
, int startup
)
486 vrf_id_t vrf_id
= ns_id
;
489 rtm
= NLMSG_DATA (h
);
491 if (!(h
->nlmsg_type
== RTM_NEWROUTE
|| h
->nlmsg_type
== RTM_DELROUTE
))
493 /* If this is not route add/delete message print warning. */
494 zlog_warn ("Kernel message: %d vrf %u\n", h
->nlmsg_type
, vrf_id
);
498 /* Connected route. */
499 if (IS_ZEBRA_DEBUG_KERNEL
)
500 zlog_debug ("%s %s %s proto %s vrf %u",
501 nl_msg_type_to_str (h
->nlmsg_type
),
502 nl_family_to_str (rtm
->rtm_family
),
503 nl_rttype_to_str (rtm
->rtm_type
),
504 nl_rtproto_to_str (rtm
->rtm_protocol
),
507 /* We don't care about change notifications for the MPLS table. */
508 /* TODO: Revisit this. */
509 if (rtm
->rtm_family
== AF_MPLS
)
512 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct rtmsg
));
516 switch (rtm
->rtm_type
)
519 netlink_route_change_read_unicast (snl
, h
, ns_id
, startup
);
522 netlink_route_change_read_multicast (snl
, h
, ns_id
, startup
);
532 /* Routing table read function using netlink interface. Only called
535 netlink_route_read (struct zebra_ns
*zns
)
539 /* Get IPv4 routing table. */
540 ret
= netlink_request (AF_INET
, RTM_GETROUTE
, &zns
->netlink_cmd
);
543 ret
= netlink_parse_info (netlink_route_change_read_unicast
, &zns
->netlink_cmd
, zns
, 0, 1);
547 /* Get IPv6 routing table. */
548 ret
= netlink_request (AF_INET6
, RTM_GETROUTE
, &zns
->netlink_cmd
);
551 ret
= netlink_parse_info (netlink_route_change_read_unicast
, &zns
->netlink_cmd
, zns
, 0, 1);
559 _netlink_route_nl_add_gateway_info (u_char route_family
, u_char gw_family
,
560 struct nlmsghdr
*nlmsg
,
561 size_t req_size
, int bytelen
,
562 struct nexthop
*nexthop
)
564 if (route_family
== AF_MPLS
)
566 struct gw_family_t gw_fam
;
568 gw_fam
.family
= gw_family
;
569 if (gw_family
== AF_INET
)
570 memcpy (&gw_fam
.gate
.ipv4
, &nexthop
->gate
.ipv4
, bytelen
);
572 memcpy (&gw_fam
.gate
.ipv6
, &nexthop
->gate
.ipv6
, bytelen
);
573 addattr_l (nlmsg
, req_size
, RTA_VIA
, &gw_fam
.family
, bytelen
+2);
577 if (gw_family
== AF_INET
)
578 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv4
, bytelen
);
580 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv6
, bytelen
);
585 _netlink_route_rta_add_gateway_info (u_char route_family
, u_char gw_family
,
586 struct rtattr
*rta
, struct rtnexthop
*rtnh
,
587 size_t req_size
, int bytelen
,
588 struct nexthop
*nexthop
)
590 if (route_family
== AF_MPLS
)
592 struct gw_family_t gw_fam
;
594 gw_fam
.family
= gw_family
;
595 if (gw_family
== AF_INET
)
596 memcpy (&gw_fam
.gate
.ipv4
, &nexthop
->gate
.ipv4
, bytelen
);
598 memcpy (&gw_fam
.gate
.ipv6
, &nexthop
->gate
.ipv6
, bytelen
);
599 rta_addattr_l (rta
, req_size
, RTA_VIA
, &gw_fam
.family
, bytelen
+2);
600 rtnh
->rtnh_len
+= RTA_LENGTH (bytelen
+ 2);
604 if (gw_family
== AF_INET
)
605 rta_addattr_l (rta
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv4
, bytelen
);
607 rta_addattr_l (rta
, req_size
, RTA_GATEWAY
, &nexthop
->gate
.ipv6
, bytelen
);
608 rtnh
->rtnh_len
+= sizeof (struct rtattr
) + bytelen
;
612 /* This function takes a nexthop as argument and adds
613 * the appropriate netlink attributes to an existing
616 * @param routedesc: Human readable description of route type
617 * (direct/recursive, single-/multipath)
618 * @param bytelen: Length of addresses in bytes.
619 * @param nexthop: Nexthop information
620 * @param nlmsg: nlmsghdr structure to fill in.
621 * @param req_size: The size allocated for the message.
624 _netlink_route_build_singlepath(
625 const char *routedesc
,
627 struct nexthop
*nexthop
,
628 struct nlmsghdr
*nlmsg
,
633 struct nexthop_label
*nh_label
;
634 mpls_lse_t out_lse
[MPLS_MAX_LABELS
];
637 if (rtmsg
->rtm_family
== AF_INET
&&
638 (nexthop
->type
== NEXTHOP_TYPE_IPV6
639 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
))
641 char buf
[16] = "169.254.0.1";
642 struct in_addr ipv4_ll
;
644 inet_pton (AF_INET
, buf
, &ipv4_ll
);
645 rtmsg
->rtm_flags
|= RTNH_F_ONLINK
;
646 addattr_l (nlmsg
, req_size
, RTA_GATEWAY
, &ipv4_ll
, 4);
647 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
649 if (nexthop
->rmap_src
.ipv4
.s_addr
&& (cmd
== RTM_NEWROUTE
))
650 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
651 &nexthop
->rmap_src
.ipv4
, bytelen
);
652 else if (nexthop
->src
.ipv4
.s_addr
&& (cmd
== RTM_NEWROUTE
))
653 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
654 &nexthop
->src
.ipv4
, bytelen
);
656 if (IS_ZEBRA_DEBUG_KERNEL
)
657 zlog_debug(" 5549: _netlink_route_build_singlepath() (%s): "
658 "nexthop via %s if %u",
659 routedesc
, buf
, nexthop
->ifindex
);
664 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
665 * (in the case of LER)
667 nh_label
= nexthop
->nh_label
;
668 if (rtmsg
->rtm_family
== AF_MPLS
)
671 assert (nh_label
->num_labels
== 1);
674 if (nh_label
&& nh_label
->num_labels
)
676 int i
, num_labels
= 0;
680 for (i
= 0; i
< nh_label
->num_labels
; i
++)
682 if (nh_label
->label
[i
] != MPLS_IMP_NULL_LABEL
)
684 bos
= ((i
== (nh_label
->num_labels
- 1)) ? 1 : 0);
685 out_lse
[i
] = mpls_lse_encode (nh_label
->label
[i
], 0, 0, bos
);
687 sprintf (label_buf
, "label %d", nh_label
->label
[i
]);
690 sprintf (label_buf1
, "/%d", nh_label
->label
[i
]);
691 strcat (label_buf
, label_buf1
);
698 if (rtmsg
->rtm_family
== AF_MPLS
)
699 addattr_l (nlmsg
, req_size
, RTA_NEWDST
,
700 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
704 u_int16_t encap
= LWTUNNEL_ENCAP_MPLS
;
706 addattr_l(nlmsg
, req_size
, RTA_ENCAP_TYPE
,
707 &encap
, sizeof (u_int16_t
));
708 nest
= addattr_nest(nlmsg
, req_size
, RTA_ENCAP
);
709 addattr_l (nlmsg
, req_size
, MPLS_IPTUNNEL_DST
,
710 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
711 addattr_nest_end(nlmsg
, nest
);
716 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
717 rtmsg
->rtm_flags
|= RTNH_F_ONLINK
;
719 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
720 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
722 /* Send deletes to the kernel without specifying the next-hop */
723 if (cmd
!= RTM_DELROUTE
)
724 _netlink_route_nl_add_gateway_info (rtmsg
->rtm_family
, AF_INET
, nlmsg
,
725 req_size
, bytelen
, nexthop
);
727 if (cmd
== RTM_NEWROUTE
)
729 if (nexthop
->rmap_src
.ipv4
.s_addr
)
730 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
731 &nexthop
->rmap_src
.ipv4
, bytelen
);
732 else if (nexthop
->src
.ipv4
.s_addr
)
733 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
734 &nexthop
->src
.ipv4
, bytelen
);
737 if (IS_ZEBRA_DEBUG_KERNEL
)
738 zlog_debug("netlink_route_multipath() (%s): "
739 "nexthop via %s %s if %u",
741 inet_ntoa (nexthop
->gate
.ipv4
),
742 label_buf
, nexthop
->ifindex
);
744 if (nexthop
->type
== NEXTHOP_TYPE_IPV6
745 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
747 _netlink_route_nl_add_gateway_info (rtmsg
->rtm_family
, AF_INET6
, nlmsg
,
748 req_size
, bytelen
, nexthop
);
750 if (cmd
== RTM_NEWROUTE
)
752 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
753 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
754 &nexthop
->rmap_src
.ipv6
, bytelen
);
755 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
756 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
757 &nexthop
->src
.ipv6
, bytelen
);
760 if (IS_ZEBRA_DEBUG_KERNEL
)
761 zlog_debug("netlink_route_multipath() (%s): "
762 "nexthop via %s %s if %u",
764 inet6_ntoa (nexthop
->gate
.ipv6
),
765 label_buf
, nexthop
->ifindex
);
767 if (nexthop
->type
== NEXTHOP_TYPE_IFINDEX
768 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
770 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
772 if (cmd
== RTM_NEWROUTE
)
774 if (nexthop
->rmap_src
.ipv4
.s_addr
)
775 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
776 &nexthop
->rmap_src
.ipv4
, bytelen
);
777 else if (nexthop
->src
.ipv4
.s_addr
)
778 addattr_l (nlmsg
, req_size
, RTA_PREFSRC
,
779 &nexthop
->src
.ipv4
, bytelen
);
782 if (IS_ZEBRA_DEBUG_KERNEL
)
783 zlog_debug("netlink_route_multipath() (%s): "
784 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
787 if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
789 addattr32 (nlmsg
, req_size
, RTA_OIF
, nexthop
->ifindex
);
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 if %u", routedesc
, nexthop
->ifindex
);
807 /* This function takes a nexthop as argument and
808 * appends to the given rtattr/rtnexthop pair the
809 * representation of the nexthop. If the nexthop
810 * defines a preferred source, the src parameter
811 * will be modified to point to that src, otherwise
812 * it will be kept unmodified.
814 * @param routedesc: Human readable description of route type
815 * (direct/recursive, single-/multipath)
816 * @param bytelen: Length of addresses in bytes.
817 * @param nexthop: Nexthop information
818 * @param rta: rtnetlink attribute structure
819 * @param rtnh: pointer to an rtnetlink nexthop structure
820 * @param src: pointer pointing to a location where
821 * the prefsrc should be stored.
824 _netlink_route_build_multipath(
825 const char *routedesc
,
827 struct nexthop
*nexthop
,
829 struct rtnexthop
*rtnh
,
833 struct nexthop_label
*nh_label
;
834 mpls_lse_t out_lse
[MPLS_MAX_LABELS
];
837 rtnh
->rtnh_len
= sizeof (*rtnh
);
838 rtnh
->rtnh_flags
= 0;
840 rta
->rta_len
+= rtnh
->rtnh_len
;
842 if (rtmsg
->rtm_family
== AF_INET
&&
843 (nexthop
->type
== NEXTHOP_TYPE_IPV6
844 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
))
846 char buf
[16] = "169.254.0.1";
847 struct in_addr ipv4_ll
;
849 inet_pton (AF_INET
, buf
, &ipv4_ll
);
851 rtnh
->rtnh_flags
|= RTNH_F_ONLINK
;
852 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTA_GATEWAY
,
854 rtnh
->rtnh_len
+= sizeof (struct rtattr
) + bytelen
;
855 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
857 if (nexthop
->rmap_src
.ipv4
.s_addr
)
858 *src
= &nexthop
->rmap_src
;
859 else if (nexthop
->src
.ipv4
.s_addr
)
860 *src
= &nexthop
->src
;
862 if (IS_ZEBRA_DEBUG_KERNEL
)
863 zlog_debug(" 5549: netlink_route_build_multipath() (%s): "
864 "nexthop via %s if %u",
865 routedesc
, buf
, nexthop
->ifindex
);
870 /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP
871 * (in the case of LER)
873 nh_label
= nexthop
->nh_label
;
874 if (rtmsg
->rtm_family
== AF_MPLS
)
877 assert (nh_label
->num_labels
== 1);
880 if (nh_label
&& nh_label
->num_labels
)
882 int i
, num_labels
= 0;
886 for (i
= 0; i
< nh_label
->num_labels
; i
++)
888 if (nh_label
->label
[i
] != MPLS_IMP_NULL_LABEL
)
890 bos
= ((i
== (nh_label
->num_labels
- 1)) ? 1 : 0);
891 out_lse
[i
] = mpls_lse_encode (nh_label
->label
[i
], 0, 0, bos
);
893 sprintf (label_buf
, "label %d", nh_label
->label
[i
]);
896 sprintf (label_buf1
, "/%d", nh_label
->label
[i
]);
897 strcat (label_buf
, label_buf1
);
904 if (rtmsg
->rtm_family
== AF_MPLS
)
906 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTA_NEWDST
,
907 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
908 rtnh
->rtnh_len
+= RTA_LENGTH (num_labels
* sizeof(mpls_lse_t
));
913 u_int16_t encap
= LWTUNNEL_ENCAP_MPLS
;
914 int len
= rta
->rta_len
;
916 rta_addattr_l(rta
, NL_PKT_BUF_SIZE
, RTA_ENCAP_TYPE
,
917 &encap
, sizeof (u_int16_t
));
918 nest
= rta_nest(rta
, NL_PKT_BUF_SIZE
, RTA_ENCAP
);
919 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, MPLS_IPTUNNEL_DST
,
920 &out_lse
, num_labels
* sizeof(mpls_lse_t
));
921 rta_nest_end(rta
, nest
);
922 rtnh
->rtnh_len
+= rta
->rta_len
- len
;
927 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
928 rtnh
->rtnh_flags
|= RTNH_F_ONLINK
;
930 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
931 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
933 _netlink_route_rta_add_gateway_info (rtmsg
->rtm_family
, AF_INET
, rta
,
934 rtnh
, NL_PKT_BUF_SIZE
, bytelen
, nexthop
);
935 if (nexthop
->rmap_src
.ipv4
.s_addr
)
936 *src
= &nexthop
->rmap_src
;
937 else if (nexthop
->src
.ipv4
.s_addr
)
938 *src
= &nexthop
->src
;
940 if (IS_ZEBRA_DEBUG_KERNEL
)
941 zlog_debug("netlink_route_multipath() (%s): "
942 "nexthop via %s %s if %u",
944 inet_ntoa (nexthop
->gate
.ipv4
),
945 label_buf
, nexthop
->ifindex
);
947 if (nexthop
->type
== NEXTHOP_TYPE_IPV6
948 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
950 _netlink_route_rta_add_gateway_info (rtmsg
->rtm_family
, AF_INET6
, rta
,
951 rtnh
, NL_PKT_BUF_SIZE
, bytelen
, nexthop
);
953 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
954 *src
= &nexthop
->rmap_src
;
955 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
956 *src
= &nexthop
->src
;
958 if (IS_ZEBRA_DEBUG_KERNEL
)
959 zlog_debug("netlink_route_multipath() (%s): "
960 "nexthop via %s %s if %u",
962 inet6_ntoa (nexthop
->gate
.ipv6
),
963 label_buf
, nexthop
->ifindex
);
966 if (nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
967 || nexthop
->type
== NEXTHOP_TYPE_IFINDEX
)
969 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
971 if (nexthop
->rmap_src
.ipv4
.s_addr
)
972 *src
= &nexthop
->rmap_src
;
973 else if (nexthop
->src
.ipv4
.s_addr
)
974 *src
= &nexthop
->src
;
976 if (IS_ZEBRA_DEBUG_KERNEL
)
977 zlog_debug("netlink_route_multipath() (%s): "
978 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
980 else if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
982 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
984 if (IS_ZEBRA_DEBUG_KERNEL
)
985 zlog_debug("netlink_route_multipath() (%s): "
986 "nexthop via if %u", routedesc
, nexthop
->ifindex
);
990 rtnh
->rtnh_ifindex
= 0;
995 _netlink_mpls_build_singlepath(
996 const char *routedesc
,
997 zebra_nhlfe_t
*nhlfe
,
998 struct nlmsghdr
*nlmsg
,
1006 family
= NHLFE_FAMILY (nhlfe
);
1007 bytelen
= (family
== AF_INET
? 4 : 16);
1008 _netlink_route_build_singlepath(routedesc
, bytelen
, nhlfe
->nexthop
,
1009 nlmsg
, rtmsg
, req_size
, cmd
);
1014 _netlink_mpls_build_multipath(
1015 const char *routedesc
,
1016 zebra_nhlfe_t
*nhlfe
,
1018 struct rtnexthop
*rtnh
,
1019 struct rtmsg
*rtmsg
,
1025 family
= NHLFE_FAMILY (nhlfe
);
1026 bytelen
= (family
== AF_INET
? 4 : 16);
1027 _netlink_route_build_multipath(routedesc
, bytelen
, nhlfe
->nexthop
,
1028 rta
, rtnh
, rtmsg
, src
);
1032 /* Log debug information for netlink_route_multipath
1033 * if debug logging is enabled.
1035 * @param cmd: Netlink command which is to be processed
1036 * @param p: Prefix for which the change is due
1037 * @param nexthop: Nexthop which is currently processed
1038 * @param routedesc: Semantic annotation for nexthop
1039 * (recursive, multipath, etc.)
1040 * @param family: Address family which the change concerns
1043 _netlink_route_debug(
1046 struct nexthop
*nexthop
,
1047 const char *routedesc
,
1049 struct zebra_vrf
*zvrf
)
1051 if (IS_ZEBRA_DEBUG_KERNEL
)
1053 char buf
[PREFIX_STRLEN
];
1054 zlog_debug ("netlink_route_multipath() (%s): %s %s vrf %u type %s",
1056 nl_msg_type_to_str (cmd
),
1057 prefix2str (p
, buf
, sizeof(buf
)), zvrf_id (zvrf
),
1058 (nexthop
) ? nexthop_type_to_str (nexthop
->type
) : "UNK");
1063 _netlink_mpls_debug(
1066 const char *routedesc
)
1068 if (IS_ZEBRA_DEBUG_KERNEL
)
1069 zlog_debug ("netlink_mpls_multipath() (%s): %s %u/20",
1070 routedesc
, nl_msg_type_to_str (cmd
), label
);
1074 netlink_neigh_update (int cmd
, int ifindex
, uint32_t addr
, char *lla
, int llalen
)
1082 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1084 memset(&req
.n
, 0, sizeof(req
.n
));
1085 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
1087 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ndmsg
));
1088 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1089 req
.n
.nlmsg_type
= cmd
; //RTM_NEWNEIGH or RTM_DELNEIGH
1090 req
.ndm
.ndm_family
= AF_INET
;
1091 req
.ndm
.ndm_state
= NUD_PERMANENT
;
1092 req
.ndm
.ndm_ifindex
= ifindex
;
1093 req
.ndm
.ndm_type
= RTN_UNICAST
;
1095 addattr_l(&req
.n
, sizeof(req
), NDA_DST
, &addr
, 4);
1096 addattr_l(&req
.n
, sizeof(req
), NDA_LLADDR
, lla
, llalen
);
1098 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
, 0);
1101 /* Routing table change via netlink interface. */
1102 /* Update flag indicates whether this is a "replace" or not. */
1104 netlink_route_multipath (int cmd
, struct prefix
*p
, struct prefix
*src_p
,
1105 struct rib
*rib
, int update
)
1108 struct sockaddr_nl snl
;
1109 struct nexthop
*nexthop
= NULL
, *tnexthop
;
1111 unsigned int nexthop_num
;
1113 int family
= PREFIX_FAMILY(p
);
1114 const char *routedesc
;
1122 char buf
[NL_PKT_BUF_SIZE
];
1125 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1126 struct zebra_vrf
*zvrf
= vrf_info_lookup (rib
->vrf_id
);
1128 memset (&req
, 0, sizeof req
- NL_PKT_BUF_SIZE
);
1130 bytelen
= (family
== AF_INET
? 4 : 16);
1132 req
.n
.nlmsg_len
= NLMSG_LENGTH (sizeof (struct rtmsg
));
1133 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1134 if ((cmd
== RTM_NEWROUTE
) && update
)
1135 req
.n
.nlmsg_flags
|= NLM_F_REPLACE
;
1136 req
.n
.nlmsg_type
= cmd
;
1137 req
.r
.rtm_family
= family
;
1138 req
.r
.rtm_dst_len
= p
->prefixlen
;
1139 req
.r
.rtm_src_len
= src_p
? src_p
->prefixlen
: 0;
1140 req
.r
.rtm_protocol
= RTPROT_ZEBRA
;
1141 req
.r
.rtm_scope
= RT_SCOPE_UNIVERSE
;
1143 if ((rib
->flags
& ZEBRA_FLAG_BLACKHOLE
) || (rib
->flags
& ZEBRA_FLAG_REJECT
))
1148 if (cmd
== RTM_NEWROUTE
)
1152 if (rib
->flags
& ZEBRA_FLAG_BLACKHOLE
)
1153 req
.r
.rtm_type
= RTN_BLACKHOLE
;
1154 else if (rib
->flags
& ZEBRA_FLAG_REJECT
)
1155 req
.r
.rtm_type
= RTN_UNREACHABLE
;
1157 assert (RTN_BLACKHOLE
!= RTN_UNREACHABLE
); /* false */
1160 req
.r
.rtm_type
= RTN_UNICAST
;
1163 addattr_l (&req
.n
, sizeof req
, RTA_DST
, &p
->u
.prefix
, bytelen
);
1165 addattr_l (&req
.n
, sizeof req
, RTA_SRC
, &src_p
->u
.prefix
, bytelen
);
1168 /* Hardcode the metric for all routes coming from zebra. Metric isn't used
1169 * either by the kernel or by zebra. Its purely for calculating best path(s)
1170 * by the routing protocol and for communicating with protocol peers.
1172 addattr32 (&req
.n
, sizeof req
, RTA_PRIORITY
, NL_DEFAULT_ROUTE_METRIC
);
1174 /* Table corresponding to this route. */
1175 if (rib
->table
< 256)
1176 req
.r
.rtm_table
= rib
->table
;
1179 req
.r
.rtm_table
= RT_TABLE_UNSPEC
;
1180 addattr32(&req
.n
, sizeof req
, RTA_TABLE
, rib
->table
);
1183 if (rib
->mtu
|| rib
->nexthop_mtu
)
1185 char buf
[NL_PKT_BUF_SIZE
];
1186 struct rtattr
*rta
= (void *) buf
;
1187 u_int32_t mtu
= rib
->mtu
;
1188 if (!mtu
|| (rib
->nexthop_mtu
&& rib
->nexthop_mtu
< mtu
))
1189 mtu
= rib
->nexthop_mtu
;
1190 rta
->rta_type
= RTA_METRICS
;
1191 rta
->rta_len
= RTA_LENGTH(0);
1192 rta_addattr_l (rta
, NL_PKT_BUF_SIZE
, RTAX_MTU
, &mtu
, sizeof mtu
);
1193 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_METRICS
, RTA_DATA (rta
),
1199 if (cmd
== RTM_NEWROUTE
)
1200 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1202 /* We shouldn't encounter recursive nexthops on discard routes,
1203 * but it is probably better to handle that case correctly anyway.
1205 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1211 /* Count overall nexthops so we can decide whether to use singlepath
1212 * or multipath case. */
1214 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1216 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1218 if (cmd
== RTM_NEWROUTE
&& !CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1220 if (cmd
== RTM_DELROUTE
&& !CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))
1226 /* Singlepath case. */
1227 if (nexthop_num
== 1 || multipath_num
== 1)
1230 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1232 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1236 if (family
== AF_INET
)
1238 if (nexthop
->rmap_src
.ipv4
.s_addr
!= 0)
1240 src
.ipv4
= nexthop
->rmap_src
.ipv4
;
1243 else if (nexthop
->src
.ipv4
.s_addr
!= 0)
1245 src
.ipv4
= nexthop
->src
.ipv4
;
1249 else if (family
== AF_INET6
)
1251 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
1253 src
.ipv6
= nexthop
->rmap_src
.ipv6
;
1256 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
1258 src
.ipv6
= nexthop
->src
.ipv6
;
1266 if ((cmd
== RTM_NEWROUTE
1267 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1268 || (cmd
== RTM_DELROUTE
1269 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
)))
1271 routedesc
= recursing
? "recursive, 1 hop" : "single hop";
1273 _netlink_route_debug(cmd
, p
, nexthop
, routedesc
, family
, zvrf
);
1274 _netlink_route_build_singlepath(routedesc
, bytelen
,
1275 nexthop
, &req
.n
, &req
.r
,
1281 if (setsrc
&& (cmd
== RTM_NEWROUTE
))
1283 if (family
== AF_INET
)
1284 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv4
, bytelen
);
1285 else if (family
== AF_INET6
)
1286 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv6
, bytelen
);
1291 char buf
[NL_PKT_BUF_SIZE
];
1292 struct rtattr
*rta
= (void *) buf
;
1293 struct rtnexthop
*rtnh
;
1294 union g_addr
*src1
= NULL
;
1296 rta
->rta_type
= RTA_MULTIPATH
;
1297 rta
->rta_len
= RTA_LENGTH (0);
1298 rtnh
= RTA_DATA (rta
);
1301 for (ALL_NEXTHOPS_RO(rib
->nexthop
, nexthop
, tnexthop
, recursing
))
1303 if (nexthop_num
>= multipath_num
)
1306 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1308 /* This only works for IPv4 now */
1311 if (family
== AF_INET
)
1313 if (nexthop
->rmap_src
.ipv4
.s_addr
!= 0)
1315 src
.ipv4
= nexthop
->rmap_src
.ipv4
;
1318 else if (nexthop
->src
.ipv4
.s_addr
!= 0)
1320 src
.ipv4
= nexthop
->src
.ipv4
;
1324 else if (family
== AF_INET6
)
1326 if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->rmap_src
.ipv6
))
1328 src
.ipv6
= nexthop
->rmap_src
.ipv6
;
1331 else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop
->src
.ipv6
))
1333 src
.ipv6
= nexthop
->src
.ipv6
;
1341 if ((cmd
== RTM_NEWROUTE
1342 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1343 || (cmd
== RTM_DELROUTE
1344 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
)))
1346 routedesc
= recursing
? "recursive, multihop" : "multihop";
1349 _netlink_route_debug(cmd
, p
, nexthop
,
1350 routedesc
, family
, zvrf
);
1351 _netlink_route_build_multipath(routedesc
, bytelen
,
1352 nexthop
, rta
, rtnh
, &req
.r
, &src1
);
1353 rtnh
= RTNH_NEXT (rtnh
);
1355 if (!setsrc
&& src1
)
1357 if (family
== AF_INET
)
1358 src
.ipv4
= src1
->ipv4
;
1359 else if (family
== AF_INET6
)
1360 src
.ipv6
= src1
->ipv6
;
1366 if (setsrc
&& (cmd
== RTM_NEWROUTE
))
1368 if (family
== AF_INET
)
1369 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv4
, bytelen
);
1370 else if (family
== AF_INET6
)
1371 addattr_l (&req
.n
, sizeof req
, RTA_PREFSRC
, &src
.ipv6
, bytelen
);
1372 if (IS_ZEBRA_DEBUG_KERNEL
)
1373 zlog_debug("Setting source");
1376 if (rta
->rta_len
> RTA_LENGTH (0))
1377 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_MULTIPATH
, RTA_DATA (rta
),
1381 /* If there is no useful nexthop then return. */
1382 if (nexthop_num
== 0)
1384 if (IS_ZEBRA_DEBUG_KERNEL
)
1385 zlog_debug ("netlink_route_multipath(): No useful nexthop.");
1391 /* Destination netlink address. */
1392 memset (&snl
, 0, sizeof snl
);
1393 snl
.nl_family
= AF_NETLINK
;
1395 /* Talk to netlink socket. */
1396 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
, 0);
1400 kernel_get_ipmr_sg_stats (void *in
)
1403 struct mcast_route_data
*mr
= (struct mcast_route_data
*)in
;
1411 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1413 memset(&req
.n
, 0, sizeof(req
.n
));
1414 memset(&req
.ndm
, 0, sizeof(req
.ndm
));
1416 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ndmsg
));
1417 req
.n
.nlmsg_flags
= NLM_F_REQUEST
;
1418 req
.ndm
.ndm_family
= AF_INET
;
1419 req
.n
.nlmsg_type
= RTM_GETROUTE
;
1421 addattr_l (&req
.n
, sizeof (req
), RTA_IIF
, &mroute
->ifindex
, 4);
1422 addattr_l (&req
.n
, sizeof (req
), RTA_OIF
, &mroute
->ifindex
, 4);
1423 addattr_l (&req
.n
, sizeof (req
), RTA_SRC
, &mroute
->sg
.src
.s_addr
, 4);
1424 addattr_l (&req
.n
, sizeof (req
), RTA_DST
, &mroute
->sg
.grp
.s_addr
, 4);
1426 suc
= netlink_talk (netlink_route_change_read_multicast
, &req
.n
, &zns
->netlink_cmd
, zns
, 0);
1433 kernel_route_rib (struct prefix
*p
, struct prefix
*src_p
,
1434 struct rib
*old
, struct rib
*new)
1437 return netlink_route_multipath (RTM_NEWROUTE
, p
, src_p
, new, 0);
1439 return netlink_route_multipath (RTM_DELROUTE
, p
, src_p
, old
, 0);
1441 return netlink_route_multipath (RTM_NEWROUTE
, p
, src_p
, new, 1);
1445 kernel_neigh_update (int add
, int ifindex
, uint32_t addr
, char *lla
, int llalen
)
1447 return netlink_neigh_update(add
? RTM_NEWNEIGH
: RTM_DELNEIGH
, ifindex
, addr
,
1452 * MPLS label forwarding table change via netlink interface.
1455 netlink_mpls_multipath (int cmd
, zebra_lsp_t
*lsp
)
1458 zebra_nhlfe_t
*nhlfe
;
1459 struct nexthop
*nexthop
= NULL
;
1460 unsigned int nexthop_num
;
1461 const char *routedesc
;
1462 struct zebra_ns
*zns
= zebra_ns_lookup (NS_DEFAULT
);
1468 char buf
[NL_PKT_BUF_SIZE
];
1471 memset (&req
, 0, sizeof req
- NL_PKT_BUF_SIZE
);
1475 * Count # nexthops so we can decide whether to use singlepath
1476 * or multipath case.
1479 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1481 nexthop
= nhlfe
->nexthop
;
1484 if (cmd
== RTM_NEWROUTE
)
1486 /* Count all selected NHLFEs */
1487 if (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
1488 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1493 /* Count all installed NHLFEs */
1494 if (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
1495 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))
1500 if (nexthop_num
== 0) // unexpected
1503 req
.n
.nlmsg_len
= NLMSG_LENGTH (sizeof (struct rtmsg
));
1504 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1505 req
.n
.nlmsg_type
= cmd
;
1506 req
.r
.rtm_family
= AF_MPLS
;
1507 req
.r
.rtm_table
= RT_TABLE_MAIN
;
1508 req
.r
.rtm_dst_len
= MPLS_LABEL_LEN_BITS
;
1509 req
.r
.rtm_protocol
= RTPROT_ZEBRA
;
1510 req
.r
.rtm_scope
= RT_SCOPE_UNIVERSE
;
1511 req
.r
.rtm_type
= RTN_UNICAST
;
1513 if (cmd
== RTM_NEWROUTE
)
1514 /* We do a replace to handle update. */
1515 req
.n
.nlmsg_flags
|= NLM_F_REPLACE
;
1517 /* Fill destination */
1518 lse
= mpls_lse_encode (lsp
->ile
.in_label
, 0, 0, 1);
1519 addattr_l (&req
.n
, sizeof req
, RTA_DST
, &lse
, sizeof(mpls_lse_t
));
1521 /* Fill nexthops (paths) based on single-path or multipath. The paths
1522 * chosen depend on the operation.
1524 if (nexthop_num
== 1 || multipath_num
== 1)
1526 routedesc
= "single hop";
1527 _netlink_mpls_debug(cmd
, lsp
->ile
.in_label
, routedesc
);
1530 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1532 nexthop
= nhlfe
->nexthop
;
1536 if ((cmd
== RTM_NEWROUTE
&&
1537 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
1538 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))) ||
1539 (cmd
== RTM_DELROUTE
&&
1540 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
1541 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))))
1543 /* Add the gateway */
1544 _netlink_mpls_build_singlepath(routedesc
, nhlfe
,
1545 &req
.n
, &req
.r
, sizeof req
, cmd
);
1546 if (cmd
== RTM_NEWROUTE
)
1548 SET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1549 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1553 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1554 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1561 else /* Multipath case */
1563 char buf
[NL_PKT_BUF_SIZE
];
1564 struct rtattr
*rta
= (void *) buf
;
1565 struct rtnexthop
*rtnh
;
1566 union g_addr
*src1
= NULL
;
1568 rta
->rta_type
= RTA_MULTIPATH
;
1569 rta
->rta_len
= RTA_LENGTH (0);
1570 rtnh
= RTA_DATA (rta
);
1572 routedesc
= "multihop";
1573 _netlink_mpls_debug(cmd
, lsp
->ile
.in_label
, routedesc
);
1576 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1578 nexthop
= nhlfe
->nexthop
;
1582 if (nexthop_num
>= multipath_num
)
1585 if ((cmd
== RTM_NEWROUTE
&&
1586 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_SELECTED
) &&
1587 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))) ||
1588 (cmd
== RTM_DELROUTE
&&
1589 (CHECK_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
) &&
1590 CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
))))
1594 /* Build the multipath */
1595 _netlink_mpls_build_multipath(routedesc
, nhlfe
, rta
,
1596 rtnh
, &req
.r
, &src1
);
1597 rtnh
= RTNH_NEXT (rtnh
);
1599 if (cmd
== RTM_NEWROUTE
)
1601 SET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1602 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1606 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1607 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1613 /* Add the multipath */
1614 if (rta
->rta_len
> RTA_LENGTH (0))
1615 addattr_l (&req
.n
, NL_PKT_BUF_SIZE
, RTA_MULTIPATH
, RTA_DATA (rta
),
1619 /* Talk to netlink socket. */
1620 return netlink_talk (netlink_talk_filter
, &req
.n
, &zns
->netlink_cmd
, zns
, 0);
1624 * Handle failure in LSP install, clear flags for NHLFE.
1627 clear_nhlfe_installed (zebra_lsp_t
*lsp
)
1629 zebra_nhlfe_t
*nhlfe
;
1630 struct nexthop
*nexthop
;
1632 for (nhlfe
= lsp
->nhlfe_list
; nhlfe
; nhlfe
= nhlfe
->next
)
1634 nexthop
= nhlfe
->nexthop
;
1638 UNSET_FLAG (nhlfe
->flags
, NHLFE_FLAG_INSTALLED
);
1639 UNSET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);