}
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;
{
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);
}
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))
{
}
}
}
+ /* 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. */
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 */
{
}
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;
}
}
if (if_is_operative (ifc->ifp))
- bgp_nbr_connected_delete (ifc);
+ bgp_nbr_connected_delete (ifc, 0);
nbr_connected_free (ifc);
#include "zebra/irdp.h"
#include "zebra/zebra_ptm.h"
#include "zebra/rt_netlink.h"
+#include "zebra/zserv.h"
#define ZEBRA_PTM_SUPPORT
}
}
+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)
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