From 421d43013a16c9c2e025c66fea06f97e3f927bb9 Mon Sep 17 00:00:00 2001 From: Prasanna Huddar Date: Mon, 28 Oct 2013 20:22:46 +0530 Subject: [PATCH] Initial code structure of MDSAL based FRM module. This is base code structure for using MD-SAL from NSF. This is not integrated with MAIN Pom.xml. Its still independent bundle. We need provider in plugin to execute this code. Also there is addFlowTest() in file FlowConsumerImpl file is used to send hardcoded data to provider in plugin comment out the code if you use rest conf API. Signed-off-by: Prasanna Huddar Change-Id: Iaba741863a5aaa9d9f588a7964fc699771cee1ed --- .../openflow/pom.xml | 103 ++++++ .../consumer/impl/FRMConsumerImpl.java | 98 ++++++ .../consumer/impl/FlowConsumerImpl.java | 317 ++++++++++++++++++ .../consumer/impl/GroupConsumerImpl.java | 7 + 4 files changed, 525 insertions(+) create mode 100644 opendaylight/forwardingrulesmanager_mdsal/openflow/pom.xml create mode 100644 opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMConsumerImpl.java create mode 100644 opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FlowConsumerImpl.java create mode 100644 opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/GroupConsumerImpl.java diff --git a/opendaylight/forwardingrulesmanager_mdsal/openflow/pom.xml b/opendaylight/forwardingrulesmanager_mdsal/openflow/pom.xml new file mode 100644 index 0000000000..9b96f86c92 --- /dev/null +++ b/opendaylight/forwardingrulesmanager_mdsal/openflow/pom.xml @@ -0,0 +1,103 @@ + + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.1-SNAPSHOT + ../../commons/opendaylight + + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main + HEAD + + + forwardingrulesmanager_mdsal + 1.0-SNAPSHOT + bundle + + + + + org.apache.felix + maven-bundle-plugin + ${bundle.plugin.version} + true + + + + org.opendaylight.controller.sal.binding.api, + org.opendaylight.controller.sal.binding.api.data, + org.opendaylight.controller.md.sal.common.api.data, + org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.flow, + org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819, + org.opendaylight.yangtools.concepts, + org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819, + org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819, + org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes, + org.opendaylight.controller.sal.common.util, + org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows, + org.opendaylight.yangtools.yang.common, + org.opendaylight.yangtools.yang.binding, + org.apache.commons.lang3.builder, + org.apache.commons.lang3.tuple, + org.apache.felix.dm, + org.slf4j, + org.eclipse.osgi.framework.console, + org.osgi.framework, + javax.net.ssl + + + + + false + + + org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl.FRMConsumerImpl + + + ${project.basedir}/META-INF + + + + + + + junit + junit + + + equinoxSDK381 + org.eclipse.osgi + + + org.opendaylight.controller + sal-binding-api + 1.0-SNAPSHOT + + + org.opendaylight.controller + flow-management-compatibility + 1.0-SNAPSHOT + + + org.opendaylight.controller.model + model-flow-service + 1.0-SNAPSHOT + + + org.opendaylight.controller.model + model-flow-management + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-binding-broker-impl + 1.0-SNAPSHOT + provided + + + diff --git a/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMConsumerImpl.java b/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMConsumerImpl.java new file mode 100644 index 0000000000..ae488b689f --- /dev/null +++ b/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMConsumerImpl.java @@ -0,0 +1,98 @@ + +/* + * Copyright (c) 2013 Ericsson , Inc. and others. All rights reserved. + * + * 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 + */ + +package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl; + + +import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext; +import org.opendaylight.controller.sal.binding.api.NotificationService; +import org.opendaylight.controller.sal.binding.api.data.DataBrokerService; +import org.opendaylight.controller.sal.binding.api.data.DataProviderService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class FRMConsumerImpl extends AbstractBindingAwareProvider { + protected static final Logger logger = LoggerFactory.getLogger(FRMConsumerImpl.class); + private static ProviderContext p_session; + private static DataBrokerService dataBrokerService; + private static NotificationService notificationService; + private FlowConsumerImpl flowImplRef; + private GroupConsumerImpl groupImplRef; + private static DataProviderService dataProviderService; + + @Override + public void onSessionInitiated(ProviderContext session) { + + FRMConsumerImpl.p_session = session; + + if (null != session) { + notificationService = session.getSALService(NotificationService.class); + + if (null != notificationService) { + dataBrokerService = session.getSALService(DataBrokerService.class); + + if (null != dataBrokerService) { + dataProviderService = session.getSALService(DataProviderService.class); + + if (null != dataProviderService) { + flowImplRef = new FlowConsumerImpl(); + groupImplRef = new GroupConsumerImpl(); + } + else { + logger.error("Data Provider Service is down or NULL. " + + "Accessing data from configuration data store will not be possible"); + System.out.println("Data Broker Service is down or NULL."); + } + + } + else { + logger.error("Data Broker Service is down or NULL."); + System.out.println("Data Broker Service is down or NULL."); + } + } + else { + logger.error("Notification Service is down or NULL."); + System.out.println("Notification Service is down or NULL."); + } + } + else { + logger.error("Consumer session is NULL. Please check if provider is registered"); + System.out.println("Consumer session is NULL. Please check if provider is registered"); + } + + } + + public static DataProviderService getDataProviderService() { + return dataProviderService; + } + + public FlowConsumerImpl getFlowImplRef() { + return flowImplRef; + } + + public GroupConsumerImpl getGroupImplRef() { + return groupImplRef; + } + + public static ProviderContext getProviderSession() { + return p_session; + } + + public static NotificationService getNotificationService() { + return notificationService; + } + + public static DataBrokerService getDataBrokerService() { + return dataBrokerService; + } + +} + diff --git a/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FlowConsumerImpl.java b/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FlowConsumerImpl.java new file mode 100644 index 0000000000..a6a3c71325 --- /dev/null +++ b/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FlowConsumerImpl.java @@ -0,0 +1,317 @@ +package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Future; + +import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler; +import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction; +import org.opendaylight.controller.md.sal.common.api.data.DataModification; +import org.opendaylight.controller.sal.binding.api.data.DataChangeListener; +import org.opendaylight.controller.sal.common.util.Rpcs; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; +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.flow.config.rev130819.flows.FlowKey; +import org.opendaylight.yangtools.concepts.Registration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.NotificationListener; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FlowConsumerImpl { + protected static final Logger logger = LoggerFactory.getLogger(FlowConsumerImpl.class); + private FlowEventListener flowEventListener = new FlowEventListener(); + private Registration listener1Reg; + private SalFlowService flowService; + private FlowDataListener listener; + private FlowDataCommitHandler commitHandler; + private ConcurrentHashMap originalSwView; + + public FlowConsumerImpl() { + InstanceIdentifier path = InstanceIdentifier.builder().node(Flows.class).toInstance(); + flowService = FRMConsumerImpl.getProviderSession().getRpcService(SalFlowService.class); + + if (null == flowService) { + logger.error("Consumer SAL Service is down or NULL. FRM may not function as intended"); + System.out.println("Consumer SAL Service is down or NULL."); + return; + } + + listener = new FlowDataListener(); + if (null == FRMConsumerImpl.getDataBrokerService().registerDataChangeListener(path, listener)) { + logger.error("Failed to listen on flow data modifcation events"); + System.out.println("Consumer SAL Service is down or NULL."); + return; + } + + // For switch events + listener1Reg = FRMConsumerImpl.getNotificationService().registerNotificationListener(flowEventListener); + + if (null == listener1Reg) { + logger.error("Listener to listen on flow data modifcation events"); + System.out.println("Consumer SAL Service is down or NULL."); + return; + } + addFlowTest(); + System.out.println("-------------------------------------------------------------------"); + allocateCaches(); + commitHandler = new FlowDataCommitHandler(); + FRMConsumerImpl.getDataProviderService().registerCommitHandler(path, commitHandler); + } + + private void allocateCaches() { + originalSwView = new ConcurrentHashMap(); + } + + private void addFlowTest() + { + try { + NodeRef nodeOne = createNodeRef("foo:node:1"); + AddFlowInputBuilder input1 = new AddFlowInputBuilder(); + + input1.setNode(nodeOne); + AddFlowInput firstMsg = input1.build(); + + if(null != flowService) { + System.out.println(flowService.toString()); + } + else + { + System.out.println("ConsumerFlowService is NULL"); + } + @SuppressWarnings("unused") + Future> result1 = flowService.addFlow(firstMsg); + + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + /** + * Adds flow to the southbound plugin and our internal database + * + * @param path + * @param dataObject + */ + private void addFlow(InstanceIdentifier path, Flow dataObject) { + + AddFlowInputBuilder input = new AddFlowInputBuilder(); + input.setNode((dataObject).getNode()); + input.setPriority((dataObject).getPriority()); + input.setMatch((dataObject).getMatch()); + input.setCookie((dataObject).getCookie()); + input.setAction((dataObject).getAction()); + + // We send flow to the sounthbound plugin + flowService.addFlow(input.build()); + } + + private void commitToPlugin(internalTransaction transaction) { + for(Entry, Flow> entry :transaction.additions.entrySet()) { + addFlow(entry.getKey(),entry.getValue()); + } + for(@SuppressWarnings("unused") Entry, Flow> entry :transaction.additions.entrySet()) { + // updateFlow(entry.getKey(),entry.getValue()); + } + + for(@SuppressWarnings("unused") InstanceIdentifier removal : transaction.removals) { + // removeFlow(removal); + } + } + + private final class FlowDataCommitHandler implements DataCommitHandler, DataObject> { + + @SuppressWarnings("unchecked") + @Override + public DataCommitTransaction requestCommit(DataModification, DataObject> modification) { + // We should verify transaction + System.out.println("Coming in FlowDatacommitHandler"); + internalTransaction transaction = new internalTransaction(modification); + transaction.prepareUpdate(); + return transaction; + } + } + + private final class internalTransaction implements DataCommitTransaction, DataObject> { + + private final DataModification, DataObject> modification; + + @Override + public DataModification, DataObject> getModification() { + return modification; + } + + public internalTransaction(DataModification, DataObject> modification) { + this.modification = modification; + } + + Map, Flow> additions = new HashMap<>(); + Map, Flow> updates = new HashMap<>(); + Set> removals = new HashSet<>(); + + /** + * We create a plan which flows will be added, which will be updated and + * which will be removed based on our internal state. + * + */ + void prepareUpdate() { + + Set, DataObject>> puts = modification.getUpdatedConfigurationData().entrySet(); + for (Entry, DataObject> entry : puts) { + if (entry.getValue() instanceof Flow) { + Flow flow = (Flow) entry.getValue(); + preparePutEntry(entry.getKey(), flow); + } + + } + + removals = modification.getRemovedConfigurationData(); + } + + private void preparePutEntry(InstanceIdentifier key, Flow flow) { + Flow original = originalSwView.get(key); + if (original != null) { + // It is update for us + updates.put(key, flow); + } else { + // It is addition for us + additions.put(key, flow); + } + } + + /** + * We are OK to go with execution of plan + * + */ + @Override + public RpcResult finish() throws IllegalStateException { + + commitToPlugin(this); + // We return true if internal transaction is successful. + // return Rpcs.getRpcResult(true, null, Collections.emptySet()); + return Rpcs.getRpcResult(true, null, null); + } + + /** + * + * We should rollback our preparation + * + */ + @Override + public RpcResult rollback() throws IllegalStateException { + // NOOP - we did not modified any internal state during + // requestCommit phase + // return Rpcs.getRpcResult(true, null, Collections.emptySet()); + return Rpcs.getRpcResult(true, null, null); + + } + + } + + final class FlowEventListener implements SalFlowListener { + + List addedFlows = new ArrayList<>(); + List removedFlows = new ArrayList<>(); + List updatedFlows = new ArrayList<>(); + + @Override + public void onFlowAdded(FlowAdded notification) { + System.out.println("added flow.........................."); + addedFlows.add(notification); + } + + @Override + public void onFlowRemoved(FlowRemoved notification) { + removedFlows.add(notification); + }; + + @Override + public void onFlowUpdated(FlowUpdated notification) { + updatedFlows.add(notification); + } + + } + + final class FlowDataListener implements DataChangeListener { + private SalFlowService flowService; + + public FlowDataListener() { + + } + + @Override + public void onDataChanged( + DataChangeEvent, DataObject> change) { + System.out.println("Coming in onDataChange.............."); + @SuppressWarnings("unchecked") + Collection additions = (Collection) change.getCreatedConfigurationData(); + // we can check for getCreated, getDeleted or getUpdated from DataChange Event class + for (DataObject dataObject : additions) { + if (dataObject instanceof NodeFlow) { + NodeRef nodeOne = createNodeRef("foo:node:1"); + // validating the dataObject here + AddFlowInputBuilder input = new AddFlowInputBuilder(); + input.setNode(((NodeFlow) dataObject).getNode()); + input.setNode(nodeOne); + // input.setPriority(((NodeFlow) dataObject).getPriority()); + //input.setMatch(((NodeFlow) dataObject).getMatch()); + //input.setFlowTable(((NodeFlow) dataObject).getFlowTable()); + //input.setCookie(((NodeFlow) dataObject).getCookie()); + //input.setAction(((NodeFlow) dataObject).getAction()); + + @SuppressWarnings("unused") + Future> result = flowService.addFlow(input.build()); + } + } + } + } + + + + private static NodeRef createNodeRef(String string) { + NodeKey key = new NodeKey(new NodeId(string)); + InstanceIdentifier path = InstanceIdentifier.builder().node(Nodes.class).node(Node.class, key) + .toInstance(); + + return new NodeRef(path); + } + + /* private void loadFlowData() { + + DataModification modification = (DataModification) dataservice.beginTransaction(); + String id = "abc"; + FlowKey key = new FlowKey(id, new NodeRef()); + InstanceIdentifier path1; + FlowBuilder flow = new FlowBuilder(); + flow.setKey(key); + path1 = InstanceIdentifier.builder().node(Flows.class).node(Flow.class, key).toInstance(); + DataObject cls = (DataObject) modification.readConfigurationData(path); + modification.putConfigurationData(path, flow.build()); + modification.commit(); + }*/ + +} diff --git a/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/GroupConsumerImpl.java b/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/GroupConsumerImpl.java new file mode 100644 index 0000000000..cc42e21f2a --- /dev/null +++ b/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/GroupConsumerImpl.java @@ -0,0 +1,7 @@ +package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl; + +public class GroupConsumerImpl { + public GroupConsumerImpl() { + + } +} -- 2.36.6