This patch alters the 'ovn-nbctl lsp-set-addresses' command to check if the IP addresses being added are duplicates of already-set IP addresses. Test cases have been added for this detection.
This patch also adds a warning message to ovn-northd if duplicate IPv4 addresses are detected on a switch. Signed-off-by: Mark Michelson <[email protected]> --- v2 -> v3: * Removed checks for duplicate MACs from ovn-nbctl. Based on tests for ovn-controller-vtep, it is legitimate to add multiple switch ports (on separate switches) with duplicate MACs. The duplicate address checking code has been updated as well. * Dynamic addressing test was updated since it attempted a test that now is invalid v1 -> v2: Fixed sparse warning from using htons() instead of htonl() --- ovn/northd/ovn-northd.c | 6 ++++ ovn/utilities/ovn-nbctl.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++ tests/ovn.at | 69 ++++++++++++++++++++++++++++++++++------ 3 files changed, 146 insertions(+), 10 deletions(-) diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c index 72e25181d..31ea5f410 100644 --- a/ovn/northd/ovn-northd.c +++ b/ovn/northd/ovn-northd.c @@ -944,6 +944,12 @@ 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)) { + if (bitmap_is_set(od->ipam_info.allocated_ipv4s, + ip - od->ipam_info.start_ipv4)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + VLOG_WARN_RL(&rl, "Duplicate IP set on switch %s: "IP_FMT, + od->nbs->name, IP_ARGS(htonl(ip))); + } bitmap_set1(od->ipam_info.allocated_ipv4s, ip - od->ipam_info.start_ipv4); } diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c index 4f7e7241a..eabd30308 100644 --- a/ovn/utilities/ovn-nbctl.c +++ b/ovn/utilities/ovn-nbctl.c @@ -1437,6 +1437,74 @@ nbctl_lsp_get_tag(struct ctl_context *ctx) } } +static char * +lsp_contains_duplicate_ip(struct lport_addresses *laddrs1, + struct lport_addresses *laddrs2) +{ + for (size_t i = 0; i < laddrs1->n_ipv4_addrs; i++) { + for (size_t j = 0; j < laddrs2->n_ipv4_addrs; j++) { + if (laddrs1->ipv4_addrs[i].addr == laddrs2->ipv4_addrs[j].addr) { + return xasprintf("duplicate IPv4 address %s", + laddrs1->ipv4_addrs[i].addr_s); + } + } + } + + for (size_t i = 0; i < laddrs1->n_ipv6_addrs; i++) { + for (size_t j = 0; j < laddrs2->n_ipv6_addrs; j++) { + if (IN6_ARE_ADDR_EQUAL(&laddrs1->ipv6_addrs[i].addr, + &laddrs2->ipv6_addrs[j].addr)) { + return xasprintf("duplicate IPv6 address %s", + laddrs1->ipv6_addrs[i].addr_s); + } + } + } + + return NULL; +} + +static char * +lsp_contains_duplicates(const struct nbrec_logical_switch *ls, + const struct nbrec_logical_switch_port *lsp, + const char *address) +{ + struct lport_addresses laddrs; + if (!extract_lsp_addresses(address, &laddrs)) { + return NULL; + } + + char *sub_error = NULL; + for (size_t i = 0; i < ls->n_ports; i++) { + struct nbrec_logical_switch_port *lsp_test = ls->ports[i]; + if (lsp_test == lsp) { + continue; + } + for (size_t j = 0; j < lsp_test->n_addresses; j++) { + struct lport_addresses laddrs_test; + char *addr = lsp_test->addresses[j]; + if (is_dynamic_lsp_address(addr)) { + addr = lsp_test->dynamic_addresses; + } + if (extract_lsp_addresses(addr, &laddrs_test)) { + sub_error = lsp_contains_duplicate_ip(&laddrs, &laddrs_test); + destroy_lport_addresses(&laddrs_test); + if (sub_error) { + goto err_out; + } + } + } + } + +err_out: ; + char *error = NULL; + if (sub_error) { + error = xasprintf("Error on switch %s: %s", ls->name, sub_error); + free(sub_error); + } + destroy_lport_addresses(&laddrs); + return error; +} + static void nbctl_lsp_set_addresses(struct ctl_context *ctx) { @@ -1449,6 +1517,13 @@ nbctl_lsp_set_addresses(struct ctl_context *ctx) return; } + const struct nbrec_logical_switch *ls; + error = lsp_to_ls(ctx->idl, lsp, &ls); + if (error) { + ctx->error = error; + return; + } + int i; for (i = 2; i < ctx->argc; i++) { struct eth_addr ea; @@ -1463,6 +1538,12 @@ nbctl_lsp_set_addresses(struct ctl_context *ctx) "argument.", ctx->argv[i]); return; } + + error = lsp_contains_duplicates(ls, lsp, ctx->argv[i]); + if (error) { + ctl_error(ctx, "%s", error); + return; + } } nbrec_logical_switch_port_set_addresses(lsp, diff --git a/tests/ovn.at b/tests/ovn.at index e10a7f9ba..e4e510728 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -5606,18 +5606,11 @@ AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0], ["f0:00:00:00:10:2b 192.168.1.2" ]) -# Add another port with a conflicting static IPv4 address. p41 should update. -ovn-nbctl --wait=sb lsp-add sw5 p42 -- lsp-set-addresses p42 \ -"f0:00:00:00:10:2c 192.168.1.2" -AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0], - ["f0:00:00:00:10:2b 192.168.1.3" -]) - # Add an excluded IP address that conflicts with p41. p41 should update. ovn-nbctl --wait=sb add Logical-Switch sw5 other_config \ -exclude_ips="192.168.1.3" +exclude_ips="192.168.1.2" AT_CHECK([ovn-nbctl get Logical-Switch-Port p41 dynamic_addresses], [0], - ["f0:00:00:00:10:2b 192.168.1.4" + ["f0:00:00:00:10:2b 192.168.1.3" ]) as ovn-sb @@ -6297,7 +6290,7 @@ AT_CHECK([ovn-nbctl lsp-add lsw0 localvif1]) AT_CHECK([ovn-nbctl lsp-set-addresses localvif1 "f0:00:00:00:00:01 192.168.1.1"]) AT_CHECK([ovn-nbctl lsp-set-port-security localvif1 "f0:00:00:00:00:01"]) AT_CHECK([ovn-nbctl lsp-add lsw0 localvif2]) -AT_CHECK([ovn-nbctl lsp-set-addresses localvif2 "f0:00:00:00:00:01 192.168.1.2"]) +AT_CHECK([ovn-nbctl lsp-set-addresses localvif2 "f0:00:00:00:00:02 192.168.1.2"]) AT_CHECK([ovn-nbctl lsp-set-port-security localvif2 "f0:00:00:00:00:02"]) AT_CHECK([ovn-nbctl lsp-add lsw0 localvif3]) AT_CHECK([ovn-nbctl lsp-set-addresses localvif3 "f0:00:00:00:00:03 192.168.1.3"]) @@ -11194,3 +11187,59 @@ as hv2 start_daemon ovn-controller OVN_CLEANUP([hv1],[hv2]) AT_CLEANUP + +AT_SETUP([ovn -- ovn-nbctl duplicate addresses]) +ovn_start + +# Set up a switch with some switch ports of varying address types +ovn-nbctl ls-add sw1 +ovn-nbctl set logical_switch sw1 other_config:subnet=192.168.0.0/24 + +ovn-nbctl lsp-add sw1 sw1-p1 +ovn-nbctl lsp-add sw1 sw1-p2 +ovn-nbctl lsp-add sw1 sw1-p3 +ovn-nbctl lsp-add sw1 sw1-p4 + +ovn-nbctl lsp-set-addresses sw1-p1 "00:00:00:00:00:01 10.0.0.1 aef0::1" "00:00:00:00:00:02 10.0.0.2 aef0::2" +ovn-nbctl lsp-set-addresses sw1-p2 "00:00:00:00:00:03 dynamic" +ovn-nbctl lsp-set-addresses sw1-p3 "dynamic" +ovn-nbctl lsp-set-addresses sw1-p4 "router" +ovn-nbctl lsp-set-addresses sw1-p5 "unknown" + +ovn-nbctl list logical_switch_port + +# Now try to add duplicate addresses on a new port. These should all fail +ovn-nbctl lsp-add sw1 sw1-p5 +AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04 10.0.0.1"], [1], [], +[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 10.0.0.1 +]) +AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04 10.0.0.2"], [1], [], +[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 10.0.0.2 +]) +AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04 aef0::1"], [1], [], +[ovn-nbctl: Error on switch sw1: duplicate IPv6 address aef0::1 +]) +AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04 aef0::2"], [1], [], +[ovn-nbctl: Error on switch sw1: duplicate IPv6 address aef0::2 +]) +AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04 192.168.0.2"], [1], [], +[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 192.168.0.2 +]) +AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p5 "00:00:00:00:00:04 192.168.0.3"], [1], [], +[ovn-nbctl: Error on switch sw1: duplicate IPv4 address 192.168.0.3 +]) + +# Now try re-setting sw1-p1. This should succeed +AT_CHECK([ovn-nbctl lsp-set-addresses sw1-p1 "00:00:00:00:00:01 10.0.0.1 aef0::1"]) + +# Now create a new switch and try setting IP addresses the same as the +# first switch. This should succeed. +ovn-nbctl ls-add sw2 +ovn-nbctl lsp-add sw2 sw2-p1 + +AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04 10.0.0.1"]) +AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04 192.168.0.2"]) +AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04 192.168.0.3"]) +AT_CHECK([ovn-nbctl lsp-set-addresses sw2-p1 "00:00:00:00:00:04 aef0::1"]) + +AT_CLEANUP -- 2.14.4 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
