fixed RPC to instantiate SFC to SFP (selects SFs randomly) 95/8995/1
authorKonstantin Blagov <[email protected]>
Mon, 14 Jul 2014 16:45:53 +0000 (18:45 +0200)
committerKonstantin Blagov <[email protected]>
Mon, 14 Jul 2014 16:45:53 +0000 (18:45 +0200)
Change-Id: I2ed4d0f0b5a76caabd06005b46cc480fc2cc409d
Signed-off-by: Konstantin Blagov <[email protected]>
sfc-provider/src/main/java/org/opendaylight/controller/config/yang/config/sfc_provider/impl/SfcProviderModule.java
sfc-provider/src/main/java/org/opendaylight/sfc/provider/SfcProviderRpc.java
sfc-provider/src/main/java/org/opendaylight/sfc/provider/SfcSftMapper.java [new file with mode: 0755]
sfc-provider/src/main/java/org/opendaylight/sfc/provider/SfcSnMapper.java [new file with mode: 0755]
sfc-test-consumer/src/main/java/org/opendaylight/sfc/sfc_test_consumer/SfcTestConsumerImpl.java

index 6eddb6909c3e6158bc968ffec7465ad5b9119f97..3f845a835c74b56a9d5aadc8492fd7c81235a0c0 100755 (executable)
@@ -20,6 +20,7 @@ import org.opendaylight.sfc.provider.SfcProviderSnDataListener;
 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;
@@ -105,11 +106,17 @@ public class SfcProviderModule extends org.opendaylight.controller.config.yang.c
                 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 {
 
@@ -123,6 +130,7 @@ public class SfcProviderModule extends org.opendaylight.controller.config.yang.c
                 sffDataChangeListenerRegistration.close();
                 sfRpcRegistration.close();
                 sfcRpcRegistration.close();
+                snRpcRegistration.close();
 
                 //runtimeReg.close();
                 opendaylightSfc.close();
index a4a6a831f371032328cdc9317dac58ed37a919b7..5ae19827557dbffd5ac9d7a25b20e11c531b229c 100755 (executable)
@@ -26,9 +26,13 @@ import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev1407
 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;
@@ -36,7 +40,10 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 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;
 
@@ -51,7 +58,8 @@ 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);
@@ -81,7 +89,6 @@ public class SfcProviderRpc implements ServiceFunctionService, ServiceFunctionCh
         LOG.info("\n####### Start: {}", Thread.currentThread().getStackTrace()[1]);
         LOG.info("\n####### Input: " + input);
 
-
         if (odlSfc.dataProvider != null) {
 
             // Data PLane Locator
@@ -155,7 +162,7 @@ public class SfcProviderRpc implements ServiceFunctionService, ServiceFunctionCh
         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) {
@@ -174,7 +181,7 @@ public class SfcProviderRpc implements ServiceFunctionService, ServiceFunctionCh
         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());
@@ -209,7 +216,7 @@ public class SfcProviderRpc implements ServiceFunctionService, ServiceFunctionCh
 
         if (odlSfc.dataProvider != null) {
             final DataModificationTransaction t = odlSfc.dataProvider.beginTransaction();
-            t.putConfigurationData(odlSfc.sfcIID, sfcs);
+            t.putConfigurationData(OpendaylightSfc.sfcIID, sfcs);
 
             try {
                 t.commit().get();
@@ -223,38 +230,36 @@ public class SfcProviderRpc implements ServiceFunctionService, ServiceFunctionCh
                 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()));
     }
 
@@ -271,14 +276,14 @@ public class SfcProviderRpc implements ServiceFunctionService, ServiceFunctionCh
                     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() + "\"");
                         }
@@ -332,6 +337,7 @@ public class SfcProviderRpc implements ServiceFunctionService, ServiceFunctionCh
         }
     }
 
+    // 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 =
@@ -346,46 +352,18 @@ public class SfcProviderRpc implements ServiceFunctionService, ServiceFunctionCh
         }
     }
 
-    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) {
diff --git a/sfc-provider/src/main/java/org/opendaylight/sfc/provider/SfcSftMapper.java b/sfc-provider/src/main/java/org/opendaylight/sfc/provider/SfcSftMapper.java
new file mode 100755 (executable)
index 0000000..2164a41
--- /dev/null
@@ -0,0 +1,106 @@
+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>
+ * @author Konstantin Blagov ([email protected])
+ * @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).");
+        }
+    }
+
+
+}
diff --git a/sfc-provider/src/main/java/org/opendaylight/sfc/provider/SfcSnMapper.java b/sfc-provider/src/main/java/org/opendaylight/sfc/provider/SfcSnMapper.java
new file mode 100755 (executable)
index 0000000..7e1a0ca
--- /dev/null
@@ -0,0 +1,54 @@
+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>
+ * @author Konstantin Blagov ([email protected])
+ * @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);
+        }
+    }
+
+}
index d6c2fecce2cee9d58ff9e511785e0e244704a0d8..2a778f13ec69ef59465c332d4f40cd7645ad81ff 100755 (executable)
@@ -359,19 +359,35 @@ public class SfcTestConsumerImpl implements SfcTestConsumer, SfcTestConsumerRunt
     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");