Support range in port forwarding rules configuration

Registered by Pedro Henrique Pereira Martins

RFE: https://bugs.launchpad.net/neutron/+bug/1885921

Problem Description
=================

Currently, if a user wants to create NAT rules that cover multiple ports, he/she needs to create them one by one, which is cumbersome in some use cases. Having said that, we suggest changing the Floating IP port forwarding API to allow the use of port ranges to create NAT rules. The changes are presented as follows

Proposed Change
===============

### API JSON

We propose to extend the current floating IP port forwarding API to handle a range of ports instead of a one-to-one mapping. We have different alternatives to implement such a feature. We can change the JSON the API receives, adding new attributes, such as `internal_port_range` or `internal_port_beg` and `internal_port_end`, or we can just send a String in the attribute `internal_port` such as `80-83` and the same to the `external_port`.

For example:

Current JSON :

{
  "port_forwarding": {
    "protocol": "tcp",
    "internal_ip_address": "172.16.0.7",
    "internal_port": 80,
    "internal_port_id": "b67a7746-dc69-45b4-9b84-bb229fe198a0",
    "external_port": 8080,
    "description": "desc"
  }
}

Adding new attributes :

{
  "port_forwarding": {
    "protocol": "tcp",
    "internal_ip_address": "172.16.0.7",
    "internal_port_beg": 80,
    "internal_port_end": 83,
    "internal_port_id": "b67a7746-dc69-45b4-9b84-bb229fe198a0",
    "external_port_beg": 8080,
    "external_port_end": 8083,
    "description": "desc"
  }
}

Or, the alternative, changing the content of the attributes:

{
  "port_forwarding": {
    "protocol": "tcp",
    "internal_ip_address": "172.16.0.7",
    "internal_port": "80-83",
    "internal_port_id": "b67a7746-dc69-45b4-9b84-bb229fe198a0",
    "external_port": "8080-8083"
    "description": "desc"
  }
}

We believe that the last JSON format is the best one; because it generates fewer changes in the API usage and is simple for the user to understand and use. Therefore, these are the changes we are proposing to be implemented.

### Database persistence

Besides the JSON (rest API), we will need to change the way that the application persists the port forwarding rules in the database. We have two different alternatives to change the database schema.

Using the current database schema sample:

+-----------------------------------+-----------------------+-----------------------+
| id______________________| A1_____________| B4_____________|
+-----------------------------------+-----------------------+-----------------------+
| floatingip_id____________| C2_____________| C2______________|
+-----------------------------------+-----------------------+-----------------------+
| external_port___________| 80_____________| 81______________|
+-----------------------------------+-----------------------+-----------------------+
| internal_neutron_port_id | D3_____________| D3_____________|
+-----------------------------------+-----------------------+-----------------------+
| protocol________________| tcp____________| tcp_____________|
+-----------------------------------+-----------------------+-----------------------+
| socket__________________| 172.16.0.7:8080 | 172.16.0.7:8081 |
+-----------------------------------+-----------------------+-----------------------+

The above DB dump shows the scenario of a user creating a floatingip port forwarding rules with the port ranges 80-81 mapping into a VM ports range 8080-8081. Using this method, we will delegate all the responsibility of maintaining the ranges to the application level since the ports range is not specified in the DB schema.

On a different approach, we can work using an extended database schema:

+-----------------------------------+-----------------+
| id______________________| A1_________|
+-----------------------------------+-----------------+
| floatingip_id____________| C2_________|
+-----------------------------------+-----------------+
| external_port___________| 80-81______|
+-----------------------------------+-----------------+
| internal_neutron_port_id | D3_________|
+-----------------------------------+-----------------+
| protocol________________| tcp________|
+-----------------------------------+-----------------+
| internal_ip_address______| 172.16.0.7 _|
+-----------------------------------+-----------------+
| internal_port____________| 8080-8081 |
+-----------------------------------+-----------------+

Using the above proposal, we will reduce the number of entries in the database to represent a port range; therefore, we will remove from the application level the responsibility to find and join all the sequential ports in a floatingip id rule. However, the application has to handle ports collision.

We think that the last alternative for the DB schema changes suits better the context we have in Neutron, because we can easily see an entry in the DB table and identify the ports that this rule uses.

### Validations

Here follows a summary of all of the validation executed by the system:

    - Only N(external port[s]) to N (internal port[s]) are allowed or N(external port[s]) to 1 (internal port). Therefore, all of the other combinations (1-N, N-M, M-N) are not allowed and will generate an error

    - When defining a port(s) range, the ports in this range cannot be already in use by any other port forwarding rule for the same floating IP and protocol

    - A valid port is a number between 1 and 65535. All other cases will generate an error. Even though “0” is a valid port, we will not allow its use as it is reserved.

    - The notation to define a port range is the following: <port_range_begin>[-<port_range_end>]; anything that does not match this definition will generate an error.

This is the change we are proposing to be implemented.

Blueprint information

Status:
Complete
Approver:
None
Priority:
Undefined
Drafter:
Pedro Henrique Pereira Martins
Direction:
Approved
Assignee:
Pedro Henrique Pereira Martins
Definition:
Approved
Series goal:
None
Implementation:
Implemented
Milestone target:
None
Started by
Slawek Kaplonski
Completed by
Rodolfo Alonso

Related branches

Sprints

(?)

Work Items

Work items:
API def changes in neutron-lib: TODO
Neutron change: TODO
OpenstackSDK change: TODO
Python-openstackclient change: TODO

This blueprint contains Public information 
Everyone can see this information.