2 * Copyright (c) 2013 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.spi;
10 import com.google.common.base.MoreObjects;
11 import com.google.common.base.MoreObjects.ToStringHelper;
12 import com.google.common.base.Preconditions;
13 import java.util.HashMap;
14 import java.util.Iterator;
16 import java.util.Map.Entry;
17 import javax.annotation.Nullable;
18 import javax.annotation.concurrent.GuardedBy;
19 import javax.annotation.concurrent.ThreadSafe;
20 import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Update;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.UpdateBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.Attributes;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.AttributesBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes1;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes1Builder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes2;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes2Builder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlriBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlriBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.Route;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
35 import org.opendaylight.yangtools.yang.binding.Identifiable;
36 import org.opendaylight.yangtools.yang.binding.Identifier;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
44 public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K extends Identifier<D>> implements AdjRIBsIn<I, D>, RouteEncoder {
45 protected abstract static class RIBEntryData<I, D extends Identifiable<K> & Route, K extends Identifier<D>> {
46 private final Attributes attributes;
47 private final Peer peer;
49 protected RIBEntryData(final Peer peer, final Attributes attributes) {
50 this.attributes = Preconditions.checkNotNull(attributes);
51 this.peer = Preconditions.checkNotNull(peer);
54 public Attributes getAttributes() {
55 return this.attributes;
58 public Peer getPeer() {
63 * Create a data object given the key and target instance identifier.
65 * @param key Route key
66 * @param id Data store target identifier
67 * @return Data object to be written to the data store.
69 protected abstract D getDataObject(I key, K id);
72 public final String toString() {
73 return addToStringAttributes(MoreObjects.toStringHelper(this)).toString();
76 protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
77 return toStringHelper.add("attributes", this.attributes);
81 private static final Logger LOG = LoggerFactory.getLogger(AbstractAdjRIBs.class);
82 private final KeyedInstanceIdentifier<Tables, TablesKey> basePath;
83 private final BgpTableType tableType;
84 private final Update eor;
87 private final Map<I, RIBEntry<I, D, K>> entries = new HashMap<>();
90 private final Map<Peer, Boolean> peers = new HashMap<>();
92 protected AbstractAdjRIBs(final KeyedInstanceIdentifier<Tables, TablesKey> basePath) {
93 this.basePath = Preconditions.checkNotNull(basePath);
94 this.tableType = new BgpTableTypeImpl(basePath.getKey().getAfi(), basePath.getKey().getSafi());
95 this.eor = new UpdateBuilder().setAttributes(new AttributesBuilder().addAugmentation(
96 Attributes1.class, new Attributes1Builder().setMpReachNlri(new MpReachNlriBuilder(this.tableType)
97 .build()).build()).build()).build();
101 public final synchronized void clear(final AdjRIBsTransaction trans, final Peer peer) {
102 final Iterator<Entry<I, RIBEntry<I, D, K>>> i = this.entries.entrySet().iterator();
103 while (i.hasNext()) {
104 final Entry<I, RIBEntry<I, D, K>> e = i.next();
106 if (e.getValue().removeState(trans, peer)) {
111 this.peers.remove(peer);
112 trans.setUptodate(getBasePath(), !this.peers.values().contains(Boolean.FALSE));
115 public final synchronized void addAllEntries(final AdjRIBsTransaction trans) {
116 for (final Entry<I, RIBEntry<I, D, K>> e : this.entries.entrySet()) {
117 final RIBEntry<I, D, K> entry = e.getValue();
118 final RIBEntryData<I, D, K> state = entry.currentState;
119 trans.advertise(this, e.getKey(), entry.name, state.peer, state.getDataObject(entry.getKey(), entry.name.getKey()));
124 * Construct a datastore identifier for an entry key.
126 * @param basePath datastore base path under which the entry to be stored
127 * @param id object identifier
128 * @return Data store identifier, may not be null
130 * @deprecated Please override {@link #identifierForKey(Object)} instead. The basePath
131 * argument is constant for a particular instance and is the one your
132 * constructor specifies.
135 protected abstract KeyedInstanceIdentifier<D, K> identifierForKey(InstanceIdentifier<Tables> basePath, I id);
138 * Return the base path specified at construction time.
142 protected final KeyedInstanceIdentifier<Tables, TablesKey> getBasePath() {
143 return this.basePath;
147 * Construct a datastore identifier for an entry key.
149 * @param id object identifier
150 * @return Data store identifier, may not be null
152 protected KeyedInstanceIdentifier<D, K> identifierForKey(final I id) {
153 return identifierForKey(getBasePath(), id);
156 public void addWith(final MpUnreachNlriBuilder builder, final InstanceIdentifier<?> key) {
157 this.addWithdrawal(builder, keyForIdentifier(this.routeIdentifier(key)));
161 * Transform a withdrawn identifier into a the corresponding NLRI in MP_UNREACH attribute.
162 * @param builder MpUnreachNlriBuilder
163 * @param id Route key
165 protected abstract void addWithdrawal(MpUnreachNlriBuilder builder, I id);
168 * Creates router identifier out of instance identifier
169 * @param id instance identifier
170 * @return router identifier
173 public abstract KeyedInstanceIdentifier<D, K> routeIdentifier(InstanceIdentifier<?> id);
176 * Craates route key out of instance identifier
177 * @param id instance identifier
180 public abstract I keyForIdentifier(KeyedInstanceIdentifier<D, K> id);
183 * Common backend for {@link AdjRIBsIn#addRoutes(AdjRIBsTransaction, Peer, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlri, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.Attributes)} implementations.
185 * If a new route is added, check first for its existence in Map of entries.
186 * If the route is already there, change it's state. Then check for peer in
187 * Map of peers, if it's not there, add it.
189 * @param trans Transaction context
190 * @param peer Originating peer
191 * @param id Data store instance identifier
192 * @param data Data object to be written
194 protected final synchronized void add(final AdjRIBsTransaction trans, final Peer peer, final I id, final RIBEntryData<I, D, K> data) {
195 LOG.debug("Adding state {} for {} peer {}", data, id, peer);
197 RIBEntry<I, D, K> e = this.entries.get(Preconditions.checkNotNull(id));
199 e = new RIBEntry<I, D, K>(this, id);
200 this.entries.put(id, e);
203 e.setState(trans, peer, data);
204 if (!this.peers.containsKey(peer)) {
205 this.peers.put(peer, Boolean.FALSE);
206 trans.setUptodate(getBasePath(), Boolean.FALSE);
211 * Common backend for {@link AdjRIBsIn#removeRoutes(AdjRIBsTransaction, Peer, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlri)} implementations.
213 * @param trans Transaction context
214 * @param peer Originating peer
215 * @param id Data store instance identifier
217 protected final synchronized void remove(final AdjRIBsTransaction trans, final Peer peer, final I id) {
218 final RIBEntry<I, D, K> e = this.entries.get(id);
219 if (e != null && e.removeState(trans, peer)) {
220 LOG.debug("Removed last state, removing entry for {}", id);
221 this.entries.remove(id);
226 public final void markUptodate(final AdjRIBsTransaction trans, final Peer peer) {
227 this.peers.put(peer, Boolean.TRUE);
228 trans.setUptodate(getBasePath(), !this.peers.values().contains(Boolean.FALSE));
232 public final Update endOfRib() {
237 public Update updateMessageFor(final Object key, final Route route) {
238 final UpdateBuilder ub = new UpdateBuilder();
239 final AttributesBuilder pab = new AttributesBuilder();
242 final MpReachNlriBuilder reach = new MpReachNlriBuilder(this.tableType);
244 addAdvertisement(reach, (D)route);
245 pab.fieldsFrom(route.getAttributes());
246 pab.addAugmentation(Attributes1.class, new Attributes1Builder().setMpReachNlri(reach.build()).build()).build();
248 final MpUnreachNlriBuilder unreach = new MpUnreachNlriBuilder(this.tableType);
249 addWithdrawal(unreach, (I)key);
250 pab.addAugmentation(Attributes2.class, new Attributes2Builder().setMpUnreachNlri(unreach.build()).build()).build();
253 ub.setAttributes(pab.build());