BUG-2982 : moved path-attributes container to grouping
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / protocol / bgp / rib / impl / BGPSynchronization.java
index c505fa661356a230e50baf57c8a7df0ce2146b1b..7024374e648ca80eb98ef441ceb6fb88113ebefe 100644 (file)
@@ -7,33 +7,26 @@
  */
 package org.opendaylight.protocol.bgp.rib.impl;
 
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
-
-import org.opendaylight.protocol.bgp.concepts.BGPObject;
-import org.opendaylight.protocol.bgp.parser.BGPLink;
-import org.opendaylight.protocol.bgp.parser.BGPNode;
-import org.opendaylight.protocol.bgp.parser.BGPPrefix;
-import org.opendaylight.protocol.bgp.parser.BGPRoute;
-import org.opendaylight.protocol.bgp.parser.BGPSession;
-import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
-import org.opendaylight.protocol.bgp.parser.BGPTableType;
-import org.opendaylight.protocol.bgp.parser.BGPUpdateMessage;
-import org.opendaylight.protocol.bgp.parser.BGPUpdateSynchronized;
-import org.opendaylight.protocol.bgp.util.BGPIPv4RouteImpl;
-import org.opendaylight.protocol.bgp.util.BGPIPv6RouteImpl;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.LinkstateAddressFamily;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev130918.LinkstateSubsequentAddressFamily;
+import org.opendaylight.protocol.bgp.rib.spi.BGPSession;
+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.message.rev130919.UpdateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.AttributesBuilder;
+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.multiprotocol.rev130919.Attributes2Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlriBuilder;
+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.Ipv6AddressFamily;
 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
@@ -41,96 +34,116 @@ 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<BGPTableType, SyncVariables> syncStorage = Maps.newHashMap();
-
-       private final BGPSessionListener listener;
-
-       private final BGPSession session;
-
-       public BGPSynchronization(final BGPSession session, final BGPSessionListener listener, final Set<BGPTableType> types) {
-               this.listener = Preconditions.checkNotNull(listener);
-               this.session = Preconditions.checkNotNull(session);
-
-               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 BGPUpdateMessage msg) {
-               BGPTableType type = null;
-               if (!msg.getAddedObjects().isEmpty()) {
-                       final BGPObject obj = msg.getAddedObjects().iterator().next();
-                       if (obj instanceof BGPRoute) {
-                               if ((BGPRoute) obj instanceof BGPIPv4RouteImpl) {
-                                       type = new BGPTableType(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
-                               } else if ((BGPRoute) obj instanceof BGPIPv6RouteImpl) {
-                                       type = new BGPTableType(Ipv6AddressFamily.class, UnicastSubsequentAddressFamily.class);
-                               }
-                       } else if (obj instanceof BGPLink || obj instanceof BGPNode || obj instanceof BGPPrefix<?>) {
-                               type = new BGPTableType(LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class);
-                       }
-               }
-               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<BGPTableType, SyncVariables> entry : this.syncStorage.entrySet()) {
-                       final SyncVariables s = entry.getValue();
-                       if (!s.getEor()) {
-                               if (!s.getUpd()) {
-                                       s.setEorTrue();
-                                       final BGPUpdateSynchronized up = generateEOR(entry.getKey());
-                                       logger.debug("Sending synchronization message: {}", up);
-                                       this.listener.onMessage(this.session, up);
-                               }
-                               s.setUpd(false);
-                       }
-               }
-       }
-
-       private BGPUpdateSynchronized generateEOR(final BGPTableType type) {
-               return new BGPUpdateSynchronizedImpl(type);
-       }
+    private static final Logger LOG = 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<TablesKey, SyncVariables> syncStorage = Maps.newHashMap();
+
+    private final BGPSessionListener listener;
+
+    private final BGPSession session;
+
+    public BGPSynchronization(final BGPSession bgpSession, final BGPSessionListener listener, final Set<TablesKey> types) {
+        this.listener = Preconditions.checkNotNull(listener);
+        this.session = Preconditions.checkNotNull(bgpSession);
+
+        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;
+            }
+        }
+        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();
+            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<TablesKey, SyncVariables> 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());
+                    final Update up = generateEOR(entry.getKey());
+                    LOG.debug("Sending synchronization message: {}", up);
+                    this.listener.onMessage(this.session, up);
+                }
+                s.setUpd(false);
+            }
+        }
+    }
+
+    private Update generateEOR(final TablesKey type) {
+        return new UpdateBuilder().setAttributes(
+                new AttributesBuilder().addAugmentation(
+                        Attributes2.class,
+                        new Attributes2Builder().setMpUnreachNlri(
+                                new MpUnreachNlriBuilder().setAfi(type.getAfi()).setSafi(type.getSafi()).build()).build()).build()).build();
+    }
 }