Merge "OVSDB QoS - move QoS and Queue lists to OVSDB Node"
[netvirt.git] / openstack / net-virt-sfc / impl / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / sfc / workaround / NetvirtSfcWorkaroundOF13Provider.java
index 4d13ddb7e58a5f33b2851f4588ef43c79a9e7070..cbd14b48eb97cf983b164ee46659935a0cf500e7 100644 (file)
@@ -14,30 +14,29 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
 import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
+import org.opendaylight.ovsdb.openstack.netvirt.api.OvsdbTables;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.INetvirtSfcOF13Provider;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.ISfcClassifierService;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.NshUtils;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.SfcUtils;
-import org.opendaylight.ovsdb.openstack.netvirt.sfc.workaround.services.SfcClassifierService;
-import org.opendaylight.ovsdb.southbound.SouthboundConstants;
 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
 import org.opendaylight.sfc.provider.api.SfcProviderRenderedPathAPI;
+import org.opendaylight.sfc.provider.api.SfcProviderServiceForwarderAPI;
 import org.opendaylight.sfc.provider.api.SfcProviderServiceFunctionAPI;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.locator.type.Ip;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInput;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.path.first.hop.info.RenderedServicePathFirstHop;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHop;
 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.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
 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.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.Acl;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.Ace;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.Matches;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.acl.rev150105.RedirectToSfc;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.Classifiers;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.Classifier;
@@ -45,8 +44,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.bridges.Bridge;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.sffs.Sff;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
 import org.osgi.framework.ServiceReference;
@@ -59,13 +58,10 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
     private volatile Southbound southbound;
     private volatile ISfcClassifierService sfcClassifierService;
     private static final short SFC_TABLE = 150;
-    private static final int GPE_PORT = 6633;
-    private static final String NETWORK_TYPE_VXLAN = "vxlan";
     private MdsalUtils mdsalUtils;
     private SfcUtils sfcUtils;
     private static final String VXGPE = "vxgpe";
-    private static final String TUNNEL_DST = "192.168.120.31";
-    private static final String TUNNEL_VNID = "10";
+    public static final String TUNNEL_ENDPOINT_KEY = "local_ip";
 
     public NetvirtSfcWorkaroundOF13Provider(final DataBroker dataBroker, MdsalUtils mdsalUtils, SfcUtils sfcUtils) {
         Preconditions.checkNotNull(dataBroker, "Input dataBroker cannot be NULL!");
@@ -150,91 +146,178 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
         }
         LOG.info("handleRenderedServicePath: pathHopList: {}", pathHopList);
 
+        RenderedServicePathFirstHop firstRspHop = SfcProviderRenderedPathAPI
+                .readRenderedServicePathFirstHop(rsp.getName());
+        LOG.info("handleRenderedServicePath: firstRspHop: {}", firstRspHop);
+
+        RenderedServicePathHop firstHop = pathHopList.get(0);
+        RenderedServicePathHop lastHop = pathHopList.get(pathHopList.size()-1);
+
         final List<Node> bridgeNodes = nodeCacheManager.getBridgeNodes();
         if (bridgeNodes == null || bridgeNodes.isEmpty()) {
             LOG.warn("handleRenderedServicePath: There are no bridges to process");
             return;
         }
-        for (Node bridgeNode : bridgeNodes) {
-            OvsdbBridgeAugmentation ovsdbBridgeAugmentation = southbound.getBridge(bridgeNode, "br-int");
-            if (ovsdbBridgeAugmentation == null) {
-                continue;
-            }
-            long vxGpeOfPort = getOFPort(bridgeNode, VXGPE);
-            if (vxGpeOfPort == 0L) {
-                LOG.warn("programAclEntry: Could not identify tunnel port {} -> OF ({}) on {}",
-                        VXGPE, vxGpeOfPort, bridgeNode);
-                continue;
-            }
-            long dataPathId = southbound.getDataPathId(bridgeNode);
-            if (dataPathId == 0L) {
-                LOG.warn("programAclEntry: Could not identify datapathId on {}", bridgeNode);
-                continue;
-            }
+        for (RenderedServicePathHop hop : pathHopList) {
+            for (Node bridgeNode : bridgeNodes) {
+                // ignore bridges other than br-int
+                OvsdbBridgeAugmentation ovsdbBridgeAugmentation = southbound.getBridge(bridgeNode, "br-int");
+                if (ovsdbBridgeAugmentation == null) {
+                    continue;
+                }
+                long vxGpeOfPort = getOFPort(bridgeNode, VXGPE);
+                if (vxGpeOfPort == 0L) {
+                    LOG.warn("programAclEntry: Could not identify gpe vtep {} -> OF ({}) on {}",
+                            VXGPE, vxGpeOfPort, bridgeNode);
+                    continue;
+                }
+                long dataPathId = southbound.getDataPathId(bridgeNode);
+                if (dataPathId == 0L) {
+                    LOG.warn("programAclEntry: Could not identify datapathId on {}", bridgeNode);
+                    continue;
+                }
 
-            // Find the first Hop within an RSP.
-            // The classifier flow needs to send all matched traffic to this first hop SFF.
-            RenderedServicePathFirstHop firstRspHop = SfcProviderRenderedPathAPI
-                    .readRenderedServicePathFirstHop(rsp.getName());
+                ServiceFunction serviceFunction =
+                        SfcProviderServiceFunctionAPI.readServiceFunction(firstHop.getServiceFunctionName());
+                if (serviceFunction == null) {
+                    LOG.warn("programAclEntry: Could not identify ServiceFunction {} on {}",
+                            firstHop.getServiceFunctionName().getValue(), bridgeNode);
+                    continue;
+                }
+                ServiceFunctionForwarder serviceFunctionForwarder =
+                        SfcProviderServiceForwarderAPI
+                                .readServiceFunctionForwarder(hop.getServiceFunctionForwarder());
+                if (serviceFunctionForwarder == null) {
+                    LOG.warn("programAclEntry: Could not identify ServiceFunctionForwarder {} on {}",
+                            firstHop.getServiceFunctionName().getValue(), bridgeNode);
+                    continue;
+                }
 
-            LOG.info("handleRenderedServicePath: firstRspHop: {}", firstRspHop);
-            LOG.debug("handleRenderedServicePath: First Hop IPAddress = {}, Port = {}",
-                    firstRspHop.getIp().getIpv4Address().getValue(),
-                    firstRspHop.getPort().getValue().intValue());
+                handleSf(bridgeNode, serviceFunction);
+                handleSff(bridgeNode, serviceFunctionForwarder, serviceFunction, hop, firstHop, lastHop,
+                        entry.getRuleName(), matches, vxGpeOfPort, rsp);
+                if (firstHop == lastHop) {
+                    handleSff(bridgeNode, serviceFunctionForwarder, serviceFunction, hop, null, lastHop,
+                            entry.getRuleName(), matches, vxGpeOfPort, rsp);
+                }
+            }
+        }
+    }
 
+    private void handleSff(Node bridgeNode, ServiceFunctionForwarder serviceFunctionForwarder,
+                           ServiceFunction serviceFunction,
+                           RenderedServicePathHop hop,
+                           RenderedServicePathHop firstHop,
+                           RenderedServicePathHop lastHop,
+                           String ruleName, Matches matches,
+                           long vxGpeOfPort, RenderedServicePath rsp) {
+        long dataPathId = southbound.getDataPathId(bridgeNode);
+
+        if (hop == firstHop) {
+            LOG.info("handleSff: first hop processing {} - {}",
+                    bridgeNode.getNodeId(), serviceFunctionForwarder.getName());
             NshUtils nshHeader = new NshUtils();
-            nshHeader.setNshMetaC1(NshUtils.convertIpAddressToLong(new Ipv4Address(TUNNEL_DST)));
-            nshHeader.setNshMetaC2(Long.parseLong(TUNNEL_VNID)); // get from register //get from
             nshHeader.setNshNsp(rsp.getPathId());
-
-            RenderedServicePathHop firstHop = pathHopList.get(0);
-            RenderedServicePathHop lastHop = pathHopList.get(pathHopList.size()-1);
-            ServiceFunction serviceFunction =
-                    SfcProviderServiceFunctionAPI.readServiceFunction(
-                            SfName.getDefaultInstance(firstHop.getServiceFunctionName().getValue()));
-            if (serviceFunction == null) {
-                LOG.warn("programAclEntry: Could not identify ServiceFunction {} on {}",
-                        firstHop.getServiceFunctionName().getValue(), bridgeNode);
-                continue;
-            }
-
             nshHeader.setNshNsi(firstHop.getServiceIndex());
-            // workaround: bypass sff and got directly to sf
-            //nshHeader.setNshTunIpDst(firstRspHop.getIp().getIpv4Address());
-            IpAddress sfIpAddress = sfcUtils.getSfIp(serviceFunction);
+            if (isSffOnBridge(bridgeNode, serviceFunctionForwarder)) {
+                LOG.info("handleSff: sff and bridge are the same: {} - {}, skipping first sff",
+                        bridgeNode.getNodeId(), serviceFunctionForwarder.getName());
+                Ip ip = sfcUtils.getSfIp(serviceFunction);
+                nshHeader.setNshTunIpDst(ip.getIp().getIpv4Address());
+                nshHeader.setNshTunUdpPort(ip.getPort());
+            } else {
+                LOG.info("handleSff: sff and bridge are not the same: {} - {}, sending to first sff",
+                        bridgeNode.getNodeId(), serviceFunctionForwarder.getName());
+                Ip ip = sfcUtils.getSffIp(serviceFunctionForwarder);
+                nshHeader.setNshTunIpDst(ip.getIp().getIpv4Address());
+                nshHeader.setNshTunUdpPort(ip.getPort());
+            }
+            sfcClassifierService.programIngressClassifier(dataPathId, ruleName, matches,
+                    nshHeader, vxGpeOfPort, true);
+        } else if (hop == lastHop) {
+            LOG.info("handleSff: last hop processing {} - {}",
+                    bridgeNode.getNodeId(), serviceFunctionForwarder.getName());
+            short lastServiceindex = (short)((lastHop.getServiceIndex()).intValue() - 1);
             String sfDplName = sfcUtils.getSfDplName(serviceFunction);
-            //sfcUtils.getSfIp(firstHop.getServiceFunctionName().getValue());
-            nshHeader.setNshTunIpDst(sfIpAddress.getIpv4Address());
-            nshHeader.setNshTunUdpPort(firstRspHop.getPort());
-            LOG.debug("handleRenderedServicePath: NSH Header = {}", nshHeader);
+            long sfOfPort = getSfPort(bridgeNode, sfDplName);
+            sfcClassifierService.programEgressClassifier(dataPathId, vxGpeOfPort, rsp.getPathId(),
+                    lastServiceindex, sfOfPort, 0, true);
+            sfcClassifierService.programEgressClassifierBypass(dataPathId, vxGpeOfPort, rsp.getPathId(),
+                    lastServiceindex, sfOfPort, 0, true);
+        } else {
+            // add typical sff flows
+        }
 
-            sfcClassifierService.programIngressClassifier(dataPathId, entry.getRuleName(), matches,
-                    nshHeader, vxGpeOfPort, true);
+        sfcClassifierService.programSfcTable(dataPathId, vxGpeOfPort, SFC_TABLE, true);
+    }
 
-            sfcClassifierService.program_sfEgress(dataPathId, GPE_PORT, true);
-            //not needed if ip route and arp can be added to stack
+    void handleSf(Node bridgeNode, ServiceFunction serviceFunction) {
+        if (isSfOnBridge(bridgeNode, serviceFunction)) {
+            LOG.info("handleSf: sf and bridge are on the same node: {} - {}, adding workaround and arp",
+                    bridgeNode.getNodeId(), serviceFunction.getName());
+            long dataPathId = southbound.getDataPathId(bridgeNode);
+            Ip ip = sfcUtils.getSfIp(serviceFunction);
+            String sfIpAddr = String.valueOf(ip.getIp().getValue());
+            int sfIpPort = ip.getPort().getValue(); //GPE_PORT
+            String sfDplName = sfcUtils.getSfDplName(serviceFunction);
             long sfOfPort = getSfPort(bridgeNode, sfDplName);
-
             String sfMac = getMacFromExternalIds(bridgeNode, sfDplName);
-            String sfIpString = new String(sfIpAddress.getValue());
-            LOG.info("handleRenderedServicePath: sfDplName: {}, sfMac: {}, sfOfPort: {}, sfIpAddress: {}",
-                    sfDplName, sfMac, sfOfPort, sfIpString);
-            if (sfMac != null) { // install if the sf is on this bridge, expand when using multiple bridges
-                sfcClassifierService.program_sfIngress(dataPathId, GPE_PORT, sfOfPort, sfIpString, sfDplName, true);
-                sfcClassifierService.programStaticArpEntry(dataPathId, 0L, sfMac, sfIpString, true);
+            if (sfMac == null) {
+                LOG.warn("handleSff: could not find mac for {} on {}", sfDplName, bridgeNode);
+                return;
             }
+            //should be sffdplport, but they should all be the same 6633/4790
+            sfcClassifierService.program_sfEgress(dataPathId, sfIpPort, true);
+            sfcClassifierService.program_sfIngress(dataPathId, sfIpPort, sfOfPort, sfIpAddr, sfDplName, true);
+            sfcClassifierService.programStaticArpEntry(dataPathId, 0L, sfMac, sfIpAddr, true);
+        }
+    }
 
-            short lastServiceindex = (short)((lastHop.getServiceIndex()).intValue() - 1);
-            sfcClassifierService.programEgressClassifier1(dataPathId, vxGpeOfPort, rsp.getPathId(),
-                    lastServiceindex, (int)sfOfPort, 0, (short)0, true);
-            sfcClassifierService.programEgressClassifier2(dataPathId, vxGpeOfPort, rsp.getPathId(),
-                    lastServiceindex, (int)sfOfPort, 0, true);
+    private boolean isSffOnBridge(Node bridgeNode, ServiceFunctionForwarder serviceFunctionForwarder) {
+        String local_ip = "";
+        Ip ip = sfcUtils.getSffIp(serviceFunctionForwarder);
+        Node ovsdbNode = southbound.readOvsdbNode(bridgeNode);
+        if (ovsdbNode != null) {
+            OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
+            if (ovsdbNodeAugmentation != null && ovsdbNodeAugmentation.getOpenvswitchOtherConfigs() != null) {
+                local_ip = southbound.getOtherConfig(ovsdbNode, OvsdbTables.OPENVSWITCH, TUNNEL_ENDPOINT_KEY);
+            }
 
-            sfcClassifierService.programSfcTable(dataPathId, vxGpeOfPort, SFC_TABLE, true);
         }
+        return local_ip.equals(String.valueOf(ip.getIp().getValue()));
+    }
+
+    private boolean isSfOnBridge(Node bridgeNode, ServiceFunction serviceFunction) {
+        String sfDplName = sfcUtils.getSfDplName(serviceFunction);
+        long sfOfPort = getSfPort(bridgeNode, sfDplName);
+        return sfOfPort != 0L;
     }
 
     private RenderedServicePath getRenderedServicePath (Ace entry) {
+        RenderedServicePath rsp = null;
+        RedirectToSfc sfcRedirect = entry.getActions().getAugmentation(RedirectToSfc.class);
+        LOG.debug("Processing ACL entry = {} sfcRedirect = {}", entry.getRuleName(), sfcRedirect);
+        if (sfcRedirect == null) {
+            LOG.warn("processAClEntry: sfcRedirect is null");
+            return null;
+        }
+
+        if (sfcRedirect.getRspName() != null) {
+            rsp = getRenderedServicePathFromRsp(sfcRedirect.getRspName());
+        } else if (sfcRedirect.getSfpName() != null) {
+            LOG.warn("getRenderedServicePath: sfp not handled yet");
+        } else {
+            rsp = getRenderedServicePathFromSfc(entry);
+        }
+        LOG.info("getRenderedServicePath: rsp: {}", rsp);
+        return rsp;
+    }
+
+    private RenderedServicePath getRenderedServicePathFromRsp(String rspName) {
+        return sfcUtils.getRsp(rspName);
+    }
+
+    private RenderedServicePath getRenderedServicePathFromSfc (Ace entry) {
         RedirectToSfc sfcRedirect = entry.getActions().getAugmentation(RedirectToSfc.class);
         LOG.debug("Processing ACL entry = {} sfcRedirect = {}", entry.getRuleName(), sfcRedirect);
         if (sfcRedirect == null) {
@@ -242,14 +325,14 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
             return null;
         }
 
-        String sfcName = sfcRedirect.getRedirectSfc();
+        String sfcName = sfcRedirect.getSfcName();
         ServiceFunctionPath sfp = sfcUtils.getSfp(sfcName);
         if (sfp == null || sfp.getName() == null) {
             LOG.warn("There is no configured SFP with sfcName = {}; so skip installing the ACL entry!!", sfcName);
             return null;
         }
 
-        LOG.debug("Processing Redirect to SFC = {}, SFP = {}", sfcRedirect.getRedirectSfc(), sfp);
+        LOG.debug("Processing Redirect to SFC = {}, SFP = {}", sfcName, sfp);
         // If RSP doesn't exist, create an RSP.
         String sfpName = sfp.getName().getValue();
         RenderedServicePath rsp = sfcUtils.getRspforSfp(sfpName);
@@ -285,50 +368,26 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
         return rsp;
     }
 
-    // loop through all ports looking for vxlan types, skip vxgpe, keep the rest
-    // first pass we only have two tunnels: one for normal vxlan and the other for gpe
-    // so just return the first non-gpe vxlan port
-    private long getTunnelOfPort(Node bridgeNode, String vxGpePortName) {
-        long port = 0L;
-        List<OvsdbTerminationPointAugmentation> ovsdbTerminationPointAugmentations =
-                southbound.getTerminationPointsOfBridge(bridgeNode);
-        if (!ovsdbTerminationPointAugmentations.isEmpty()) {
-            for (OvsdbTerminationPointAugmentation terminationPointAugmentation : ovsdbTerminationPointAugmentations) {
-                if (terminationPointAugmentation.getInterfaceType() ==
-                        SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP.get(NETWORK_TYPE_VXLAN)) {
-                    if (!terminationPointAugmentation.getName().equals(vxGpePortName)) {
-                        port = terminationPointAugmentation.getOfport();
-                        break;
-                    }
-                }
-            }
-        }
-        return port;
-    }
-
     private long getSfPort(Node bridgeNode, String sfPortName) {
-        long port = 0L;
-        port = getOFPort(bridgeNode, sfPortName);
-        return port;
+        return getOFPort(bridgeNode, sfPortName);
     }
 
     private long getOFPort(Node bridgeNode, String portName) {
         long ofPort = 0L;
-        OvsdbTerminationPointAugmentation port = southbound.extractTerminationPointAugmentation(bridgeNode, portName);
+        OvsdbTerminationPointAugmentation port =
+                southbound.extractTerminationPointAugmentation(bridgeNode, portName);
         if (port != null) {
             ofPort = southbound.getOFPort(port);
         }
         if (ofPort == 0L) {
             for (int i = 0; i < 5; i++) {
                 LOG.info("Looking for ofPort {}, try: {}", portName, i);
-                if (ofPort == 0L) {
-                    TerminationPoint tp = southbound.readTerminationPoint(bridgeNode, null, portName);
-                    if (tp != null) {
-                        port = tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
-                        if (port != null) {
-                            ofPort = southbound.getOFPort(port);
-                            break;
-                        }
+                TerminationPoint tp = southbound.readTerminationPoint(bridgeNode, null, portName);
+                if (tp != null) {
+                    port = tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
+                    if (port != null) {
+                        ofPort = southbound.getOFPort(port);
+                        break;
                     }
                 }
                 try {
@@ -341,26 +400,9 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
         return ofPort;
     }
 
-    private String getMacFromOptions(Node bridgeNode, String portName) {
-        String mac = null;
-        OvsdbTerminationPointAugmentation port = southbound.extractTerminationPointAugmentation(bridgeNode, portName);
-        LOG.info("getMac: portName: {}, bridgeNode: {},,, port: {}", portName, bridgeNode, port);
-        if (port != null && port.getOptions() != null) {
-            //mac = southbound.getOptionsValue(port.getOptions(), EXTERNAL_ID_VM_MAC);
-            for (Options option : port.getOptions()) {
-                LOG.info("getMac: option: {}", option);
-                if (option.getOption().equals(Constants.EXTERNAL_ID_VM_MAC)) {
-                    mac = option.getValue();
-                    break;
-                }
-            }
-        }
-        return mac;
-    }
-
     private String getMacFromExternalIds(Node bridgeNode, String portName) {
         String mac = null;
-        OvsdbTerminationPointAugmentation port = southbound.extractTerminationPointAugmentation(bridgeNode, portName);
+        OvsdbTerminationPointAugmentation port = southbound.getTerminationPointOfBridge(bridgeNode, portName);
         LOG.info("getMac: portName: {}, bridgeNode: {},,, port: {}", portName, bridgeNode, port);
         if (port != null && port.getInterfaceExternalIds() != null) {
             mac = southbound.getInterfaceExternalIdsValue(port, Constants.EXTERNAL_ID_VM_MAC);