This is an automated email from the ASF dual-hosted git repository.

pearl11594 pushed a commit to branch nsx-static-nat
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit be49197bc5625a1a0ea04e774af3af1a98c4a2bd
Author: Pearl Dsilva <[email protected]>
AuthorDate: Wed Oct 25 18:42:44 2023 -0400

    Support to add and delete Port forward rules
---
 .../agent/api/CreateNsxPortForwardRuleCommand.java |  36 ++++
 .../agent/api/CreateNsxStaticNatCommand.java       |  75 +------
 .../agent/api/DeleteNsxNatRuleCommand.java         |  25 +++
 .../agent/api/DeleteNsxStaticNatCommand.java       |  43 ----
 .../cloudstack/agent/api/NsxNetworkCommand.java    |  87 ++++++++
 .../apache/cloudstack/resource/NsxNetworkRule.java | 226 +++++++++++++++++++++
 .../apache/cloudstack/resource/NsxResource.java    |  55 +++--
 .../apache/cloudstack/service/NsxApiClient.java    | 115 ++++++++++-
 .../org/apache/cloudstack/service/NsxElement.java  | 102 +++++++++-
 .../apache/cloudstack/service/NsxServiceImpl.java  |  49 +++--
 .../apache/cloudstack/service/NsxServiceList.java  |  17 ++
 .../cloudstack/utils/NsxControllerUtils.java       |   9 +-
 .../com/cloud/server/ConfigurationServerImpl.java  |   2 +
 13 files changed, 691 insertions(+), 150 deletions(-)

diff --git 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/CreateNsxPortForwardRuleCommand.java
 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/CreateNsxPortForwardRuleCommand.java
new file mode 100644
index 00000000000..6c5a261db6f
--- /dev/null
+++ 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/CreateNsxPortForwardRuleCommand.java
@@ -0,0 +1,36 @@
+package org.apache.cloudstack.agent.api;
+
+public class CreateNsxPortForwardRuleCommand extends NsxNetworkCommand {
+    private final String publicPort;
+    private final String privatePort;
+    private final String protocol;
+    private final long ruleId;
+
+
+    public CreateNsxPortForwardRuleCommand(long domainId, long accountId, long 
zoneId, Long networkResourceId,
+                                           String networkResourceName, boolean 
isResourceVpc, Long vmId,
+                                           long ruleId, String publicIp, 
String vmIp, String publicPort, String privatePort, String protocol) {
+        super(domainId, accountId, zoneId, networkResourceId, 
networkResourceName, isResourceVpc, vmId, publicIp, vmIp);
+        this.publicPort = publicPort;
+        this.privatePort = privatePort;
+        this.ruleId = ruleId;
+        this.protocol = protocol;
+
+    }
+
+    public String getPublicPort() {
+        return publicPort;
+    }
+
+    public String getPrivatePort() {
+        return privatePort;
+    }
+
+    public long getRuleId() {
+        return ruleId;
+    }
+
+    public String getProtocol() {
+        return protocol;
+    }
+}
diff --git 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/CreateNsxStaticNatCommand.java
 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/CreateNsxStaticNatCommand.java
index 9768b9ecb93..f32bc6888c2 100644
--- 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/CreateNsxStaticNatCommand.java
+++ 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/CreateNsxStaticNatCommand.java
@@ -1,76 +1,9 @@
 package org.apache.cloudstack.agent.api;
 
-import java.util.Objects;
+public class CreateNsxStaticNatCommand extends NsxNetworkCommand {
 
-public class CreateNsxStaticNatCommand extends NsxCommand {
-
-    private long vpcId;
-    private String vpcName;
-    private long vmId;
-    private String publicIp;
-    private String vmIp;
-
-    public CreateNsxStaticNatCommand(long domainId, long accountId, long 
zoneId, long vpcId, String vpcName,
-                                     long vmId, String publicIp, String vmIp) {
-        super(domainId, accountId, zoneId);
-        this.vpcId = vpcId;
-        this.vpcName = vpcName;
-        this.vmId = vmId;
-        this.publicIp = publicIp;
-        this.vmIp = vmIp;
-    }
-
-    public long getVpcId() {
-        return vpcId;
-    }
-
-    public void setVpcId(long vpcId) {
-        this.vpcId = vpcId;
-    }
-
-    public String getVpcName() {
-        return vpcName;
-    }
-
-    public void setVpcName(String vpcName) {
-        this.vpcName = vpcName;
-    }
-
-    public long getVmId() {
-        return vmId;
-    }
-
-    public void setVmId(long vmId) {
-        this.vmId = vmId;
-    }
-
-    public String getPublicIp() {
-        return publicIp;
-    }
-
-    public void setPublicIp(String publicIp) {
-        this.publicIp = publicIp;
-    }
-
-    public String getVmIp() {
-        return vmIp;
-    }
-
-    public void setVmIp(String vmIp) {
-        this.vmIp = vmIp;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-        if (!super.equals(o)) return false;
-        CreateNsxStaticNatCommand that = (CreateNsxStaticNatCommand) o;
-        return vpcId == that.vpcId && Objects.equals(publicIp, that.publicIp) 
&& Objects.equals(vmIp, that.vmIp);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(super.hashCode(), vpcId, publicIp, vmIp);
+    public CreateNsxStaticNatCommand(long domainId, long accountId, long 
zoneId, Long networkResourceId, String networkResourceName,
+                                     boolean isResourceVpc, Long vmId, String 
publicIp, String vmIp) {
+        super(domainId, accountId, zoneId, networkResourceId, 
networkResourceName, isResourceVpc, vmId, publicIp, vmIp);
     }
 }
diff --git 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/DeleteNsxNatRuleCommand.java
 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/DeleteNsxNatRuleCommand.java
new file mode 100644
index 00000000000..3d5b17f7ccf
--- /dev/null
+++ 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/DeleteNsxNatRuleCommand.java
@@ -0,0 +1,25 @@
+package org.apache.cloudstack.agent.api;
+
+import com.cloud.network.Network;
+
+public class DeleteNsxNatRuleCommand extends NsxNetworkCommand {
+    private Long ruleId;
+    private Network.Service service;
+    public DeleteNsxNatRuleCommand(long domainId, long accountId, long zoneId, 
Long networkResourceId, String networkResourceName,
+                                   boolean isResourceVpc, Long vmId, Long 
ruleId, String publicIp, String vmIp) {
+        super(domainId, accountId, zoneId, networkResourceId, 
networkResourceName, isResourceVpc, vmId, publicIp, vmIp);
+        this.ruleId = ruleId;
+    }
+
+    public Long getRuleId() {
+        return ruleId;
+    }
+
+    public Network.Service getService() {
+        return service;
+    }
+
+    public void setService(Network.Service service) {
+        this.service = service;
+    }
+}
diff --git 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/DeleteNsxStaticNatCommand.java
 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/DeleteNsxStaticNatCommand.java
deleted file mode 100644
index a4c30c1c701..00000000000
--- 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/DeleteNsxStaticNatCommand.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.apache.cloudstack.agent.api;
-
-import java.util.Objects;
-
-public class DeleteNsxStaticNatCommand extends NsxCommand {
-    private long vpcId;
-    private String vpcName;
-    public DeleteNsxStaticNatCommand(long domainId, long accountId, long 
zoneId, long vpcId, String vpcName) {
-        super(domainId, accountId, zoneId);
-        this.vpcId = vpcId;
-        this.vpcName = vpcName;
-    }
-
-    public long getVpcId() {
-        return vpcId;
-    }
-
-    public void setVpcId(long vpcId) {
-        this.vpcId = vpcId;
-    }
-
-    public String getVpcName() {
-        return vpcName;
-    }
-
-    public void setVpcName(String vpcName) {
-        this.vpcName = vpcName;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-        if (!super.equals(o)) return false;
-        DeleteNsxStaticNatCommand that = (DeleteNsxStaticNatCommand) o;
-        return vpcId == that.vpcId && Objects.equals(vpcName, that.vpcName);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(super.hashCode(), vpcId, vpcName);
-    }
-}
diff --git 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/NsxNetworkCommand.java
 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/NsxNetworkCommand.java
new file mode 100644
index 00000000000..82c20fb97bd
--- /dev/null
+++ 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/NsxNetworkCommand.java
@@ -0,0 +1,87 @@
+package org.apache.cloudstack.agent.api;
+
+import java.util.Objects;
+
+public class NsxNetworkCommand extends NsxCommand {
+    private Long networkResourceId;
+    private String networkResourceName;
+    private boolean isResourceVpc;
+    private Long vmId;
+    private String publicIp;
+    private String vmIp;
+
+    public NsxNetworkCommand(long domainId, long accountId, long zoneId, Long 
networkResourceId, String networkResourceName,
+                             boolean isResourceVpc, Long vmId, String 
publicIp, String vmIp) {
+        super(domainId, accountId, zoneId);
+        this.networkResourceId = networkResourceId;
+        this.networkResourceName = networkResourceName;
+        this.isResourceVpc = isResourceVpc;
+        this.vmId = vmId;
+        this.publicIp = publicIp;
+        this.vmIp = vmIp;
+    }
+
+    public Long getNetworkResourceId() {
+        return networkResourceId;
+    }
+
+    public void setNetworkResourceId(long networkResourceId) {
+        this.networkResourceId = networkResourceId;
+    }
+
+    public String getNetworkResourceName() {
+        return networkResourceName;
+    }
+
+    public void setNetworkResourceName(String networkResourceName) {
+        this.networkResourceName = networkResourceName;
+    }
+
+    public boolean isResourceVpc() {
+        return isResourceVpc;
+    }
+
+    public void setResourceVpc(boolean resourceVpc) {
+        isResourceVpc = resourceVpc;
+    }
+
+    public Long getVmId() {
+        return vmId;
+    }
+
+    public void setVmId(Long vmId) {
+        this.vmId = vmId;
+    }
+
+    public String getPublicIp() {
+        return publicIp;
+    }
+
+    public void setPublicIp(String publicIp) {
+        this.publicIp = publicIp;
+    }
+
+    public String getVmIp() {
+        return vmIp;
+    }
+
+    public void setVmIp(String vmIp) {
+        this.vmIp = vmIp;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        if (!super.equals(o)) return false;
+        NsxNetworkCommand that = (NsxNetworkCommand) o;
+        return networkResourceId == that.networkResourceId && vmId == 
that.vmId &&
+                Objects.equals(networkResourceName, that.networkResourceName) 
&& Objects.equals(publicIp, that.publicIp)
+                && Objects.equals(vmIp, that.vmIp);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(super.hashCode(), networkResourceId, 
networkResourceName, vmId, publicIp, vmIp);
+    }
+}
diff --git 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxNetworkRule.java
 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxNetworkRule.java
new file mode 100644
index 00000000000..fe2240b0297
--- /dev/null
+++ 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxNetworkRule.java
@@ -0,0 +1,226 @@
+package org.apache.cloudstack.resource;
+
+public class NsxNetworkRule {
+    private long domainId;
+    private long accountId;
+    private long zoneId;
+    private Long networkResourceId;
+    private String networkResourceName;
+    private boolean isVpcResource;
+    private long vmId;
+    private long ruleId;
+    private String publicIp;
+    private String vmIp;
+    private String publicPort;
+    private String privatePort;
+    private String protocol;
+
+    public long getDomainId() {
+        return domainId;
+    }
+
+    public void setDomainId(long domainId) {
+        this.domainId = domainId;
+    }
+
+    public long getAccountId() {
+        return accountId;
+    }
+
+    public void setAccountId(long accountId) {
+        this.accountId = accountId;
+    }
+
+    public long getZoneId() {
+        return zoneId;
+    }
+
+    public void setZoneId(long zoneId) {
+        this.zoneId = zoneId;
+    }
+
+    public Long getNetworkResourceId() {
+        return networkResourceId;
+    }
+
+    public void setNetworkResourceId(Long networkResourceId) {
+        this.networkResourceId = networkResourceId;
+    }
+
+    public String getNetworkResourceName() {
+        return networkResourceName;
+    }
+
+    public void setNetworkResourceName(String networkResourceName) {
+        this.networkResourceName = networkResourceName;
+    }
+
+    public boolean isVpcResource() {
+        return isVpcResource;
+    }
+
+    public void setVpcResource(boolean vpcResource) {
+        isVpcResource = vpcResource;
+    }
+
+    public long getVmId() {
+        return vmId;
+    }
+
+    public void setVmId(long vmId) {
+        this.vmId = vmId;
+    }
+
+    public long getRuleId() {
+        return ruleId;
+    }
+
+    public void setRuleId(long ruleId) {
+        this.ruleId = ruleId;
+    }
+
+    public String getPublicIp() {
+        return publicIp;
+    }
+
+    public void setPublicIp(String publicIp) {
+        this.publicIp = publicIp;
+    }
+
+    public String getVmIp() {
+        return vmIp;
+    }
+
+    public void setVmIp(String vmIp) {
+        this.vmIp = vmIp;
+    }
+
+    public String getPublicPort() {
+        return publicPort;
+    }
+
+    public void setPublicPort(String publicPort) {
+        this.publicPort = publicPort;
+    }
+
+    public String getPrivatePort() {
+        return privatePort;
+    }
+
+    public void setPrivatePort(String privatePort) {
+        this.privatePort = privatePort;
+    }
+
+    public String getProtocol() {
+        return protocol;
+    }
+
+    public void setProtocol(String protocol) {
+        this.protocol = protocol;
+    }
+
+    public static final class Builder {
+        private long domainId;
+        private long accountId;
+        private long zoneId;
+        private Long networkResourceId;
+        private String networkResourceName;
+        private boolean isVpcResource;
+        private long vmId;
+
+        private long ruleId;
+        private String publicIp;
+        private String vmIp;
+        private String publicPort;
+        private String privatePort;
+        private String protocol;
+
+        public Builder() {
+        }
+
+        public Builder setDomainId(long domainId) {
+            this.domainId = domainId;
+            return this;
+        }
+
+        public Builder setAccountId(long accountId) {
+            this.accountId = accountId;
+            return this;
+        }
+
+        public Builder setZoneId(long zoneId) {
+            this.zoneId = zoneId;
+            return this;
+        }
+
+        public Builder setNetworkResourceId(Long networkResourceId) {
+            this.networkResourceId = networkResourceId;
+            return this;
+        }
+
+        public Builder setNetworkResourceName(String networkResourceName) {
+            this.networkResourceName = networkResourceName;
+            return this;
+        }
+
+        public Builder setVpcResource(boolean isVpcResource) {
+            this.isVpcResource = isVpcResource;
+            return this;
+        }
+
+
+        public Builder setVmId(long vmId) {
+            this.vmId = vmId;
+            return this;
+        }
+
+        public Builder setRuleId(long ruleId) {
+            this.ruleId = ruleId;
+            return this;
+        }
+
+        public Builder setPublicIp(String publicIp) {
+            this.publicIp = publicIp;
+            return this;
+        }
+
+        public Builder setVmIp(String vmIp) {
+            this.vmIp = vmIp;
+            return this;
+        }
+
+        public Builder setPublicPort(String publicPort) {
+            this.publicPort = publicPort;
+            return this;
+        }
+
+        public Builder setPrivatePort(String privatePort) {
+            this.privatePort = privatePort;
+            return this;
+        }
+
+        public Builder setProtocol(String protocol) {
+            this.protocol = protocol;
+            return this;
+        }
+
+        public NsxNetworkRule build() {
+            NsxNetworkRule rule = new NsxNetworkRule();
+            rule.setDomainId(this.domainId);
+            rule.setAccountId(this.accountId);
+            rule.setZoneId(this.zoneId);
+            rule.setNetworkResourceId(this.networkResourceId);
+            rule.setNetworkResourceName(this.networkResourceName);
+            rule.setVpcResource(this.isVpcResource);
+            rule.setVmId(this.vmId);
+            rule.setVmIp(this.vmIp);
+            rule.setPublicIp(this.publicIp);
+            rule.setPublicPort(this.publicPort);
+            rule.setPrivatePort(this.privatePort);
+            rule.setProtocol(this.protocol);
+            rule.setRuleId(this.ruleId);
+            return rule;
+        }
+    }
+}
+
diff --git 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java
 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java
index 7892938ce9a..0b32ac517ab 100644
--- 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java
+++ 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java
@@ -24,6 +24,7 @@ import com.cloud.agent.api.ReadyAnswer;
 import com.cloud.agent.api.ReadyCommand;
 import com.cloud.agent.api.StartupCommand;
 import com.cloud.host.Host;
+import com.cloud.network.Network;
 import com.cloud.resource.ServerResource;
 import com.cloud.utils.exception.CloudRuntimeException;
 
@@ -35,11 +36,12 @@ import com.vmware.nsx_policy.model.SiteListResult;
 import org.apache.cloudstack.NsxAnswer;
 import org.apache.cloudstack.StartupNsxCommand;
 import org.apache.cloudstack.agent.api.CreateNsxDhcpRelayConfigCommand;
+import org.apache.cloudstack.agent.api.CreateNsxPortForwardRuleCommand;
 import org.apache.cloudstack.agent.api.CreateNsxSegmentCommand;
 import org.apache.cloudstack.agent.api.CreateNsxStaticNatCommand;
 import org.apache.cloudstack.agent.api.CreateNsxTier1GatewayCommand;
 import org.apache.cloudstack.agent.api.DeleteNsxSegmentCommand;
-import org.apache.cloudstack.agent.api.DeleteNsxStaticNatCommand;
+import org.apache.cloudstack.agent.api.DeleteNsxNatRuleCommand;
 import org.apache.cloudstack.agent.api.DeleteNsxTier1GatewayCommand;
 import org.apache.cloudstack.service.NsxApiClient;
 import org.apache.cloudstack.utils.NsxControllerUtils;
@@ -108,8 +110,10 @@ public class NsxResource implements ServerResource {
             return executeRequest((CreateNsxDhcpRelayConfigCommand) cmd);
         } else if (cmd instanceof CreateNsxStaticNatCommand) {
             return executeRequest((CreateNsxStaticNatCommand) cmd);
-        } else if (cmd instanceof DeleteNsxStaticNatCommand) {
-            return executeRequest((DeleteNsxStaticNatCommand) cmd);
+        } else if (cmd instanceof DeleteNsxNatRuleCommand) {
+            return executeRequest((DeleteNsxNatRuleCommand) cmd);
+        } else if (cmd instanceof CreateNsxPortForwardRuleCommand) {
+          return executeRequest((CreateNsxPortForwardRuleCommand) cmd);
         } else {
             return Answer.createUnsupportedCommandAnswer(cmd);
         }
@@ -345,27 +349,52 @@ public class NsxResource implements ServerResource {
 
     private NsxAnswer executeRequest(CreateNsxStaticNatCommand cmd) {
         String staticNatRuleName = 
NsxControllerUtils.getStaticNatRuleName(cmd.getDomainId(), cmd.getAccountId(), 
cmd.getZoneId(),
-                cmd.getVpcId());
+                cmd.getNetworkResourceId(), cmd.isResourceVpc());
         String tier1GatewayName = 
NsxControllerUtils.getTier1GatewayName(cmd.getDomainId(), cmd.getAccountId(), 
cmd.getZoneId(),
-                cmd.getVpcId());
+                cmd.getNetworkResourceId(), cmd.isResourceVpc());
         try {
-            nsxApiClient.createStaticNatRule(cmd.getVpcName(), 
tier1GatewayName, staticNatRuleName, cmd.getPublicIp(), cmd.getVmIp());
+            nsxApiClient.createStaticNatRule(cmd.getNetworkResourceName(), 
tier1GatewayName, staticNatRuleName, cmd.getPublicIp(), cmd.getVmIp());
         } catch (Exception e) {
-            LOGGER.error(String.format("Failed to add NSX static NAT rule %s 
for network: %s", staticNatRuleName, cmd.getVpcName()));
+            LOGGER.error(String.format("Failed to add NSX static NAT rule %s 
for network: %s", staticNatRuleName, cmd.getNetworkResourceName()));
             return new NsxAnswer(cmd, new 
CloudRuntimeException(e.getMessage()));
         }
         return new NsxAnswer(cmd, true, null);
     }
 
-    private NsxAnswer executeRequest(DeleteNsxStaticNatCommand cmd) {
-        String staticNatRuleName = 
NsxControllerUtils.getStaticNatRuleName(cmd.getDomainId(), cmd.getAccountId(), 
cmd.getZoneId(),
-                cmd.getVpcId());
+    private NsxAnswer executeRequest(DeleteNsxNatRuleCommand cmd) {
+        String ruleName = null;
+        if (cmd.getService() == Network.Service.StaticNat) {
+            ruleName = 
NsxControllerUtils.getStaticNatRuleName(cmd.getDomainId(), cmd.getAccountId(), 
cmd.getZoneId(),
+                    cmd.getNetworkResourceId(), cmd.isResourceVpc());
+        } else if (cmd.getService() == Network.Service.PortForwarding) {
+            ruleName = 
NsxControllerUtils.getPortForwardRuleName(cmd.getDomainId(), 
cmd.getAccountId(), cmd.getZoneId(),
+                    cmd.getNetworkResourceId(), cmd.getRuleId(), 
cmd.isResourceVpc());
+        }
         String tier1GatewayName = 
NsxControllerUtils.getTier1GatewayName(cmd.getDomainId(), cmd.getAccountId(), 
cmd.getZoneId(),
-                cmd.getVpcId());
+                cmd.getNetworkResourceId(), cmd.isResourceVpc());
         try {
-            nsxApiClient.deleteStaticNatRule(cmd.getVpcName(), 
tier1GatewayName, staticNatRuleName);
+            nsxApiClient.deleteNatRule(cmd.getNetworkResourceName(), 
tier1GatewayName, ruleName);
+        } catch (Exception e) {
+            LOGGER.error(String.format("Failed to add NSX static NAT rule %s 
for network: %s", ruleName, cmd.getNetworkResourceName()));
+            return new NsxAnswer(cmd, new 
CloudRuntimeException(e.getMessage()));
+        }
+        return new NsxAnswer(cmd, true, null);
+    }
+
+    private NsxAnswer executeRequest(CreateNsxPortForwardRuleCommand cmd) {
+        String ruleName = 
NsxControllerUtils.getPortForwardRuleName(cmd.getDomainId(), 
cmd.getAccountId(), cmd.getZoneId(),
+                cmd.getNetworkResourceId(), cmd.getRuleId(), 
cmd.isResourceVpc());
+        String tier1GatewayName = 
NsxControllerUtils.getTier1GatewayName(cmd.getDomainId(), cmd.getAccountId(), 
cmd.getZoneId(),
+                cmd.getNetworkResourceId(), cmd.isResourceVpc());
+        try {
+            String privatePort = cmd.getPrivatePort();
+            String service = privatePort.contains("-") ? 
nsxApiClient.createNsxInfraService(ruleName, privatePort, cmd.getProtocol()) :
+                    nsxApiClient.getNsxInfraServices(ruleName, privatePort, 
cmd.getProtocol());
+
+            nsxApiClient.createPortForwardingRule(ruleName, tier1GatewayName, 
cmd.getNetworkResourceName(), cmd.getPublicIp(),
+                    cmd.getVmIp(), cmd.getPublicPort(), service);
         } catch (Exception e) {
-            LOGGER.error(String.format("Failed to add NSX static NAT rule %s 
for network: %s", staticNatRuleName, cmd.getVpcName()));
+            LOGGER.error(String.format("Failed to add NSX port forward rule %s 
for network: %s", ruleName, cmd.getNetworkResourceName()));
             return new NsxAnswer(cmd, new 
CloudRuntimeException(e.getMessage()));
         }
         return new NsxAnswer(cmd, true, null);
diff --git 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java
 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java
index 3fafff9813b..815dad97ea0 100644
--- 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java
+++ 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java
@@ -22,6 +22,7 @@ import com.vmware.nsx.model.TransportZone;
 import com.vmware.nsx.model.TransportZoneListResult;
 import com.vmware.nsx_policy.infra.DhcpRelayConfigs;
 import com.vmware.nsx_policy.infra.Segments;
+import com.vmware.nsx_policy.infra.Services;
 import com.vmware.nsx_policy.infra.Sites;
 import com.vmware.nsx_policy.infra.Tier1s;
 import com.vmware.nsx_policy.infra.sites.EnforcementPoints;
@@ -30,10 +31,12 @@ import com.vmware.nsx_policy.infra.tier_1s.nat.NatRules;
 import com.vmware.nsx_policy.model.ApiError;
 import com.vmware.nsx_policy.model.DhcpRelayConfig;
 import com.vmware.nsx_policy.model.EnforcementPointListResult;
+import com.vmware.nsx_policy.model.L4PortSetServiceEntry;
 import com.vmware.nsx_policy.model.LocaleServicesListResult;
 import com.vmware.nsx_policy.model.PolicyNatRule;
 import com.vmware.nsx_policy.model.Segment;
 import com.vmware.nsx_policy.model.SegmentSubnet;
+import com.vmware.nsx_policy.model.ServiceListResult;
 import com.vmware.nsx_policy.model.SiteListResult;
 import com.vmware.nsx_policy.model.Tier1;
 import com.vmware.vapi.bindings.Service;
@@ -48,10 +51,13 @@ import 
com.vmware.vapi.internal.protocol.client.rest.authn.BasicAuthenticationAp
 import com.vmware.vapi.protocol.HttpConfiguration;
 import com.vmware.vapi.std.errors.Error;
 import org.apache.cloudstack.utils.NsxControllerUtils;
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.log4j.Logger;
 
 import java.util.List;
+import java.util.Objects;
 import java.util.function.Function;
+import java.util.stream.Collectors;
 
 public class NsxApiClient {
 
@@ -326,17 +332,120 @@ public class NsxApiClient {
         }
     }
 
-    public void deleteStaticNatRule(String vpcName, String tier1GatewayName, 
String ruleName) {
+    public void deleteNatRule(String networkName, String tier1GatewayName, 
String ruleName) {
         try {
             NatRules natService = (NatRules) nsxService.apply(NatRules.class);
-            LOGGER.debug(String.format("Deleting NSX static NAT rule %s for 
tier-1 gateway %s (VPC: %s)", ruleName, tier1GatewayName, vpcName));
+            LOGGER.debug(String.format("Deleting NSX static NAT rule %s for 
tier-1 gateway %s (network: %s)", ruleName, tier1GatewayName, networkName));
             natService.delete(tier1GatewayName, NatId.USER.name(), ruleName);
         } catch (Error error) {
             ApiError ae = error.getData()._convertTo(ApiError.class);
             String msg = String.format("Failed to delete NSX Static NAT rule 
%s for tier-1 gateway %s (VPC: %s), due to %s",
-                    ruleName, tier1GatewayName, vpcName, ae.getErrorMessage());
+                    ruleName, tier1GatewayName, networkName, 
ae.getErrorMessage());
             LOGGER.error(msg);
             throw new CloudRuntimeException(msg);
         }
     }
+
+    public void createPortForwardingRule(String ruleName, String 
tier1GatewayName, String networkName, String publicIp,
+                                         String vmIp, String publicPort, 
String service) {
+        try {
+            NatRules natService = (NatRules) nsxService.apply(NatRules.class);
+            LOGGER.debug(String.format("Creating NSX Port-Forwarding NAT %s 
for network %s", ruleName, networkName));
+            PolicyNatRule rule = new PolicyNatRule.Builder()
+                    .setId(ruleName)
+                    .setDisplayName(ruleName)
+                    .setAction(NatAction.DNAT.name())
+                    
.setFirewallMatch(FirewallMatch.MATCH_INTERNAL_ADDRESS.name())
+                    .setDestinationNetwork(publicIp)
+                    .setTranslatedNetwork(vmIp)
+                    .setTranslatedPorts(String.valueOf(publicPort))
+                    .setService(service)
+                    .setEnabled(true)
+                    .build();
+            natService.patch(tier1GatewayName, NatId.USER.name(), ruleName, 
rule);
+        } catch (Error error) {
+            ApiError ae = error.getData()._convertTo(ApiError.class);
+            String msg = String.format("Failed to delete NSX Port-forward rule 
%s for network: %s, due to %s",
+                    ruleName, networkName, ae.getErrorMessage());
+            LOGGER.error(msg);
+            throw new CloudRuntimeException(msg);
+        }
+    }
+
+    public String getNsxInfraServices(String ruleName, String port, String 
protocol) {
+        try {
+            Services service = (Services) nsxService.apply(Services.class);
+
+            // Find default service if present
+            ServiceListResult serviceList = service.list(null, true, false, 
null, null, null, null);
+
+            List<com.vmware.nsx_policy.model.Service> services = 
serviceList.getResults();
+            List<String> matchedDefaultSvc = 
services.parallelStream().filter(svc ->
+                            (svc.getServiceEntries().get(0) instanceof 
L4PortSetServiceEntry) &&
+                                    ((L4PortSetServiceEntry) 
svc.getServiceEntries().get(0)).getDestinationPorts().get(0).equals(port)
+                    && (((L4PortSetServiceEntry) 
svc.getServiceEntries().get(0)).getL4Protocol().equals(protocol)))
+                    .map(svc -> ((L4PortSetServiceEntry) 
svc.getServiceEntries().get(0)).getDestinationPorts().get(0))
+                    .collect(Collectors.toList());
+            if (!CollectionUtils.isEmpty(matchedDefaultSvc)) {
+                return matchedDefaultSvc.get(0);
+            }
+
+            // Else, find if there's a service matching the rule name
+            String servicePath = getServiceById(ruleName);
+            if (Objects.nonNull(servicePath)) {
+                return servicePath;
+            }
+
+            // Else, create a service entry
+            return createNsxInfraService(ruleName, port, protocol);
+        } catch (Error error) {
+            ApiError ae = error.getData()._convertTo(ApiError.class);
+            String msg = String.format("Failed to list NSX infra service, due 
to: %s", ae.getErrorMessage());
+            LOGGER.error(msg);
+            throw new CloudRuntimeException(msg);
+        }
+    }
+
+    public String createNsxInfraService(String ruleName, String port, String 
protocol) {
+        try {
+            String serviceEntryName = ruleName + "-SE-" + port;
+            String serviceName = ruleName + "-SVC-" + port;
+            Services service = (Services) nsxService.apply(Services.class);
+            com.vmware.nsx_policy.model.Service infraService = new 
com.vmware.nsx_policy.model.Service.Builder()
+                    .setServiceEntries(List.of(
+                            new L4PortSetServiceEntry.Builder()
+                                    .setId(serviceEntryName)
+                                    .setDisplayName(serviceEntryName)
+                                    .setDestinationPorts(List.of(port))
+                                    .setL4Protocol(protocol)
+                                    .build()
+                    ))
+                    .setId(serviceName)
+                    .setDisplayName(serviceName)
+                    .build();
+            service.patch(serviceName, infraService);
+
+            com.vmware.nsx_policy.model.Service svc = service.get(serviceName);
+            return 
svc.getServiceEntries().get(0)._getDataValue().getField("parent_path").toString();
+
+        } catch (Error error) {
+            ApiError ae = error.getData()._convertTo(ApiError.class);
+            String msg = String.format("Failed to create NSX infra service, 
due to: %s", ae.getErrorMessage());
+            LOGGER.error(msg);
+            throw new CloudRuntimeException(msg);
+        }
+    }
+
+    private String getServiceById(String ruleName) {
+        try {
+            Services service = (Services) nsxService.apply(Services.class);
+            com.vmware.nsx_policy.model.Service svc1 = service.get(ruleName);
+            if (Objects.nonNull(svc1)) {
+                return ((L4PortSetServiceEntry) 
svc1.getServiceEntries().get(0)).getParentPath();
+            }
+        } catch (Exception e) {
+            return null;
+        }
+        return null;
+    }
 }
diff --git 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java
 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java
index 008e25e197f..27c2f67759c 100644
--- 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java
+++ 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java
@@ -24,6 +24,7 @@ import com.cloud.agent.api.AgentControlCommand;
 import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.Command;
 import com.cloud.agent.api.StartupCommand;
+import com.cloud.api.ApiDBUtils;
 import com.cloud.dc.DataCenterVO;
 import com.cloud.dc.dao.DataCenterDao;
 import com.cloud.deploy.DeployDestination;
@@ -51,13 +52,18 @@ import com.cloud.network.dao.PhysicalNetworkVO;
 import com.cloud.network.element.DhcpServiceProvider;
 import com.cloud.network.element.DnsServiceProvider;
 import com.cloud.network.element.IpDeployer;
+import com.cloud.network.element.PortForwardingServiceProvider;
 import com.cloud.network.element.StaticNatServiceProvider;
 import com.cloud.network.element.VpcProvider;
+import com.cloud.network.rules.FirewallRule;
+import com.cloud.network.rules.PortForwardingRule;
 import com.cloud.network.rules.StaticNat;
 import com.cloud.network.vpc.NetworkACLItem;
 import com.cloud.network.vpc.PrivateGateway;
 import com.cloud.network.vpc.StaticRouteProfile;
 import com.cloud.network.vpc.Vpc;
+import com.cloud.network.vpc.VpcVO;
+import com.cloud.network.vpc.dao.VpcDao;
 import com.cloud.offering.NetworkOffering;
 import com.cloud.resource.ResourceManager;
 import com.cloud.resource.ResourceStateAdapter;
@@ -65,6 +71,7 @@ import com.cloud.resource.ServerResource;
 import com.cloud.resource.UnableDeleteHostException;
 import com.cloud.user.Account;
 import com.cloud.user.AccountManager;
+import com.cloud.uservm.UserVm;
 import com.cloud.utils.Pair;
 import com.cloud.utils.component.AdapterBase;
 import com.cloud.utils.exception.CloudRuntimeException;
@@ -76,6 +83,7 @@ import com.cloud.vm.VirtualMachineProfile;
 import com.cloud.vm.dao.VMInstanceDao;
 import net.sf.ehcache.config.InvalidConfigurationException;
 import org.apache.cloudstack.StartupNsxCommand;
+import org.apache.cloudstack.resource.NsxNetworkRule;
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
@@ -83,6 +91,7 @@ import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
@@ -90,7 +99,7 @@ import java.util.function.LongFunction;
 
 @Component
 public class NsxElement extends AdapterBase implements DhcpServiceProvider, 
DnsServiceProvider, VpcProvider,
-        StaticNatServiceProvider, IpDeployer, ResourceStateAdapter, Listener {
+        StaticNatServiceProvider, IpDeployer, PortForwardingServiceProvider, 
ResourceStateAdapter, Listener {
 
     @Inject
     AccountManager accountMgr;
@@ -114,6 +123,8 @@ public class NsxElement extends AdapterBase implements 
DhcpServiceProvider, DnsS
     IPAddressDao ipAddressDao;
     @Inject
     VMInstanceDao vmInstanceDao;
+    @Inject
+    VpcDao vpcDao;
 
     private static final Logger LOGGER = Logger.getLogger(NsxElement.class);
 
@@ -452,14 +463,99 @@ public class NsxElement extends AdapterBase implements 
DhcpServiceProvider, DnsS
             }
             Nic nic = networkModel.getNicInNetworkIncludingRemoved(vm.getId(), 
config.getId());
             Network publicNetwork = 
networkModel.getSystemNetworkByZoneAndTrafficType(config.getDataCenterId(), 
Networks.TrafficType.Public);
+            Pair<VpcVO, NetworkVO> vpcOrNetwork = 
getVpcOrNetwork(config.getVpcId(), config.getId());
+            VpcVO vpc = vpcOrNetwork.first();
+            NetworkVO network = vpcOrNetwork.second();
+            Long networkResourceId = Objects.nonNull(vpc) ? vpc.getId() : 
network.getId();
+            String networkResourceName = Objects.nonNull(vpc) ? vpc.getName() 
: network.getName();
+            boolean isVpcResource = Objects.nonNull(vpc);
             if (!staticNat.isForRevoke()) {
                 return 
nsxService.createStaticNatRule(config.getDataCenterId(), config.getDomainId(), 
config.getAccountId(),
-                        config.getVpcId(), vm.getId(), 
ipAddressVO.getAddress().addr(), staticNat.getDestIpAddress());
+                        networkResourceId, networkResourceName, isVpcResource, 
vm.getId(),
+                        ipAddressVO.getAddress().addr(), 
staticNat.getDestIpAddress());
             } else {
                 return 
nsxService.deleteStaticNatRule(config.getDataCenterId(), config.getDomainId(), 
config.getAccountId(),
-                        config.getVpcId());
+                        networkResourceId, networkResourceName, isVpcResource);
             }
         }
         return false;
     }
+
+    @Override
+    public boolean applyPFRules(Network network, List<PortForwardingRule> 
rules) throws ResourceUnavailableException {
+        if (!canHandle(network, Network.Service.PortForwarding)) {
+            return false;
+        }
+        for (PortForwardingRule rule : rules) {
+            IPAddressVO publicIp = 
ApiDBUtils.findIpAddressById(rule.getSourceIpAddressId());
+            UserVm vm = ApiDBUtils.findUserVmById(rule.getVirtualMachineId());
+            if (vm == null || networkModel.getNicInNetwork(vm.getId(), 
network.getId()) == null) {
+                continue;
+            }
+            Pair<VpcVO, NetworkVO> vpcOrNetwork = 
getVpcOrNetwork(network.getVpcId(), network.getId());
+            VpcVO vpc = vpcOrNetwork.first();
+            NetworkVO networkVO = vpcOrNetwork.second();
+            Long networkResourceId = Objects.nonNull(vpc) ? vpc.getId() : 
networkVO.getId();
+            String networkResourceName = Objects.nonNull(vpc) ? vpc.getName() 
: networkVO.getName();
+            boolean isVpcResource = Objects.nonNull(vpc);
+            long domainId = Objects.nonNull(vpc) ? vpc.getDomainId() : 
networkVO.getDomainId();
+            long accountId = Objects.nonNull(vpc) ? vpc.getAccountId() : 
networkVO.getAccountId();
+            long zoneId = Objects.nonNull(vpc) ? vpc.getZoneId() : 
networkVO.getDataCenterId();
+            String publicPort = getPublicPortRange(rule);
+
+            String privatePort = getPrivatePortRange(rule);
+
+            // TODO: add builder to reduce signature params ; should we pass 
port range?
+            NsxNetworkRule networkRule = new NsxNetworkRule.Builder()
+                    .setDomainId(domainId)
+                    .setAccountId(accountId)
+                    .setZoneId(zoneId)
+                    .setNetworkResourceId(networkResourceId)
+                    .setNetworkResourceName(networkResourceName)
+                    .setVpcResource(isVpcResource)
+                    .setVmId(vm.getId())
+                    .setVmIp(vm.getPrivateIpAddress())
+                    .setPublicIp(publicIp.getAddress().addr())
+                    .setPrivatePort(privatePort)
+                    .setPublicPort(publicPort)
+                    .setRuleId(rule.getId())
+                    .setProtocol(rule.getProtocol().toUpperCase(Locale.ROOT))
+                    .build();
+            if (rule.getState() == FirewallRule.State.Add) {
+                return nsxService.createPortForwardRule(networkRule);
+            } else {
+                return nsxService.deletePortForwardRule(networkRule);
+            }
+        }
+        return true;
+    }
+
+    public Pair<VpcVO, NetworkVO> getVpcOrNetwork(Long vpcId, long networkId) {
+        VpcVO vpc = null;
+        NetworkVO network = null;
+        if (Objects.nonNull(vpcId)) {
+            vpc = vpcDao.findById(vpcId);
+            if (Objects.isNull(vpc)) {
+                throw new CloudRuntimeException(String.format("Failed to find 
VPC with id: %s", vpcId));
+            }
+        } else {
+            network = networkDao.findById(networkId);
+            if (Objects.isNull(network)) {
+                throw new CloudRuntimeException(String.format("Failed to find 
network with id: %s", networkId));
+            }
+        }
+        return new Pair<>(vpc, network);
+    }
+
+    private static String getPublicPortRange(PortForwardingRule rule) {
+        return rule.getDestinationPortStart() == rule.getDestinationPortEnd() ?
+                String.valueOf(rule.getDestinationPortStart()) :
+                
String.valueOf(rule.getDestinationPortStart()).concat("-").concat(String.valueOf(rule.getDestinationPortEnd()));
+    }
+
+    private static String getPrivatePortRange(PortForwardingRule rule) {
+        return Objects.equals(rule.getSourcePortStart(), 
rule.getSourcePortEnd()) ?
+                String.valueOf(rule.getSourcePortStart()) :
+                
String.valueOf(rule.getSourcePortStart()).concat("-").concat(String.valueOf(rule.getSourcePortEnd()));
+    }
 }
diff --git 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxServiceImpl.java
 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxServiceImpl.java
index 5cd7001c5e7..466b75b78a3 100644
--- 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxServiceImpl.java
+++ 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxServiceImpl.java
@@ -16,16 +16,20 @@
 // under the License.
 package org.apache.cloudstack.service;
 
+import com.cloud.network.Network;
+import com.cloud.network.dao.NetworkDao;
 import com.cloud.network.dao.NetworkVO;
 import com.cloud.network.vpc.VpcVO;
 import com.cloud.network.vpc.dao.VpcDao;
 import com.cloud.utils.exception.CloudRuntimeException;
 import org.apache.cloudstack.NsxAnswer;
+import org.apache.cloudstack.agent.api.CreateNsxPortForwardRuleCommand;
 import org.apache.cloudstack.agent.api.CreateNsxStaticNatCommand;
 import org.apache.cloudstack.agent.api.CreateNsxTier1GatewayCommand;
 import org.apache.cloudstack.agent.api.DeleteNsxSegmentCommand;
-import org.apache.cloudstack.agent.api.DeleteNsxStaticNatCommand;
+import org.apache.cloudstack.agent.api.DeleteNsxNatRuleCommand;
 import org.apache.cloudstack.agent.api.DeleteNsxTier1GatewayCommand;
+import org.apache.cloudstack.resource.NsxNetworkRule;
 import org.apache.cloudstack.utils.NsxControllerUtils;
 import org.apache.log4j.Logger;
 
@@ -37,6 +41,8 @@ public class NsxServiceImpl implements NsxService {
     NsxControllerUtils nsxControllerUtils;
     @Inject
     VpcDao vpcDao;
+    @Inject
+    NetworkDao networkDao;
 
     private static final Logger LOGGER = 
Logger.getLogger(NsxServiceImpl.class);
 
@@ -83,26 +89,39 @@ public class NsxServiceImpl implements NsxService {
         return result.getResult();
     }
 
-    public boolean createStaticNatRule(long zoneId, long domainId, long 
accountId, long vpcId,
-                                       long vmId, String publicIp, String 
vmIp) {
-        VpcVO vpc = vpcDao.findById(vpcId);
-        if (Objects.isNull(vpc)) {
-            throw new CloudRuntimeException(String.format("Failed to find VPC 
with id: %s", vpcId));
-        }
+    public boolean createStaticNatRule(long zoneId, long domainId, long 
accountId, Long networkResourceId, String networkResourceName,
+                                       boolean isVpcResource, long vmId, 
String publicIp, String vmIp) {
         CreateNsxStaticNatCommand createNsxStaticNatCommand = new 
CreateNsxStaticNatCommand(domainId, accountId, zoneId,
-                vpcId, vpc.getName(), vmId, publicIp, vmIp);
+                networkResourceId, networkResourceName, isVpcResource, vmId, 
publicIp, vmIp);
         NsxAnswer result = 
nsxControllerUtils.sendNsxCommand(createNsxStaticNatCommand, zoneId);
         return result.getResult();
     }
 
-    public boolean deleteStaticNatRule(long zoneId, long domainId, long 
accountId, long vpcId) {
-        VpcVO vpc = vpcDao.findById(vpcId);
-        if (Objects.isNull(vpc)) {
-            throw new CloudRuntimeException(String.format("Failed to find VPC 
with id: %s", vpcId));
-        }
-        DeleteNsxStaticNatCommand deleteNsxStaticNatCommand = new 
DeleteNsxStaticNatCommand(domainId, accountId, zoneId,
-                vpcId, vpc.getName());
+    public boolean deleteStaticNatRule(long zoneId, long domainId, long 
accountId, Long networkResourceId, String networkResourceName,
+                                       boolean isVpcResource) {
+        DeleteNsxNatRuleCommand deleteNsxStaticNatCommand = new 
DeleteNsxNatRuleCommand(domainId, accountId, zoneId,
+                networkResourceId, networkResourceName, isVpcResource, null, 
null, null, null);
+        deleteNsxStaticNatCommand.setService(Network.Service.StaticNat);
         NsxAnswer result = 
nsxControllerUtils.sendNsxCommand(deleteNsxStaticNatCommand, zoneId);
         return result.getResult();
     }
+
+    public boolean createPortForwardRule(NsxNetworkRule netRule) {
+        // TODO: if port doesn't exist in default list of services, create a 
service entry
+        CreateNsxPortForwardRuleCommand createPortForwardCmd = new 
CreateNsxPortForwardRuleCommand(netRule.getDomainId(),
+                netRule.getAccountId(), netRule.getZoneId(), 
netRule.getNetworkResourceId(),
+                netRule.getNetworkResourceName(), netRule.isVpcResource(), 
netRule.getVmId(), netRule.getRuleId(),
+                netRule.getPublicIp(), netRule.getVmIp(), 
netRule.getPublicPort(), netRule.getPrivatePort(), netRule.getProtocol());
+        NsxAnswer result = 
nsxControllerUtils.sendNsxCommand(createPortForwardCmd, netRule.getZoneId());
+        return result.getResult();
+    }
+
+    public boolean deletePortForwardRule(NsxNetworkRule netRule) {
+        DeleteNsxNatRuleCommand deleteCmd = new 
DeleteNsxNatRuleCommand(netRule.getDomainId(),
+                netRule.getAccountId(), netRule.getZoneId(), 
netRule.getNetworkResourceId(),
+                netRule.getNetworkResourceName(), netRule.isVpcResource(),  
netRule.getVmId(), netRule.getRuleId(), null, null);
+        deleteCmd.setService(Network.Service.PortForwarding);
+        NsxAnswer result = nsxControllerUtils.sendNsxCommand(deleteCmd, 
netRule.getZoneId());
+        return result.getResult();
+    }
 }
diff --git 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxServiceList.java
 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxServiceList.java
new file mode 100644
index 00000000000..05ea43fde9b
--- /dev/null
+++ 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxServiceList.java
@@ -0,0 +1,17 @@
+package org.apache.cloudstack.service;
+
+public enum NsxServiceList {
+    AD_Server(1024, "/infra/services/AD_Server", "TCP"),
+    Active_Directory_Server(464, "/infra/services/Active_Directory_Server", 
"TCP"),
+    SSH(22, "/infra/services/SSH", "TCP");
+
+    int port;
+    String service;
+    String path;
+    String protocol;
+    NsxServiceList(int port, String path, String protocol) {
+        this.port = port;
+        this.path = path;
+        this.protocol = protocol;
+    }
+}
diff --git 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/utils/NsxControllerUtils.java
 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/utils/NsxControllerUtils.java
index 1ac04200ce3..8c545476a6e 100644
--- 
a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/utils/NsxControllerUtils.java
+++ 
b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/utils/NsxControllerUtils.java
@@ -81,8 +81,13 @@ public class NsxControllerUtils {
         return String.format("D%s-A%s-Z%s-V%s-S%s-%s", domainId, accountId, 
zoneId, vpcId, networkId, suffix);
     }
 
-    public static String getStaticNatRuleName(long domainId, long accountId, 
long zoneId, Long vpcId) {
+    public static String getStaticNatRuleName(long domainId, long accountId, 
long zoneId, Long networkResourceId, boolean isVpcResource) {
         String suffix = "-STATICNAT";
-       return getTier1GatewayName(domainId, accountId, zoneId, vpcId) + suffix;
+       return getTier1GatewayName(domainId, accountId, zoneId, 
networkResourceId, isVpcResource) + suffix;
+    }
+
+    public static String getPortForwardRuleName(long domainId, long accountId, 
long zoneId, Long networkResourceId, long ruleId, boolean isVpcResource) {
+        String suffix = "-PF";
+        return getTier1GatewayName(domainId, accountId, zoneId, 
networkResourceId, isVpcResource) + suffix + ruleId;
     }
 }
diff --git a/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java 
b/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java
index 610be14dfef..031f622e30d 100644
--- a/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java
+++ b/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java
@@ -1248,6 +1248,8 @@ public class ConfigurationServerImpl extends ManagerBase 
implements Configuratio
         if (nsxMode == NetworkOffering.NsxMode.NATTED) {
             serviceProviderMap.put(Service.SourceNat, Provider.Nsx);
             serviceProviderMap.put(Service.StaticNat, Provider.Nsx);
+            serviceProviderMap.put(Service.PortForwarding, Provider.Nsx);
+            serviceProviderMap.put(Service.Lb, Provider.Nsx);
         }
         return serviceProviderMap;
     }

Reply via email to