BUG-2383 : LocRib smal fixes + logs 31/17631/2
authorDana Kutenicsova <dkutenic@cisco.com>
Wed, 1 Apr 2015 15:37:56 +0000 (17:37 +0200)
committerDana Kutenicsova <dkutenic@cisco.com>
Thu, 2 Apr 2015 19:32:47 +0000 (21:32 +0200)
Change-Id: I911c9e0cf1eda3af4e45b73f7a4dd84e38ce3b14
Signed-off-by: Dana Kutenicsova <dkutenic@cisco.com>
bgp/controller-config/src/main/resources/initial/41-bgp-example.xml
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibInWriter.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BestPathSelector.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BestPathState.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/LocRibWriter.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RouteEntry.java

index ecade95933e64549a8e355a27dad85846ad2ef38..3d1026ebe7df0525cc8cfa871b244e1ac6792215 100644 (file)
                     </data-provider>
                     <dom-data-provider>
                         <type xmlns:sal="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">sal:dom-async-data-broker</type>
-                        <name>pingpong-broker</name>
+                        <name>inmemory-data-broker</name>
                     </dom-data-provider>
                     <codec-tree-factory>
                         <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-codec-tree-factory</type>
index 7d2ea4ed4be5ec5335f8ab2428a5ddd33823c01e..cf254619537646b2a7c2192a17c2ccdb717d9e54 100644 (file)
@@ -30,6 +30,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.Peer;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.AdjRibIn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.AdjRibOut;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.EffectiveRibIn;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
@@ -61,6 +62,7 @@ final class AdjRibInWriter {
     private static final QName PEER_ID_QNAME = QName.cachedReference(QName.create(Peer.QNAME, "peer-id"));
     private static final QName PEER_ROLE_QNAME = QName.cachedReference(QName.create(Peer.QNAME, "peer-role"));
     private static final NodeIdentifier ADJRIBIN = new NodeIdentifier(AdjRibIn.QNAME);
+    private static final NodeIdentifier ADJRIBOUT = new NodeIdentifier(AdjRibOut.QNAME);
     private static final NodeIdentifier EFFRIBIN = new NodeIdentifier(EffectiveRibIn.QNAME);
     private static final NodeIdentifier PEER_ID = new NodeIdentifier(PEER_ID_QNAME);
     private static final NodeIdentifier PEER_ROLE = new NodeIdentifier(PEER_ROLE_QNAME);
@@ -69,6 +71,7 @@ final class AdjRibInWriter {
     // FIXME: is there a utility method to construct this?
     private static final ContainerNode EMPTY_ADJRIBIN = Builders.containerBuilder().withNodeIdentifier(ADJRIBIN).addChild(ImmutableNodes.mapNodeBuilder(Tables.QNAME).build()).build();
     private static final ContainerNode EMPTY_EFFRIBIN = Builders.containerBuilder().withNodeIdentifier(EFFRIBIN).addChild(ImmutableNodes.mapNodeBuilder(Tables.QNAME).build()).build();
+    private static final ContainerNode EMPTY_ADJRIBOUT = Builders.containerBuilder().withNodeIdentifier(ADJRIBOUT).addChild(ImmutableNodes.mapNodeBuilder(Tables.QNAME).build()).build();
 
     private final Map<TablesKey, TableContext> tables;
     private final YangInstanceIdentifier tablesRoot;
@@ -144,6 +147,7 @@ final class AdjRibInWriter {
             pb.withChild(ImmutableNodes.leafNode(PEER_ROLE, this.role));
             pb.withChild(EMPTY_ADJRIBIN);
             pb.withChild(EMPTY_EFFRIBIN);
+            pb.withChild(EMPTY_ADJRIBOUT);
 
             tx.put(LogicalDatastoreType.OPERATIONAL, newPeerPath, pb.build());
             LOG.debug("New peer {} structure installed.", newPeerPath);
index 279958b77cc8235b37317f606734e3377b85da92..d65ae1eb223a610e2a950205edd5983804f3c7f0 100644 (file)
@@ -22,8 +22,11 @@ import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 final class BestPathSelector {
+    private static final Logger LOG = LoggerFactory.getLogger(BestPathSelector.class);
     private static final Collection<PathArgument> ORIGINATOR_ID = ImmutableList.<PathArgument>of(new NodeIdentifier(OriginatorId.QNAME), new NodeIdentifier(QName.create(OriginatorId.QNAME, "originator")));
 
     private final Long ourAs;
@@ -57,7 +60,8 @@ final class BestPathSelector {
              * are better.
              */
             final BestPathState state = new BestPathState(attrs);
-            if (this.bestOriginatorId == null || selectPath(originatorId, state)) {
+            if (this.bestOriginatorId == null || !selectPath(originatorId, state)) {
+                LOG.trace("Selecting path from router {} state {}", routerId, state);
                 this.bestOriginatorId = originatorId;
                 this.bestRouterId = routerId;
                 this.bestState = state;
index e928ee4d459b8fc2094e04f978deab11f831fb0c..06f0c8fc97e6df94a51966dd440e8b5b933a3ad7 100644 (file)
@@ -157,4 +157,7 @@ final class BestPathState {
         return first.getAList().getAsSequence().get(0).getAs();
     }
 
+    ContainerNode getAttributes() {
+        return this.attributes;
+    }
 }
index 1b980323004836e9b341d78199ecfda5a2e3c296..3b0ed261e57790e91a3ff66e994585c160011440 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.protocol.bgp.rib.impl;
 
 import com.google.common.base.Preconditions;
 import com.google.common.primitives.UnsignedInteger;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
@@ -22,27 +23,42 @@ import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
 import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
+import org.opendaylight.protocol.bgp.rib.spi.RibSupportUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.Peer;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.EffectiveRibIn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
+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.rib.rev130925.rib.tables.Routes;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-// FIXME: instantiate for each table, listen on wildcard peer and routes
 @NotThreadSafe
 final class LocRibWriter implements AutoCloseable, DOMDataTreeChangeListener {
+
+    private static final Logger LOG = LoggerFactory.getLogger(LocRibWriter.class);
+
     private final Map<PathArgument, RouteEntry> routeEntries = new HashMap<>();
     private final YangInstanceIdentifier target;
     private final DOMTransactionChain chain;
     private final ExportPolicyPeerTracker peerPolicyTracker;
     private final NodeIdentifier attributesIdentifier;
     private final Long ourAs;
+    private final RIBSupport ribSupport;
 
     LocRibWriter(final RIBSupport ribSupport, final DOMTransactionChain chain, final YangInstanceIdentifier target, final Long ourAs,
         final DOMDataTreeChangeService service, final PolicyDatabase pd) {
@@ -51,13 +67,20 @@ final class LocRibWriter implements AutoCloseable, DOMDataTreeChangeListener {
         this.ourAs = Preconditions.checkNotNull(ourAs);
         this.attributesIdentifier = ribSupport.routeAttributesIdentifier();
         this.peerPolicyTracker = new ExportPolicyPeerTracker(service, target, pd);
+        this.ribSupport = ribSupport;
 
-        service.registerDataTreeChangeListener(new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, target.node(EffectiveRibIn.QNAME)), this);
+        service.registerDataTreeChangeListener(new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, target), this);
     }
 
-    public static LocRibWriter create(@Nonnull final RIBSupport ribSupport, @Nonnull final DOMTransactionChain chain, @Nonnull final YangInstanceIdentifier target,
+    public static LocRibWriter create(@Nonnull final RIBSupport ribSupport, @Nonnull final TablesKey tablesKey, @Nonnull final DOMTransactionChain chain, @Nonnull final YangInstanceIdentifier target,
         @Nonnull final AsNumber ourAs, @Nonnull final DOMDataTreeChangeService service, @Nonnull final PolicyDatabase pd) {
-        return new LocRibWriter(ribSupport, chain, target, ourAs.getValue(), service, pd);
+
+        final YangInstanceIdentifier tableId = target.node(Peer.QNAME).node(Peer.QNAME).node(EffectiveRibIn.QNAME).node(Tables.QNAME).node(RibSupportUtils.toYangTablesKey(tablesKey));
+
+        final QName list = BindingReflections.findQName(ribSupport.routesListClass());
+        final YangInstanceIdentifier routeId = tableId.node(Routes.QNAME).node(BindingReflections.findQName(ribSupport.routesContainerClass())).node(list);
+
+        return new LocRibWriter(ribSupport, chain, routeId, ourAs.getValue(), service, pd);
     }
 
     @Override
@@ -65,14 +88,30 @@ final class LocRibWriter implements AutoCloseable, DOMDataTreeChangeListener {
         this.peerPolicyTracker.close();
     }
 
+    private static void printChildren(final DataTreeCandidateNode root) {
+        LOG.debug("Candidate node {} type {} identifier {}", root, root.getModificationType(), root.getIdentifier());
+        if (ModificationType.WRITE.equals(root.getModificationType())) {
+            LOG.debug("Data after {}", root.getDataAfter());
+        }
+        if (root.getChildNodes().isEmpty()) {
+            return;
+        }
+        for (final DataTreeCandidateNode child : root.getChildNodes()) {
+            printChildren(child);
+        }
+    }
+
     @Override
     public void onDataTreeChanged(final Collection<DataTreeCandidate> changes) {
+        LOG.trace("Received data change to LocRib {}", Arrays.toString(changes.toArray()));
         /*
          * We use two-stage processing here in hopes that we avoid duplicate
          * calculations when multiple peers have changed a particular entry.
          */
         final Map<RouteUpdateKey, RouteEntry> toUpdate = new HashMap<>();
         for (final DataTreeCandidate tc : changes) {
+            printChildren(tc.getRootNode());
+
             final YangInstanceIdentifier path = tc.getRootPath();
             final PathArgument routeId = path.getLastPathArgument();
             final NodeIdentifierWithPredicates peerKey = IdentifierUtils.peerKey(path);
@@ -84,14 +123,19 @@ final class LocRibWriter implements AutoCloseable, DOMDataTreeChangeListener {
                 if (entry == null) {
                     entry = new RouteEntry();
                     this.routeEntries.put(routeId, entry);
+                    LOG.trace("Created new entry for {}", routeId);
                 }
 
-                entry.addRoute(routerId, (ContainerNode) tc.getRootNode().getDataAfter().get());
+                final ContainerNode advertisedAttrs = (ContainerNode) NormalizedNodes.findNode(tc.getRootNode().getDataAfter(), this.ribSupport.routeAttributesIdentifier()).orNull();
+                entry.addRoute(routerId, advertisedAttrs);
+                LOG.trace("Added route from {} attributes{}", routerId, advertisedAttrs);
             } else if (entry != null && entry.removeRoute(routerId)) {
                 this.routeEntries.remove(routeId);
                 entry = null;
+                LOG.trace("Removed route from {}", routerId);
             }
 
+            LOG.debug("Updated route {} entry {}", routeId, entry);
             toUpdate.put(new RouteUpdateKey(peerId, routeId), entry);
         }
 
@@ -99,23 +143,27 @@ final class LocRibWriter implements AutoCloseable, DOMDataTreeChangeListener {
 
         // Now walk all updated entries
         for (final Entry<RouteUpdateKey, RouteEntry> e : toUpdate.entrySet()) {
+            LOG.trace("Walking through {}", e);
             final RouteEntry entry = e.getValue();
             final NormalizedNode<?, ?> value;
 
             if (entry != null) {
                 if (!entry.selectBest(this.ourAs)) {
                     // Best path has not changed, no need to do anything else. Proceed to next route.
+                    LOG.trace("Continuing");
                     continue;
                 }
-
                 value = entry.bestValue(e.getKey().getRouteId());
+                LOG.trace("Selected best value {}", value);
             } else {
                 value = null;
             }
 
             if (value != null) {
+                LOG.debug("Write route to LocRib {}", value);
                 tx.put(LogicalDatastoreType.OPERATIONAL, this.target.node(e.getKey().getRouteId()), value);
             } else {
+                LOG.debug("Delete route from LocRib {}", entry);
                 tx.delete(LogicalDatastoreType.OPERATIONAL, this.target.node(e.getKey().getRouteId()));
             }
 
@@ -140,6 +188,7 @@ final class LocRibWriter implements AutoCloseable, DOMDataTreeChangeListener {
                         final YangInstanceIdentifier routeTarget = pid.getValue().node(e.getKey().getRouteId());
 
                         if (effectiveAttributes != null && value != null && !peerId.equals(pid.getKey())) {
+                            LOG.debug("Write route to AdjRibsOut {}", value);
                             tx.put(LogicalDatastoreType.OPERATIONAL, routeTarget, value);
                             tx.put(LogicalDatastoreType.OPERATIONAL, routeTarget.node(this.attributesIdentifier), effectiveAttributes);
                         } else {
index 78d4aaed73a8b01c445f24593044d9c601b28e68..1333790640b6aff536d907075d734a09125864d4 100644 (file)
@@ -230,7 +230,7 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
             // create locRibWriter for each table
             // FIXME: temporary create writer only for Ipv4
             if (key.getAfi().equals(Ipv4AddressFamily.class)) {
-                //LocRibWriter.create(this.ribContextRegistry.getRIBSupportContext(key).getRibSupport(), domChain, getYangRibId(), localAs, (DOMDataTreeChangeService) service, pd);
+                LocRibWriter.create(this.ribContextRegistry.getRIBSupportContext(key).getRibSupport(), key, domChain, getYangRibId(), localAs, (DOMDataTreeChangeService) service, pd);
             }
         }
     }
index 7768a6b5dbcf90fbcec263f75c05a011a98246d3..ba100e4c5e2211945bed9fadd8b63b19807e73e1 100644 (file)
@@ -10,9 +10,15 @@ package org.opendaylight.protocol.bgp.rib.impl;
 import com.google.common.primitives.UnsignedInteger;
 import java.util.Objects;
 import javax.annotation.concurrent.NotThreadSafe;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * A single route entry inside a route table. Maintains the attributes of
@@ -23,6 +29,9 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
  */
 @NotThreadSafe
 final class RouteEntry {
+
+    private static final Logger LOG = LoggerFactory.getLogger(RouteEntry.class);
+
     private static final ContainerNode[] EMPTY_ATTRIBUTES = new ContainerNode[0];
 
     private OffsetMap offsets = OffsetMap.EMPTY;
@@ -30,25 +39,25 @@ final class RouteEntry {
     private BestPath bestPath;
 
     void addRoute(final UnsignedInteger routerId, final ContainerNode attributes) {
-        int offset = offsets.offsetOf(routerId);
+        int offset = this.offsets.offsetOf(routerId);
         if (offset < 0) {
-            final OffsetMap newOffsets = offsets.with(routerId);
+            final OffsetMap newOffsets = this.offsets.with(routerId);
             offset = newOffsets.offsetOf(routerId);
 
-            final ContainerNode[] newAttributes = newOffsets.expand(offsets, this.values, offset);
+            final ContainerNode[] newAttributes = newOffsets.expand(this.offsets, this.values, offset);
             this.values = newAttributes;
             this.offsets = newOffsets;
         }
 
-        offsets.setValue(this.values, offset, attributes);
+        this.offsets.setValue(this.values, offset, attributes);
     }
 
     // Indicates whether this was the last route
     boolean removeRoute(final UnsignedInteger routerId) {
-        if (offsets.size() != 1) {
+        if (this.offsets.size() != 1) {
             // FIXME: actually shrink the array
-            int offset = offsets.offsetOf(routerId);
-            offsets.setValue(values, offset, null);
+            final int offset = this.offsets.offsetOf(routerId);
+            this.offsets.setValue(this.values, offset, null);
             return false;
         } else {
             return true;
@@ -66,21 +75,23 @@ final class RouteEntry {
         for (int i = 0; i < this.offsets.size(); ++i) {
             final UnsignedInteger routerId = this.offsets.getRouterId(i);
             final ContainerNode attributes = this.offsets.getValue(this.values, i);
-
+            LOG.trace("Processing router id {} attributes {}", routerId, attributes);
             selector.processPath(routerId, attributes);
         }
 
         // Get the newly-selected best path.
         final BestPath newBestPath = selector.result();
         // FIXME: run deeper comparison
-        final boolean ret = !Objects.equals(bestPath, newBestPath);
-
-        bestPath = newBestPath;
+        final boolean ret = !Objects.equals(this.bestPath, newBestPath);
+        LOG.trace("Previous best {}, current best {}, result {}", this.bestPath, newBestPath, ret);
+        this.bestPath = newBestPath;
         return ret;
     }
 
     NormalizedNode<?, ?> bestValue(final PathArgument key) {
-        // TODO Auto-generated method stub
-        return null;
+        final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> b = Builders.mapEntryBuilder();
+        b.withNodeIdentifier((NodeIdentifierWithPredicates) key);
+        b.addChild(this.bestPath.getState().getAttributes());
+        return b.build();
     }
 }