diff options
Diffstat (limited to 'zebra')
-rw-r--r-- | zebra/zebra_rib.c | 65 |
1 files changed, 49 insertions, 16 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 301e0cc1..3106523d 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -500,16 +500,37 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop)); SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE); - - resolved_hop->type = newhop->type; - if (newhop->type == NEXTHOP_TYPE_IPV4 || - newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - resolved_hop->gate.ipv4 = newhop->gate.ipv4; - + /* If the resolving route specifies a gateway, use it */ + if (newhop->type == NEXTHOP_TYPE_IPV4 + || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX + || newhop->type == NEXTHOP_TYPE_IPV4_IFNAME) + { + resolved_hop->type = newhop->type; + resolved_hop->gate.ipv4 = newhop->gate.ipv4; + + if (newhop->ifindex) + { + resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX; + resolved_hop->ifindex = newhop->ifindex; + } + } + + /* If the resolving route is an interface route, + * it means the gateway we are looking up is connected + * to that interface. (The actual network is _not_ onlink). + * Therefore, the resolved route should have the original + * gateway as nexthop as it is directly connected. + * + * On Linux, we have to set the onlink netlink flag because + * otherwise, the kernel won't accept the route. */ if (newhop->type == NEXTHOP_TYPE_IFINDEX - || newhop->type == NEXTHOP_TYPE_IFNAME - || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - resolved_hop->ifindex = newhop->ifindex; + || newhop->type == NEXTHOP_TYPE_IFNAME) + { + resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; + resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX; + resolved_hop->gate.ipv4 = nexthop->gate.ipv4; + resolved_hop->ifindex = newhop->ifindex; + } _nexthop_add(&nexthop->resolved, resolved_hop); } @@ -622,18 +643,30 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set, resolved_hop = XCALLOC(MTYPE_NEXTHOP, sizeof (struct nexthop)); SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE); - - resolved_hop->type = newhop->type; + /* See nexthop_active_ipv4 for a description how the + * resolved nexthop is constructed. */ if (newhop->type == NEXTHOP_TYPE_IPV6 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME) - resolved_hop->gate.ipv6 = newhop->gate.ipv6; + { + resolved_hop->type = newhop->type; + resolved_hop->gate.ipv6 = newhop->gate.ipv6; + + if (newhop->ifindex) + { + resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX; + resolved_hop->ifindex = newhop->ifindex; + } + } if (newhop->type == NEXTHOP_TYPE_IFINDEX - || newhop->type == NEXTHOP_TYPE_IFNAME - || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX - || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME) - resolved_hop->ifindex = newhop->ifindex; + || newhop->type == NEXTHOP_TYPE_IFNAME) + { + resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; + resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX; + resolved_hop->gate.ipv6 = nexthop->gate.ipv6; + resolved_hop->ifindex = newhop->ifindex; + } _nexthop_add(&nexthop->resolved, resolved_hop); } |