mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 22:10:19 +00:00
Zebra: Make redistribute do replace instead of del/add for better convergence
Ticket: CM-6768 Reviewed By: CCR-3207 Testing Done: bgpsmoke, smoke, topo to create failure Redistributing routes goes through a del/add cycle whenever a redistributed is updated. This del/add cycle causes disruption by causing traffic loss for brief/long periods of time(6-8 s in case of OSPF). The modifications in this patch remove the del/add cycle to ensure that this disruption doesn't happen. Also fixed sending no forwarding address when announcing IPv4 routes with IPv6 nexthops, and sending nexthop only when there is a single path. Signed-off-by: Dinesh G Dutt <ddutt@cumulusnetworks.com> Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com> Reviewed-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
This commit is contained in:
parent
d0f9e40016
commit
5048fe1444
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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); */
|
||||
|
@ -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)
|
||||
@ -151,13 +152,21 @@ ospf_external_info_add (u_char type, u_short instance, struct prefix_ipv4 p,
|
||||
/* If old info exists, -- discard new one or overwrite with new one? */
|
||||
if (rn)
|
||||
if (rn->info)
|
||||
{
|
||||
new = rn->info;
|
||||
if ((new->ifindex == ifindex) &&
|
||||
(new->nexthop.s_addr == nexthop.s_addr) && (new->tag == tag))
|
||||
{
|
||||
route_unlock_node(rn);
|
||||
zlog_warn ("Redistribute[%s][%d]: %s/%d already exists, discard.",
|
||||
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.",
|
||||
{
|
||||
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);
|
||||
inet_ntoa (p.prefix), p.prefixlen, inetbuf);
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
else
|
||||
{
|
||||
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
|
||||
zlog_warn ("ospf_zebra_read_ipv4() : %s already exists",
|
||||
inet_ntoa (p.prefix));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
@ -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);
|
||||
|
@ -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,14 +244,14 @@ 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,
|
||||
zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV6_DEL, client, p,
|
||||
rib);
|
||||
#endif /* HAVE_IPV6 */
|
||||
}
|
||||
@ -256,13 +260,13 @@ 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,
|
||||
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,
|
||||
zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV6_DEL, client, p,
|
||||
rib);
|
||||
#endif /* HAVE_IPV6 */
|
||||
}
|
||||
|
@ -1683,8 +1683,6 @@ 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. */
|
||||
@ -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,6 +1756,8 @@ rib_process (struct route_node *rn)
|
||||
|
||||
zfpm_trigger_update (rn, "removing existing route");
|
||||
|
||||
/* 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,8 +2956,11 @@ static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
|
||||
redistribute_add (&rn->p, rib);
|
||||
}
|
||||
else
|
||||
{
|
||||
redistribute_delete (&rn->p, rib);
|
||||
rib_uninstall_kernel (rn, rib);
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete the nexthop and dereg from NHT */
|
||||
nh_p.family = AF_INET;
|
||||
|
@ -480,30 +480,17 @@ 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,
|
||||
zsend_redistribute_route (int cmd, struct zserv *client, struct prefix *p,
|
||||
struct rib *rib)
|
||||
{
|
||||
int psize;
|
||||
@ -512,9 +499,11 @@ 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);
|
||||
|
||||
@ -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:
|
||||
/* 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);
|
||||
|
@ -149,7 +149,7 @@ 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 *,
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user