package org.opendaylight.openflowplugin.applications.frm.impl;
+import java.util.concurrent.atomic.AtomicInteger;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesManager;
import org.opendaylight.openflowplugin.common.wait.SimpleTaskRetryLooper;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.StaleGroupKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeaturesKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.*;
-import java.util.concurrent.Callable;
/**
* forwardingrules-manager
private final DataBroker dataBroker;
private final ForwardingRulesManager provider;
+ public static final String SEPARATOR = ":";
private ListenerRegistration<DataChangeListener> listenerRegistration;
/* All DataObjects for remove */
final Set<InstanceIdentifier<?>> removeData = changeEvent.getRemovedPaths() != null
? changeEvent.getRemovedPaths() : Collections.<InstanceIdentifier<?>> emptySet();
+ /* All updated DataObjects */
+ final Map<InstanceIdentifier<?>, DataObject> updateData = changeEvent.getUpdatedData() != null
+ ? changeEvent.getUpdatedData() : Collections.<InstanceIdentifier<?>, DataObject>emptyMap();
for (InstanceIdentifier<?> entryKey : removeData) {
final InstanceIdentifier<FlowCapableNode> nodeIdent = entryKey
flowNodeConnected(nodeIdent);
}
}
+
+ // FIXME: just a hack to cover DS/operational dirty start
+ // if all conventional ways failed and there is update
+ if (removeData.isEmpty() && createdData.isEmpty() && updateData.size() == 1) {
+ for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : updateData.entrySet()) {
+ // and only if this update covers top element (flow-capable-node)
+ if (FlowCapableNode.class.equals(entry.getKey().getTargetType())) {
+ final InstanceIdentifier<FlowCapableNode> nodeIdent = entry.getKey()
+ .firstIdentifierOf(FlowCapableNode.class);
+ if (!nodeIdent.isWildcarded()) {
+ // then force registration to local node cache and reconcile
+ flowNodeConnected(nodeIdent, true);
+ }
+ }
+ }
+ }
}
@Override
@Override
public void flowNodeConnected(InstanceIdentifier<FlowCapableNode> connectedNode) {
- if ( ! provider.isNodeActive(connectedNode)) {
+ flowNodeConnected(connectedNode, false);
+ }
+
+ private void flowNodeConnected(InstanceIdentifier<FlowCapableNode> connectedNode, boolean force) {
+ if (force || !provider.isNodeActive(connectedNode)) {
provider.registrateNewNode(connectedNode);
+
+ if(!provider.isNodeOwner(connectedNode)) { return; }
+
if (provider.getConfiguration().isStaleMarkingEnabled()) {
LOG.info("Stale-Marking is ENABLED and proceeding with deletion of stale-marked entities on switch {}",
connectedNode.toString());
private void reconciliation(final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+ String sNode = nodeIdent.firstKeyOf(Node.class, NodeKey.class).getId().getValue();
+ long nDpId = getDpnIdFromNodeName(sNode);
+
ReadOnlyTransaction trans = provider.getReadTranaction();
Optional<FlowCapableNode> flowNode = Optional.absent();
+ AtomicInteger counter = new AtomicInteger();
+ //initialize the counter
+ counter.set(0);
try {
flowNode = trans.read(LogicalDatastoreType.CONFIGURATION, nodeIdent).get();
}
if (flowNode.isPresent()) {
/* Tables - have to be pushed before groups */
// CHECK if while pusing the update, updateTableInput can be null to emulate a table add
- List<Table> tableList = flowNode.get().getTable() != null
- ? flowNode.get().getTable() : Collections.<Table> emptyList() ;
- for (Table table : tableList) {
- TableKey tableKey = table.getKey();
+ List<TableFeatures> tableList = flowNode.get().getTableFeatures() != null
+ ? flowNode.get().getTableFeatures() : Collections.<TableFeatures> emptyList() ;
+ for (TableFeatures tableFeaturesItem : tableList) {
+ TableFeaturesKey tableKey = tableFeaturesItem.getKey();
KeyedInstanceIdentifier<TableFeatures, TableFeaturesKey> tableFeaturesII
- = nodeIdent.child(Table.class, tableKey).child(TableFeatures.class, new TableFeaturesKey(tableKey.getId()));
- List<TableFeatures> tableFeatures = table.getTableFeatures();
- if (tableFeatures != null) {
- for (TableFeatures tableFeaturesItem : tableFeatures) {
+ = nodeIdent.child(TableFeatures.class, new TableFeaturesKey(tableKey.getTableId()));
provider.getTableFeaturesCommiter().update(tableFeaturesII, tableFeaturesItem, null, nodeIdent);
- }
- }
}
/* Groups - have to be first */
List<Group> toBeInstalledGroups = new ArrayList<>();
toBeInstalledGroups.addAll(groups);
List<Long> alreadyInstalledGroupids = new ArrayList<>();
+ //new list for suspected groups pointing to ports .. when the ports come up late
+ List<Group> suspectedGroups = new ArrayList<>();
+
+ while ((!(toBeInstalledGroups.isEmpty()) || !(suspectedGroups.isEmpty())) &&
+ (counter.get()<=provider.getConfiguration().getReconciliationRetryCount())) { //also check if the counter has not crossed the threshold
+
+ if(toBeInstalledGroups.isEmpty() && ! suspectedGroups.isEmpty()){
+ LOG.error("These Groups are pointing to node-connectors that are not up yet {}",suspectedGroups.toString());
+ toBeInstalledGroups.addAll(suspectedGroups);
+ break;
+ }
- while (!toBeInstalledGroups.isEmpty()) {
ListIterator<Group> iterator = toBeInstalledGroups.listIterator();
while (iterator.hasNext()) {
Group group = iterator.next();
boolean okToInstall = true;
for (Bucket bucket : group.getBuckets().getBucket()) {
for (Action action : bucket.getAction()) {
+ //chained-port
if (action.getAction().getImplementedInterface().getName()
+ .equals("org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase")){
+ String nodeConnectorUri = ((OutputActionCase)(action.getAction()))
+ .getOutputAction().getOutputNodeConnector().getValue();
+
+ LOG.warn("Installing the group for node connector {}",nodeConnectorUri);
+
+ //check if the nodeconnector is there in the multimap
+ boolean isPresent = provider.getFlowNodeConnectorInventoryTranslatorImpl()
+ .isNodeConnectorUpdated(nDpId, nodeConnectorUri);
+ //if yes set okToInstall = true
+
+ if(isPresent){
+ break;
+ }//else put it in a different list and still set okToInstall = true
+ else {
+ suspectedGroups.add(group);
+ LOG.error("Not yet received the node-connector updated for {} " +
+ "for the group with id {}",nodeConnectorUri,group.getGroupId().toString());
+ break;
+ }
+
+
+ }
+ //chained groups
+ else if (action.getAction().getImplementedInterface().getName()
.equals("org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCase")) {
Long groupId = ((GroupActionCase) (action.getAction())).getGroupAction().getGroupId();
if (!alreadyInstalledGroupids.contains(groupId)) {
}
}
if (!okToInstall){
+ //increment retry counter value
+ counter.incrementAndGet();
break;
}
+
+
+
}
this.provider.getGroupCommiter().add(groupIdent, group, nodeIdent);
alreadyInstalledGroupids.add(group.getGroupId().getValue());
iterator.remove();
+ // resetting the counter to zero
+ counter.set(0);
}
}
}
+
+ /* installation of suspected groups*/
+ if(!toBeInstalledGroups.isEmpty()){
+ for(Group group :toBeInstalledGroups){
+ LOG.error("Installing the group {} finally although the port is not up after checking for {} times "
+ ,group.getGroupId().toString(),provider.getConfiguration().getReconciliationRetryCount());
+ final KeyedInstanceIdentifier<Group, GroupKey> groupIdent =
+ nodeIdent.child(Group.class, group.getKey());
+ this.provider.getGroupCommiter().add(groupIdent, group, nodeIdent);
+ }
+ }
/* Meters */
List<Meter> meters = flowNode.get().getMeter() != null
? flowNode.get().getMeter() : Collections.<Meter> emptyList();
/* clean transaction */
trans.close();
}
-
-
+ private long getDpnIdFromNodeName(String nodeName) {
+ String dpId = nodeName.substring(nodeName.lastIndexOf(SEPARATOR) + 1);
+ return Long.parseLong(dpId);
+ }
private void reconciliationPreProcess(final InstanceIdentifier<FlowCapableNode> nodeIdent) {
final KeyedInstanceIdentifier<Group, GroupKey> groupIdent =
nodeIdent.child(Group.class, toBeDeletedGroup.getKey());
- this.provider.getGroupCommiter().add(groupIdent, toBeDeletedGroup, nodeIdent);
+ this.provider.getGroupCommiter().remove(groupIdent, toBeDeletedGroup, nodeIdent);
staleGroupsToBeBulkDeleted.add(getStaleGroupInstanceIdentifier(staleGroup, nodeIdent));
}
nodeIdent.child(Meter.class, toBeDeletedMeter.getKey());
- this.provider.getMeterCommiter().add(meterIdent, toBeDeletedMeter, nodeIdent);
+ this.provider.getMeterCommiter().remove(meterIdent, toBeDeletedMeter, nodeIdent);
staleMetersToBeBulkDeleted.add(getStaleMeterInstanceIdentifier(staleMeter, nodeIdent));
}