diff options
Diffstat (limited to 'zebra/rt_netlink.c')
| -rw-r--r-- | zebra/rt_netlink.c | 66 |
1 files changed, 41 insertions, 25 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index c9a9a81b18..fff569c092 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -83,8 +83,8 @@ struct gw_family_t { union g_addr gate; }; -char ipv4_ll_buf[16] = "169.254.0.1"; -struct in_addr ipv4_ll; +static const char ipv4_ll_buf[16] = "169.254.0.1"; +static struct in_addr ipv4_ll; /* * The ipv4_ll data structure is used for all 5549 @@ -390,7 +390,7 @@ parse_nexthop_unicast(ns_id_t ns_id, struct rtmsg *rtm, struct rtattr **tb, } static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id, - struct route_entry *re, + struct nexthop_group *ng, struct rtmsg *rtm, struct rtnexthop *rtnh, struct rtattr **tb, @@ -407,8 +407,6 @@ static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id, int len = RTA_PAYLOAD(tb[RTA_MULTIPATH]); vrf_id_t nh_vrf_id = vrf_id; - re->ng = nexthop_group_new(); - for (;;) { struct nexthop *nh = NULL; @@ -454,29 +452,32 @@ static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id, if (gate && rtm->rtm_family == AF_INET) { if (index) - nh = route_entry_nexthop_ipv4_ifindex_add( - re, gate, prefsrc, index, nh_vrf_id); + nh = nexthop_from_ipv4_ifindex( + gate, prefsrc, index, nh_vrf_id); else - nh = route_entry_nexthop_ipv4_add( - re, gate, prefsrc, nh_vrf_id); + nh = nexthop_from_ipv4(gate, prefsrc, + nh_vrf_id); } else if (gate && rtm->rtm_family == AF_INET6) { if (index) - nh = route_entry_nexthop_ipv6_ifindex_add( - re, gate, index, nh_vrf_id); + nh = nexthop_from_ipv6_ifindex( + gate, index, nh_vrf_id); else - nh = route_entry_nexthop_ipv6_add(re, gate, - nh_vrf_id); + nh = nexthop_from_ipv6(gate, nh_vrf_id); } else - nh = route_entry_nexthop_ifindex_add(re, index, - nh_vrf_id); + nh = nexthop_from_ifindex(index, nh_vrf_id); if (nh) { + nh->weight = rtnh->rtnh_hops + 1; + if (num_labels) nexthop_add_labels(nh, ZEBRA_LSP_STATIC, num_labels, labels); if (rtnh->rtnh_flags & RTNH_F_ONLINK) SET_FLAG(nh->flags, NEXTHOP_FLAG_ONLINK); + + /* Add to temporary list */ + nexthop_group_add_sorted(ng, nh); } if (rtnh->rtnh_len == 0) @@ -486,10 +487,7 @@ static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id, rtnh = RTNH_NEXT(rtnh); } - uint8_t nhop_num = nexthop_group_nexthop_num(re->ng); - - if (!nhop_num) - nexthop_group_delete(&re->ng); + uint8_t nhop_num = nexthop_group_nexthop_num(ng); return nhop_num; } @@ -737,6 +735,7 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, } else { /* This is a multipath route */ struct route_entry *re; + struct nexthop_group *ng = NULL; struct rtnexthop *rtnh = (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]); @@ -753,19 +752,30 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, re->nhe_id = nhe_id; if (!nhe_id) { - uint8_t nhop_num = + uint8_t nhop_num; + + /* Use temporary list of nexthops; parse + * message payload's nexthops. + */ + ng = nexthop_group_new(); + nhop_num = parse_multipath_nexthops_unicast( - ns_id, re, rtm, rtnh, tb, + ns_id, ng, rtm, rtnh, tb, prefsrc, vrf_id); zserv_nexthop_num_warn( __func__, (const struct prefix *)&p, nhop_num); + + if (nhop_num == 0) { + nexthop_group_delete(&ng); + ng = NULL; + } } - if (nhe_id || re->ng) + if (nhe_id || ng) rib_add_multipath(afi, SAFI_UNICAST, &p, - &src_p, re); + &src_p, re, ng); else XFREE(MTYPE_RE, re); } @@ -1411,6 +1421,9 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen, "nexthop via if %u", routedesc, nexthop->ifindex); } + + if (nexthop->weight) + rtnh->rtnh_hops = nexthop->weight - 1; } static inline void _netlink_mpls_build_singlepath(const char *routedesc, @@ -1913,7 +1926,7 @@ static void _netlink_nexthop_build_group(struct nlmsghdr *n, size_t req_size, if (count) { for (int i = 0; i < count; i++) { grp[i].id = z_grp[i].id; - grp[i].weight = z_grp[i].weight; + grp[i].weight = z_grp[i].weight - 1; if (IS_ZEBRA_DEBUG_KERNEL) { if (i == 0) @@ -2031,6 +2044,9 @@ static int netlink_nexthop(int cmd, struct zebra_dplane_ctx *ctx) addattr32(&req.n, req_size, NHA_OIF, nh->ifindex); + if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ONLINK)) + req.nhm.nh_flags |= RTNH_F_ONLINK; + num_labels = build_label_stack(nh->nh_label, out_lse, label_buf, sizeof(label_buf)); @@ -2339,7 +2355,7 @@ static int netlink_nexthop_process_group(struct rtattr **tb, for (int i = 0; ((i < count) && (i < z_grp_size)); i++) { z_grp[i].id = n_grp[i].id; - z_grp[i].weight = n_grp[i].weight; + z_grp[i].weight = n_grp[i].weight + 1; } return count; } |
