diff options
-rw-r--r-- | bgpd/bgp_zebra.c | 12 | ||||
-rw-r--r-- | isisd/isis_zebra.c | 6 | ||||
-rw-r--r-- | lib/zclient.c | 16 | ||||
-rw-r--r-- | lib/zclient.h | 4 | ||||
-rw-r--r-- | lib/zebra.h | 6 | ||||
-rw-r--r-- | ospf6d/ospf6_zebra.c | 6 | ||||
-rw-r--r-- | ospfd/ospf_asbr.c | 29 | ||||
-rw-r--r-- | ospfd/ospf_zebra.c | 24 | ||||
-rw-r--r-- | ripd/rip_zebra.c | 6 | ||||
-rw-r--r-- | zebra/redistribute.c | 34 | ||||
-rw-r--r-- | zebra/zebra_rib.c | 24 | ||||
-rw-r--r-- | zebra/zserv.c | 98 | ||||
-rw-r--r-- | zebra/zserv.h | 4 |
13 files changed, 175 insertions, 94 deletions
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index ee6b32244..c7b0b4364 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -484,7 +484,7 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length) else api.tag = 0; - if (command == ZEBRA_IPV4_ROUTE_ADD) + if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) { if (bgp_debug_zebra((struct prefix *)&p)) { @@ -500,7 +500,7 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length) bgp_redistribute_add((struct prefix *)&p, &nexthop, NULL, ifindex, api.metric, api.type, api.instance, api.tag); } - else + else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) { if (bgp_debug_zebra((struct prefix *)&p)) { @@ -582,7 +582,7 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length) if (IN6_IS_ADDR_LINKLOCAL (&p.prefix)) return 0; - if (command == ZEBRA_IPV6_ROUTE_ADD) + if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) { if (bgp_debug_zebra((struct prefix *)&p)) { @@ -598,7 +598,7 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length) bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop, ifindex, api.metric, api.type, api.instance, api.tag); } - else + else if (command == ZEBRA_REDISTRIBUTE_IPV6_DEL) { if (bgp_debug_zebra((struct prefix *)&p)) { @@ -1696,11 +1696,15 @@ bgp_zebra_init (struct thread_master *master) zclient->interface_nbr_address_delete = bgp_interface_nbr_address_delete; zclient->ipv4_route_add = zebra_read_ipv4; zclient->ipv4_route_delete = zebra_read_ipv4; + zclient->redistribute_route_ipv4_add = zebra_read_ipv4; + zclient->redistribute_route_ipv4_del = zebra_read_ipv4; zclient->interface_up = bgp_interface_up; zclient->interface_down = bgp_interface_down; #ifdef HAVE_IPV6 zclient->ipv6_route_add = zebra_read_ipv6; zclient->ipv6_route_delete = zebra_read_ipv6; + zclient->redistribute_route_ipv6_add = zebra_read_ipv6; + zclient->redistribute_route_ipv6_del = zebra_read_ipv6; #endif /* HAVE_IPV6 */ zclient->nexthop_update = bgp_read_nexthop_update; zclient->import_check_update = bgp_read_import_check_update; diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index f4179e50e..a29ad6817 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -555,7 +555,7 @@ isis_zebra_read_ipv4 (int command, struct zclient *zclient, else api.metric = 0; - if (command == ZEBRA_IPV4_ROUTE_ADD) + if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) { if (isis->debugs & DEBUG_ZEBRA) zlog_debug ("IPv4 Route add from Z"); @@ -606,9 +606,13 @@ isis_zebra_init (struct thread_master *master) zclient->interface_address_delete = isis_zebra_if_address_del; zclient->ipv4_route_add = isis_zebra_read_ipv4; zclient->ipv4_route_delete = isis_zebra_read_ipv4; + zclient->redistribute_route_ipv4_add = isis_zebra_read_ipv4; + zclient->redistribute_route_ipv4_del = isis_zebra_read_ipv4; #ifdef HAVE_IPV6 zclient->ipv6_route_add = isis_zebra_read_ipv6; zclient->ipv6_route_delete = isis_zebra_read_ipv6; + zclient->redistribute_route_ipv6_add = isis_zebra_read_ipv6; + zclient->redistribute_route_ipv6_del = isis_zebra_read_ipv6; #endif /* HAVE_IPV6 */ return; diff --git a/lib/zclient.c b/lib/zclient.c index e071228cc..623ca1583 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1259,6 +1259,22 @@ zclient_read (struct thread *thread) if (zclient->bfd_dest_replay) (*zclient->bfd_dest_replay) (command, zclient, length); break; + case ZEBRA_REDISTRIBUTE_IPV4_ADD: + if (zclient->redistribute_route_ipv4_add) + (*zclient->redistribute_route_ipv4_add) (command, zclient, length); + break; + case ZEBRA_REDISTRIBUTE_IPV4_DEL: + if (zclient->redistribute_route_ipv4_del) + (*zclient->redistribute_route_ipv4_del) (command, zclient, length); + break; + case ZEBRA_REDISTRIBUTE_IPV6_ADD: + if (zclient->redistribute_route_ipv6_add) + (*zclient->redistribute_route_ipv6_add) (command, zclient, length); + break; + case ZEBRA_REDISTRIBUTE_IPV6_DEL: + if (zclient->redistribute_route_ipv6_del) + (*zclient->redistribute_route_ipv6_del) (command, zclient, length); + break; default: break; } diff --git a/lib/zclient.h b/lib/zclient.h index 1fbb80da9..8caf682d8 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -98,6 +98,10 @@ struct zclient int (*nexthop_update) (int, struct zclient *, uint16_t); int (*import_check_update) (int, struct zclient *, uint16_t); int (*bfd_dest_replay) (int, struct zclient *, uint16_t); + int (*redistribute_route_ipv4_add) (int, struct zclient *, uint16_t); + int (*redistribute_route_ipv4_del) (int, struct zclient *, uint16_t); + int (*redistribute_route_ipv6_add) (int, struct zclient *, uint16_t); + int (*redistribute_route_ipv6_del) (int, struct zclient *, uint16_t); }; /* Zebra API message flag. */ diff --git a/lib/zebra.h b/lib/zebra.h index 41de01ec2..0a1dd7f46 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -438,7 +438,11 @@ struct in_pktinfo #define ZEBRA_BFD_DEST_DEREGISTER 35 #define ZEBRA_BFD_DEST_UPDATE 36 #define ZEBRA_BFD_DEST_REPLAY 37 -#define ZEBRA_MESSAGE_MAX 38 +#define ZEBRA_REDISTRIBUTE_IPV4_ADD 38 +#define ZEBRA_REDISTRIBUTE_IPV4_DEL 39 +#define ZEBRA_REDISTRIBUTE_IPV6_ADD 40 +#define ZEBRA_REDISTRIBUTE_IPV6_DEL 41 +#define ZEBRA_MESSAGE_MAX 42 /* Marker value used in new Zserv, in the byte location corresponding * the command value in the old zserv header. To allow old and new diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index a28571493..f97a9db72 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -261,7 +261,7 @@ ospf6_zebra_read_ipv6 (int command, struct zclient *zclient, zebra_route_string(api.type), prefixstr, nexthopstr, ifindex); } - if (command == ZEBRA_IPV6_ROUTE_ADD) + if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) ospf6_asbr_redistribute_add (api.type, ifindex, (struct prefix *) &p, api.nexthop_num, nexthop); else @@ -649,8 +649,12 @@ ospf6_zebra_init (struct thread_master *master) zclient->interface_address_delete = ospf6_zebra_if_address_update_delete; zclient->ipv4_route_add = NULL; zclient->ipv4_route_delete = NULL; + zclient->redistribute_route_ipv4_add = NULL; + zclient->redistribute_route_ipv4_del = NULL; zclient->ipv6_route_add = ospf6_zebra_read_ipv6; zclient->ipv6_route_delete = ospf6_zebra_read_ipv6; + zclient->redistribute_route_ipv6_add = ospf6_zebra_read_ipv6; + zclient->redistribute_route_ipv6_del = ospf6_zebra_read_ipv6; /* redistribute connected route by default */ /* ospf6_zebra_redistribute (ZEBRA_ROUTE_CONNECT); */ diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c index 5eb97d8f6..397ab6037 100644 --- a/ospfd/ospf_asbr.c +++ b/ospfd/ospf_asbr.c @@ -142,6 +142,7 @@ ospf_external_info_add (u_char type, u_short instance, struct prefix_ipv4 p, struct external_info *new; struct route_node *rn; struct ospf_external *ext; + char inetbuf[INET6_BUFSIZ]; ext = ospf_external_lookup(type, instance); if (!ext) @@ -152,12 +153,20 @@ ospf_external_info_add (u_char type, u_short instance, struct prefix_ipv4 p, if (rn) if (rn->info) { - route_unlock_node (rn); - zlog_warn ("Redistribute[%s][%d]: %s/%d already exists, discard.", + new = rn->info; + if ((new->ifindex == ifindex) && + (new->nexthop.s_addr == nexthop.s_addr) && (new->tag == tag)) + { + route_unlock_node(rn); + return NULL; /* NULL => no LSA to refresh */ + } + + inet_ntop(AF_INET, (void *)&nexthop.s_addr, inetbuf, INET6_BUFSIZ); + zlog_warn ("Redistribute[%s][%d]: %s/%d discarding old info with NH %s.", ospf_redist_string(type), instance, - inet_ntoa (p.prefix), p.prefixlen); - /* XFREE (MTYPE_OSPF_TMP, rn->info); */ - return rn->info; + inet_ntoa (p.prefix), p.prefixlen, inetbuf); + XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info); + rn->info = NULL; } /* Create new External info instance. */ @@ -167,13 +176,17 @@ ospf_external_info_add (u_char type, u_short instance, struct prefix_ipv4 p, new->nexthop = nexthop; new->tag = tag; + /* we don't unlock rn from the get() because we're attaching the info */ if (rn) rn->info = new; if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("Redistribute[%s]: %s/%d external info created.", - ospf_redist_string(type), - inet_ntoa (p.prefix), p.prefixlen); + { + inet_ntop(AF_INET, (void *)&nexthop.s_addr, inetbuf, INET6_BUFSIZ); + zlog_debug ("Redistribute[%s]: %s/%d external info created, with NH %s", + ospf_redist_string(type), + inet_ntoa (p.prefix), p.prefixlen, inetbuf); + } return new; } diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 8c152cdf7..a95b2e1b6 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -1070,7 +1070,7 @@ ospf_zebra_read_ipv4 (int command, struct zclient *zclient, if (ospf == NULL) return 0; - if (command == ZEBRA_IPV4_ROUTE_ADD) + if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) { /* XXX|HACK|TODO|FIXME: * Maybe we should ignore reject/blackhole routes? Testing shows that @@ -1098,7 +1098,11 @@ ospf_zebra_read_ipv4 (int command, struct zclient *zclient, ei = ospf_external_info_add (api.type, api.instance, p, ifindex, nexthop, api.tag); - + if (ei == NULL) + { + /* Nothing has changed, so nothing to do; return */ + return 0; + } if (ospf->router_id.s_addr == 0) /* Set flags to generate AS-external-LSA originate event for each redistributed protocols later. */ @@ -1116,17 +1120,19 @@ ospf_zebra_read_ipv4 (int command, struct zclient *zclient, current = ospf_external_info_find_lsa (ospf, &ei->p); if (!current) ospf_external_lsa_originate (ospf, ei); - else if (IS_LSA_MAXAGE (current)) - ospf_external_lsa_refresh (ospf, current, - ei, LSA_REFRESH_FORCE); else - zlog_warn ("ospf_zebra_read_ipv4() : %s already exists", - inet_ntoa (p.prefix)); + { + if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) + zlog_debug ("ospf_zebra_read_ipv4() : %s refreshing LSA", + inet_ntoa (p.prefix)); + ospf_external_lsa_refresh (ospf, current, + ei, LSA_REFRESH_FORCE); + } } } } } - else /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */ + else /* if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) */ { ospf_external_info_delete (api.type, api.instance, p); if (is_prefix_default (&p)) @@ -1554,6 +1560,8 @@ ospf_zebra_init (struct thread_master *master, u_short instance) zclient->interface_address_delete = ospf_interface_address_delete; zclient->ipv4_route_add = ospf_zebra_read_ipv4; zclient->ipv4_route_delete = ospf_zebra_read_ipv4; + zclient->redistribute_route_ipv4_add = ospf_zebra_read_ipv4; + zclient->redistribute_route_ipv4_del = ospf_zebra_read_ipv4; access_list_add_hook (ospf_filter_update); access_list_delete_hook (ospf_filter_update); diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index e0092f542..a5cc8260d 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -140,10 +140,10 @@ rip_zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length) api.metric = 0; /* Then fetch IPv4 prefixes. */ - if (command == ZEBRA_IPV4_ROUTE_ADD) + if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) rip_redistribute_add (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex, &nexthop, api.metric, api.distance); - else + else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) rip_redistribute_delete (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex); return 0; @@ -683,6 +683,8 @@ rip_zclient_init (struct thread_master *master) zclient->ipv4_route_delete = rip_zebra_read_ipv4; zclient->interface_up = rip_interface_up; zclient->interface_down = rip_interface_down; + zclient->redistribute_route_ipv4_add = rip_zebra_read_ipv4; + zclient->redistribute_route_ipv4_del = rip_zebra_read_ipv4; /* Install zebra node. */ install_node (&zebra_node, config_write_zebra); diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 0f4cf9521..f55b04ee0 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -105,7 +105,7 @@ zebra_redistribute_default (struct zserv *client) RNODE_FOREACH_RIB (rn, newrib) if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED) && newrib->distance != DISTANCE_INFINITY) - zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, &rn->p, newrib); + zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV4_ADD, client, &rn->p, newrib); route_unlock_node (rn); } } @@ -125,7 +125,7 @@ zebra_redistribute_default (struct zserv *client) RNODE_FOREACH_RIB (rn, newrib) if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED) && newrib->distance != DISTANCE_INFINITY) - zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, &rn->p, newrib); + zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV6_ADD, client, &rn->p, newrib); route_unlock_node (rn); } } @@ -151,7 +151,7 @@ zebra_redistribute (struct zserv *client, int type, u_short instance) && zebra_check_addr (&rn->p)) { client->redist_v4_add_cnt++; - zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, &rn->p, newrib); + zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV4_ADD, client, &rn->p, newrib); } #ifdef HAVE_IPV6 @@ -166,7 +166,7 @@ zebra_redistribute (struct zserv *client, int type, u_short instance) && zebra_check_addr (&rn->p)) { client->redist_v6_add_cnt++; - zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, &rn->p, newrib); + zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV6_ADD, client, &rn->p, newrib); } #endif /* HAVE_IPV6 */ } @@ -187,7 +187,8 @@ redistribute_add (struct prefix *p, struct rib *rib) rib->instance))) { client->redist_v4_add_cnt++; - zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, p, rib); + zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV4_ADD, client, + p, rib); } #ifdef HAVE_IPV6 if ((p->family == AF_INET6) && @@ -196,7 +197,8 @@ redistribute_add (struct prefix *p, struct rib *rib) rib->instance))) { client->redist_v6_add_cnt++; - zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, p, rib); + zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV6_ADD, client, + p, rib); } #endif /* HAVE_IPV6 */ } @@ -207,7 +209,8 @@ redistribute_add (struct prefix *p, struct rib *rib) rib->instance)) { client->redist_v4_add_cnt++; - zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, p, rib); + zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV4_ADD, client, + p, rib); } #ifdef HAVE_IPV6 if ((p->family == AF_INET6) && @@ -215,7 +218,8 @@ redistribute_add (struct prefix *p, struct rib *rib) rib->instance)) { client->redist_v6_add_cnt++; - zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, p, rib); + zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV6_ADD, client, + p, rib); } #endif /* HAVE_IPV6 */ } @@ -240,15 +244,15 @@ redistribute_delete (struct prefix *p, struct rib *rib) (client->redist_default || redist_check_instance(&client->redist[AFI_IP][rib->type], rib->instance))) - zsend_route_multipath (ZEBRA_IPV4_ROUTE_DELETE, client, p, + zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV4_DEL, client, p, rib); #ifdef HAVE_IPV6 if ((p->family == AF_INET6) && (client->redist_default || redist_check_instance(&client->redist[AFI_IP6][rib->type], rib->instance))) - zsend_route_multipath (ZEBRA_IPV6_ROUTE_DELETE, client, p, - rib); + zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV6_DEL, client, p, + rib); #endif /* HAVE_IPV6 */ } else @@ -256,14 +260,14 @@ redistribute_delete (struct prefix *p, struct rib *rib) if ((p->family == AF_INET) && redist_check_instance(&client->redist[AFI_IP][rib->type], rib->instance)) - zsend_route_multipath (ZEBRA_IPV4_ROUTE_DELETE, client, p, - rib); + zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV4_DEL, client, p, + rib); #ifdef HAVE_IPV6 if ((p->family == AF_INET6) && redist_check_instance(&client->redist[AFI_IP6][rib->type], rib->instance)) - zsend_route_multipath (ZEBRA_IPV6_ROUTE_DELETE, client, p, - rib); + zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV6_DEL, client, p, + rib); #endif /* HAVE_IPV6 */ } } diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 8e873211a..4e4306b9f 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1683,13 +1683,11 @@ rib_process (struct route_node *rn) { zfpm_trigger_update (rn, "updating existing route"); - redistribute_delete (&rn->p, select); - if (! RIB_SYSTEM_ROUTE (select)) { /* For v4, use the replace semantics of netlink. */ if (PREFIX_FAMILY (&rn->p) == AF_INET) - update_ok = 1; + update_ok = 1; else rib_uninstall_kernel (rn, select); } @@ -1709,10 +1707,15 @@ rib_process (struct route_node *rn) } if (! RIB_SYSTEM_ROUTE (select)) rib_install_kernel (rn, select, update_ok); + + /* assuming that the receiver knows how to dedup */ redistribute_add (&rn->p, select); } else { + /* Withdraw unreachable redistribute route */ + redistribute_delete(&rn->p, select); + /* For IPv4, do the uninstall here. */ if (update_ok) rib_uninstall_kernel (rn, select); @@ -1753,7 +1756,9 @@ rib_process (struct route_node *rn) zfpm_trigger_update (rn, "removing existing route"); - redistribute_delete (&rn->p, fib); + /* If there's no route to replace this with, withdraw redistribute */ + if (!select) + redistribute_delete(&rn->p, fib); if (! RIB_SYSTEM_ROUTE (fib)) { @@ -1762,7 +1767,7 @@ rib_process (struct route_node *rn) */ if (PREFIX_FAMILY (&rn->p) == AF_INET) { - if (!select || RIB_SYSTEM_ROUTE(select)) + if (!select) rib_uninstall_kernel (rn, fib); else update_ok = 1; @@ -1802,6 +1807,7 @@ rib_process (struct route_node *rn) if (! RIB_SYSTEM_ROUTE (select)) rib_install_kernel (rn, select, update_ok); SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED); + /* Unconditionally announce, this part is exercised by new routes */ redistribute_add (&rn->p, select); } else @@ -1812,6 +1818,8 @@ rib_process (struct route_node *rn) assert (fib); rib_uninstall_kernel (rn, fib); } + /* if "select", the earlier redist delete wouldn't have happened */ + redistribute_delete(&rn->p, select); } UNSET_FLAG(select->flags, ZEBRA_FLAG_CHANGED); } @@ -2941,7 +2949,6 @@ static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si) UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) { - redistribute_delete (&rn->p, rib); /* If there are other active nexthops, do an update. */ if (rib->nexthop_active_num > 1) { @@ -2949,7 +2956,10 @@ static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si) redistribute_add (&rn->p, rib); } else - rib_uninstall_kernel (rn, rib); + { + redistribute_delete (&rn->p, rib); + rib_uninstall_kernel (rn, rib); + } } /* Delete the nexthop and dereg from NHT */ diff --git a/zebra/zserv.c b/zebra/zserv.c index 1bd5b9882..ba3c59aaf 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -480,31 +480,18 @@ zsend_interface_update (int cmd, struct zserv *client, struct interface *ifp) } /* - * The zebra server sends the clients a ZEBRA_IPV4_ROUTE_ADD or a - * ZEBRA_IPV6_ROUTE_ADD via zsend_route_multipath in the following - * situations: - * - when the client starts up, and requests default information - * by sending a ZEBRA_REDISTRIBUTE_DEFAULT_ADD to the zebra server, in the - * - case of rip, ripngd, ospfd and ospf6d, when the client sends a - * ZEBRA_REDISTRIBUTE_ADD as a result of the "redistribute" vty cmd, - * - when the zebra server redistributes routes after it updates its rib + * This is the new function to announce and withdraw redistributed routes, used + * by Zebra. This is the old zsend_route_multipath() function. That function + * was duplicating code to send a lot of information that was essentially thrown + * away or ignored by the receiver. This is the leaner function that is not a + * duplicate of the zapi_ipv4_route_add/del. * - * The zebra server sends clients a ZEBRA_IPV4_ROUTE_DELETE or a - * ZEBRA_IPV6_ROUTE_DELETE via zsend_route_multipath when: - * - a "ip route" or "ipv6 route" vty command is issued, a prefix is - * - deleted from zebra's rib, and this info - * has to be redistributed to the clients - * - * XXX The ZEBRA_IPV*_ROUTE_ADD message is also sent by the client to the - * zebra server when the client wants to tell the zebra server to add a - * route to the kernel (zapi_ipv4_add etc. ). Since it's essentially the - * same message being sent back and forth, this function and - * zapi_ipv{4,6}_{add, delete} should be re-written to avoid code - * duplication. + * The primary difference is that this function merely sends a single NH instead of + * all the nexthops. */ int -zsend_route_multipath (int cmd, struct zserv *client, struct prefix *p, - struct rib *rib) +zsend_redistribute_route (int cmd, struct zserv *client, struct prefix *p, + struct rib *rib) { int psize; struct stream *s; @@ -512,17 +499,19 @@ zsend_route_multipath (int cmd, struct zserv *client, struct prefix *p, unsigned long nhnummark = 0, messmark = 0; int nhnum = 0; u_char zapi_flags = 0; - + struct nexthop dummy_nh; + s = client->obuf; stream_reset (s); - + memset(&dummy_nh, 0, sizeof(struct nexthop)); + zserv_create_header (s, cmd); - + /* Put type and nexthop. */ stream_putc (s, rib->type); stream_putw (s, rib->instance); stream_putc (s, rib->flags); - + /* marker for message flags field */ messmark = stream_get_endp (s); stream_putc (s, 0); @@ -532,30 +521,45 @@ zsend_route_multipath (int cmd, struct zserv *client, struct prefix *p, stream_putc (s, p->prefixlen); stream_write (s, (u_char *) & p->u.prefix, psize); - /* - * XXX The message format sent by zebra below does not match the format - * of the corresponding message expected by the zebra server - * itself (e.g., see zread_ipv4_add). The nexthop_num is not set correctly, - * (is there a bug on the client side if more than one segment is sent?) - * nexthop ZEBRA_NEXTHOP_IPV4 is never set, ZEBRA_NEXTHOP_IFINDEX - * is hard-coded. - */ - /* Nexthop */ - for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) { + /* We don't send any nexthops when there's a multipath */ + if (rib->nexthop_active_num > 1) + { + SET_FLAG (zapi_flags, ZAPI_MESSAGE_NEXTHOP); + SET_FLAG (zapi_flags, ZAPI_MESSAGE_IFINDEX); + + stream_putc(s, 1); + if (p->family == AF_INET) + { + stream_put_in_addr (s, &dummy_nh.gate.ipv4); + } + else if (p->family == AF_INET6) + { + stream_write (s, (u_char *) &dummy_nh.gate.ipv6, 16); + } + else + { + /* We don't handle anything else now, abort */ + zlog_err("%s: Unable to redistribute route of unknown family, %d\n", + __func__, p->family); + return -1; + } + stream_putc (s, 1); + stream_putl (s, 0); /* dummy ifindex */ + break; + } + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB) || nexthop_has_fib_child(nexthop)) { SET_FLAG (zapi_flags, ZAPI_MESSAGE_NEXTHOP); SET_FLAG (zapi_flags, ZAPI_MESSAGE_IFINDEX); - if (nhnummark == 0) { nhnummark = stream_get_endp (s); stream_putc (s, 1); /* placeholder */ } - nhnum++; switch(nexthop->type) @@ -568,12 +572,16 @@ zsend_route_multipath (int cmd, struct zserv *client, struct prefix *p, case NEXTHOP_TYPE_IPV6: case NEXTHOP_TYPE_IPV6_IFINDEX: case NEXTHOP_TYPE_IPV6_IFNAME: - stream_write (s, (u_char *) &nexthop->gate.ipv6, 16); + /* Only BGP supports IPv4 prefix with IPv6 NH, so kill this */ + if (p->family == AF_INET) + stream_put_in_addr(s, &dummy_nh.gate.ipv4); + else + stream_write (s, (u_char *) &nexthop->gate.ipv6, 16); break; #endif default: - if (cmd == ZEBRA_IPV4_ROUTE_ADD - || cmd == ZEBRA_IPV4_ROUTE_DELETE) + if (cmd == ZEBRA_REDISTRIBUTE_IPV4_ADD + || cmd == ZEBRA_REDISTRIBUTE_IPV4_DEL) { struct in_addr empty; memset (&empty, 0, sizeof (struct in_addr)); @@ -596,7 +604,7 @@ zsend_route_multipath (int cmd, struct zserv *client, struct prefix *p, } /* Metric */ - if (cmd == ZEBRA_IPV4_ROUTE_ADD || cmd == ZEBRA_IPV6_ROUTE_ADD) + if (cmd == ZEBRA_REDISTRIBUTE_IPV4_ADD || cmd == ZEBRA_REDISTRIBUTE_IPV6_ADD) { SET_FLAG (zapi_flags, ZAPI_MESSAGE_DISTANCE); stream_putc (s, rib->distance); @@ -610,14 +618,14 @@ zsend_route_multipath (int cmd, struct zserv *client, struct prefix *p, stream_putw(s, rib->tag); } } - + /* write real message flags value */ stream_putc_at (s, messmark, zapi_flags); - + /* Write next-hop number */ if (nhnummark) stream_putc_at (s, nhnummark, nhnum); - + /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); diff --git a/zebra/zserv.h b/zebra/zserv.h index 41aaecef1..41a4b9ea9 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -149,8 +149,8 @@ extern void nbr_connected_replacement_add_ipv6 (struct interface *, struct in6_addr *, u_char); extern void nbr_connected_delete_ipv6 (struct interface *, struct in6_addr *, u_char); extern int zsend_interface_update (int, struct zserv *, struct interface *); -extern int zsend_route_multipath (int, struct zserv *, struct prefix *, - struct rib *); +extern int zsend_redistribute_route (int, struct zserv *, struct prefix *, + struct rib *); extern int zsend_router_id_update(struct zserv *, struct prefix *); extern pid_t pid; |