import org.opendaylight.sfc.provider.SfcProviderSffDataListener;
import org.opendaylight.sfc.provider.SfcProviderSfEntryDataListener;
import org.opendaylight.sfc.provider.SfcProviderSfcEntryDataListener;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sn.rev140701.ServiceNodeService;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.ServiceFunctionChainService;
getRpcRegistryDependency()
.addRpcImplementation(ServiceFunctionService.class,
sfcProviderRpc);
+
final BindingAwareBroker.RpcRegistration<ServiceFunctionChainService> sfcRpcRegistration =
getRpcRegistryDependency()
.addRpcImplementation(ServiceFunctionChainService.class,
sfcProviderRpc);
+ final BindingAwareBroker.RpcRegistration<ServiceNodeService> snRpcRegistration =
+ getRpcRegistryDependency()
+ .addRpcImplementation(ServiceNodeService.class,
+ sfcProviderRpc);
+
// close()
final class AutoCloseableSfc implements AutoCloseable {
sffDataChangeListenerRegistration.close();
sfRpcRegistration.close();
sfcRpcRegistration.close();
+ snRpcRegistration.close();
//runtimeReg.close();
opendaylightSfc.close();
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPathBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.service.function.path.SfpServiceFunction;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.service.function.path.SfpServiceFunctionBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sn.rev140701.PutServiceNodeInput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sn.rev140701.ServiceNodeService;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sn.rev140701.ServiceNodes;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sn.rev140701.service.nodes.ServiceNode;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sn.rev140701.service.nodes.ServiceNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sn.rev140701.service.nodes.ServiceNodeKey;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
* @since 2014-06-30
*/
-public class SfcProviderRpc implements ServiceFunctionService, ServiceFunctionChainService {
+public class SfcProviderRpc implements ServiceFunctionService,
+ ServiceFunctionChainService, ServiceNodeService {
private static final Logger LOG = LoggerFactory
.getLogger(SfcProviderRpc.class);
LOG.info("\n####### Start: {}", Thread.currentThread().getStackTrace()[1]);
LOG.info("\n####### Input: " + input);
-
if (odlSfc.dataProvider != null) {
// Data PLane Locator
if (odlSfc.dataProvider != null) {
final DataModificationTransaction t = odlSfc.dataProvider
.beginTransaction();
- t.removeConfigurationData(odlSfc.sfsIID);
+ t.removeConfigurationData(OpendaylightSfc.sfsIID);
try {
t.commit().get();
} catch (InterruptedException | ExecutionException e) {
LOG.info("\n########## Start: {}", Thread.currentThread().getStackTrace()[1]);
LOG.info("Input: " + input);
if (odlSfc.dataProvider != null) {
- DataObject dataObject = odlSfc.dataProvider.readConfigurationData(odlSfc.sfsIID);
+ DataObject dataObject = odlSfc.dataProvider.readConfigurationData(OpendaylightSfc.sfsIID);
if (dataObject instanceof ServiceFunctions) {
ServiceFunctionKey sfkey = new ServiceFunctionKey(input.getName());
if (odlSfc.dataProvider != null) {
final DataModificationTransaction t = odlSfc.dataProvider.beginTransaction();
- t.putConfigurationData(odlSfc.sfcIID, sfcs);
+ t.putConfigurationData(OpendaylightSfc.sfcIID, sfcs);
try {
t.commit().get();
Collections.<RpcError>emptySet()));
}
- public Future<RpcResult<Void>> updateFunctionDpiWa20() {
- LOG.info("\n########## Start: {}", Thread.currentThread().getStackTrace()[1]);
- IpAddress ip = new IpAddress("10.0.0.11".toCharArray());
- ServiceFunctionBuilder sfbuilder = new ServiceFunctionBuilder();
- ServiceFunctionKey sfkey = new ServiceFunctionKey("fw-wa");
- sfbuilder.setKey(sfkey);
- ServiceFunction sf = sfbuilder.setName("fw-wa")
- .setType("Firewall.class")
- .setIpMgmtAddress(ip).build();
-
+ @Override
+ public Future<RpcResult<Void>> putServiceNode(PutServiceNodeInput input) {
+ LOG.info("\n####### Start: {}", Thread.currentThread().getStackTrace()[1]);
+ LOG.info("\n####### Input: " + input);
- LOG.info("updateFunctionDpiWa20: bbb\n");
if (odlSfc.dataProvider != null) {
- LOG.info("updateFunctionDpiWa20: dataProvider not null\n");
- final DataModificationTransaction t = odlSfc.dataProvider
- .beginTransaction();
-
- InstanceIdentifier<ServiceFunction> sfIID = InstanceIdentifier.builder(ServiceFunctions.class).
- child(ServiceFunction.class, sf.getKey()).toInstance();
-
- t.putConfigurationData(sfIID, sf);
- try {
- t.commit().get();
- } catch (ExecutionException | InterruptedException e) {
- LOG.warn("Failed to update-function, operational otherwise", e);
- }
+ ServiceNodeKey snKey = new ServiceNodeKey(input.getName());
+ ServiceNodeBuilder builder = new ServiceNodeBuilder();
+ ServiceNode sn = builder.setKey(snKey)
+ .setName(input.getName())
+ .setIpMgmtAddress(input.getIpMgmtAddress())
+ .setServiceFunction(input.getServiceFunction())
+ .build();
+
+ InstanceIdentifier<ServiceNode> snEntryIID = InstanceIdentifier.builder(ServiceNodes.class).
+ child(ServiceNode.class, sn.getKey()).toInstance();
+ final DataModificationTransaction t = odlSfc.dataProvider
+ .beginTransaction();
+
+ t.putConfigurationData(snEntryIID, sn);
+ try {
+ t.commit().get();
+ } catch (ExecutionException | InterruptedException e) {
+ LOG.warn("\n########## {} failed, operational otherwise", Thread.currentThread().getStackTrace()[1], e);
}
- else{
- LOG.info("updateFunctionDpiWa20: dataProvider not null\n");
+ } else {
+ LOG.warn("\n####### Data Provider is NULL : {}", Thread.currentThread().getStackTrace()[1]);
}
LOG.info("\n########## Stop: {}", Thread.currentThread().getStackTrace()[1]);
- return Futures.immediateFuture(Rpcs.<Void> getRpcResult(true,
+ return Futures.immediateFuture(Rpcs.<Void>getRpcResult(true,
Collections.<RpcError>emptySet()));
}
ServiceFunctionPathBuilder pathBuilder = new ServiceFunctionPathBuilder();
List<SfpServiceFunction> instances = new ArrayList<>();
+ Random rand = new Random(); // temporarily
for (SfcServiceFunction ref : sfRefList) {
- ServiceFunction sf = findServiceFunction(ref.getName());
- List<SfpServiceFunction> instanceNames = findInstances(sf);
- if (instanceNames != null && instanceNames.size() > 0) {
+ List<SfpServiceFunction> instanceList = findInstancesByType(ref.getType());
+ LOG.info("\n********** instanceList ***********\n" + instanceList);
+ if (instanceList != null && instanceList.size() > 0) {
// select instance
- // for now, takes first element
- LOG.info("\n********** instanceNames.get(0) ***********\n" + instanceNames.get(0));
- instances.add(instanceNames.get(0));
+ // for now, takes an element randomly
+ instances.add(instanceList.get(rand.nextInt(instanceList.size())));
} else {
throw new IllegalStateException("No instances found for Service Function \"" + ref.getName() + "\"");
}
}
}
+ // TODO this is duplicated in SFCSftMapper (and used only there, not here; better to DRY
private ServiceFunction findServiceFunction(String name) {
ServiceFunctionKey key = new ServiceFunctionKey(name);
InstanceIdentifier<ServiceFunction> iid =
}
}
- private List<SfpServiceFunction> findInstances(ServiceFunction sf) {
- String name = sf.getName();
-// Class<? extends ServiceFunctionTypeIdentity> type = sf.getType();
- String type = sf.getType();
- IpAddress ip = sf.getIpMgmtAddress();
-
- DataObject dataObject = odlSfc.dataProvider.readConfigurationData(OpendaylightSfc.snIID);
- if (dataObject instanceof ServiceNodes) {
- ServiceNodes nodes = (ServiceNodes) dataObject;
- List<ServiceNode> list = nodes.getServiceNode();
- // lookup node by IP
- Map<IpAddress, ServiceNode> nodesByIp = new HashMap<>();
- for (ServiceNode e : list) {
- nodesByIp.put(e.getIpMgmtAddress(), e);
- }
- ServiceNode node = nodesByIp.get(ip);
- if (node != null) {
- List<String> instances = node.getServiceFunction();
- LOG.info("\n********** instances ***********\n" + instances);
- if (instances.size() > 0) {
- // names of instances of given type
- List<SfpServiceFunction> names = new ArrayList<>();
- for (String inst : instances) {
- if (inst.equals(type)) {
- // FIXME type mismatch
- //names.add(inst);
- }
- }
- LOG.info("\n********** names ***********\n" + names);
- return names;
- } else {
- throw new IllegalStateException("No Service Function instances at node \"" + node.getName() + "\".");
- }
- } else {
- throw new IllegalStateException("No node with IP " + ip.toString() + " registered.");
- }
+ private List<SfpServiceFunction> findInstancesByType(String sfType) {
+ List<SfpServiceFunction> ret = new ArrayList<>();
- } else {
- throw new IllegalStateException("Wrong dataObject instance.");
+ SfcSftMapper mapper = new SfcSftMapper(odlSfc);
+ List<ServiceFunction> sfList = mapper.getSfList(sfType);
+ for(ServiceFunction sf : sfList){
+ SfpServiceFunctionBuilder builder = new SfpServiceFunctionBuilder();
+ ret.add(builder.setName(sf.getName())
+ .setServiceFunctionForwarder(sf.getServiceFunctionForwarder())
+ .build());
}
+ return ret;
}
private ServiceFunctionPaths buildServiceFunctionPaths(List<ServiceFunctionPath> list) {
--- /dev/null
+package org.opendaylight.sfc.provider;
+
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ServiceFunctions;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunctionKey;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sn.rev140701.ServiceNodes;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sn.rev140701.service.nodes.ServiceNode;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class maps service function types to service node mappers
+ *
+ * @see org.opendaylight.sfc.provider.SfcSnMapper
+ * <p>
+ * @version 0.1
+ * @since 2014-07-14
+ */
+public class SfcSftMapper {
+ private Map<String, SfcSnMapper> map;
+
+ private final OpendaylightSfc odlSfc;
+
+ public SfcSftMapper(OpendaylightSfc odlSfc){
+ this.map = new HashMap<>();
+ this.odlSfc = odlSfc;
+ this.update();
+ }
+
+ public void update() {
+ if (odlSfc != null) {
+ DataObject dataObject = odlSfc.dataProvider.readConfigurationData(OpendaylightSfc.snIID);
+ if (dataObject instanceof ServiceNodes) {
+ ServiceNodes nodes = (ServiceNodes) dataObject;
+ List<ServiceNode> snList = nodes.getServiceNode();
+
+ for(ServiceNode sn : snList){
+ List<String> sfNameList = sn.getServiceFunction();
+ for(String sfName : sfNameList){
+ ServiceFunction sf = findServiceFunction(sfName);
+ this.add(sf.getType(), sn.getName(), sf);
+ }
+ }
+ } else {
+ throw new IllegalStateException("Wrong dataObject instance.");
+ }
+ } else {
+ throw new NullPointerException("odlSfc is null");
+ }
+ }
+
+ public void add(String type, String snName, ServiceFunction sf){
+ if(this.map.containsKey(type)){
+ this.map.get(type).add(snName, sf);
+ }else{
+ SfcSnMapper snMapper = new SfcSnMapper(type);
+ snMapper.add(snName, sf);
+ this.map.put(type, snMapper);
+ }
+ }
+
+ public void addAll(String type, String snName, List<ServiceFunction> sfList){
+ if(this.map.containsKey(type)){
+ this.map.get(type).addAll(snName, sfList);
+ }else{
+ SfcSnMapper snMapper = new SfcSnMapper(type);
+ snMapper.addAll(snName, sfList);
+ this.map.put(type, snMapper);
+ }
+ }
+
+ public List<ServiceFunction> getSfList(String type) {
+ List<ServiceFunction> ret = new ArrayList<>();
+ if (this.map.containsKey(type)) {
+ SfcSnMapper snMapper = this.map.get(type);
+ Map<String, List<ServiceFunction>> snMap = snMapper.getMap();
+ for (String nodeName : snMap.keySet()) {
+ List<ServiceFunction> listOnNode = snMap.get(nodeName);
+ ret.addAll(listOnNode);
+ }
+ }
+ return ret;
+ }
+
+ private ServiceFunction findServiceFunction(String name) {
+ ServiceFunctionKey key = new ServiceFunctionKey(name);
+ InstanceIdentifier<ServiceFunction> iid =
+ InstanceIdentifier.builder(ServiceFunctions.class)
+ .child(ServiceFunction.class, key)
+ .toInstance();
+ DataObject dataObject = odlSfc.dataProvider.readConfigurationData(iid);
+ if (dataObject instanceof ServiceFunction) {
+ return (ServiceFunction) dataObject;
+ } else {
+ throw new IllegalStateException("Wrong dataObject instance (expected ServiceFunction).");
+ }
+ }
+
+
+}
--- /dev/null
+package org.opendaylight.sfc.provider;
+
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
+
+import java.util.*;
+
+/**
+ * This class maps service nodes to lists of service functions,
+ * filtered by a chosen service function type,
+ * i.e. node-1 -> [firewall-1, firewall-2, ...]
+ *
+ * <p>
+ * @version 0.1
+ * @since 2014-07-14
+ */
+class SfcSnMapper {
+ private final String type;
+ // partial list of SFs, filtered by given SFType
+ // SNodeName -> SFNameList
+ private Map<String, List<ServiceFunction>> map;
+
+ public SfcSnMapper(String sfType) {
+ this.type = sfType;
+ this.map = new HashMap<>();
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public Map<String, List<ServiceFunction>> getMap() {
+ return map;
+ }
+
+ public void add(String nodeName, ServiceFunction sf) {
+ if (this.map.containsKey(nodeName)) {
+ this.map.get(nodeName).add(sf);
+ } else {
+ List<ServiceFunction> list = new ArrayList<>();
+ list.add(sf);
+ this.map.put(nodeName, list);
+ }
+ }
+
+ public void addAll(String nodeName, List<ServiceFunction> sfList) {
+ if (this.map.containsKey(nodeName)) {
+ this.map.get(nodeName).addAll(sfList);
+ } else {
+ this.map.put(nodeName, sfList);
+ }
+ }
+
+}
public Boolean testCPutData() {
LOG.info("\n####### Start: {}", Thread.currentThread().getStackTrace()[1]);
- Boolean res = putSf("firewall-101-testC", "firewall", "10.3.1.101", "10.3.1.101", 10000);
- res = putSf("dpi-102-testC", "dpi", "10.3.1.102", "10.3.1.102", 10000) && res;
- res = putSf("napt44-103-testC", "napt44", "10.3.1.103", "10.3.1.103", 10000) && res;
- res = putSf("firewall-104-testC", "firewall", "10.3.1.104", "10.3.1.104", 10000) && res;
-
+ // Service Functions (real, not abstract)
+ Boolean res = putSf("firewall-101-1", "firewall", "10.3.1.101", "10.3.1.101", 10001);
+ res = putSf("firewall-101-2", "firewall", "10.3.1.101", "10.3.1.101", 10002) && res;
+ res = putSf("dpi-102-1", "dpi", "10.3.1.102", "10.3.1.102", 10001) && res;
+ res = putSf("dpi-102-2", "dpi", "10.3.1.102", "10.3.1.102", 10002) && res;
+ res = putSf("dpi-102-3", "dpi", "10.3.1.102", "10.3.1.102", 10003) && res;
+ res = putSf("napt44-103-1", "napt44", "10.3.1.103", "10.3.1.103", 10001) && res;
+ res = putSf("napt44-103-2", "napt44", "10.3.1.103", "10.3.1.103", 10002) && res;
+ res = putSf("firewall-104", "firewall", "10.3.1.104", "10.3.1.104", 10001) && res;
+ res = putSf("napt44-104", "napt44", "10.3.1.104", "10.3.1.104", 10020) && res;
+
+ // SFC1
List<SfcServiceFunction> sfRefList = new ArrayList<>();
SfcServiceFunctionBuilder sfBuilder = new SfcServiceFunctionBuilder();
- sfRefList.add(sfBuilder.setName("firewall-101-testC").build());
- sfRefList.add(sfBuilder.setName("dpi-102-testC").build());
- sfRefList.add(sfBuilder.setName("napt44-103-testC").build());
+ sfRefList.add(sfBuilder.setName("firewall-abstract1").setType("firewall").build());
+ sfRefList.add(sfBuilder.setName("dpi-abstract1").setType("dpi").build());
+ sfRefList.add(sfBuilder.setName("napt44-abstract1").setType("napt44").build());
res = putChain("SFC1", sfRefList) && res;
+ // SFC2
+ sfRefList.clear();
+ sfBuilder = new SfcServiceFunctionBuilder();
+ sfRefList.add(sfBuilder.setName("firewall-abstract2").setType("firewall").build());
+ sfRefList.add(sfBuilder.setName("napt44-abstract2").setType("napt44").build());
+
+ res = putChain("SFC2", sfRefList) && res;
+
+ // Nodes
List<String> iList = new ArrayList<>();
iList.add("firewall-101-1");
iList.add("firewall-101-2");