2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.protocol.bgp.rib.impl;
10 import static java.util.Objects.requireNonNull;
12 import java.util.EnumMap;
13 import java.util.HashMap;
15 import java.util.Optional;
16 import java.util.function.BiConsumer;
17 import javax.annotation.concurrent.GuardedBy;
18 import javax.annotation.concurrent.ThreadSafe;
19 import org.opendaylight.protocol.bgp.rib.impl.spi.PeerExportGroupRegistry;
20 import org.opendaylight.protocol.bgp.rib.spi.ExportPolicyPeerTracker;
21 import org.opendaylight.protocol.bgp.rib.spi.PeerExportGroup;
22 import org.opendaylight.protocol.bgp.rib.spi.PeerExportGroup.PeerExporTuple;
23 import org.opendaylight.protocol.concepts.AbstractRegistration;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.SendReceive;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.PeerId;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.PeerRole;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.rib.TablesKey;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
29 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
34 * There is one ExportPolicyPeerTracker per table
35 * - peerTables: keep track of registered peers, the ones which support this table.
36 * - peerTables: flag indicates whether the structure of the peer has been created, and therefore it can start
38 * - peerAddPathTables: keeps track of peer which supports Additional Path for this table and which Add Path
39 * configuration they are using.
40 * - groups: Contains peers grouped by peerRole and therefore sharing the same export policy.
43 final class ExportPolicyPeerTrackerImpl implements ExportPolicyPeerTracker {
44 private static final Logger LOG = LoggerFactory.getLogger(ExportPolicyPeerTrackerImpl.class);
46 private final Map<YangInstanceIdentifier, PeerRole> peerRoles = new HashMap<>();
48 private final Map<PeerId, SendReceive> peerAddPathTables = new HashMap<>();
50 private final Map<PeerId, Boolean> peerTables = new HashMap<>();
51 private final PolicyDatabase policyDatabase;
52 private final TablesKey localTableKey;
54 private final Map<PeerRole, PeerExportGroupRegistry> groups = new EnumMap<>(PeerRole.class);
56 ExportPolicyPeerTrackerImpl(final PolicyDatabase policyDatabase, final TablesKey localTablesKey) {
57 this.policyDatabase = requireNonNull(policyDatabase);
58 this.localTableKey = localTablesKey;
61 private synchronized AbstractRegistration addToExportGroups(final PeerId peerId,
62 final YangInstanceIdentifier peerPath, final PeerRole peerRole) {
63 final PeerExportGroupRegistry peerExp = this.groups.computeIfAbsent(peerRole,
64 k -> new PeerExportGroupImpl(this.policyDatabase.exportPolicyForRole(peerRole)));
66 final AbstractRegistration registration = peerExp.registerPeer(peerId, new PeerExporTuple(peerPath, peerRole));
68 return new AbstractRegistration() {
70 protected void removeRegistration() {
72 if (ExportPolicyPeerTrackerImpl.this.groups.get(peerRole).isEmpty()) {
73 ExportPolicyPeerTrackerImpl.this.groups.remove(peerRole);
80 public synchronized AbstractRegistration registerPeer(final PeerId peerId, final SendReceive sendReceive,
81 final YangInstanceIdentifier peerPath, final PeerRole peerRole) {
82 if (sendReceive != null) {
83 this.peerAddPathTables.put(peerId, sendReceive);
84 LOG.debug("Supported Add BestPath table {} added to peer {}", sendReceive, peerId);
86 this.peerTables.put(peerId, false);
87 this.peerRoles.put(peerPath, peerRole);
88 LOG.debug("Supported table {} added to peer {} role {}", this.localTableKey, peerId, peerRole);
89 final AbstractRegistration registration = addToExportGroups(peerId, peerPath, peerRole);
91 final Object lock = this;
92 return new AbstractRegistration() {
94 protected void removeRegistration() {
96 final SendReceive sendReceiveValue = ExportPolicyPeerTrackerImpl.this.peerAddPathTables.remove(peerId);
97 if (sendReceiveValue != null) {
98 LOG.debug("Supported Add BestPath table {} removed to peer {}", sendReceiveValue, peerId);
100 ExportPolicyPeerTrackerImpl.this.peerTables.remove(peerId);
101 LOG.debug("Removed peer {} from supported table {}", peerId, ExportPolicyPeerTrackerImpl.this.localTableKey);
102 ExportPolicyPeerTrackerImpl.this.peerRoles.remove(peerPath);
103 registration.close();
110 public synchronized PeerExportGroup getPeerGroup(final PeerRole role) {
111 return this.groups.get(requireNonNull(role));
115 public synchronized boolean isTableSupported(final PeerId peerId) {
116 return this.peerTables.containsKey(peerId);
120 public synchronized PeerRole getRole(final YangInstanceIdentifier peerId) {
121 return this.peerRoles.get(peerId);
125 public synchronized boolean isAddPathSupportedByPeer(final PeerId peerId) {
126 final SendReceive sendReceive = this.peerAddPathTables.get(peerId);
127 return sendReceive != null && (sendReceive.equals(SendReceive.Both) || sendReceive.equals(SendReceive.Receive));
131 public synchronized void registerPeerAsInitialized(final PeerId peerId) {
132 this.peerTables.computeIfPresent(peerId, (k, v) -> true);
136 public synchronized boolean isTableStructureInitialized(final PeerId peerId) {
137 return this.peerTables.get(peerId);
140 final class PeerExportGroupImpl implements PeerExportGroupRegistry {
142 private final Map<PeerId, PeerExporTuple> peers = new HashMap<>();
143 private final AbstractExportPolicy policy;
145 public PeerExportGroupImpl(final AbstractExportPolicy policy) {
146 this.policy = requireNonNull(policy);
150 public ContainerNode effectiveAttributes(final PeerRole role, final ContainerNode attributes) {
151 return attributes == null || role == null ? null : this.policy.effectiveAttributes(role, attributes);
155 public boolean containsPeer(final PeerId routePeerId) {
156 synchronized (this.peers) {
157 return this.peers.containsKey(routePeerId);
162 public void forEach(final BiConsumer<PeerId, YangInstanceIdentifier> action) {
163 synchronized (ExportPolicyPeerTrackerImpl.this) {
164 synchronized (this.peers) {
165 for (final Map.Entry<PeerId, PeerExporTuple> pid : this.peers.entrySet()) {
166 action.accept(pid.getKey(), pid.getValue().getYii());
173 public AbstractRegistration registerPeer(final PeerId peerId, final PeerExporTuple peerExporTuple) {
174 synchronized (ExportPolicyPeerTrackerImpl.this) {
175 synchronized (this.peers) {
176 this.peers.put(peerId, peerExporTuple);
179 return new AbstractRegistration() {
181 protected void removeRegistration() {
182 synchronized (ExportPolicyPeerTrackerImpl.this) {
183 synchronized (PeerExportGroupImpl.this.peers) {
184 PeerExportGroupImpl.this.peers.remove(peerId);
193 public boolean isEmpty() {
194 synchronized (this.peers) {
195 return this.peers.isEmpty();