X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=bgp%2Frib-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fprotocol%2Fbgp%2Frib%2Fimpl%2FBGPPeer.java;h=a605c773eb8e7682548422b08167d68b6fc07e36;hb=8f08616218159ae4ede961f38b9227cc9fa1cabe;hp=b7f4f39d5139b3292f8b88f88d35b122600b43f1;hpb=6cbac58169704455a9732765ae797d03640c6f6d;p=bgpcep.git diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java index b7f4f39d51..a605c773eb 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java @@ -1,17 +1,35 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ + package org.opendaylight.protocol.bgp.rib.impl; +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.net.InetAddresses; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; import java.util.Set; - -import org.opendaylight.protocol.bgp.parser.BGPSession; -import org.opendaylight.protocol.bgp.parser.BGPSessionListener; -import org.opendaylight.protocol.bgp.parser.BGPTerminationReason; +import javax.annotation.concurrent.GuardedBy; +import org.opendaylight.controller.config.yang.bgp.rib.impl.BGPPeerRuntimeMXBean; +import org.opendaylight.controller.config.yang.bgp.rib.impl.BGPPeerRuntimeRegistration; +import org.opendaylight.controller.config.yang.bgp.rib.impl.BGPPeerRuntimeRegistrator; +import org.opendaylight.controller.config.yang.bgp.rib.impl.BgpPeerState; +import org.opendaylight.controller.config.yang.bgp.rib.impl.BgpSessionState; +import org.opendaylight.controller.config.yang.bgp.rib.impl.RouteTable; +import org.opendaylight.protocol.bgp.rib.impl.spi.AdjRIBsOutRegistration; +import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionStatistics; +import org.opendaylight.protocol.bgp.rib.impl.spi.RIB; +import org.opendaylight.protocol.bgp.rib.impl.spi.ReusableBGPPeer; +import org.opendaylight.protocol.bgp.rib.spi.BGPSession; +import org.opendaylight.protocol.bgp.rib.spi.BGPTerminationReason; import org.opendaylight.protocol.bgp.rib.spi.Peer; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Update; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType; @@ -20,73 +38,180 @@ import org.opendaylight.yangtools.yang.binding.Notification; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.base.Objects; -import com.google.common.base.Objects.ToStringHelper; -import com.google.common.base.Preconditions; -import com.google.common.collect.Sets; /** * Class representing a peer. We have a single instance for each peer, which provides translation from BGP events into * RIB actions. */ -public final class BGPPeer implements BGPSessionListener, Peer { - private static final Logger logger = LoggerFactory.getLogger(BGPPeer.class); - private final Set tables = Sets.newHashSet(); - private final String name; - private final RIBImpl rib; - - public BGPPeer(final RIBImpl rib, final String name) { - this.rib = Preconditions.checkNotNull(rib); - this.name = Preconditions.checkNotNull(name); - } - - @Override - public void onMessage(final BGPSession session, final Notification message) { - if (message instanceof Update) { - this.rib.updateTables(this, (Update) message); - } else { - logger.info("Ignoring unhandled message class " + message.getClass()); - } - } - - @Override - public void onSessionUp(final BGPSession session) { - logger.info("Session with peer {} went up with tables: {}", this.name, session.getAdvertisedTableTypes()); - - for (final BgpTableType t : session.getAdvertisedTableTypes()) { - this.tables.add(new TablesKey(t.getAfi(), t.getSafi())); - } - } - - private void cleanup() { - // FIXME: support graceful restart - for (final TablesKey key : this.tables) { - this.rib.clearTable(this, key); - } - - this.tables.clear(); - } - - @Override - public void onSessionDown(final BGPSession session, final Exception e) { - logger.info("Session with peer {} went down", this.name, e); - cleanup(); - } - - @Override - public void onSessionTerminated(final BGPSession session, final BGPTerminationReason cause) { - logger.info("Session with peer {} terminated: {}", this.name, cause); - cleanup(); - } - - @Override - public final String toString() { - return addToStringAttributes(Objects.toStringHelper(this)).toString(); - } - - protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) { - toStringHelper.add("name", this.name); - toStringHelper.add("tables", this.tables); - return toStringHelper; - } +public class BGPPeer implements ReusableBGPPeer, Peer, AutoCloseable, BGPPeerRuntimeMXBean { + + private static final Logger LOG = LoggerFactory.getLogger(BGPPeer.class); + + @GuardedBy("this") + private final Set tables = new HashSet<>(); + private final RIB rib; + private final String name; + + @GuardedBy("this") + private BGPSession session; + @GuardedBy("this") + private byte[] rawIdentifier; + @GuardedBy("this") + private AdjRIBsOutRegistration reg; + + private BGPPeerRuntimeRegistrator registrator; + private BGPPeerRuntimeRegistration runtimeReg; + private long sessionEstablishedCounter = 0L; + + public BGPPeer(final String name, final RIB rib) { + this.rib = Preconditions.checkNotNull(rib); + this.name = name; + } + + @Override + public synchronized void close() { + dropConnection(); + // TODO should this perform cleanup ? + } + + @Override + public void onMessage(final BGPSession session, final Notification message) { + if (message instanceof Update) { + this.rib.updateTables(this, (Update) message); + } else { + LOG.info("Ignoring unhandled message class {}", message.getClass()); + } + } + + @Override + public synchronized void onSessionUp(final BGPSession session) { + LOG.info("Session with peer {} went up with tables: {}", this.name, session.getAdvertisedTableTypes()); + + this.session = session; + this.rawIdentifier = InetAddresses.forString(session.getBgpId().getValue()).getAddress(); + + for (final BgpTableType t : session.getAdvertisedTableTypes()) { + final TablesKey key = new TablesKey(t.getAfi(), t.getSafi()); + + this.tables.add(key); + this.rib.initTable(this, key); + } + + // Not particularly nice, but what can + if (session instanceof BGPSessionImpl) { + this.reg = this.rib.registerRIBsOut(this, new SessionRIBsOut((BGPSessionImpl) session)); + } + this.sessionEstablishedCounter++; + if (this.registrator != null) { + this.runtimeReg = this.registrator.register(this); + } + } + + private synchronized void cleanup() { + // FIXME: BUG-196: support graceful restart + for (final TablesKey key : this.tables) { + this.rib.clearTable(this, key); + } + + if (this.reg != null) { + this.reg.close(); + this.reg = null; + } + + this.tables.clear(); + } + + @Override + public void onSessionDown(final BGPSession session, final Exception e) { + LOG.info("Session with peer {} went down", this.name, e); + releaseConnection(); + } + + @Override + public void onSessionTerminated(final BGPSession session, final BGPTerminationReason cause) { + LOG.info("Session with peer {} terminated: {}", this.name, cause); + releaseConnection(); + } + + @Override + public String toString() { + return addToStringAttributes(Objects.toStringHelper(this)).toString(); + } + + protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) { + toStringHelper.add("name", this.name); + toStringHelper.add("tables", this.tables); + return toStringHelper; + } + + @Override + public String getName() { + return this.name; + } + + protected RIB getRib() { + return this.rib; + } + + @Override + public void releaseConnection() { + dropConnection(); + cleanup(); + } + + @GuardedBy("this") + private void dropConnection() { + if (this.runtimeReg != null) { + this.runtimeReg.close(); + this.runtimeReg = null; + } + if (this.session != null) { + this.session.close(); + this.session = null; + } + } + + @Override + public synchronized byte[] getRawIdentifier() { + return Arrays.copyOf(this.rawIdentifier, this.rawIdentifier.length); + } + + @Override + public void resetSession() { + releaseConnection(); + } + + @Override + public void resetStats() { + if (this.session instanceof BGPSessionStatistics) { + ((BGPSessionStatistics) this.session).resetSessionStats(); + } + } + + public synchronized void registerRootRuntimeBean(final BGPPeerRuntimeRegistrator registrator) { + this.registrator = registrator; + } + + @Override + public BgpSessionState getBgpSessionState() { + if (this.session instanceof BGPSessionStatistics) { + return ((BGPSessionStatistics) this.session).getBgpSesionState(); + } + return new BgpSessionState(); + } + + @Override + public synchronized BgpPeerState getBgpPeerState() { + final BgpPeerState peerState = new BgpPeerState(); + final List routes = Lists.newArrayList(); + for (final TablesKey tablesKey : this.tables) { + final RouteTable routeTable = new RouteTable(); + routeTable.setTableType("afi=" + tablesKey.getAfi().getSimpleName() + ",safi=" + tablesKey.getSafi().getSimpleName()); + routeTable.setRoutesCount(this.rib.getRoutesCount(tablesKey)); + routes.add(routeTable); + } + peerState.setRouteTable(routes); + peerState.setSessionEstablishedCount(this.sessionEstablishedCounter); + return peerState; + } }