From cf245afd5dd1f8c7c80089465e610acaaa1e2f24 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 5 Feb 2010 04:31:56 +0100 Subject: zebra: cleanup blackhole support blackhole support was horribly broken. cleanup by removing blackhole stuff from ZEBRA_FLAG_*, instead add a "zflags" field inside struct rib. introduces support for "prohibit" routes (Linux/netlink only) also clean up blackhole options on "ip route" vty commands. --- zebra/zebra_rib.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) (limited to 'zebra/zebra_rib.c') diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 7374f73d..28ca3b12 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -299,7 +299,6 @@ nexthop_blackhole_add (struct rib *rib) nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); nexthop->type = NEXTHOP_TYPE_BLACKHOLE; - SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE); nexthop_add (rib, nexthop); @@ -1556,6 +1555,7 @@ rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p, rib->type = type; rib->distance = distance; rib->flags = flags; + rib->zflags = flags >> 8; rib->metric = metric; rib->table = vrf_id; rib->nexthop_num = 0; @@ -2016,7 +2016,7 @@ static_install_ipv4 (struct prefix *p, struct static_ipv4 *si) } /* Save the flags of this static routes (reject, blackhole) */ - rib->flags = si->flags; + rib->zflags = si->zflags; /* Link this rib to the tree. */ rib_addnode (rn, rib); @@ -2104,7 +2104,7 @@ static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si) /* Add static route into static route configuration. */ int static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, - u_char flags, u_char distance, u_int32_t vrf_id) + unsigned zflags, u_char distance, u_int32_t vrf_id) { u_char type = 0; struct route_node *rn; @@ -2123,12 +2123,14 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, rn = route_node_get (stable, p); /* Make flags. */ - if (gate) + if (RIB_ZF_BLACKHOLE_FLAGS (zflags)) + type = STATIC_IPV4_BLACKHOLE; + else if (gate) type = STATIC_IPV4_GATEWAY; else if (ifname) type = STATIC_IPV4_IFNAME; else - type = STATIC_IPV4_BLACKHOLE; + return -1; /* Do nothing if there is a same static route. */ for (si = rn->info; si; si = si->next) @@ -2156,7 +2158,7 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, si->type = type; si->distance = distance; - si->flags = flags; + si->zflags = zflags; if (gate) si->gate.ipv4 = *gate; @@ -2345,6 +2347,7 @@ rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p, rib->type = type; rib->distance = distance; rib->flags = flags; + rib->zflags = flags >> 8; rib->metric = metric; rib->table = vrf_id; rib->nexthop_num = 0; @@ -2538,6 +2541,9 @@ static_install_ipv6 (struct prefix *p, struct static_ipv6 *si) case STATIC_IPV6_GATEWAY_IFNAME: nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname); break; + case STATIC_IPV6_BLACKHOLE: + nexthop_blackhole_add (rib); + break; } rib_queue_add (&zebrad, rn); } @@ -2562,10 +2568,13 @@ static_install_ipv6 (struct prefix *p, struct static_ipv6 *si) case STATIC_IPV6_GATEWAY_IFNAME: nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname); break; + case STATIC_IPV6_BLACKHOLE: + nexthop_blackhole_add (rib); + break; } /* Save the flags of this static routes (reject, blackhole) */ - rib->flags = si->flags; + rib->zflags = si->zflags; /* Link this rib to the tree. */ rib_addnode (rn, rib); @@ -2588,6 +2597,9 @@ static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si) && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6) && strcmp (nexthop->ifname, si->ifname) == 0) return 1; + if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE + && si->type == STATIC_IPV6_BLACKHOLE) + return 1; return 0; } @@ -2656,7 +2668,7 @@ static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si) /* Add static route into static route configuration. */ int static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - const char *ifname, u_char flags, u_char distance, + const char *ifname, unsigned zflags, u_char distance, u_int32_t vrf_id) { struct route_node *rn; @@ -2699,7 +2711,7 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, si->type = type; si->distance = distance; - si->flags = flags; + si->zflags = zflags; switch (type) { @@ -2713,6 +2725,8 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, si->ipv6 = *gate; si->ifname = XSTRDUP (0, ifname); break; + case STATIC_IPV6_BLACKHOLE: + break; } /* Add new static route information to the tree with sort by -- cgit v1.2.3 From 38c85a4010c812a381a3e3f14bfac5db7f192d99 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 5 Feb 2010 04:58:46 +0100 Subject: zebra: netlink: grab blackhole list from kernel support processing of RTM_BLACKHOLE et al. from kernel and dump them into appropriate blackhole rib entries. this exhibits the deletion bug famously fixed by Joakim Tjernlund, if that patch isn't applied blackhole route deletion from kernel doesn't work... --- zebra/zebra_rib.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'zebra/zebra_rib.c') diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 28ca3b12..0f2e7784 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1562,7 +1562,9 @@ rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p, rib->uptime = time (NULL); /* Nexthop settings. */ - if (gate) + if (RIB_ZF_BLACKHOLE_FLAGS (rib->zflags)) + nexthop_blackhole_add (rib); + else if (gate) { if (ifindex) nexthop_ipv4_ifindex_add (rib, gate, src, ifindex); -- cgit v1.2.3 From 5f23da374fc5ca4a69fd3a3b9f4f2bc337d2b21e Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Fri, 4 Dec 2009 19:25:26 +0000 Subject: zebra: Don't delete too many routes. If there are two paralell PtP links to the same router: C * 192.168.101.112/32 is directly connected, p1-4-19-4-20 C>* 192.168.101.112/32 is directly connected, p1-4-17-4-18 and the cable is to one of the ppp links is pulled, Zebra deletes both routes instead of just the one that got yanked. This fixes it to only delete the route to the interface that got yanked. In fact, the whole delete route pattern matching expressions needed a total makeover. --- zebra/zebra_rib.c | 86 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 56 insertions(+), 30 deletions(-) (limited to 'zebra/zebra_rib.c') diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 0f2e7784..f6f8980f 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1846,12 +1846,19 @@ rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p, /* Apply mask. */ apply_mask_ipv4 (p); - if (IS_ZEBRA_DEBUG_KERNEL && gate) - zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d", - inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN), - p->prefixlen, - inet_ntoa (*gate), - ifindex); + if (IS_ZEBRA_DEBUG_KERNEL) + if (gate) + zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d", + inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ), + p->prefixlen, + inet_ntoa (*gate), + ifindex); + else + zlog_debug ("rib_delete_ipv4(): route delete %s/%d ifname %s ifindex %d", + inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ), + p->prefixlen, + ifindex2ifname(ifindex), + ifindex); /* Lookup route node. */ rn = route_node_lookup (table, (struct prefix *) p); @@ -1885,11 +1892,29 @@ rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p, if (rib->type != type) continue; - if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) && - nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex) + + if (gate) { - if (rib->refcnt) + if ((nexthop = rib->nexthop) && + (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) || + IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate))) { + if (ifindex && ifindex != nexthop->ifindex) + continue; /* ifindex doesn't match */ + same = rib; + break; + } + } + else + { + nexthop = rib->nexthop; + if (nexthop && nexthop->ifindex != ifindex) + continue; + if (nexthop && + rib->type == ZEBRA_ROUTE_CONNECT && + nexthop->type == NEXTHOP_TYPE_IFINDEX && + rib->refcnt) + { /* Duplicated connected route. */ rib->refcnt--; route_unlock_node (rn); route_unlock_node (rn); @@ -1898,15 +1923,6 @@ rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p, same = rib; break; } - /* Make sure that the route found has the same gateway. */ - else if (gate == NULL || - ((nexthop = rib->nexthop) && - (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) || - IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate)))) - { - same = rib; - break; - } } /* If same type of route can't be found and this message is from @@ -2436,11 +2452,29 @@ rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p, if (rib->type != type) continue; - if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) && - nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex) + + if (gate) { - if (rib->refcnt) + if ((nexthop = rib->nexthop) && + (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) || + IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate))) { + if (ifindex && ifindex != nexthop->ifindex) + continue; /* ifindex doesn't match */ + same = rib; + break; + } + } + else + { + nexthop = rib->nexthop; + if (nexthop && nexthop->ifindex != ifindex) + continue; + if (nexthop && + rib->type == ZEBRA_ROUTE_CONNECT && + nexthop->type == NEXTHOP_TYPE_IFINDEX && + rib->refcnt) + { /* Duplicated connected route. */ rib->refcnt--; route_unlock_node (rn); route_unlock_node (rn); @@ -2449,15 +2483,7 @@ rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p, same = rib; break; } - /* Make sure that the route found has the same gateway. */ - else if (gate == NULL || - ((nexthop = rib->nexthop) && - (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) || - IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate)))) - { - same = rib; - break; - } + } /* If same type of route can't be found and this message is from -- cgit v1.2.3 From 659811a522cda0c95e83bfdde41b970442b1fbd3 Mon Sep 17 00:00:00 2001 From: Tom Goff Date: Wed, 27 Jan 2010 00:30:22 +0000 Subject: zebra: consider all nexthops when looking for a gateway match * zebra_rib.c: (rib_delete_ipv4 and rib_delete_ipv6) A route is not deleted unless the given gateway is first in the nexthop list. This can leave a route containing an invalid nexthop in the routing table which might later be used. Instead look at all nexthops to find a match. forward-ported to apply on top of Joakim Tjernlund's "don't delete too many routes" by David Lamparter. Signed-off-by: David Lamparter --- zebra/zebra_rib.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'zebra/zebra_rib.c') diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index f6f8980f..fc9c6aa2 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1895,12 +1895,15 @@ rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p, if (gate) { - if ((nexthop = rib->nexthop) && - (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) || - IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate))) + for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) + if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) || + IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate)) + /* make sure ifindex matches if specified */ + if (!ifindex || ifindex == nexthop->ifindex) + break; + + if (nexthop) { - if (ifindex && ifindex != nexthop->ifindex) - continue; /* ifindex doesn't match */ same = rib; break; } @@ -2455,12 +2458,15 @@ rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p, if (gate) { - if ((nexthop = rib->nexthop) && - (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) || - IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate))) + for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) + if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) || + IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate)) + /* make sure ifindex matches if specified */ + if (!ifindex || ifindex == nexthop->ifindex) + break; + + if (nexthop) { - if (ifindex && ifindex != nexthop->ifindex) - continue; /* ifindex doesn't match */ same = rib; break; } -- cgit v1.2.3 From 647e8e064d8e5316fc89587714a056b1240fa298 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 5 Feb 2010 05:54:47 +0100 Subject: zebra: rib: support blackhole kernel deletion notification properly receive the deletion notify for blackhole routes and mark the rib entry. --- zebra/zebra_rib.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'zebra/zebra_rib.c') diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index fc9c6aa2..50a19477 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1837,6 +1837,7 @@ rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p, struct nexthop *nexthop; char buf1[INET_ADDRSTRLEN]; char buf2[INET_ADDRSTRLEN]; + unsigned discard = RIB_ZF_BLACKHOLE_FLAGS (flags >> 8); /* Lookup table. */ table = vrf_table (AFI_IP, SAFI_UNICAST, 0); @@ -1893,6 +1894,11 @@ rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p, if (rib->type != type) continue; + if (rib->zflags == discard) + { + same = rib; + break; + } if (gate) { for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) @@ -2414,6 +2420,7 @@ rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p, struct nexthop *nexthop; char buf1[INET6_ADDRSTRLEN]; char buf2[INET6_ADDRSTRLEN]; + unsigned discard = RIB_ZF_BLACKHOLE_FLAGS (flags >> 8); /* Apply mask. */ apply_mask_ipv6 (p); @@ -2456,6 +2463,11 @@ rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p, if (rib->type != type) continue; + if (rib->zflags == discard) + { + same = rib; + break; + } if (gate) { for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) -- cgit v1.2.3