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;
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;
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
* the component are unregistered, this will be followed by a "destroy ()"
* calls
*/
- void stop() {
+ void stopping() {
for (Connection connection : ovsdbConnections.values()) {
connection.disconnect();
}
Connection connection;
String identifier;
+ @Override
public void run() {
try {
initializeInventoryForNewNode(connection);
private void startOvsdbManager() {
new Thread() {
+ @Override
public void run() {
ovsdbManager();
}
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;
private ConcurrentMap<Node, Map<String, Property>> nodeProps;
private ConcurrentMap<NodeConnector, Map<String, Property>> nodeConnectorProps;
private Map<Node, NodeDB> dbCache = Maps.newHashMap();
+ private ScheduledExecutorService executor;
/**
* Function called by the dependency manager when all the required
nodeConnectorProps = new ConcurrentHashMap<NodeConnector, Map<String, Property>>();
Node.NodeIDType.registerIDType("OVS", String.class);
NodeConnector.NodeConnectorIDType.registerIDType("OVS", String.class, "OVS");
+ this.executor = Executors.newSingleThreadScheduledExecutor();
}
/**
*
*/
public void stop() {
+ this.executor.shutdownNow();
}
public void setPluginOutInventoryServices(IPluginOutInventoryService service) {
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);
}
}
}
+ private void updateOFBridgeName(final Node node, final Bridge bridge) {
+ Runnable updateNameRunnable = new Runnable() {
+ @Override
+ public void run() {
+ OvsDBSet<String> 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<Property> props = new HashSet<Property>();
+ 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);