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.function.BiConsumer;
16 import javax.annotation.concurrent.GuardedBy;
17 import javax.annotation.concurrent.ThreadSafe;
18 import org.opendaylight.protocol.bgp.rib.impl.spi.PeerExportGroupRegistry;
19 import org.opendaylight.protocol.bgp.rib.spi.ExportPolicyPeerTracker;
20 import org.opendaylight.protocol.bgp.rib.spi.PeerExportGroup;
21 import org.opendaylight.protocol.bgp.rib.spi.PeerExportGroup.PeerExporTuple;
22 import org.opendaylight.protocol.concepts.AbstractRegistration;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.SendReceive;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.PeerId;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.PeerRole;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.rib.TablesKey;
27 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
28 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
33 * There is one ExportPolicyPeerTracker per table
34 * - peerTables: keep track of registered peers, the ones which support this table.
35 * - peerTables: flag indicates whether the structure of the peer has been created, and therefore it can start
37 * - peerAddPathTables: keeps track of peer which supports Additional Path for this table and which Add Path
38 * configuration they are using.
39 * - groups: Contains peers grouped by peerRole and therefore sharing the same export policy.
42 final class ExportPolicyPeerTrackerImpl implements ExportPolicyPeerTracker {
43 private static final Logger LOG = LoggerFactory.getLogger(ExportPolicyPeerTrackerImpl.class);
45 private final Map<YangInstanceIdentifier, PeerRole> peerRoles = new HashMap<>();
47 private final Map<PeerId, SendReceive> peerAddPathTables = new HashMap<>();
49 private final Map<PeerId, Boolean> peerTables = new HashMap<>();
50 private final PolicyDatabase policyDatabase;
51 private final TablesKey localTableKey;
53 private final Map<PeerRole, PeerExportGroupRegistry> groups = new EnumMap<>(PeerRole.class);
55 ExportPolicyPeerTrackerImpl(final PolicyDatabase policyDatabase, final TablesKey localTablesKey) {
56 this.policyDatabase = requireNonNull(policyDatabase);
57 this.localTableKey = localTablesKey;
60 private synchronized AbstractRegistration addToExportGroups(final PeerId peerId,
61 final YangInstanceIdentifier peerPath, final PeerRole peerRole) {
62 final PeerExportGroupRegistry peerExp = this.groups.computeIfAbsent(peerRole,
63 k -> new PeerExportGroupImpl(this.policyDatabase.exportPolicyForRole(peerRole)));
65 final AbstractRegistration registration = peerExp.registerPeer(peerId, new PeerExporTuple(peerPath, peerRole));
67 return new AbstractRegistration() {
69 protected void removeRegistration() {
71 if (ExportPolicyPeerTrackerImpl.this.groups.get(peerRole).isEmpty()) {
72 ExportPolicyPeerTrackerImpl.this.groups.remove(peerRole);
79 public synchronized AbstractRegistration registerPeer(final PeerId peerId, final SendReceive sendReceive,
80 final YangInstanceIdentifier peerPath, final PeerRole peerRole) {
81 if (sendReceive != null) {
82 this.peerAddPathTables.put(peerId, sendReceive);
83 LOG.debug("Supported Add BestPath table {} added to peer {}", sendReceive, peerId);
85 this.peerTables.put(peerId, false);
86 this.peerRoles.put(peerPath, peerRole);
87 LOG.debug("Supported table {} added to peer {} role {}", this.localTableKey, peerId, peerRole);
88 final AbstractRegistration registration = addToExportGroups(peerId, peerPath, peerRole);
90 final Object lock = this;
91 return new AbstractRegistration() {
93 protected void removeRegistration() {
95 final SendReceive sendReceiveValue = ExportPolicyPeerTrackerImpl.this.peerAddPathTables.remove(peerId);
96 if (sendReceiveValue != null) {
97 LOG.debug("Supported Add BestPath table {} removed to peer {}", sendReceiveValue, peerId);
99 ExportPolicyPeerTrackerImpl.this.peerTables.remove(peerId);
100 LOG.debug("Removed peer {} from supported table {}", peerId, ExportPolicyPeerTrackerImpl.this.localTableKey);
101 ExportPolicyPeerTrackerImpl.this.peerRoles.remove(peerPath);
102 registration.close();
109 public synchronized PeerExportGroup getPeerGroup(final PeerRole role) {
110 return this.groups.get(requireNonNull(role));
114 public synchronized boolean isTableSupported(final PeerId peerId) {
115 return this.peerTables.containsKey(peerId);
119 public synchronized PeerRole getRole(final YangInstanceIdentifier peerId) {
120 return this.peerRoles.get(peerId);
124 public synchronized boolean isAddPathSupportedByPeer(final PeerId peerId) {
125 final SendReceive sendReceive = this.peerAddPathTables.get(peerId);
126 return sendReceive != null && (sendReceive.equals(SendReceive.Both) || sendReceive.equals(SendReceive.Receive));
130 public synchronized void registerPeerAsInitialized(final PeerId peerId) {
131 this.peerTables.computeIfPresent(peerId, (k, v) -> true);
135 public synchronized boolean isTableStructureInitialized(final PeerId peerId) {
136 return this.peerTables.get(peerId);
139 final class PeerExportGroupImpl implements PeerExportGroupRegistry {
141 private final Map<PeerId, PeerExporTuple> peers = new HashMap<>();
142 private final AbstractExportPolicy policy;
144 public PeerExportGroupImpl(final AbstractExportPolicy policy) {
145 this.policy = requireNonNull(policy);
149 public ContainerNode effectiveAttributes(final PeerRole role, final ContainerNode attributes) {
150 return attributes == null || role == null ? null : this.policy.effectiveAttributes(role, attributes);
154 public boolean containsPeer(final PeerId routePeerId) {
155 synchronized (this.peers) {
156 return this.peers.containsKey(routePeerId);
161 public void forEach(final BiConsumer<PeerId, YangInstanceIdentifier> action) {
162 synchronized (ExportPolicyPeerTrackerImpl.this) {
163 synchronized (this.peers) {
164 for (final Map.Entry<PeerId, PeerExporTuple> pid : this.peers.entrySet()) {
165 action.accept(pid.getKey(), pid.getValue().getYii());
172 public AbstractRegistration registerPeer(final PeerId peerId, final PeerExporTuple peerExporTuple) {
173 synchronized (ExportPolicyPeerTrackerImpl.this) {
174 synchronized (this.peers) {
175 this.peers.put(peerId, peerExporTuple);
178 return new AbstractRegistration() {
180 protected void removeRegistration() {
181 synchronized (ExportPolicyPeerTrackerImpl.this) {
182 synchronized (PeerExportGroupImpl.this.peers) {
183 PeerExportGroupImpl.this.peers.remove(peerId);
192 public boolean isEmpty() {
193 synchronized (this.peers) {
194 return this.peers.isEmpty();