diff options
Diffstat (limited to 'zebra/rt_netlink.c')
| -rw-r--r-- | zebra/rt_netlink.c | 554 |
1 files changed, 287 insertions, 267 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 4913aa878f..6ac1314496 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * along with GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * 02111-1307, USA. */ #include <zebra.h> @@ -40,6 +40,7 @@ #include "privs.h" #include "nexthop.h" #include "vrf.h" +#include "vty.h" #include "mpls.h" #include "zebra/zserv.h" @@ -54,6 +55,8 @@ #include "zebra/zebra_mpls.h" #include "zebra/kernel_netlink.h" #include "zebra/rt_netlink.h" +#include "zebra/zebra_mroute.h" + /* TODO - Temporary definitions, need to refine. */ #ifndef AF_MPLS @@ -76,6 +79,10 @@ #define RTA_ENCAP 22 #endif +#ifndef RTA_EXPIRES +#define RTA_EXPIRES 23 +#endif + #ifndef LWTUNNEL_ENCAP_MPLS #define LWTUNNEL_ENCAP_MPLS 1 #endif @@ -83,6 +90,10 @@ #ifndef MPLS_IPTUNNEL_DST #define MPLS_IPTUNNEL_DST 1 #endif + +#ifndef NDA_MASTER +#define NDA_MASTER 9 +#endif /* End of temporary definitions */ struct gw_family_t @@ -115,32 +126,34 @@ vrf_lookup_by_table (u_int32_t table_id) /* Looking up routing table by netlink interface. */ static int -netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id) +netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup) { int len; struct rtmsg *rtm; struct rtattr *tb[RTA_MAX + 1]; u_char flags = 0; struct prefix p; + struct prefix_ipv6 src_p; vrf_id_t vrf_id = VRF_DEFAULT; char anyaddr[16] = { 0 }; - int index; + int index = 0; int table; - int metric; + int metric = 0; u_int32_t mtu = 0; - void *dest; - void *gate; - void *src; + void *dest = NULL; + void *gate = NULL; + void *prefsrc = NULL; /* IPv4 preferred source host address */ + void *src = NULL; /* IPv6 srcdest source prefix */ rtm = NLMSG_DATA (h); - if (h->nlmsg_type != RTM_NEWROUTE) + if (startup && h->nlmsg_type != RTM_NEWROUTE) return 0; - if (rtm->rtm_type != RTN_UNICAST) + if (startup && rtm->rtm_type != RTN_UNICAST) return 0; len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); @@ -157,7 +170,9 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, if (rtm->rtm_protocol == RTPROT_KERNEL) return 0; - if (rtm->rtm_src_len != 0) + if (!startup && + rtm->rtm_protocol == RTPROT_ZEBRA && + h->nlmsg_type == RTM_NEWROUTE) return 0; /* We don't care about change notifications for the MPLS table. */ @@ -184,12 +199,6 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, if (rtm->rtm_protocol == RTPROT_ZEBRA) flags |= ZEBRA_FLAG_SELFROUTE; - index = 0; - metric = 0; - dest = NULL; - gate = NULL; - src = NULL; - if (tb[RTA_OIF]) index = *(int *) RTA_DATA (tb[RTA_OIF]); @@ -198,25 +207,33 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, else dest = anyaddr; + if (tb[RTA_SRC]) + src = RTA_DATA (tb[RTA_SRC]); + else + src = anyaddr; + if (tb[RTA_PREFSRC]) - src = RTA_DATA (tb[RTA_PREFSRC]); + prefsrc = RTA_DATA (tb[RTA_PREFSRC]); if (tb[RTA_GATEWAY]) gate = RTA_DATA (tb[RTA_GATEWAY]); - if (tb[RTA_PRIORITY]) - metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]); - - if (tb[RTA_METRICS]) + if (h->nlmsg_type == RTM_NEWROUTE) { - struct rtattr *mxrta[RTAX_MAX+1]; + if (tb[RTA_PRIORITY]) + metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]); + + if (tb[RTA_METRICS]) + { + struct rtattr *mxrta[RTAX_MAX+1]; - memset (mxrta, 0, sizeof mxrta); - netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]), - RTA_PAYLOAD(tb[RTA_METRICS])); + memset (mxrta, 0, sizeof mxrta); + netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]), + RTA_PAYLOAD(tb[RTA_METRICS])); - if (mxrta[RTAX_MTU]) - mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]); + if (mxrta[RTAX_MTU]) + mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]); + } } if (rtm->rtm_family == AF_INET) @@ -224,11 +241,48 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, p.family = AF_INET; memcpy (&p.u.prefix4, dest, 4); p.prefixlen = rtm->rtm_dst_len; + } + else if (rtm->rtm_family == AF_INET6) + { + p.family = AF_INET6; + memcpy (&p.u.prefix6, dest, 16); + p.prefixlen = rtm->rtm_dst_len; + src_p.family = AF_INET6; + memcpy (&src_p.prefix, src, 16); + src_p.prefixlen = rtm->rtm_src_len; + } + + if (rtm->rtm_src_len != 0) + { + char buf[PREFIX_STRLEN]; + zlog_warn ("unsupported IPv[4|6] sourcedest route (dest %s vrf %u)", + prefix2str (&p, buf, sizeof(buf)), vrf_id); + return 0; + } + + if (IS_ZEBRA_DEBUG_KERNEL) + { + char buf[PREFIX_STRLEN]; + char buf2[PREFIX_STRLEN]; + zlog_debug ("%s %s%s%s vrf %u", + nl_msg_type_to_str (h->nlmsg_type), + prefix2str (&p, buf, sizeof(buf)), + src_p.prefixlen ? " from " : "", + src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2)) : "", + vrf_id); + } + + afi_t afi = AFI_IP; + if (rtm->rtm_family == AF_INET6) + afi = AFI_IP6; + + if (h->nlmsg_type == RTM_NEWROUTE) + { if (!tb[RTA_MULTIPATH]) - rib_add (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, flags, &p, gate, src, index, - table, metric, mtu, 0); + rib_add (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, + 0, flags, &p, NULL, gate, prefsrc, index, + table, metric, mtu, 0); else { /* This is a multipath route */ @@ -268,10 +322,20 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, if (gate) { - if (index) - rib_nexthop_ipv4_ifindex_add (rib, gate, src, index); - else - rib_nexthop_ipv4_add (rib, gate, src); + if (rtm->rtm_family == AF_INET) + { + if (index) + rib_nexthop_ipv4_ifindex_add (rib, gate, prefsrc, index); + else + rib_nexthop_ipv4_add (rib, gate, prefsrc); + } + else if (rtm->rtm_family == AF_INET6) + { + if (index) + rib_nexthop_ipv6_ifindex_add (rib, gate, index); + else + rib_nexthop_ipv6_add (rib,gate); + } } else rib_nexthop_ifindex_add (rib, index); @@ -280,265 +344,186 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, rtnh = RTNH_NEXT(rtnh); } - zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, - rib->nexthop_num); + zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, + rib->nexthop_num); if (rib->nexthop_num == 0) XFREE (MTYPE_RIB, rib); else - rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, rib); + rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, NULL, rib); } } - if (rtm->rtm_family == AF_INET6) + else { - p.family = AF_INET6; - memcpy (&p.u.prefix6, dest, 16); - p.prefixlen = rtm->rtm_dst_len; + if (!tb[RTA_MULTIPATH]) + rib_delete (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags, + &p, NULL, gate, index, table); + else + { + struct rtnexthop *rtnh = + (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]); - rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, flags, &p, gate, src, index, - table, metric, mtu, 0); + len = RTA_PAYLOAD (tb[RTA_MULTIPATH]); + + for (;;) + { + if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len) + break; + + gate = NULL; + if (rtnh->rtnh_len > sizeof (*rtnh)) + { + memset (tb, 0, sizeof (tb)); + netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh), + rtnh->rtnh_len - sizeof (*rtnh)); + if (tb[RTA_GATEWAY]) + gate = RTA_DATA (tb[RTA_GATEWAY]); + } + + if (gate) + rib_delete (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags, + &p, NULL, gate, index, table); + + len -= NLMSG_ALIGN(rtnh->rtnh_len); + rtnh = RTNH_NEXT(rtnh); + } + } } return 0; } -/* Routing information change from the kernel. */ -int -netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id) +static struct mcast_route_data *mroute = NULL; + +static int +netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup) { int len; struct rtmsg *rtm; struct rtattr *tb[RTA_MAX + 1]; - u_char zebra_flags = 0; - struct prefix p; - vrf_id_t vrf_id = VRF_DEFAULT; - - char anyaddr[16] = { 0 }; - - int index; - int table; - int metric; - u_int32_t mtu = 0; - - void *dest; - void *gate; - void *src; - - rtm = NLMSG_DATA (h); - - if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) - { - /* If this is not route add/delete message print warning. */ - zlog_warn ("Kernel message: %d", h->nlmsg_type); - return 0; - } - - /* Connected route. */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s %s %s proto %s", - h->nlmsg_type == - RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE", - rtm->rtm_family == AF_INET ? "ipv4" : "ipv6", - rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast", - nl_rtproto_to_str (rtm->rtm_protocol)); - - if (rtm->rtm_type != RTN_UNICAST) + struct mcast_route_data *m; + struct mcast_route_data mr; + int iif = 0; + int count; + int oif[256]; + int oif_count = 0; + char sbuf[40]; + char gbuf[40]; + char oif_list[256] = "\0"; + vrf_id_t vrf = ns_id; + + if (mroute) + m = mroute; + else { - return 0; + memset (&mr, 0, sizeof (mr)); + m = &mr; } - /* We don't care about change notifications for the MPLS table. */ - /* TODO: Revisit this. */ - if (rtm->rtm_family == AF_MPLS) - return 0; + rtm = NLMSG_DATA (h); len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); - if (len < 0) - return -1; memset (tb, 0, sizeof tb); netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len); - if (rtm->rtm_flags & RTM_F_CLONED) - return 0; - if (rtm->rtm_protocol == RTPROT_REDIRECT) - return 0; - if (rtm->rtm_protocol == RTPROT_KERNEL) - return 0; + if (tb[RTA_IIF]) + iif = *(int *)RTA_DATA (tb[RTA_IIF]); - if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE) - return 0; - if (rtm->rtm_protocol == RTPROT_ZEBRA) - SET_FLAG(zebra_flags, ZEBRA_FLAG_SELFROUTE); - - if (rtm->rtm_src_len != 0) - { - zlog_warn ("netlink_route_change(): no src len"); - return 0; - } - - /* Table corresponding to route. */ - if (tb[RTA_TABLE]) - table = *(int *) RTA_DATA (tb[RTA_TABLE]); - else - table = rtm->rtm_table; - - /* Map to VRF */ - vrf_id = vrf_lookup_by_table(table); - if (vrf_id == VRF_DEFAULT) - { - if (!is_zebra_valid_kernel_table(table) && - !is_zebra_main_routing_table(table)) - return 0; - } - - index = 0; - metric = 0; - dest = NULL; - gate = NULL; - src = NULL; - - if (tb[RTA_OIF]) - index = *(int *) RTA_DATA (tb[RTA_OIF]); + if (tb[RTA_SRC]) + m->sg.src = *(struct in_addr *)RTA_DATA (tb[RTA_SRC]); if (tb[RTA_DST]) - dest = RTA_DATA (tb[RTA_DST]); - else - dest = anyaddr; + m->sg.grp = *(struct in_addr *)RTA_DATA (tb[RTA_DST]); - if (tb[RTA_GATEWAY]) - gate = RTA_DATA (tb[RTA_GATEWAY]); + if ((RTA_EXPIRES <= RTA_MAX) && tb[RTA_EXPIRES]) + m->lastused = *(unsigned long long *)RTA_DATA (tb[RTA_EXPIRES]); - if (tb[RTA_PREFSRC]) - src = RTA_DATA (tb[RTA_PREFSRC]); - - if (h->nlmsg_type == RTM_NEWROUTE) + if (tb[RTA_MULTIPATH]) { - if (tb[RTA_PRIORITY]) - metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]); + struct rtnexthop *rtnh = + (struct rtnexthop *)RTA_DATA (tb[RTA_MULTIPATH]); - if (tb[RTA_METRICS]) + len = RTA_PAYLOAD (tb[RTA_MULTIPATH]); + for (;;) { - struct rtattr *mxrta[RTAX_MAX+1]; + if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len) + break; - memset (mxrta, 0, sizeof mxrta); - netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]), - RTA_PAYLOAD(tb[RTA_METRICS])); + oif[oif_count] = rtnh->rtnh_ifindex; + oif_count++; - if (mxrta[RTAX_MTU]) - mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]); + len -= NLMSG_ALIGN (rtnh->rtnh_len); + rtnh = RTNH_NEXT (rtnh); } } - if (rtm->rtm_family == AF_INET) + if (IS_ZEBRA_DEBUG_KERNEL) { - p.family = AF_INET; - memcpy (&p.u.prefix4, dest, 4); - p.prefixlen = rtm->rtm_dst_len; - - if (IS_ZEBRA_DEBUG_KERNEL) - { - char buf[PREFIX_STRLEN]; - zlog_debug ("%s %s vrf %u", - h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE", - prefix2str (&p, buf, sizeof(buf)), vrf_id); - } - - if (h->nlmsg_type == RTM_NEWROUTE) - { - if (!tb[RTA_MULTIPATH]) - rib_add (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, 0, &p, gate, src, index, - table, metric, mtu, 0); - else - { - /* This is a multipath route */ - - struct rib *rib; - struct rtnexthop *rtnh = - (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]); - - len = RTA_PAYLOAD (tb[RTA_MULTIPATH]); - - rib = XCALLOC (MTYPE_RIB, sizeof (struct rib)); - rib->type = ZEBRA_ROUTE_KERNEL; - rib->distance = 0; - rib->flags = 0; - rib->metric = metric; - rib->mtu = mtu; - rib->vrf_id = vrf_id; - rib->table = table; - rib->nexthop_num = 0; - rib->uptime = time (NULL); - - for (;;) - { - if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len) - break; - - index = rtnh->rtnh_ifindex; - gate = 0; - if (rtnh->rtnh_len > sizeof (*rtnh)) - { - memset (tb, 0, sizeof (tb)); - netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh), - rtnh->rtnh_len - sizeof (*rtnh)); - if (tb[RTA_GATEWAY]) - gate = RTA_DATA (tb[RTA_GATEWAY]); - } + struct interface *ifp; + strcpy (sbuf, inet_ntoa (m->sg.src)); + strcpy (gbuf, inet_ntoa (m->sg.grp)); + for (count = 0; count < oif_count; count++) + { + ifp = if_lookup_by_index_vrf (oif[count], vrf); + char temp[256]; - if (gate) - { - if (index) - rib_nexthop_ipv4_ifindex_add (rib, gate, src, index); - else - rib_nexthop_ipv4_add (rib, gate, src); - } - else - rib_nexthop_ifindex_add (rib, index); + sprintf (temp, "%s ", ifp->name); + strcat (oif_list, temp); + } + ifp = if_lookup_by_index_vrf (iif, vrf); + zlog_debug ("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld", + nl_msg_type_to_str(h->nlmsg_type), sbuf, gbuf, ifp->name, oif_list, m->lastused); + } + return 0; +} - len -= NLMSG_ALIGN(rtnh->rtnh_len); - rtnh = RTNH_NEXT(rtnh); - } +int +netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup) +{ + int len; + vrf_id_t vrf_id = ns_id; + struct rtmsg *rtm; - zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, - rib->nexthop_num); + rtm = NLMSG_DATA (h); - if (rib->nexthop_num == 0) - XFREE (MTYPE_RIB, rib); - else - rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, rib); - } - } - else - rib_delete (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, gate, index, table); + if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) + { + /* If this is not route add/delete message print warning. */ + zlog_warn ("Kernel message: %d vrf %u\n", h->nlmsg_type, vrf_id); + return 0; } - if (rtm->rtm_family == AF_INET6) - { - struct prefix p; + /* Connected route. */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("%s %s %s proto %s vrf %u", + nl_msg_type_to_str (h->nlmsg_type), + nl_family_to_str (rtm->rtm_family), + nl_rttype_to_str (rtm->rtm_type), + nl_rtproto_to_str (rtm->rtm_protocol), + vrf_id); - p.family = AF_INET6; - memcpy (&p.u.prefix6, dest, 16); - p.prefixlen = rtm->rtm_dst_len; + /* We don't care about change notifications for the MPLS table. */ + /* TODO: Revisit this. */ + if (rtm->rtm_family == AF_MPLS) + return 0; - if (IS_ZEBRA_DEBUG_KERNEL) - { - char buf[PREFIX_STRLEN]; - zlog_debug ("%s %s vrf %u", - h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE", - prefix2str (&p, buf, sizeof(buf)), vrf_id); - } + len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); + if (len < 0) + return -1; - if (h->nlmsg_type == RTM_NEWROUTE) - rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, 0, &p, gate, src, index, - table, metric, mtu, 0); - else - rib_delete (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, zebra_flags, &p, gate, index, table); + switch (rtm->rtm_type) + { + case RTN_UNICAST: + netlink_route_change_read_unicast (snl, h, ns_id, startup); + break; + case RTN_MULTICAST: + netlink_route_change_read_multicast (snl, h, ns_id, startup); + break; + default: + return 0; + break; } return 0; @@ -555,19 +540,17 @@ netlink_route_read (struct zebra_ns *zns) ret = netlink_request (AF_INET, RTM_GETROUTE, &zns->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_routing_table, &zns->netlink_cmd, zns, 0); + ret = netlink_parse_info (netlink_route_change_read_unicast, &zns->netlink_cmd, zns, 0, 1); if (ret < 0) return ret; -#ifdef HAVE_IPV6 /* Get IPv6 routing table. */ ret = netlink_request (AF_INET6, RTM_GETROUTE, &zns->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_routing_table, &zns->netlink_cmd, zns, 0); + ret = netlink_parse_info (netlink_route_change_read_unicast, &zns->netlink_cmd, zns, 0, 1); if (ret < 0) return ret; -#endif /* HAVE_IPV6 */ return 0; } @@ -693,7 +676,7 @@ _netlink_route_build_singlepath( int i, num_labels = 0; u_int32_t bos; char label_buf1[20]; - + for (i = 0; i < nh_label->num_labels; i++) { if (nh_label->label[i] != MPLS_IMP_NULL_LABEL) @@ -1074,7 +1057,7 @@ _netlink_route_debug( prefix2str (p, buf, sizeof(buf)), zvrf_id (zvrf), (nexthop) ? nexthop_type_to_str (nexthop->type) : "UNK"); } -} + } static void _netlink_mpls_debug( @@ -1112,20 +1095,20 @@ netlink_neigh_update (int cmd, int ifindex, uint32_t addr, char *lla, int llalen addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4); addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); - return netlink_talk (&req.n, &zns->netlink_cmd, zns); + return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); } /* Routing table change via netlink interface. */ /* Update flag indicates whether this is a "replace" or not. */ static int -netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, - int update) +netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p, + struct rib *rib, int update) { int bytelen; struct sockaddr_nl snl; struct nexthop *nexthop = NULL, *tnexthop; int recursing; - int nexthop_num; + unsigned int nexthop_num; int discard; int family = PREFIX_FAMILY(p); const char *routedesc; @@ -1153,6 +1136,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, req.n.nlmsg_type = cmd; req.r.rtm_family = family; req.r.rtm_dst_len = p->prefixlen; + req.r.rtm_src_len = src_p ? src_p->prefixlen : 0; req.r.rtm_protocol = RTPROT_ZEBRA; req.r.rtm_scope = RT_SCOPE_UNIVERSE; @@ -1177,6 +1161,8 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, } addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen); + if (src_p) + addattr_l (&req.n, sizeof req, RTA_SRC, &src_p->u.prefix, bytelen); /* Metric. */ /* Hardcode the metric for all routes coming from zebra. Metric isn't used @@ -1238,7 +1224,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, } /* Singlepath case. */ - if (nexthop_num == 1 || MULTIPATH_NUM == 1) + if (nexthop_num == 1 || multipath_num == 1) { nexthop_num = 0; for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) @@ -1314,7 +1300,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, nexthop_num = 0; for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) { - if (nexthop_num >= MULTIPATH_NUM) + if (nexthop_num >= multipath_num) break; if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) @@ -1407,18 +1393,52 @@ skip: snl.nl_family = AF_NETLINK; /* Talk to netlink socket. */ - return netlink_talk (&req.n, &zns->netlink_cmd, zns); + return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); +} + +int +kernel_get_ipmr_sg_stats (void *in) +{ + int suc = 0; + struct mcast_route_data *mr = (struct mcast_route_data *)in; + struct { + struct nlmsghdr n; + struct ndmsg ndm; + char buf[256]; + } req; + + mroute = mr; + struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); + + memset(&req.n, 0, sizeof(req.n)); + memset(&req.ndm, 0, sizeof(req.ndm)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.ndm.ndm_family = AF_INET; + req.n.nlmsg_type = RTM_GETROUTE; + + addattr_l (&req.n, sizeof (req), RTA_IIF, &mroute->ifindex, 4); + addattr_l (&req.n, sizeof (req), RTA_OIF, &mroute->ifindex, 4); + addattr_l (&req.n, sizeof (req), RTA_SRC, &mroute->sg.src.s_addr, 4); + addattr_l (&req.n, sizeof (req), RTA_DST, &mroute->sg.grp.s_addr, 4); + + suc = netlink_talk (netlink_route_change_read_multicast, &req.n, &zns->netlink_cmd, zns, 0); + + mroute = NULL; + return suc; } int -kernel_route_rib (struct prefix *p, struct rib *old, struct rib *new) +kernel_route_rib (struct prefix *p, struct prefix *src_p, + struct rib *old, struct rib *new) { if (!old && new) - return netlink_route_multipath (RTM_NEWROUTE, p, new, 0); + return netlink_route_multipath (RTM_NEWROUTE, p, src_p, new, 0); if (old && !new) - return netlink_route_multipath (RTM_DELROUTE, p, old, 0); + return netlink_route_multipath (RTM_DELROUTE, p, src_p, old, 0); - return netlink_route_multipath (RTM_NEWROUTE, p, new, 1); + return netlink_route_multipath (RTM_NEWROUTE, p, src_p, new, 1); } int @@ -1437,7 +1457,7 @@ netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp) mpls_lse_t lse; zebra_nhlfe_t *nhlfe; struct nexthop *nexthop = NULL; - int nexthop_num; + unsigned int nexthop_num; const char *routedesc; struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); @@ -1501,7 +1521,7 @@ netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp) /* Fill nexthops (paths) based on single-path or multipath. The paths * chosen depend on the operation. */ - if (nexthop_num == 1 || MULTIPATH_NUM == 1) + if (nexthop_num == 1 || multipath_num == 1) { routedesc = "single hop"; _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); @@ -1559,7 +1579,7 @@ netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp) if (!nexthop) continue; - if (MULTIPATH_NUM != 0 && nexthop_num >= MULTIPATH_NUM) + if (nexthop_num >= multipath_num) break; if ((cmd == RTM_NEWROUTE && @@ -1597,7 +1617,7 @@ netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp) } /* Talk to netlink socket. */ - return netlink_talk (&req.n, &zns->netlink_cmd, zns); + return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); } /* |
