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.Objects;
11 import com.google.common.base.Objects.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.PathAttributes;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Update;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.UpdateBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributesBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes1;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes1Builder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes2;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes2Builder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpReachNlriBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.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;
43 public abstract class AbstractAdjRIBs<I, D extends Identifiable<K> & Route, K extends Identifier<D>> implements AdjRIBsIn<I, D>, RouteEncoder {
44 protected abstract static class RIBEntryData<I, D extends Identifiable<K> & Route, K extends Identifier<D>> {
45 private final PathAttributes attributes;
46 private final Peer peer;
48 protected RIBEntryData(final Peer peer, final PathAttributes attributes) {
49 this.attributes = Preconditions.checkNotNull(attributes);
50 this.peer = Preconditions.checkNotNull(peer);
53 public PathAttributes getPathAttributes() {
54 return this.attributes;
57 public Peer getPeer() {
62 * Create a data object given the key and target instance identifier.
64 * @param key Route key
65 * @param id Data store target identifier
66 * @return Data object to be written to the data store.
68 protected abstract D getDataObject(I key, K id);
71 public final String toString() {
72 return addToStringAttributes(Objects.toStringHelper(this)).toString();
75 protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
76 return toStringHelper.add("attributes", this.attributes);
80 private static final Logger LOG = LoggerFactory.getLogger(AbstractAdjRIBs.class);
81 private final KeyedInstanceIdentifier<Tables, TablesKey> basePath;
82 private final BgpTableType tableType;
83 private final Update eor;
86 private final Map<I, RIBEntry<I, D, K>> entries = new HashMap<>();
89 private final Map<Peer, Boolean> peers = new HashMap<>();
91 protected AbstractAdjRIBs(final KeyedInstanceIdentifier<Tables, TablesKey> basePath) {
92 this.basePath = Preconditions.checkNotNull(basePath);
93 this.tableType = new BgpTableTypeImpl(basePath.getKey().getAfi(), basePath.getKey().getSafi());
94 this.eor = new UpdateBuilder().setPathAttributes(new PathAttributesBuilder().addAugmentation(
95 PathAttributes1.class, new PathAttributes1Builder().setMpReachNlri(new MpReachNlriBuilder(this.tableType)
96 .build()).build()).build()).build();
100 public final synchronized void clear(final AdjRIBsTransaction trans, final Peer peer) {
101 final Iterator<Entry<I, RIBEntry<I, D, K>>> i = this.entries.entrySet().iterator();
102 while (i.hasNext()) {
103 final Entry<I, RIBEntry<I, D, K>> e = i.next();
105 if (e.getValue().removeState(trans, peer)) {
110 this.peers.remove(peer);
111 trans.setUptodate(getBasePath(), !this.peers.values().contains(Boolean.FALSE));
114 public final synchronized void addAllEntries(final AdjRIBsTransaction trans) {
115 for (final Entry<I, RIBEntry<I, D, K>> e : this.entries.entrySet()) {
116 final RIBEntry<I, D, K> entry = e.getValue();
117 final RIBEntryData<I, D, K> state = entry.currentState;
118 trans.advertise(this, e.getKey(), entry.name, state.peer, state.getDataObject(entry.getKey(), entry.name.getKey()));
123 * Construct a datastore identifier for an entry key.
125 * @param basePath datastore base path under which the entry to be stored
126 * @param id object identifier
127 * @return Data store identifier, may not be null
129 * @deprecated Please override {@link #identifierForKey(Object)} instead. The basePath
130 * argument is constant for a particular instance and is the one your
131 * constructor specifies.
134 protected abstract KeyedInstanceIdentifier<D, K> identifierForKey(InstanceIdentifier<Tables> basePath, I id);
137 * Return the base path specified at construction time.
141 protected final KeyedInstanceIdentifier<Tables, TablesKey> getBasePath() {
146 * Construct a datastore identifier for an entry key.
148 * @param id object identifier
149 * @return Data store identifier, may not be null
151 protected KeyedInstanceIdentifier<D, K> identifierForKey(final I id) {
152 return identifierForKey(getBasePath(), id);
155 public void addWith(final MpUnreachNlriBuilder builder, final InstanceIdentifier<?> key) {
156 this.addWithdrawal(builder, keyForIdentifier(this.routeIdentifier(key)));
160 * Transform a withdrawn identifier into a the corresponding NLRI in MP_UNREACH attribute.
162 * @param id Route key
164 protected abstract void addWithdrawal(MpUnreachNlriBuilder builder, I id);
167 * Creates router identifier out of instance identifier
168 * @param id instance identifier
169 * @return router identifier
172 public abstract KeyedInstanceIdentifier<D, K> routeIdentifier(InstanceIdentifier<?> id);
175 * Craates route key out of instance identifier
176 * @param id instance identifier
179 public abstract I keyForIdentifier(KeyedInstanceIdentifier<D, K> id);
182 * Common backend for {@link AdjRIBsIn#addRoutes()} implementations.
183 * If a new route is added, check first for its existence in Map of entries.
184 * If the route is already there, change it's state. Then check for peer in
185 * Map of peers, if it's not there, add it.
187 * @param trans Transaction context
188 * @param peer Originating peer
189 * @param id Data store instance identifier
190 * @param data Data object to be written
192 protected final synchronized void add(final AdjRIBsTransaction trans, final Peer peer, final I id, final RIBEntryData<I, D, K> data) {
193 LOG.debug("Adding state {} for {} peer {}", data, id, peer);
195 RIBEntry<I, D, K> e = this.entries.get(Preconditions.checkNotNull(id));
197 e = new RIBEntry<I, D, K>(this, id);
198 this.entries.put(id, e);
201 e.setState(trans, peer, data);
202 if (!this.peers.containsKey(peer)) {
203 this.peers.put(peer, Boolean.FALSE);
204 trans.setUptodate(getBasePath(), Boolean.FALSE);
209 * Common backend for {@link AdjRIBsIn#removeRoutes()} implementations.
211 * @param trans Transaction context
212 * @param peer Originating peer
213 * @param id Data store instance identifier
215 protected final synchronized void remove(final AdjRIBsTransaction trans, final Peer peer, final I id) {
216 final RIBEntry<I, D, K> e = this.entries.get(id);
217 if (e != null && e.removeState(trans, peer)) {
218 LOG.debug("Removed last state, removing entry for {}", id);
219 this.entries.remove(id);
224 public final void markUptodate(final AdjRIBsTransaction trans, final Peer peer) {
225 this.peers.put(peer, Boolean.TRUE);
226 trans.setUptodate(getBasePath(), !this.peers.values().contains(Boolean.FALSE));
230 public final Update endOfRib() {
235 public Update updateMessageFor(final Object key, final Route route) {
236 final UpdateBuilder ub = new UpdateBuilder();
237 final PathAttributesBuilder pab = new PathAttributesBuilder();
240 final MpReachNlriBuilder reach = new MpReachNlriBuilder(this.tableType);
242 addAdvertisement(reach, (D)route);
243 pab.fieldsFrom(route.getAttributes());
244 pab.addAugmentation(PathAttributes1.class, new PathAttributes1Builder().setMpReachNlri(reach.build()).build()).build();
246 final MpUnreachNlriBuilder unreach = new MpUnreachNlriBuilder(this.tableType);
247 addWithdrawal(unreach, (I)key);
248 pab.addAugmentation(PathAttributes2.class, new PathAttributes2Builder().setMpUnreachNlri(unreach.build()).build()).build();
251 ub.setPathAttributes(pab.build());