When an interface goes down, any neigbors learnt on that interface

using IPv6 Router Advertisements (RAs) must be deleted. When an
interface comes up and neighbors are learnt on that interface, the
BGP FSM for any interface peer must be started only if a valid
local address exists; the local address may come up later after IPv6
Duplicate Address Detection.
This commit is contained in:
Donald Sharp 2015-06-12 07:59:09 -07:00
parent 22a29185ca
commit a197c47cfb
2 changed files with 67 additions and 6 deletions

View File

@ -133,7 +133,7 @@ bgp_read_import_check_update(int command, struct zclient *zclient,
}
static void
bgp_nbr_connected_add (struct nbr_connected *ifc)
bgp_start_interface_nbrs (struct interface *ifp)
{
struct listnode *node, *nnode, *mnode;
struct bgp *bgp;
@ -143,7 +143,9 @@ bgp_nbr_connected_add (struct nbr_connected *ifc)
{
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
{
if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0))
if (peer->conf_if &&
(strcmp (peer->conf_if, ifp->name) == 0) &&
peer->status != Established)
{
if (peer_active(peer))
BGP_EVENT_ADD (peer, BGP_Stop);
@ -154,11 +156,37 @@ bgp_nbr_connected_add (struct nbr_connected *ifc)
}
static void
bgp_nbr_connected_delete (struct nbr_connected *ifc)
bgp_nbr_connected_add (struct nbr_connected *ifc)
{
struct listnode *node;
struct connected *connected;
struct interface *ifp;
struct prefix *p;
/* Kick-off the FSM for any relevant peers only if there is a
* valid local address on the interface.
*/
ifp = ifc->ifp;
for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
{
p = connected->address;
if (p->family == AF_INET6 &&
IN6_IS_ADDR_LINKLOCAL (&p->u.prefix6))
break;
}
if (!connected)
return;
bgp_start_interface_nbrs (ifp);
}
static void
bgp_nbr_connected_delete (struct nbr_connected *ifc, int del)
{
struct listnode *node, *nnode, *mnode;
struct bgp *bgp;
struct peer *peer;
struct interface *ifp;
for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
{
@ -170,6 +198,13 @@ bgp_nbr_connected_delete (struct nbr_connected *ifc)
}
}
}
/* Free neighbor also, if we're asked to. */
if (del)
{
ifp = ifc->ifp;
listnode_delete (ifp->nbr_connected, ifc);
nbr_connected_free (ifc);
}
}
/* Inteface addition message from zebra. */
@ -251,7 +286,7 @@ bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length)
bgp_connected_delete (c);
for (ALL_LIST_ELEMENTS (ifp->nbr_connected, node, nnode, nc))
bgp_nbr_connected_delete (nc);
bgp_nbr_connected_delete (nc, 1);
/* Fast external-failover */
{
@ -339,7 +374,16 @@ bgp_interface_address_add (int command, struct zclient *zclient,
}
if (if_is_operative (ifc->ifp))
bgp_connected_add (ifc);
{
bgp_connected_add (ifc);
/* If we have learnt of any neighbors on this interface,
* check to kick off any BGP interface-based neighbors,
* but only if this is a link-local address.
*/
if (IN6_IS_ADDR_LINKLOCAL(&ifc->address->u.prefix6) &&
!list_isempty(ifc->ifp->nbr_connected))
bgp_start_interface_nbrs (ifc->ifp);
}
return 0;
}
@ -416,7 +460,7 @@ bgp_interface_nbr_address_delete (int command, struct zclient *zclient,
}
if (if_is_operative (ifc->ifp))
bgp_nbr_connected_delete (ifc);
bgp_nbr_connected_delete (ifc, 0);
nbr_connected_free (ifc);

View File

@ -42,6 +42,7 @@
#include "zebra/irdp.h"
#include "zebra/zebra_ptm.h"
#include "zebra/rt_netlink.h"
#include "zebra/zserv.h"
#define ZEBRA_PTM_SUPPORT
@ -587,6 +588,19 @@ if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (struct interface *ifp)
}
}
void
if_down_del_nbr_connected (struct interface *ifp)
{
struct nbr_connected *nbr_connected;
struct listnode *node, *nnode;
for (ALL_LIST_ELEMENTS (ifp->nbr_connected, node, nnode, nbr_connected))
{
listnode_delete (ifp->nbr_connected, nbr_connected);
nbr_connected_free (nbr_connected);
}
}
/* Interface is up. */
void
if_up (struct interface *ifp)
@ -659,6 +673,9 @@ if_down (struct interface *ifp)
rib_update ();
if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp);
/* Delete all neighbor addresses learnt through IPv6 RA */
if_down_del_nbr_connected (ifp);
}
void