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