<tag>HEAD</tag>
</scm>
+ <properties>
+ <guava.version>14.0.1</guava.version>
+ <xtend.version>2.4.3</xtend.version>
+ <bundle.plugin.version>2.4.0</bundle.plugin.version>
+ <maven.clean.plugin.version>2.5</maven.clean.plugin.version>
+ </properties>
<build>
<plugins>
<plugin>
org.opendaylight.ovsdb.lib.notation,
org.opendaylight.ovsdb.lib.table,
org.opendaylight.ovsdb.lib.table.internal,
+ org.opendaylight.controller.sal.binding.api,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes,
+ org.opendaylight.yangtools.yang.binding,
org.apache.felix.dm,
org.slf4j,
- org.osgi.framework
+ org.osgi.framework,
+ *
</Import-Package>
<Bundle-Activator>
org.opendaylight.ovsdb.neutron.Activator
<artifactId>containermanager</artifactId>
<version>0.5.1-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-service</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-base</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-management</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-inventory</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-binding</artifactId>
+ <version>0.6.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-util</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
</dependencies>
</project>
--- /dev/null
+/*
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Authors : Madhu Venugopal
+ */
+
+package org.opendaylight.ovsdb.neutron;
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
+import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+public class MDSALConsumer implements BindingAwareConsumer, IMDSALConsumer {
+
+ private BundleContext ctx = null;
+ private BindingAwareBroker broker = null;
+ private ConsumerContext consumerContext = null;
+ private DataBrokerService dataBrokerService;
+
+ static final Logger logger = LoggerFactory.getLogger(MDSALConsumer.class);
+
+ void setBindingAwareBroker (BindingAwareBroker b) {
+ this.broker = b;
+ }
+
+ void unsetBindingAwareBroker(BindingAwareBroker b) {
+ if (this.broker == b) {
+ this.broker = null;
+ }
+ }
+
+ void init(Component c) {
+ this.ctx = c.getDependencyManager().getBundleContext();
+ logger.info("****** OVSDB Neutron Registered with MD-SAL ******");
+ broker.registerConsumer(this, this.ctx);
+ }
+
+ void destroy() {
+ // Now lets close MDSAL session
+ if (this.consumerContext != null) {
+ //this.consumerContext.close();
+ this.consumerContext = null;
+ }
+ }
+
+ void start() {
+ }
+
+ void stop() {
+ }
+
+ @Override
+ public void onSessionInitialized(ConsumerContext session) {
+ this.consumerContext = session;
+ dataBrokerService = session.getSALService(DataBrokerService.class);
+ logger.info("****** OVSDB Neutron Session Initilized with CONSUMER CONTEXT {} ******", session.toString());
+ }
+
+ @Override
+ public ConsumerContext getConsumerContext() {
+ return consumerContext;
+ }
+ @Override
+ public DataBrokerService getDataBrokerService() {
+ return dataBrokerService;
+ }
+}
*/
package org.opendaylight.ovsdb.neutron.provider;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.utils.HexEncode;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.ovsdb.lib.table.Bridge;
import org.opendaylight.ovsdb.lib.table.Interface;
+import org.opendaylight.ovsdb.neutron.AdminConfigManager;
+import org.opendaylight.ovsdb.neutron.IMDSALConsumer;
+import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
class OF13ProviderManager extends ProviderNetworkManager {
+ private static final Logger logger = LoggerFactory.getLogger(OF13ProviderManager.class);
+ private DataBrokerService dataBrokerService;
+
@Override
public boolean hasPerTenantTunneling() {
return false;
@Override
public void initializeFlowRules(Node node) {
+ this.initializeFlowRules(node, AdminConfigManager.getManager().getIntegrationBridgeName());
+ }
+
+ private void initializeFlowRules(Node node, String bridgeName) {
+ try {
+ // TODO : 3 second sleep hack is to make sure the OF connection is established.
+ // Correct fix is to check the MD-SAL inventory before proceeding and listen
+ // to Inventory update for processing.
+ Thread.sleep(3000);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ String brIntId = this.getInternalBridgeUUID(node, bridgeName);
+ if (brIntId == null) {
+ logger.error("Failed to initialize Flow Rules for {}", node);
+ return;
+ }
+
+ try {
+ OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+ Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId);
+ Set<String> dpids = bridge.getDatapath_id();
+ if (dpids == null || dpids.size() == 0) return;
+ Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
+ writeLLDPRule(dpidLong);
+ } catch (Exception e) {
+ logger.error("Failed to initialize Flow Rules for "+node.toString(), e);
+ }
+ }
+
+ private void writeLLDPRule(Long dpidLong) {
+ String nodeName = "openflow:"+dpidLong;
+ NodeBuilder tn = createNodeBuilder(nodeName);
+ FlowBuilder flow = new FlowBuilder();
+ flow.setMatch(createLLDPMatch().build());
+ flow.setInstructions(this.createSentToControllerInstructions().build());
+ // TODO : Investigate the need for this.
+ FlowKey key = new FlowKey(new FlowId(new Long(123)));
+ flow.setBarrier(false);
+ flow.setTableId((short)0);
+ flow.setKey(key);
+ flow.setFlowName("LLDP_" + nodeName);
+ writeFlow(flow, tn);
+ }
+
+ private void writeFlow(FlowBuilder flow, NodeBuilder nodeBuilder) {
+ IMDSALConsumer mdsalConsumer = (IMDSALConsumer)ServiceHelper.getInstance(IMDSALConsumer.class, "default", this);
+ if (mdsalConsumer == null) {
+ logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
+ return;
+ }
+
+ dataBrokerService = mdsalConsumer.getDataBrokerService();
+
+ if (dataBrokerService == null) {
+ logger.error("ERROR finding reference for DataBrokerService. Please check out the MD-SAL support on the Controller.");
+ return;
+ }
+ DataModification<InstanceIdentifier<?>, DataObject> modification = dataBrokerService.beginTransaction();
+ InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class)
+ .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class)
+ .child(Table.class, new TableKey(flow.getTableId())).child(Flow.class, flow.getKey())
+ .build();
+ modification.putOperationalData(nodeBuilderToInstanceId(nodeBuilder), nodeBuilder.build());
+ modification.putOperationalData(path1, flow.build());
+ modification.putConfigurationData(nodeBuilderToInstanceId(nodeBuilder), nodeBuilder.build());
+ modification.putConfigurationData(path1, flow.build());
+ Future<RpcResult<TransactionStatus>> commitFuture = modification.commit();
+ try {
+ RpcResult<TransactionStatus> result = commitFuture.get();
+ TransactionStatus status = result.getResult();
+ } catch (InterruptedException e) {
+ logger.error(e.getMessage(), e);
+ } catch (ExecutionException e) {
+ logger.error(e.getMessage(), e);
+ }
+ }
+
+ private static MatchBuilder createLLDPMatch() {
+ MatchBuilder match = new MatchBuilder();
+ EthernetMatchBuilder eth = new EthernetMatchBuilder();
+ EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+ ethTypeBuilder.setType(new EtherType(0x88CCL));
+ eth.setEthernetType(ethTypeBuilder.build());
+ match.setEthernetMatch(eth.build());
+ return match;
+ }
+
+ private InstructionsBuilder createSentToControllerInstructions() {
+ List<Action> actionList = new ArrayList<Action>();
+ ActionBuilder ab = new ActionBuilder();
+
+ OutputActionBuilder output = new OutputActionBuilder();
+ output.setMaxLength(56);
+ Uri value = new Uri("CONTROLLER");
+ output.setOutputNodeConnector(value);
+ ab.setAction(new OutputActionCaseBuilder().setOutputAction(output.build()).build());
+ ab.setOrder(0);
+ ab.setKey(new ActionKey(0));
+ actionList.add(ab.build());
+ // Create an Apply Action
+ ApplyActionsBuilder aab = new ApplyActionsBuilder();
+ aab.setAction(actionList);
+
+ // Wrap our Apply Action in an Instruction
+ InstructionBuilder ib = new InstructionBuilder();
+ ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+
+ // Put our Instruction in a list of Instructions
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = new ArrayList<Instruction>();
+ instructions.add(ib.build());
+ isb.setInstruction(instructions);
+ return isb;
}
@Override
public void initializeOFFlowRules(Node openflowNode) {
}
+
+ private NodeBuilder createNodeBuilder(String nodeId) {
+ NodeBuilder builder = new NodeBuilder();
+ builder.setId(new NodeId(nodeId));
+ builder.setKey(new NodeKey(builder.getId()));
+ return builder;
+ }
+
+ private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nodeBuilderToInstanceId(NodeBuilder node) {
+ return InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class, node.getKey()).toInstance();
+ }
}