From: Madhu Venugopal Date: Sun, 10 Nov 2013 17:19:11 +0000 (-0800) Subject: Updating OpenFlow Node Description that is learnt from the OVSDB bridge table. X-Git-Tag: release/beryllium-sr2~1320 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=3f61b4c1428dd72708f9190e9a5638ce8ca26cfd;p=netvirt.git Updating OpenFlow Node Description that is learnt from the OVSDB bridge table. In order to compensate for a bug in the way Openflow plugin overrides a null value on the switchmanage node description, this fix also adds a scheduled reexecution of the description update message after a few seconds to make sure the updates are not lost. Change-Id: I605a2ff237d13cb72cdeb60ecf55ad19295c3133 Signed-off-by: Madhu Venugopal --- diff --git a/ovsdb/src/main/java/org/opendaylight/ovsdb/plugin/ConnectionService.java b/ovsdb/src/main/java/org/opendaylight/ovsdb/plugin/ConnectionService.java index 7449d6da7b..61f64b65f0 100755 --- a/ovsdb/src/main/java/org/opendaylight/ovsdb/plugin/ConnectionService.java +++ b/ovsdb/src/main/java/org/opendaylight/ovsdb/plugin/ConnectionService.java @@ -2,7 +2,13 @@ package org.opendaylight.ovsdb.plugin; import io.netty.bootstrap.Bootstrap; import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.*; +import io.netty.channel.AdaptiveRecvByteBufAllocator; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; @@ -12,6 +18,17 @@ import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import io.netty.util.CharsetUtil; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; + import org.opendaylight.controller.sal.connection.ConnectionConstants; import org.opendaylight.controller.sal.connection.IPluginInConnectionService; import org.opendaylight.controller.sal.core.Node; @@ -37,17 +54,6 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.util.concurrent.ListenableFuture; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ExecutionException; - /** * Represents the openflow plugin component in charge of programming the flows @@ -108,7 +114,7 @@ public class ConnectionService implements IPluginInConnectionService, IConnectio * the component are unregistered, this will be followed by a "destroy ()" * calls */ - void stop() { + void stopping() { for (Connection connection : ovsdbConnections.values()) { connection.disconnect(); } @@ -228,6 +234,7 @@ public class ConnectionService implements IPluginInConnectionService, IConnectio Connection connection; String identifier; + @Override public void run() { try { initializeInventoryForNewNode(connection); @@ -291,6 +298,7 @@ public class ConnectionService implements IPluginInConnectionService, IConnectio private void startOvsdbManager() { new Thread() { + @Override public void run() { ovsdbManager(); } diff --git a/ovsdb/src/main/java/org/opendaylight/ovsdb/plugin/InventoryService.java b/ovsdb/src/main/java/org/opendaylight/ovsdb/plugin/InventoryService.java index 86106166b4..f92eeed522 100755 --- a/ovsdb/src/main/java/org/opendaylight/ovsdb/plugin/InventoryService.java +++ b/ovsdb/src/main/java/org/opendaylight/ovsdb/plugin/InventoryService.java @@ -2,25 +2,35 @@ package org.opendaylight.ovsdb.plugin; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.opendaylight.controller.sal.core.ConstructionException; +import org.opendaylight.controller.sal.core.Description; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.core.Property; import org.opendaylight.controller.sal.core.UpdateType; import org.opendaylight.controller.sal.inventory.IPluginInInventoryService; import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService; +import org.opendaylight.controller.sal.utils.HexEncode; +import org.opendaylight.controller.sal.utils.ServiceHelper; import org.opendaylight.ovsdb.lib.database.DatabaseSchema; import org.opendaylight.ovsdb.lib.message.TableUpdate; import org.opendaylight.ovsdb.lib.message.TableUpdate.Row; import org.opendaylight.ovsdb.lib.message.TableUpdates; +import org.opendaylight.ovsdb.lib.notation.OvsDBSet; +import org.opendaylight.ovsdb.lib.table.Bridge; import org.opendaylight.ovsdb.lib.table.internal.Table; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.collect.Maps; @@ -37,6 +47,7 @@ public class InventoryService implements IPluginInInventoryService, InventorySer private ConcurrentMap> nodeProps; private ConcurrentMap> nodeConnectorProps; private Map dbCache = Maps.newHashMap(); + private ScheduledExecutorService executor; /** * Function called by the dependency manager when all the required @@ -48,6 +59,7 @@ public class InventoryService implements IPluginInInventoryService, InventorySer nodeConnectorProps = new ConcurrentHashMap>(); Node.NodeIDType.registerIDType("OVS", String.class); NodeConnector.NodeConnectorIDType.registerIDType("OVS", String.class, "OVS"); + this.executor = Executors.newSingleThreadScheduledExecutor(); } /** @@ -74,6 +86,7 @@ public class InventoryService implements IPluginInInventoryService, InventorySer * */ public void stop() { + this.executor.shutdownNow(); } public void setPluginOutInventoryServices(IPluginOutInventoryService service) { @@ -164,6 +177,14 @@ public class InventoryService implements IPluginInInventoryService, InventorySer Table oldRow = (Table)row.getOld(); if (newRow != null) { db.updateRow(name.getName(), uuid, newRow); + if (name.getName().equalsIgnoreCase("bridge")) { + logger.debug("Received Bridge Table udpate for node {}", n); + // OVSDB has the Bridge name info while OpenFlow Spec is not + // Clear on that. From a user/manageability standpoint, it is easier + // to handle Bridge names compared to dpids. + // Updating the Openflow bridge name via the SAL Description update. + updateOFBridgeName(n, (Bridge)newRow); + } } else if (oldRow != null) { db.removeRow(name.getName(), uuid); } @@ -171,6 +192,42 @@ public class InventoryService implements IPluginInInventoryService, InventorySer } } + private void updateOFBridgeName(final Node node, final Bridge bridge) { + Runnable updateNameRunnable = new Runnable() { + @Override + public void run() { + OvsDBSet dpids = bridge.getDatapath_id(); + String bridgeName = bridge.getName(); + if (dpids == null || bridgeName == null) return; + for (String dpid : dpids) { + Long dpidLong = Long.valueOf(HexEncode.stringToLong(dpid)); + try { + Node ofNode = new Node(Node.NodeIDType.OPENFLOW, dpidLong); + Description descProp = new Description(bridgeName); + Set props = new HashSet(); + props.add(descProp); + + IPluginOutInventoryService salInventoryService = (IPluginOutInventoryService) ServiceHelper.getInstance( + IPluginOutInventoryService.class, "default", this); + if (salInventoryService != null) { + logger.debug("Updating Bridge Name {} on OF node {}", bridgeName, ofNode); + salInventoryService.updateNode(ofNode, UpdateType.CHANGED, props); + } else { + logger.error("Error accessing SAL Inventory plugin"); + } + } catch (ConstructionException e) { + e.printStackTrace(); + } + } + } + }; + executor.execute(updateNameRunnable); + // Add a delay & re-execute to compensate for the current OpenFlow plugin bug of + // overriding the Description with a Null value after the first statistics timer. + // Hopefully this will be resolved in the newer version of the Openflow plugin. + executor.schedule(updateNameRunnable, 30, TimeUnit.SECONDS); + } + @Override public void printCache(Node n) { NodeDB db = dbCache.get(n);