}
}
-void bgp_nht_register_enhe_capability_interfaces(struct peer *peer)
+void bgp_nht_reg_enhe_cap_intfs(struct peer *peer)
{
struct bgp *bgp;
struct bgp_node *rn;
return;
if (!sockunion2hostprefix(&peer->su, &p)) {
- if (BGP_DEBUG(nht, NHT))
- zlog_debug("%s: Unable to convert prefix to sockunion",
- __func__);
+ zlog_warn("%s: Unable to convert sockunion to prefix for %s",
+ __func__, peer->host);
return;
}
BGP_UNNUM_DEFAULT_RA_INTERVAL);
}
}
+
+void bgp_nht_dereg_enhe_cap_intfs(struct peer *peer)
+{
+ struct bgp *bgp;
+ struct bgp_node *rn;
+ struct bgp_nexthop_cache *bnc;
+ struct nexthop *nhop;
+ struct interface *ifp;
+ struct prefix p;
+
+ if (peer->ifp)
+ return;
+
+ bgp = peer->bgp;
+
+ if (!bgp->nexthop_cache_table[AFI_IP6])
+ return;
+
+ if (!sockunion2hostprefix(&peer->su, &p)) {
+ zlog_warn("%s: Unable to convert sockunion to prefix for %s",
+ __func__, peer->host);
+ return;
+ }
+
+ if (p.family != AF_INET6)
+ return;
+
+ rn = bgp_node_lookup(bgp->nexthop_cache_table[AFI_IP6], &p);
+ if (!rn)
+ return;
+
+ bnc = bgp_node_get_bgp_nexthop_info(rn);
+ if (!bnc)
+ return;
+
+ if (peer != bnc->nht_info)
+ return;
+
+ for (nhop = bnc->nexthop; nhop; nhop = nhop->next) {
+ ifp = if_lookup_by_index(nhop->ifindex, nhop->vrf_id);
+
+ zclient_send_interface_radv_req(zclient, nhop->vrf_id, ifp, 0,
+ 0);
+ }
+}
* this code can walk the registered nexthops and
* register the important ones with zebra for RA.
*/
-extern void bgp_nht_register_enhe_capability_interfaces(struct peer *peer);
+extern void bgp_nht_reg_enhe_cap_intfs(struct peer *peer);
+extern void bgp_nht_dereg_enhe_cap_intfs(struct peer *peer);
#endif /* _BGP_NHT_H */
}
other = peer->doppelganger;
+
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE))
+ bgp_zebra_terminate_radv(peer->bgp, peer);
+
peer_notify_unconfig(peer);
peer_delete(peer);
if (other && other->status != Deleted) {
return CMD_WARNING_CONFIG_FAILED;
}
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE))
+ bgp_zebra_terminate_radv(peer->bgp, peer);
+
peer_notify_unconfig(peer);
ret = peer_delete(peer);
zlog_debug("%u: Initiating RA for peer %s", bgp->vrf_id,
peer->host);
- zclient_send_interface_radv_req(zclient, bgp->vrf_id, peer->ifp, 1,
- ra_interval);
+ /*
+ * If unnumbered peer (peer->ifp) call thru zapi to start RAs.
+ * If we don't have an ifp pointer, call function to find the
+ * ifps for a numbered enhe peer to turn RAs on.
+ */
+ peer->ifp ? zclient_send_interface_radv_req(zclient, bgp->vrf_id,
+ peer->ifp, 1, ra_interval)
+ : bgp_nht_reg_enhe_cap_intfs(peer);
}
void bgp_zebra_terminate_radv(struct bgp *bgp, struct peer *peer)
zlog_debug("%u: Terminating RA for peer %s", bgp->vrf_id,
peer->host);
- zclient_send_interface_radv_req(zclient, bgp->vrf_id, peer->ifp, 0, 0);
+ /*
+ * If unnumbered peer (peer->ifp) call thru zapi to stop RAs.
+ * If we don't have an ifp pointer, call function to find the
+ * ifps for a numbered enhe peer to turn RAs off.
+ */
+ peer->ifp ? zclient_send_interface_radv_req(zclient, bgp->vrf_id,
+ peer->ifp, 0, 0)
+ : bgp_nht_dereg_enhe_cap_intfs(peer);
}
int bgp_zebra_advertise_subnet(struct bgp *bgp, int advertise, vni_t vni)
: BGP_DEFAULT_EBGP_ROUTEADV;
}
+ /* capability extended-nexthop apply */
+ if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_CAPABILITY_ENHE))
+ if (CHECK_FLAG(conf->flags, PEER_FLAG_CAPABILITY_ENHE))
+ SET_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE);
+
/* password apply */
if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_PASSWORD))
PEER_STR_ATTR_INHERIT(peer, group, password,
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
other = peer->doppelganger;
+
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE))
+ bgp_zebra_terminate_radv(bgp, peer);
+
peer_delete(peer);
if (other && other->status != Deleted) {
other->group = NULL;
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
other = peer->doppelganger;
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE))
+ bgp_zebra_terminate_radv(peer->bgp, peer);
+
peer_delete(peer);
if (other && other->status != Deleted) {
/* Update flag override state accordingly. */
COND_FLAG(peer->flags_override, flag, set != invert);
- if (set && flag == PEER_FLAG_CAPABILITY_ENHE)
- bgp_nht_register_enhe_capability_interfaces(peer);
+ /*
+ * For the extended next-hop encoding flag we need to turn RAs
+ * on if flag is being set, but only turn RAs off if the flag
+ * is being unset on this peer and if this peer is a member of a
+ * peer-group, the peer-group also doesn't have the flag set.
+ */
+ if (flag == PEER_FLAG_CAPABILITY_ENHE) {
+ if (set) {
+ bgp_zebra_initiate_radv(peer->bgp, peer);
+ } else if (peer_group_active(peer)) {
+ if (!CHECK_FLAG(peer->group->conf->flags, flag))
+ bgp_zebra_terminate_radv(peer->bgp,
+ peer);
+ } else
+ bgp_zebra_terminate_radv(peer->bgp, peer);
+ }
/* Execute flag action on peer. */
if (action.type == peer_change_reset)
/* Update flag on peer-group member. */
COND_FLAG(member->flags, flag, set != member_invert);
- if (set && flag == PEER_FLAG_CAPABILITY_ENHE)
- bgp_nht_register_enhe_capability_interfaces(member);
+ if (flag == PEER_FLAG_CAPABILITY_ENHE)
+ set ? bgp_zebra_initiate_radv(member->bgp, member)
+ : bgp_zebra_terminate_radv(member->bgp, member);
/* Execute flag action on peer-group member. */
if (action.type == peer_change_reset)