]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: fix recursive-routes via ifindex routes
authorChristian Franke <chris@opensourcerouting.org>
Fri, 5 Jul 2013 15:35:40 +0000 (15:35 +0000)
committerDavid Lamparter <equinox@opensourcerouting.org>
Thu, 19 Sep 2013 16:04:40 +0000 (18:04 +0200)
Signed-off-by: Christian Franke <chris@opensourcerouting.org>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
zebra/zebra_rib.c

index 301e0cc1dbdd1291f5b6c567c0dfbce86836ced1..3106523d03026ebba4c0aa946e95668f20baff8c 100644 (file)
@@ -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);
                      }