[ovs-dev] [PATCH 06/11] Make <host>:<port> parsing uniform treewide.
Mark Michelson
mmichels at redhat.com
Mon Apr 16 21:40:19 UTC 2018
On 04/13/2018 12:26 PM, Ben Pfaff wrote:
> I didn't realize until now that the tree had two different ways of parsing
> strings in the form <host>:<port> and <port>:<host>. There are the
> long-standing inet_parse_active() and inet_parse_passive() functions, and
> more recently the ipv46_parse() function. This commit eliminates the
> latter and changes the code to use the former.
>
> The two implementations interpreted some input differently. In particular,
> the older functions required IPv6 addresses to be [bracketed], but the
> newer ones did not. I'd prefer the brackets to be required, because of
> ambiguous cases like "::1:2:3:4:80" (is :80 part of the IPv6 address or a
> port number?) but for compatibility this patch changes the merged code to
> use the more liberal interpretation.
>
> Signed-off-by: Ben Pfaff <blp at ovn.org>
> ---
> lib/packets.c | 76 -------------------------
> lib/packets.h | 10 ----
> lib/socket-util.c | 140 +++++++++++++++++++++++++++-------------------
> lib/socket-util.h | 3 +-
> ovn/utilities/ovn-nbctl.c | 43 +++-----------
> ovsdb/raft.c | 5 +-
> tests/ovn-nbctl.at | 56 +++++++++----------
> 7 files changed, 125 insertions(+), 208 deletions(-)
>
> diff --git a/lib/packets.c b/lib/packets.c
> index 8ebae8cc8fe8..38bfb6015b9e 100644
> --- a/lib/packets.c
> +++ b/lib/packets.c
> @@ -652,82 +652,6 @@ ip_parse_cidr(const char *s, ovs_be32 *ip, unsigned int *plen)
> return error;
> }
>
> -/* Parses the string into an IPv4 or IPv6 address.
> - * The port flags act as follows:
> - * * PORT_OPTIONAL: A port may be present but is not required
> - * * PORT_REQUIRED: A port must be present
> - * * PORT_FORBIDDEN: A port must not be present
> - */
> -char * OVS_WARN_UNUSED_RESULT
> -ipv46_parse(const char *s, enum port_flags flags, struct sockaddr_storage *ss)
> -{
> - char *error = NULL;
> -
> - char *copy;
> - copy = xstrdup(s);
> -
> - char *addr;
> - char *port;
> - if (*copy == '[') {
> - char *end;
> -
> - addr = copy + 1;
> - end = strchr(addr, ']');
> - if (!end) {
> - error = xasprintf("No closing bracket on address %s", s);
> - goto finish;
> - }
> - *end++ = '\0';
> - if (*end == ':') {
> - port = end + 1;
> - } else {
> - port = NULL;
> - }
> - } else {
> - addr = copy;
> - port = strchr(copy, ':');
> - if (port) {
> - if (strchr(port + 1, ':')) {
> - port = NULL;
> - } else {
> - *port++ = '\0';
> - }
> - }
> - }
> -
> - if (port && !*port) {
> - error = xasprintf("Port is an empty string");
> - goto finish;
> - }
> -
> - if (port && flags == PORT_FORBIDDEN) {
> - error = xasprintf("Port forbidden in address %s", s);
> - goto finish;
> - } else if (!port && flags == PORT_REQUIRED) {
> - error = xasprintf("Port required in address %s", s);
> - goto finish;
> - }
> -
> - struct addrinfo hints = {
> - .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV,
> - .ai_family = AF_UNSPEC,
> - };
> - struct addrinfo *res;
> - int status;
> - status = getaddrinfo(addr, port, &hints, &res);
> - if (status) {
> - error = xasprintf("Error parsing address %s: %s",
> - s, gai_strerror(status));
> - goto finish;
> - }
> - memcpy(ss, res->ai_addr, res->ai_addrlen);
> - freeaddrinfo(res);
> -
> -finish:
> - free(copy);
> - return error;
> -}
> -
> /* Parses string 's', which must be an IPv6 address. Stores the IPv6 address
> * into '*ip'. Returns true if successful, otherwise false. */
> bool
> diff --git a/lib/packets.h b/lib/packets.h
> index 9a71aa3abbdb..b2bf70697e90 100644
> --- a/lib/packets.h
> +++ b/lib/packets.h
> @@ -1362,16 +1362,6 @@ struct in6_addr ipv6_create_mask(int mask);
> int ipv6_count_cidr_bits(const struct in6_addr *netmask);
> bool ipv6_is_cidr(const struct in6_addr *netmask);
>
> -enum port_flags {
> - PORT_OPTIONAL,
> - PORT_REQUIRED,
> - PORT_FORBIDDEN,
> -};
> -
> -char *ipv46_parse(const char *s, enum port_flags flags,
> - struct sockaddr_storage *ss)
> - OVS_WARN_UNUSED_RESULT;
> -
> bool ipv6_parse(const char *s, struct in6_addr *ip);
> char *ipv6_parse_masked(const char *s, struct in6_addr *ipv6,
> struct in6_addr *mask);
> diff --git a/lib/socket-util.c b/lib/socket-util.c
> index 223e3780ba5f..0964a015e3f9 100644
> --- a/lib/socket-util.c
> +++ b/lib/socket-util.c
> @@ -333,39 +333,89 @@ guess_netmask(ovs_be32 ip_)
> : htonl(0)); /* ??? */
> }
>
> -/* This is like strsep() except:
> - *
> - * - The separator string is ":".
> - *
> - * - Square brackets [] quote ":" separators and are removed from the
> - * tokens. */
> -char *
> -inet_parse_token(char **pp)
> +static char *
> +unbracket(char *s)
> +{
> + if (*s == '[') {
> + s++;
> +
> + char *end = strchr(s, '\0');
> + if (end[-1] == ']') {
> + end[-1] = '\0';
> + }
> + }
> + return s;
> +}
> +
> +/* 'host_index' is 0 if the host precedes the port within 's', 1 otherwise. */
> +static void
> +inet_parse_tokens__(char *s, int host_index, char **hostp, char **portp)
> {
> - char *p = *pp;
> -
> - if (p == NULL) {
> - return NULL;
> - } else if (*p == '\0') {
> - *pp = NULL;
> - return p;
> - } else if (*p == '[') {
> - char *start = p + 1;
> - char *end = start + strcspn(start, "]");
> - *pp = (*end == '\0' ? NULL
> - : end[1] == ':' ? end + 2
> - : end + 1);
> - *end = '\0';
> - return start;
> + char *colon = NULL;
> + bool in_brackets = false;
> + int n_colons = 0;
> + for (char *p = s; *p; p++) {
> + if (*p == '[') {
> + in_brackets = true;
> + } else if (*p == ']') {
> + in_brackets = false;
> + } else if (*p == ':' && !in_brackets) {
> + n_colons++;
> + colon = p;
> + }
> + }
> +
> + *hostp = *portp = NULL;
> + if (n_colons > 1) {
> + *hostp = s;
> } else {
> - char *start = p;
> - char *end = start + strcspn(start, ":");
> - *pp = *end == '\0' ? NULL : end + 1;
> - *end = '\0';
> - return start;
> + char **tokens[2];
> + tokens[host_index] = hostp;
> + tokens[!host_index] = portp;
> +
> + if (colon) {
> + *colon = '\0';
> + *tokens[1] = unbracket(colon + 1);
> + }
> + *tokens[0] = unbracket(s);
> }
> }
>
> +/* Parses 's', a string in the form "<host>[:<port>]", into its (required) host
> + * and (optional) port components, and stores pointers to them in '*hostp' and
> + * '*portp' respectively. Always sets '*hostp' nonnull, although possibly to
> + * an empty string empty string. Can set '*portp' to the null string.
"empty string" is repeated. Also, it's a bit of a nitpick, but if 's' is
NULL, then *hostp will get set to NULL, which contradicts the comment here.
> + *
> + * Supports both IPv4 and IPv6. IPv6 addresses may be quoted with square
> + * brackets. Resolves ambiguous cases that might represent an IPv6 address or
> + * an IPv6 address and a port as representing just a host, e.g. "::1:2:3:4:80"
> + * is a host but "[::1:2:3:4]:80" is a host and a port.
> + *
> + * Modifies 's' and points '*hostp' and '*portp' (if nonnull) into it.
> + */
> +void
> +inet_parse_host_port_tokens(char *s, char **hostp, char **portp)
> +{
> + inet_parse_tokens__(s, 0, hostp, portp);
> +}
> +
> +/* Parses 's', a string in the form "<port>[:<host>]", into its port and hos
> + * components, and stores pointers to them in '*portp' and '*hostp'
> + * respectively. Both '*portp' and '*hostp' can end up null.
I'm a bit confused here. inet_parse_tokens__() is called both from
inet_parse_host_port_tokens() and inet_parse_port_host_tokens(), just
with the host_index different. My expectation would then be that
inet_parse_port_host_tokens() should make the same non-NULL guarantee
for *portp that inet_parse_host_port_tokens() does for *hostp. What am I
missing?
> + *
> + * Supports both IPv4 and IPv6. IPv6 addresses may be quoted with square
> + * brackets. Resolves ambiguous cases that might represent an IPv6 address or
> + * an IPv6 address and a port as representing just a host, e.g. "::1:2:3:4:80"
> + * is a host but "[::1:2:3:4]:80" is a host and a port.
> + *
> + * Modifies 's' and points '*hostp' and '*portp' (if nonnull) into it.
> + */
> +void
> +inet_parse_port_host_tokens(char *s, char **portp, char **hostp)
> +{
> + inet_parse_tokens__(s, 1, hostp, portp);
> +}
> +
> static bool
> parse_sockaddr_components(struct sockaddr_storage *ss,
> char *host_s,
> @@ -441,23 +491,16 @@ inet_parse_active(const char *target_, int default_port,
> struct sockaddr_storage *ss)
> {
> char *target = xstrdup(target_);
> - const char *port;
> - char *host;
> - char *p;
> + char *port, *host;
> bool ok;
>
> - p = target;
> - host = inet_parse_token(&p);
> - port = inet_parse_token(&p);
> + inet_parse_host_port_tokens(target, &host, &port);
> if (!host) {
> VLOG_ERR("%s: host must be specified", target_);
> ok = false;
> } else if (!port && default_port < 0) {
> VLOG_ERR("%s: port must be specified", target_);
> ok = false;
> - } else if (p && p[strspn(p, " \t\r\n")] != '\0') {
> - VLOG_ERR("%s: unexpected characters follow host and port", target_);
> - ok = false;
> } else {
> ok = parse_sockaddr_components(ss, host, port, default_port, target_);
> }
> @@ -571,20 +614,13 @@ inet_parse_passive(const char *target_, int default_port,
> struct sockaddr_storage *ss)
> {
> char *target = xstrdup(target_);
> - const char *port;
> - char *host;
> - char *p;
> + char *port, *host;
> bool ok;
>
> - p = target;
> - port = inet_parse_token(&p);
> - host = inet_parse_token(&p);
> + inet_parse_port_host_tokens(target, &port, &host);
> if (!port && default_port < 0) {
> VLOG_ERR("%s: port must be specified", target_);
> ok = false;
> - } else if (p && p[strspn(p, " \t\r\n")] != '\0') {
> - VLOG_ERR("%s: unexpected characters follow port and host", target_);
> - ok = false;
> } else {
> ok = parse_sockaddr_components(ss, host, port, default_port, target_);
> }
> @@ -707,16 +743,8 @@ bool
> inet_parse_address(const char *target_, struct sockaddr_storage *ss)
> {
> char *target = xstrdup(target_);
> - char *p = target;
> - char *host = inet_parse_token(&p);
> - bool ok = false;
> - if (!host) {
> - VLOG_ERR("%s: host must be specified", target_);
> - } else if (p && p[strspn(p, " \t\r\n")] != '\0') {
> - VLOG_ERR("%s: unexpected characters follow host", target_);
> - } else {
> - ok = parse_sockaddr_components(ss, host, NULL, 0, target_);
> - }
> + char *host = unbracket(target);
> + bool ok = parse_sockaddr_components(ss, host, NULL, 0, target_);
> if (!ok) {
> memset(ss, 0, sizeof *ss);
> }
> diff --git a/lib/socket-util.h b/lib/socket-util.h
> index d927d67a0e1b..239d3f22041c 100644
> --- a/lib/socket-util.h
> +++ b/lib/socket-util.h
> @@ -46,7 +46,8 @@ int check_connection_completion(int fd);
> void drain_fd(int fd, size_t n_packets);
> ovs_be32 guess_netmask(ovs_be32 ip);
>
> -char *inet_parse_token(char **);
> +void inet_parse_host_port_tokens(char *s, char **hostp, char **portp);
> +void inet_parse_port_host_tokens(char *s, char **portp, char **hostp);
> bool inet_parse_active(const char *target, int default_port,
> struct sockaddr_storage *ssp);
> int inet_open_active(int style, const char *target, int default_port,
> diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c
> index 7efc5065c962..16698de1f049 100644
> --- a/ovn/utilities/ovn-nbctl.c
> +++ b/ovn/utilities/ovn-nbctl.c
> @@ -1798,10 +1798,7 @@ nbctl_lb_add(struct ctl_context *ctx)
> }
>
> struct sockaddr_storage ss_vip;
> - char *error;
> - error = ipv46_parse(lb_vip, PORT_OPTIONAL, &ss_vip);
> - if (error) {
> - free(error);
> + if (!inet_parse_active(lb_vip, 0, &ss_vip)) {
> ctl_fatal("%s: should be an IP address (or an IP address "
> "and a port number with : as a separator).", lb_vip);
> }
> @@ -1848,17 +1845,13 @@ nbctl_lb_add(struct ctl_context *ctx)
> token != NULL; token = strtok_r(NULL, ",", &save_ptr)) {
> struct sockaddr_storage ss_dst;
>
> - error = ipv46_parse(token, is_vip_with_port
> - ? PORT_REQUIRED
> - : PORT_FORBIDDEN,
> - &ss_dst);
> -
> - if (error) {
> - free(error);
> - if (is_vip_with_port) {
> + if (is_vip_with_port) {
> + if (!inet_parse_active(token, -1, &ss_dst)) {
> ctl_fatal("%s: should be an IP address and a port "
> - "number with : as a separator.", token);
> - } else {
> + "number with : as a separator.", token);
> + }
> + } else {
> + if (!inet_parse_address(token, &ss_dst)) {
> ctl_fatal("%s: should be an IP address.", token);
> }
> }
> @@ -1954,36 +1947,18 @@ lb_info_add_smap(const struct nbrec_load_balancer *lb,
> {
> struct ds key = DS_EMPTY_INITIALIZER;
> struct ds val = DS_EMPTY_INITIALIZER;
> - char *error, *protocol;
>
> const struct smap_node **nodes = smap_sort(&lb->vips);
> if (nodes) {
> for (int i = 0; i < smap_count(&lb->vips); i++) {
> const struct smap_node *node = nodes[i];
> - protocol = lb->protocol;
>
> struct sockaddr_storage ss;
> - error = ipv46_parse(node->key, PORT_OPTIONAL, &ss);
> - if (error) {
> - VLOG_WARN("%s", error);
> - free(error);
> + if (!inet_parse_active(node->key, 0, &ss)) {
> continue;
> }
>
> - if (ss.ss_family == AF_INET) {
> - struct sockaddr_in *sin = ALIGNED_CAST(struct sockaddr_in *,
> - &ss);
> - if (!sin->sin_port) {
> - protocol = "tcp/udp";
> - }
> - } else {
> - struct sockaddr_in6 *sin6 = ALIGNED_CAST(struct sockaddr_in6 *,
> - &ss);
> - if (!sin6->sin6_port) {
> - protocol = "tcp/udp";
> - }
> - }
> -
> + char *protocol = ss_get_port(&ss) ? lb->protocol : "tcp/udp";
> i == 0 ? ds_put_format(&val,
> UUID_FMT " %-20.16s%-11.7s%-*.*s%s",
> UUID_ARGS(&lb->header_.uuid),
> diff --git a/ovsdb/raft.c b/ovsdb/raft.c
> index edb22f2e7b60..c0c1e98977b9 100644
> --- a/ovsdb/raft.c
> +++ b/ovsdb/raft.c
> @@ -335,9 +335,8 @@ raft_make_address_passive(const char *address_)
> return xasprintf("p%s", address_);
> } else {
> char *address = xstrdup(address_);
> - char *p = strchr(address, ':') + 1;
> - char *host = inet_parse_token(&p);
> - char *port = inet_parse_token(&p);
> + char *host, *port;
> + inet_parse_host_port_tokens(strchr(address, ':') + 1, &host, &port);
>
> struct ds paddr = DS_EMPTY_INITIALIZER;
> ds_put_format(&paddr, "p%.3s:%s:", address, port);
> diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at
> index f07b47fd20ea..514e7e7d2d49 100644
> --- a/tests/ovn-nbctl.at
> +++ b/tests/ovn-nbctl.at
> @@ -460,46 +460,46 @@ AT_SETUP([ovn-nbctl - LBs])
> OVN_NBCTL_TEST_START
>
> dnl Add two LBs.
> -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80a 192.168.10.10:80,192.168.10.20:80 tcp], [1], [],
> +AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:80a 192.168.10.10:80,192.168.10.20:80 tcp], [1], [],
> [ovn-nbctl: 30.0.0.10:80a: should be an IP address (or an IP address and a port number with : as a separator).
> ])
>
> -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:a80 192.168.10.10:80,192.168.10.20:80 tcp], [1], [],
> +AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:a80 192.168.10.10:80,192.168.10.20:80 tcp], [1], [],
> [ovn-nbctl: 30.0.0.10:a80: should be an IP address (or an IP address and a port number with : as a separator).
> ])
>
> -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10: 192.168.10.10:80,192.168.10.20:80 tcp], [1], [],
> -[ovn-nbctl: 30.0.0.10:: should be an IP address (or an IP address and a port number with : as a separator).
> -])
> -
> -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10:80 192.168.10.10:80,192.168.10.20 tcp], [1], [],
> +AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10:80 192.168.10.10:80,192.168.10.20 tcp], [1], [],
> [ovn-nbctl: 192.168.10.20: should be an IP address and a port number with : as a separator.
> ])
>
> -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.1a 192.168.10.10:80,192.168.10.20:80], [1], [],
> +AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.1a 192.168.10.10:80,192.168.10.20:80], [1], [],
> [ovn-nbctl: 30.0.0.1a: should be an IP address (or an IP address and a port number with : as a separator).
> ])
>
> -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0 192.168.10.10:80,192.168.10.20:80], [1], [],
> -[ovn-nbctl: 192.168.10.10:80: should be an IP address.
> +AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0 192.168.10.10:80,192.168.10.20:80], [1], [],
> +[ovn-nbctl: 30.0.0: should be an IP address (or an IP address and a port number with : as a separator).
> ])
>
> -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 192.168.10.10,192.168.10.20:80], [1], [],
> +AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10 192.168.10.10,192.168.10.20:80], [1], [],
> [ovn-nbctl: 192.168.10.20:80: should be an IP address.
> ])
>
> -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 192.168.10.10:a80], [1], [],
> +AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10 192.168.10.10:a80], [1], [],
> [ovn-nbctl: 192.168.10.10:a80: should be an IP address.
> ])
>
> -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 192.168.10.10:], [1], [],
> +AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10 192.168.10.10:], [1], [],
> [ovn-nbctl: 192.168.10.10:: should be an IP address.
> ])
>
> -AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 192.168.10.1a], [1], [],
> +AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 30.0.0.10 192.168.10.1a], [1], [],
> [ovn-nbctl: 192.168.10.1a: should be an IP address.
> ])
>
> +AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10: 192.168.10.10:80,192.168.10.20:80 tcp], [1], [],
> +[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
> +])
> +
> AT_CHECK([ovn-nbctl lb-add lb0 30.0.0.10 192.168.10.10 tcp], [1], [],
> [ovn-nbctl: Protocol is unnecessary when no port of vip is given.
> ])
> @@ -685,56 +685,56 @@ AT_SETUP([ovn-nbctl - LBs IPv6])
> OVN_NBCTL_TEST_START
>
> dnl A bunch of commands that should fail
> -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80a [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
> +AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:80a [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
> [ovn-nbctl: [[ae0f::10]]:80a: should be an IP address (or an IP address and a port number with : as a separator).
> ])
>
>
> -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:a80 [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
> +AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:a80 [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
> [ovn-nbctl: [[ae0f::10]]:a80: should be an IP address (or an IP address and a port number with : as a separator).
> ])
>
>
> -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]: [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
> -[ovn-nbctl: [[ae0f::10]]:: should be an IP address (or an IP address and a port number with : as a separator).
> -])
> -
> -
> -AT_CHECK([ovn-nbctl lb-add lb0 [[ae0f::10]]:80 [[fd0f::10]]:80,fd0f::20 tcp], [1], [],
> +AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]:80 [[fd0f::10]]:80,fd0f::20 tcp], [1], [],
> [ovn-nbctl: fd0f::20: should be an IP address and a port number with : as a separator.
> ])
>
>
> -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10fff [[fd0f::10]]:80,fd0f::20 tcp], [1], [],
> +AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10fff [[fd0f::10]]:80,fd0f::20 tcp], [1], [],
> [ovn-nbctl: ae0f::10fff: should be an IP address (or an IP address and a port number with : as a separator).
> ])
>
>
> -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 [[fd0f::10]]:80,[[fd0f::20]]:80], [1], [],
> +AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10 [[fd0f::10]]:80,[[fd0f::20]]:80], [1], [],
> [ovn-nbctl: [[fd0f::10]]:80: should be an IP address.
> ])
>
>
> -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 fd0f::10,[[fd0f::20]]:80], [1], [],
> +AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10 fd0f::10,[[fd0f::20]]:80], [1], [],
> [ovn-nbctl: [[fd0f::20]]:80: should be an IP address.
> ])
>
>
> -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 [[fd0f::10]]:a80], [1], [],
> +AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10 [[fd0f::10]]:a80], [1], [],
> [ovn-nbctl: [[fd0f::10]]:a80: should be an IP address.
> ])
>
>
> -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 [[fd0f::10]]:], [1], [],
> +AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10 [[fd0f::10]]:], [1], [],
> [ovn-nbctl: [[fd0f::10]]:: should be an IP address.
> ])
>
>
> -AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 fd0f::1001a], [1], [],
> +AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 ae0f::10 fd0f::1001a], [1], [],
> [ovn-nbctl: fd0f::1001a: should be an IP address.
> ])
>
>
> +AT_CHECK([ovn-nbctl -vsocket_util:off lb-add lb0 [[ae0f::10]]: [[fd0f::10]]:80,[[fd0f::20]]:80 tcp], [1], [],
> +[ovn-nbctl: Protocol is unnecessary when no port of vip is given.
> +])
> +
> +
> AT_CHECK([ovn-nbctl lb-add lb0 ae0f::10 fd0f::10 tcp], [1], [],
> [ovn-nbctl: Protocol is unnecessary when no port of vip is given.
> ])
>
More information about the dev
mailing list