diff options
Diffstat (limited to 'zebra/rt_netlink.c')
-rw-r--r-- | zebra/rt_netlink.c | 39 |
1 files changed, 16 insertions, 23 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index a1274df4..a4382673 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1591,7 +1591,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, bytelen = (family == AF_INET ? 4 : 16); req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg)); - req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; + req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REPLACE | NLM_F_REQUEST; req.n.nlmsg_type = cmd; req.r.rtm_family = family; req.r.rtm_table = rib->table; @@ -1748,30 +1748,23 @@ skip: } int -kernel_add_ipv4 (struct prefix *p, struct rib *rib) +kernel_route_rib (struct prefix *p, struct rib *old, struct rib *new) { - return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET); -} - -int -kernel_delete_ipv4 (struct prefix *p, struct rib *rib) -{ - return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET); -} - -#ifdef HAVE_IPV6 -int -kernel_add_ipv6 (struct prefix *p, struct rib *rib) -{ - return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET6); -} - -int -kernel_delete_ipv6 (struct prefix *p, struct rib *rib) -{ - return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET6); + if (!old && new) + return netlink_route_multipath (RTM_NEWROUTE, p, new, PREFIX_FAMILY(p)); + if (old && !new) + return netlink_route_multipath (RTM_DELROUTE, p, old, PREFIX_FAMILY(p)); + + /* Replace, can be done atomically if metric does not change; + * netlink uses [prefix, tos, priority] to identify prefix */ + if (old->metric == new->metric) + return netlink_route_multipath (RTM_NEWROUTE, p, new, PREFIX_FAMILY(p)); + + /* Add + delete so the prefix does not disappear temporarily */ + if (netlink_route_multipath (RTM_NEWROUTE, p, new, PREFIX_FAMILY(p)) < 0) + return -1; + return netlink_route_multipath (RTM_DELROUTE, p, old, PREFIX_FAMILY(p)); } -#endif /* HAVE_IPV6 */ /* Interface address modification. */ static int |