diff --git a/zebra/rib.h b/zebra/rib.h index e3ed6210ca..61beebb409 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -71,7 +71,7 @@ struct route_entry { u_int32_t nexthop_mtu; /* Distance. */ - u_char distance; + uint8_t distance; /* Flags of this route. * This flag's definition is in lib/zebra.h ZEBRA_FLAG_* and is exposed @@ -296,7 +296,7 @@ extern int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, int flags, struct prefix *p, struct prefix_ipv6 *src_p, const struct nexthop *nh, u_int32_t table_id, u_int32_t metric, u_int32_t mtu, - u_char distance); + uint8_t distance); extern int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *, struct prefix_ipv6 *src_p, struct route_entry *); @@ -330,7 +330,7 @@ extern void rib_unlink(struct route_node *, struct route_entry *); extern int rib_gc_dest(struct route_node *rn); extern struct route_table *rib_tables_iter_next(rib_tables_iter_t *iter); -extern u_char route_distance(int type); +extern uint8_t route_distance(int type); /* * Inline functions. diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 0352dbd7e3..a939dde8d5 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -277,6 +277,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, int table; int metric = 0; u_int32_t mtu = 0; + uint8_t distance = 0; void *dest = NULL; void *gate = NULL; @@ -405,16 +406,38 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, return 0; } + /* + * For ZEBRA_ROUTE_KERNEL types: + * + * The metric/priority of the route received from the kernel + * is a 32 bit number. We are going to interpret the high + * order byte as the Admin Distance and the low order 3 bytes + * as the metric. + * + * This will allow us to do two things: + * 1) Allow the creation of kernel routes that can be + * overridden by zebra. + * 2) Allow the old behavior for 'most' kernel route types + * if a user enters 'ip route ...' v4 routes get a metric + * of 0 and v6 routes get a metric of 1024. Both of these + * values will end up with a admin distance of 0, which + * will cause them to win for the purposes of zebra. + */ + if (proto == ZEBRA_ROUTE_KERNEL) { + distance = (metric >> 24) & 0xFF; + metric = (metric & 0x00FFFFFF); + } + 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), + "%s %s%s%s vrf %u metric: %d Admin Distance: %d", 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); + vrf_id, metric, distance); } afi_t afi = AFI_IP; @@ -454,7 +477,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, memcpy(&nh.gate, gate, sz); rib_add(afi, SAFI_UNICAST, vrf_id, proto, - 0, flags, &p, NULL, &nh, table, metric, mtu, 0); + 0, flags, &p, NULL, &nh, table, metric, mtu, distance); } else { /* This is a multipath route */ @@ -466,7 +489,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); re->type = proto; - re->distance = 0; + re->distance = distance; re->flags = flags; re->metric = metric; re->mtu = mtu; diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 5c3ec10a79..1a9bd5a58e 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -129,9 +129,9 @@ _rnode_zlog(const char *_func, vrf_id_t vrf_id, struct route_node *rn, #define rnode_info(node, ...) \ _rnode_zlog(__func__, vrf_id, node, LOG_INFO, __VA_ARGS__) -u_char route_distance(int type) +uint8_t route_distance(int type) { - u_char distance; + uint8_t distance; if ((unsigned)type >= array_size(route_info)) distance = 150; @@ -2463,7 +2463,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, int flags, struct prefix *p, struct prefix_ipv6 *src_p, const struct nexthop *nh, u_int32_t table_id, u_int32_t metric, - u_int32_t mtu, u_char distance) + u_int32_t mtu, uint8_t distance) { struct route_entry *re; struct nexthop *nexthop;