On Fri, Mar 10, 2017 at 07:46:58AM +0530, nusid...@redhat.com wrote:
> From: Numan Siddique <nusid...@redhat.com>
> 
> If the CMS wants to make use of ovn ipam it can now provide a
> list of IPv4 addresses and a range of IPv4 addresses which
> will be excluded from the dynamic address assignment.
> To support this, a new option 'exclude_ips' is added in the
> Logical_switch.other_config column.
> 
> Eg. ovn-nbctl set Logical_switch sw0
> other_config:exclude_ips="10.0.0.2 10.0.0.30..10.0.0.40"
> 
> The present code, uses hash maps to store the assigned IP addresses.
> In order to support this option, this patch has refactored the IPAM
> assignment. It now uses a bitmap to manage the IP assignment with
> each bit in the bitmap representing an IPv4 address.
> 
> This patch also clears the 'Logical_switch_port.dynamic_addresses'
> if the CMS has cleared 'dynamic' address assignment request.
> 
> Signed-off-by: Numan Siddique <nusid...@redhat.com>

Thanks a lot for working on this!  I apologize that it took a long time
to review it.

I'm going to apply this to master in a few minutes.  I'm folding in the
following.

diff --git a/NEWS b/NEWS
index 05af97a1f030..8607b04b6ed5 100644
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,7 @@ Post-v2.7.0
    - New support for multiple VLANs (802.1ad or "QinQ"), including a new
      "dot1q-tunnel" port VLAN mode.
    - OVN:
+     * IPAM for IPv4 can now exclude user-defined addresses from assignment.
      * Make the DHCPv4 router setting optional.
      * Gratuitous ARP for NAT addresses on a distributed logical router.
      * Allow ovn-controller SSL configuration to be obtained from vswitchd
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index 390a8bbad641..878fb7295e33 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -544,40 +544,40 @@ init_ipam_info_for_datapath(struct ovn_datapath *od)
     /* exclude_ip_list could be in the format -
     *  "10.0.0.4 10.0.0.10 10.0.0.20..10.0.0.50 10.0.0.100..10.0.0.110".
     */
-    while(lexer_get(&lexer) || lexer.error) {
+    lexer_get(&lexer);
+    while (lexer.token.type != LEX_T_END) {
         if (lexer.token.type != LEX_T_INTEGER) {
+            lexer_syntax_error(&lexer, "expecting address");
             break;
         }
-        uint32_t start_ipv4 = 0;
-        uint32_t end_ipv4 = 0;
+        uint32_t start = ntohl(lexer.token.value.ipv4);
+        lexer_get(&lexer);
 
-        start_ipv4 = ntohl(lexer.token.value.ipv4);
-        if(lexer_lookahead(&lexer) == LEX_T_ELLIPSIS) {
-            lexer_get(&lexer);
-            lexer_get(&lexer);
+        uint32_t end = start + 1;
+        if (lexer_match(&lexer, LEX_T_ELLIPSIS)) {
             if (lexer.token.type != LEX_T_INTEGER) {
+                lexer_syntax_error(&lexer, "expecting address range");
                 break;
             }
-            end_ipv4 = ntohl(lexer.token.value.ipv4);
-        }
-
-        /* Validate start_ipv4. */
-        if ((end_ipv4 && start_ipv4 > end_ipv4) ||
-             start_ipv4 < od->ipam_info->start_ipv4 ||
-             start_ipv4 > (od->ipam_info->start_ipv4 +
-                           od->ipam_info->total_ipv4s)) {
-            /* Invalid format. Continue so we can parse further.*/
-            continue;
+            end = ntohl(lexer.token.value.ipv4) + 1;
+            lexer_get(&lexer);
         }
 
-        if (end_ipv4 > (
-                od->ipam_info->start_ipv4 + od->ipam_info->total_ipv4s)) {
-            continue;
+        /* Clamp start...end to fit the subnet. */
+        start = MAX(od->ipam_info->start_ipv4, start);
+        end = MIN(od->ipam_info->start_ipv4 + od->ipam_info->total_ipv4s, end);
+        if (end > start) {
+            bitmap_set_multiple(od->ipam_info->allocated_ipv4s,
+                                start - od->ipam_info->start_ipv4,
+                                end - start, 1);
+        } else {
+            lexer_error(&lexer, "excluded addresses not in subnet");
         }
-
-        size_t count = end_ipv4 ? (end_ipv4 - start_ipv4) + 1 : 1;
-        bitmap_set_multiple(od->ipam_info->allocated_ipv4s,
-                            start_ipv4 - od->ipam_info->start_ipv4, count, 1);
+    }
+    if (lexer.error) {
+        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
+        VLOG_WARN_RL(&rl, "logical switch "UUID_FMT": bad exclude_ips (%s)",
+                     UUID_ARGS(&od->key), lexer.error);
     }
     lexer_destroy(&lexer);
 }
@@ -894,7 +894,8 @@ ipam_insert_ip(struct ovn_datapath *od, uint32_t ip)
 
     if (ip >= od->ipam_info->start_ipv4 &&
         ip < (od->ipam_info->start_ipv4 + od->ipam_info->total_ipv4s)) {
-        bitmap_set1(od->ipam_info->allocated_ipv4s, ip - 
od->ipam_info->start_ipv4);
+        bitmap_set1(od->ipam_info->allocated_ipv4s,
+                    ip - od->ipam_info->start_ipv4);
     }
 }
 
diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml
index 75a249a9eb2b..68a00392760a 100644
--- a/ovn/ovn-nb.xml
+++ b/ovn/ovn-nb.xml
@@ -134,26 +134,35 @@
       QOS marking rules that apply to packets within the logical switch.
     </column>
 
-    <group title="other_config">
+    <group title="IP Address Assignment">
       <p>
-        Additional configuration options for the logical switch.
+        These options control automatic IP address management (IPAM) for ports
+        attached to the logical switch.  To enable IPAM, set <ref
+        column="other_config" key="subnet"/> and optionally <ref
+        column="other_config:exclude_ips"/>.  Then, to request dynamic address
+        assignment for a particular port, use the <code>dynamic</code> keyword
+        in the <ref table="Logical_Switch_Port" column="addresses"/> column of
+        the port's <ref table="Logical_Switch_Port"/> row.
       </p>
 
       <column name="other_config" key="subnet">
         Set this to an IPv4 subnet, e.g. <code>192.168.0.0/24</code>, to enable
         <code>ovn-northd</code> to automatically assign IP addresses within
-        that subnet.  Use the <code>dynamic</code> keyword in the <ref
-        table="Logical_Switch_Port"/> table's <ref table="Logical_Switch_Port"
-        column="addresses"/> column to request dynamic address assignment for a
-        particular port.
+        that subnet.  
       </column>
 
       <column name="other_config" key="exclude_ips">
-        Set this to a list of IPv4 addresses from the subnet if defined in the
-        <ref table="Logical_Switch_Port"/> table's <ref 
table="Logical_Switch_Port"
-        column="other_config:subnet"/> column. The defined list of IPs will
-        be excluded from the dynamic address assignment. A range can also be
-        specified.
+        <p>
+          To exclude some addresses from automatic IP address management, set
+          this to a list of the IPv4 addresses or <code>..</code>-delimited
+          ranges to exclude.  The addresses or ranges should be a subset of
+          those in <ref column="other_config" key="subnet"/>.
+        </p>
+        <p>
+          Whether listed or not, <code>ovn-northd</code> will never allocate
+          the first or last address in a subnet, such as 192.168.0.0 or
+          192.168.0.255 in 192.168.0.0/24.
+        </p>
         <p>
           Examples:
         </p>
@@ -1438,7 +1447,7 @@
         <column name="options" key="lease_time"
                 type='{"type": "integer", "minInteger": 0, "maxInteger": 
4294967295}'>
           <p>
-            The offered lease time in seconds,
+            The offered lease time in seconds, 
           </p>
 
           <p>
-- 
2.10.2

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to