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%2FBGPSynchronization.java;h=5e13956fc174a2e007b7273c3e97ea5b022cc7e3;hb=5ddbbec3193f9dfcbb980379a5454b70fe4847ea;hp=65d6676db60d372bfdba5e588b365c58148de6e1;hpb=7491b3120092f96f4aad83507b533f9575942ab9;p=bgpcep.git diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSynchronization.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSynchronization.java index 65d6676db6..5e13956fc1 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSynchronization.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPSynchronization.java @@ -7,29 +7,23 @@ */ package org.opendaylight.protocol.bgp.rib.impl; +import static java.util.Objects.requireNonNull; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Maps; import java.util.Map; import java.util.Map.Entry; import java.util.Set; - -import org.opendaylight.protocol.bgp.parser.BGPSession; -import org.opendaylight.protocol.bgp.parser.BGPSessionListener; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.Update; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.UpdateBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributesBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.BgpTableType; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.PathAttributes1; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.PathAttributes1Builder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.PathAttributes2; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130918.update.path.attributes.MpReachNlriBuilder; +import org.opendaylight.protocol.bgp.rib.spi.BGPSessionListener; +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.Attributes1; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes2; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; - /** * BGP speaker (without Graceful restart capability) sends KeepAlive message after sending all initial Update messages * with certain AFI/SAFI. For each AFI/SAFI, it sends one KA message. As it is undetermined which KA message belongs to @@ -37,100 +31,110 @@ import com.google.common.collect.Maps; */ public class BGPSynchronization { - private static final Logger logger = LoggerFactory.getLogger(BGPSynchronization.class); - - private static class SyncVariables { - - private boolean upd = false; - private boolean eor = false; - - public void setUpd(final boolean upd) { - this.upd = upd; - } - - public void setEorTrue() { - this.eor = true; - } - - public boolean getEor() { - return this.eor; - } - - public boolean getUpd() { - return this.upd; - } - } - - private final Map syncStorage = Maps.newHashMap(); - - private final BGPSessionListener listener; - - private final BGPSession session; - - public BGPSynchronization(final BGPSession bgpSession, final BGPSessionListener listener, final Set types) { - this.listener = Preconditions.checkNotNull(listener); - this.session = Preconditions.checkNotNull(bgpSession); - - for (final BgpTableType type : types) { - this.syncStorage.put(type, new SyncVariables()); - } - } - - /** - * For each received Update message, the upd sync variable needs to be updated to true, for particular AFI/SAFI - * combination. Currently we only assume Unicast SAFI. From the Update message we have to extract the AFI. Each - * Update message can contain BGP Object with one type of AFI. If the object is BGP Link, BGP Node or BGPPrefix - * the AFI is Linkstate. In case of BGPRoute, the AFI depends on the IP Address of the prefix. - * - * @param msg received Update message - */ - public void updReceived(final Update msg) { - TablesKey type = null; - if (msg.getNlri() != null || msg.getWithdrawnRoutes() != null) { - type = new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class); - } else if (msg.getPathAttributes().getAugmentation(PathAttributes1.class) != null) { - PathAttributes1 pa = msg.getPathAttributes().getAugmentation(PathAttributes1.class); - if (pa.getMpReachNlri() != null) { - type = new TablesKey(pa.getMpReachNlri().getAfi(), pa.getMpReachNlri().getSafi()); - } - } else if (msg.getPathAttributes().getAugmentation(PathAttributes2.class) != null) { - PathAttributes2 pa = msg.getPathAttributes().getAugmentation(PathAttributes2.class); - if (pa.getMpUnreachNlri() != null) { - type = new TablesKey(pa.getMpUnreachNlri().getAfi(), pa.getMpUnreachNlri().getSafi()); - } - } - final SyncVariables s = this.syncStorage.get(type); - if (s == null) { - logger.warn("BGPTableType was not present in open message : {}", type); - return; - } - s.setUpd(true); - } - - /** - * This method is called, when the second KA message is received. It checks each AFI/SAFI sync variables. If they - * are all false, which means, that there was at least one update message followed by one KA, the EOR is sent to - * session. - */ - public void kaReceived() { - for (final Entry entry : this.syncStorage.entrySet()) { - final SyncVariables s = entry.getValue(); - if (!s.getEor()) { - if (!s.getUpd()) { - s.setEorTrue(); - final Update up = generateEOR(entry.getKey()); - logger.debug("Sending synchronization message: {}", up); - this.listener.onMessage(this.session, up); - } - s.setUpd(false); - } - } - } - - private Update generateEOR(final BgpTableType type) { - if (type.getAfi().equals(Ipv4AddressFamily.class) && type.getSafi().equals(UnicastSubsequentAddressFamily.class)) { - return new UpdateBuilder().build(); - } - return new UpdateBuilder().setPathAttributes(new PathAttributesBuilder().addAugmentation(PathAttributes1.class, new PathAttributes1Builder().setMpReachNlri(new MpReachNlriBuilder().setAfi(type.getAfi()).setSafi(type.getSafi()).build()).build()).build()).build(); - } + private static final Logger LOG = LoggerFactory.getLogger(BGPSynchronization.class); + + @VisibleForTesting + static class SyncVariables { + + private boolean upd = false; + private boolean eor = false; + + public void setUpd(final boolean upd) { + this.upd = upd; + } + + public void setEorTrue() { + this.eor = true; + } + + public boolean getEor() { + return this.eor; + } + + public boolean getUpd() { + return this.upd; + } + } + + @VisibleForTesting + public final Map syncStorage = Maps.newHashMap(); + + private final BGPSessionListener listener; + + public BGPSynchronization(final BGPSessionListener listener, final Set types) { + this.listener = requireNonNull(listener); + + for (final TablesKey type : types) { + this.syncStorage.put(type, new SyncVariables()); + } + } + + /** + * For each received Update message, the upd sync variable needs to be updated to true, for particular AFI/SAFI + * combination. Currently we only assume Unicast SAFI. From the Update message we have to extract the AFI. Each + * Update message can contain BGP Object with one type of AFI. If the object is BGP Link, BGP Node or a BGPPrefix + * the AFI is Linkstate. In case of BGPRoute, the AFI depends on the IP Address of the prefix. + * + * @param msg received Update message + */ + public void updReceived(final Update msg) { + TablesKey type = new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class); + boolean isEOR = false; + if (msg.getNlri() == null && msg.getWithdrawnRoutes() == null) { + if (msg.getAttributes() != null) { + if (msg.getAttributes().getAugmentation(Attributes1.class) != null) { + final Attributes1 pa = msg.getAttributes().getAugmentation(Attributes1.class); + if (pa.getMpReachNlri() != null) { + type = new TablesKey(pa.getMpReachNlri().getAfi(), pa.getMpReachNlri().getSafi()); + } + } else if (msg.getAttributes().getAugmentation(Attributes2.class) != null) { + final Attributes2 pa = msg.getAttributes().getAugmentation(Attributes2.class); + if (pa.getMpUnreachNlri() != null) { + type = new TablesKey(pa.getMpUnreachNlri().getAfi(), pa.getMpUnreachNlri().getSafi()); + } + if (pa.getMpUnreachNlri().getWithdrawnRoutes() == null) { + // EOR message contains only MPUnreach attribute and no NLRI + isEOR = true; + } + } + } else { + // true for empty Update Message + isEOR = true; + } + } + syncType(type, isEOR); + } + + private void syncType(final TablesKey type, final boolean isEOR) { + final SyncVariables s = this.syncStorage.get(type); + if (s == null) { + LOG.warn("BGPTableType was not present in open message : {}", type); + return; + } + s.setUpd(true); + if (isEOR) { + s.setEorTrue(); + this.listener.markUptodate(type); + LOG.info("BGP Synchronization finished for table {} ", type); + } + } + + /** + * This method is called, when the second KA message is received. It checks each AFI/SAFI sync variables. If they + * are all false, which means, that there was at least one update message followed by one KA, the EOR is sent to + * session. + */ + public void kaReceived() { + for (final Entry entry : this.syncStorage.entrySet()) { + final SyncVariables s = entry.getValue(); + if (!s.getEor()) { + if (!s.getUpd()) { + s.setEorTrue(); + LOG.info("BGP Synchronization finished for table {} ", entry.getKey()); + this.listener.markUptodate(entry.getKey()); + } + s.setUpd(false); + } + } + } }