From patchwork Thu Apr 30 17:20:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Numan Siddique X-Patchwork-Id: 1280691 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=whitealder.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ovn.org Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49Chx14NpDz9sSK for ; Fri, 1 May 2020 03:20:53 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id D31BD88012; Thu, 30 Apr 2020 17:20:51 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id A19u+LOEgF6w; Thu, 30 Apr 2020 17:20:39 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by whitealder.osuosl.org (Postfix) with ESMTP id 5D80186373; Thu, 30 Apr 2020 17:20:39 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 435A0C0889; Thu, 30 Apr 2020 17:20:39 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 62D56C016F for ; Thu, 30 Apr 2020 17:20:38 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 52BB386E73 for ; Thu, 30 Apr 2020 17:20:38 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id q76wqI4bUNRq for ; Thu, 30 Apr 2020 17:20:36 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from relay10.mail.gandi.net (relay10.mail.gandi.net [217.70.178.230]) by fraxinus.osuosl.org (Postfix) with ESMTPS id EBE6786E97 for ; Thu, 30 Apr 2020 17:20:35 +0000 (UTC) Received: from nummac.local (unknown [125.99.245.47]) (Authenticated sender: numans@ovn.org) by relay10.mail.gandi.net (Postfix) with ESMTPSA id 83839240002; Thu, 30 Apr 2020 17:20:33 +0000 (UTC) From: numans@ovn.org To: dev@openvswitch.org Date: Thu, 30 Apr 2020 22:50:28 +0530 Message-Id: <20200430172028.1978594-1-numans@ovn.org> X-Mailer: git-send-email 2.25.4 MIME-Version: 1.0 Subject: [ovs-dev] [PATCH ovn 2/2] Support selection fields in load balancer. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: Numan Siddique This patch add a new column 'selection_fields' in Load_Balancer table in NB DB. CMS can define a set of packet headers to use while selecting a backend. If this column is set, OVN will add the flow in group table with selection method as 'hash' with the set fields. Otherwise it will use the default 'dp_hash' selection method. If a load balancer is configured with the selection_fields as selection_fields : [ip_dst, ip_src, tp_dst, tp_src] then with this patch, the modified ct_lb action will look like - ct_lb(backends=IP1:P1-IP2:P1, hash_fields="ip_dst,ip_src,tp_dst,tp_src"); And the OF flow will look like - group_id=2,type=select,selection_method=hash, fields(ip_src,ip_dst,tcp_src,tcp_dst),bucket=bucket_id:0,weight:100,actions=ct(.... Signed-off-by: Numan Siddique --- include/ovn/actions.h | 1 + lib/actions.c | 45 +++++++++++++++++++++++++++++++++----- northd/ovn-northd.c | 47 ++++++++++++++++++++++++++++++++------- ovn-nb.ovsschema | 10 +++++++-- ovn-nb.xml | 7 ++++++ tests/ovn-northd.at | 24 ++++++++++---------- tests/ovn.at | 51 ++++++++++++++++++++++++++++--------------- 7 files changed, 139 insertions(+), 46 deletions(-) diff --git a/include/ovn/actions.h b/include/ovn/actions.h index 42d45a74c..4a54abe17 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -259,6 +259,7 @@ struct ovnact_ct_lb { struct ovnact_ct_lb_dst *dsts; size_t n_dsts; uint8_t ltable; /* Logical table ID of next table. */ + char *hash_fields; }; struct ovnact_select_dst { diff --git a/lib/actions.c b/lib/actions.c index 021a376b4..6d840a73f 100644 --- a/lib/actions.c +++ b/lib/actions.c @@ -951,9 +951,18 @@ parse_ct_lb_action(struct action_context *ctx) struct ovnact_ct_lb_dst *dsts = NULL; size_t allocated_dsts = 0; size_t n_dsts = 0; + char *hash_fields = NULL; - if (lexer_match(ctx->lexer, LEX_T_LPAREN)) { - while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) { + if (lexer_match(ctx->lexer, LEX_T_LPAREN) && + !lexer_match(ctx->lexer, LEX_T_RPAREN)) { + if (!lexer_match_id(ctx->lexer, "backends") || + !lexer_force_match(ctx->lexer, LEX_T_EQUALS)) { + lexer_syntax_error(ctx->lexer, "expecting backends"); + return; + } + + while (!lexer_match(ctx->lexer, LEX_T_COMMA) && + !lexer_match(ctx->lexer, LEX_T_RPAREN)) { struct ovnact_ct_lb_dst dst; if (lexer_match(ctx->lexer, LEX_T_LSQUARE)) { /* IPv6 address and port */ @@ -1012,7 +1021,7 @@ parse_ct_lb_action(struct action_context *ctx) } } } - lexer_match(ctx->lexer, LEX_T_COMMA); + lexer_match(ctx->lexer, LEX_T_HYPHEN); /* Append to dsts. */ if (n_dsts >= allocated_dsts) { @@ -1020,12 +1029,27 @@ parse_ct_lb_action(struct action_context *ctx) } dsts[n_dsts++] = dst; } + + if (lexer_match_id(ctx->lexer, "hash_fields")) { + if (!lexer_match(ctx->lexer, LEX_T_EQUALS) || + ctx->lexer->token.type != LEX_T_STRING || + lexer_lookahead(ctx->lexer) != LEX_T_RPAREN) { + lexer_syntax_error(ctx->lexer, "invalid hash_fields"); + free(dsts); + return; + } + + hash_fields = xstrdup(ctx->lexer->token.s); + lexer_get(ctx->lexer); + lexer_get(ctx->lexer); + } } struct ovnact_ct_lb *cl = ovnact_put_CT_LB(ctx->ovnacts); cl->ltable = ctx->pp->cur_ltable + 1; cl->dsts = dsts; cl->n_dsts = n_dsts; + cl->hash_fields = hash_fields; } static void @@ -1033,10 +1057,10 @@ format_CT_LB(const struct ovnact_ct_lb *cl, struct ds *s) { ds_put_cstr(s, "ct_lb"); if (cl->n_dsts) { - ds_put_char(s, '('); + ds_put_cstr(s, "(backends="); for (size_t i = 0; i < cl->n_dsts; i++) { if (i) { - ds_put_cstr(s, ", "); + ds_put_char(s, '-'); } const struct ovnact_ct_lb_dst *dst = &cl->dsts[i]; @@ -1057,6 +1081,11 @@ format_CT_LB(const struct ovnact_ct_lb *cl, struct ds *s) } ds_put_char(s, ')'); } + + if (cl->hash_fields) { + ds_chomp(s, ')'); + ds_put_format(s, ", hash_fields=\"%s\")", cl->hash_fields); + } ds_put_char(s, ';'); } @@ -1103,7 +1132,10 @@ encode_CT_LB(const struct ovnact_ct_lb *cl, : MFF_LOG_DNAT_ZONE - MFF_REG0; struct ds ds = DS_EMPTY_INITIALIZER; - ds_put_format(&ds, "type=select,selection_method=dp_hash"); + ds_put_format(&ds, "type=select,selection_method=%s", cl->hash_fields ? "hash": "dp_hash"); + if (cl->hash_fields) { + ds_put_format(&ds, ",fields(%s)", cl->hash_fields); + } BUILD_ASSERT(MFF_LOG_CT_ZONE >= MFF_REG0); BUILD_ASSERT(MFF_LOG_CT_ZONE < MFF_REG0 + FLOW_N_REGS); @@ -1145,6 +1177,7 @@ static void ovnact_ct_lb_free(struct ovnact_ct_lb *ct_lb) { free(ct_lb->dsts); + free(ct_lb->hash_fields); } static void diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index e31794c4b..e18dd03df 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -3101,7 +3101,7 @@ struct ovn_lb { struct hmap_node hmap_node; const struct nbrec_load_balancer *nlb; /* May be NULL. */ - + char *selection_fields; struct lb_vip *vips; size_t n_vips; }; @@ -3214,6 +3214,18 @@ ovn_lb_create(struct northd_context *ctx, struct hmap *lbs, lb->vips[n_vips].addr_family = addr_family; lb->vips[n_vips].backend_ips = xstrdup(node->value); + char *ps1 = lb->vips[n_vips].backend_ips; + char *ps2 = ps1; + /* Replace all occurances of ',' with '-'. */ + while (ps2) { + ps2 = strstr(ps1, ","); + if (ps2) { + *ps2 = '-'; + ps2++; + ps1 = ps2; + } + } + struct nbrec_load_balancer_health_check *lb_health_check = NULL; if (nbrec_lb->protocol && !strcmp(nbrec_lb->protocol, "sctp")) { if (nbrec_lb->n_health_check > 0) { @@ -3329,6 +3341,16 @@ ovn_lb_create(struct northd_context *ctx, struct hmap *lbs, n_vips++; } + if (lb->nlb->n_selection_fields) { + struct ds sel_fields = DS_EMPTY_INITIALIZER; + for (size_t i = 0; i < lb->nlb->n_selection_fields; i++) { + ds_put_format(&sel_fields, "%s,", lb->nlb->selection_fields[i]); + } + ds_chomp(&sel_fields, ','); + lb->selection_fields = ds_steal_cstr(&sel_fields); + ds_destroy(&sel_fields); + } + return lb; } @@ -3347,13 +3369,15 @@ ovn_lb_destroy(struct ovn_lb *lb) free(lb->vips[i].backends); } free(lb->vips); + free(lb->selection_fields); } static void build_lb_vip_ct_lb_actions(struct lb_vip *lb_vip, - struct ds *action) + struct ds *action, + char *selection_fields) { if (lb_vip->health_check) { - ds_put_cstr(action, "ct_lb("); + ds_put_cstr(action, "ct_lb(backends="); size_t n_active_backends = 0; for (size_t k = 0; k < lb_vip->n_backends; k++) { @@ -3365,7 +3389,7 @@ static void build_lb_vip_ct_lb_actions(struct lb_vip *lb_vip, } n_active_backends++; - ds_put_format(action, "%s:%"PRIu16",", + ds_put_format(action, "%s:%"PRIu16"-", backend->ip, backend->port); } @@ -3373,11 +3397,17 @@ static void build_lb_vip_ct_lb_actions(struct lb_vip *lb_vip, ds_clear(action); ds_put_cstr(action, "drop;"); } else { - ds_chomp(action, ','); + ds_chomp(action, '-'); ds_put_cstr(action, ");"); } } else { - ds_put_format(action, "ct_lb(%s);", lb_vip->backend_ips); + ds_put_format(action, "ct_lb(backends=%s);", lb_vip->backend_ips); + } + + if (selection_fields && selection_fields[0]) { + ds_chomp(action, ';'); + ds_chomp(action, ')'); + ds_put_format(action, ", hash_fields=\"%s\");", selection_fields); } } @@ -5650,7 +5680,7 @@ build_lb_rules(struct ovn_datapath *od, struct hmap *lflows, struct ovn_lb *lb) /* New connections in Ingress table. */ struct ds action = DS_EMPTY_INITIALIZER; - build_lb_vip_ct_lb_actions(lb_vip, &action); + build_lb_vip_ct_lb_actions(lb_vip, &action, lb->selection_fields); struct ds match = DS_EMPTY_INITIALIZER; ds_put_format(&match, "ct.new && %s.dst == %s", ip_match, lb_vip->vip); @@ -9301,7 +9331,8 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, for (size_t j = 0; j < lb->n_vips; j++) { struct lb_vip *lb_vip = &lb->vips[j]; ds_clear(&actions); - build_lb_vip_ct_lb_actions(lb_vip, &actions); + build_lb_vip_ct_lb_actions(lb_vip, &actions, + lb->selection_fields); if (!sset_contains(&all_ips, lb_vip->vip)) { sset_add(&all_ips, lb_vip->vip); diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema index b2a046571..a06972aa0 100644 --- a/ovn-nb.ovsschema +++ b/ovn-nb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Northbound", - "version": "5.22.0", - "cksum": "384164739 25476", + "version": "5.23.0", + "cksum": "111023208 25806", "tables": { "NB_Global": { "columns": { @@ -179,6 +179,12 @@ "ip_port_mappings": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, + "selection_fields": { + "type": {"key": {"type": "string", + "enum": ["set", + ["eth_src", "eth_dst", "ip_src", "ip_dst", + "tp_src", "tp_dst"]]}, + "min": 0, "max": "unlimited"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}, diff --git a/ovn-nb.xml b/ovn-nb.xml index af15c550a..243a25bce 100644 --- a/ovn-nb.xml +++ b/ovn-nb.xml @@ -1513,6 +1513,13 @@

+ + Set of packet header fields to use for selecting a backend to + load balance the VIP. This can be used if CMS desires that the + backend selection is consistent and deterministic for a given + set of packet header fields. + + See External IDs at the beginning of this document. diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index 8cc3f7002..c665db89b 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -1183,7 +1183,7 @@ ovn-nbctl --wait=sb ls-lb-add sw0 lb1 ovn-sbctl dump-flows sw0 | grep ct_lb | grep priority=120 > lflows.txt AT_CHECK([cat lflows.txt], [0], [dnl - table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(10.0.0.3:80,20.0.0.3:80);) + table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(backends=10.0.0.3:80-20.0.0.3:80);) ]) # Delete the Load_Balancer_Health_Check @@ -1192,7 +1192,7 @@ OVS_WAIT_UNTIL([test 0 = `ovn-sbctl list service_monitor | wc -l`]) ovn-sbctl dump-flows sw0 | grep ct_lb | grep priority=120 > lflows.txt AT_CHECK([cat lflows.txt], [0], [dnl - table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(10.0.0.3:80,20.0.0.3:80);) + table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(backends=10.0.0.3:80-20.0.0.3:80);) ]) # Create the Load_Balancer_Health_Check again. @@ -1205,7 +1205,7 @@ service_monitor | sed '/^$/d' | wc -l`]) ovn-sbctl dump-flows sw0 | grep ct_lb | grep priority=120 > lflows.txt AT_CHECK([cat lflows.txt], [0], [dnl - table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(10.0.0.3:80,20.0.0.3:80);) + table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(backends=10.0.0.3:80-20.0.0.3:80);) ]) # Get the uuid of both the service_monitor @@ -1221,7 +1221,7 @@ OVS_WAIT_UNTIL([ ovn-sbctl dump-flows sw0 | grep ct_lb | grep priority=120 > lflows.txt AT_CHECK([cat lflows.txt], [0], [dnl - table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(10.0.0.3:80);) + table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(backends=10.0.0.3:80);) ]) # Set the service monitor for sw0-p1 to offline @@ -1251,7 +1251,7 @@ OVS_WAIT_UNTIL([ ovn-sbctl dump-flows sw0 | grep ct_lb | grep priority=120 > lflows.txt AT_CHECK([cat lflows.txt], [0], [dnl - table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(10.0.0.3:80,20.0.0.3:80);) + table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(backends=10.0.0.3:80-20.0.0.3:80);) ]) # Set the service monitor for sw1-p1 to error @@ -1263,7 +1263,7 @@ OVS_WAIT_UNTIL([ ovn-sbctl dump-flows sw0 | grep "ip4.dst == 10.0.0.10 && tcp.dst == 80" \ | grep priority=120 > lflows.txt AT_CHECK([cat lflows.txt], [0], [dnl - table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(10.0.0.3:80);) + table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(backends=10.0.0.3:80);) ]) # Add one more vip to lb1 @@ -1293,8 +1293,8 @@ service_monitor port=1000 | sed '/^$/d' | wc -l`]) ovn-sbctl dump-flows sw0 | grep ct_lb | grep priority=120 > lflows.txt AT_CHECK([cat lflows.txt], [0], [dnl - table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(10.0.0.3:80);) - table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(ct_lb(10.0.0.3:1000);) + table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(backends=10.0.0.3:80);) + table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(ct_lb(backends=10.0.0.3:1000);) ]) # Set the service monitor for sw1-p1 to online @@ -1306,16 +1306,16 @@ OVS_WAIT_UNTIL([ ovn-sbctl dump-flows sw0 | grep ct_lb | grep priority=120 > lflows.txt AT_CHECK([cat lflows.txt], [0], [dnl - table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(10.0.0.3:80,20.0.0.3:80);) - table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(ct_lb(10.0.0.3:1000,20.0.0.3:80);) + table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(backends=10.0.0.3:80-20.0.0.3:80);) + table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(ct_lb(backends=10.0.0.3:1000-20.0.0.3:80);) ]) # Associate lb1 to sw1 ovn-nbctl --wait=sb ls-lb-add sw1 lb1 ovn-sbctl dump-flows sw1 | grep ct_lb | grep priority=120 > lflows.txt AT_CHECK([cat lflows.txt], [0], [dnl - table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(10.0.0.3:80,20.0.0.3:80);) - table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(ct_lb(10.0.0.3:1000,20.0.0.3:80);) + table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(backends=10.0.0.3:80-20.0.0.3:80);) + table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && tcp.dst == 1000), action=(ct_lb(backends=10.0.0.3:1000-20.0.0.3:80);) ]) # Now create lb2 same as lb1 but udp protocol. diff --git a/tests/ovn.at b/tests/ovn.at index 7befc8224..729bc1853 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -970,29 +970,44 @@ ct_lb(); encodes as ct(table=19,zone=NXM_NX_REG13[0..15],nat) has prereqs ip ct_lb(192.168.1.2:80, 192.168.1.3:80); + Syntax error at `192.168.1.2' expecting backends. +ct_lb(backends=192.168.1.2:80, 192.168.1.3:80); + Syntax error at `192.168.1.3' expecting `;'. +ct_lb(backends=192.168.1.2:80-192.168.1.3:80); encodes as group:1 uses group: id(1), name(type=select,selection_method=dp_hash,bucket=bucket_id=0,weight:100,actions=ct(nat(dst=192.168.1.2:80),commit,table=19,zone=NXM_NX_REG13[0..15]),bucket=bucket_id=1,weight:100,actions=ct(nat(dst=192.168.1.3:80),commit,table=19,zone=NXM_NX_REG13[0..15])) has prereqs ip -ct_lb(192.168.1.2, 192.168.1.3, ); - formats as ct_lb(192.168.1.2, 192.168.1.3); +ct_lb(backends=192.168.1.2- 192.168.1.3- ); + formats as ct_lb(backends=192.168.1.2-192.168.1.3); encodes as group:2 uses group: id(2), name(type=select,selection_method=dp_hash,bucket=bucket_id=0,weight:100,actions=ct(nat(dst=192.168.1.2),commit,table=19,zone=NXM_NX_REG13[0..15]),bucket=bucket_id=1,weight:100,actions=ct(nat(dst=192.168.1.3),commit,table=19,zone=NXM_NX_REG13[0..15])) has prereqs ip -ct_lb(fd0f::2, fd0f::3, ); - formats as ct_lb(fd0f::2, fd0f::3); +ct_lb(backends=fd0f::2- fd0f::3- ); + formats as ct_lb(backends=fd0f::2-fd0f::3); encodes as group:3 uses group: id(3), name(type=select,selection_method=dp_hash,bucket=bucket_id=0,weight:100,actions=ct(nat(dst=fd0f::2),commit,table=19,zone=NXM_NX_REG13[0..15]),bucket=bucket_id=1,weight:100,actions=ct(nat(dst=fd0f::3),commit,table=19,zone=NXM_NX_REG13[0..15])) has prereqs ip -ct_lb(192.168.1.2:); +ct_lb(backends=192.168.1.2:); Syntax error at `)' expecting port number. -ct_lb(192.168.1.2:123456); +ct_lb(backends=192.168.1.2:123456); Syntax error at `123456' expecting port number. -ct_lb(foo); +ct_lb(backends=foo); Syntax error at `foo' expecting IP address. -ct_lb([192.168.1.2]); +ct_lb(backends=[192.168.1.2]); Syntax error at `192.168.1.2' expecting IPv6 address. +ct_lb(backends=192.168.1.2:80-192.168.1.3:80, hash_fields=eth_src,eth_dst,ip_src); + Syntax error at `eth_src' invalid hash_fields. +ct_lb(backends=192.168.1.2:80-192.168.1.3:80, hash_fields="eth_src,eth_dst,ip_src"); + encodes as group:4 + uses group: id(4), name(type=select,selection_method=hash,fields(eth_src,eth_dst,ip_src),bucket=bucket_id=0,weight:100,actions=ct(nat(dst=192.168.1.2:80),commit,table=19,zone=NXM_NX_REG13[0..15]),bucket=bucket_id=1,weight:100,actions=ct(nat(dst=192.168.1.3:80),commit,table=19,zone=NXM_NX_REG13[0..15])) + has prereqs ip +ct_lb(backends=fd0f::2-fd0f::3, hash_fields="eth_src,eth_dst,ip_src,ip_dst,tp_src,tp_dst"); + encodes as group:5 + uses group: id(5), name(type=select,selection_method=hash,fields(eth_src,eth_dst,ip_src,ip_dst,tp_src,tp_dst),bucket=bucket_id=0,weight:100,actions=ct(nat(dst=fd0f::2),commit,table=19,zone=NXM_NX_REG13[0..15]),bucket=bucket_id=1,weight:100,actions=ct(nat(dst=fd0f::3),commit,table=19,zone=NXM_NX_REG13[0..15])) + has prereqs ip + # ct_next ct_next; encodes as ct(table=19,zone=NXM_NX_REG13[0..15]) @@ -1520,13 +1535,13 @@ handle_svc_check(reg0); # select reg9[16..31] = select(1=50, 2=100, 3, ); formats as reg9[16..31] = select(1=50, 2=100, 3=100); - encodes as group:4 - uses group: id(4), name(type=select,selection_method=dp_hash,bucket=bucket_id=0,weight:50,actions=load:1->xreg4[16..31],resubmit(,19),bucket=bucket_id=1,weight:100,actions=load:2->xreg4[16..31],resubmit(,19),bucket=bucket_id=2,weight:100,actions=load:3->xreg4[16..31],resubmit(,19)) + encodes as group:6 + uses group: id(6), name(type=select,selection_method=dp_hash,bucket=bucket_id=0,weight:50,actions=load:1->xreg4[16..31],resubmit(,19),bucket=bucket_id=1,weight:100,actions=load:2->xreg4[16..31],resubmit(,19),bucket=bucket_id=2,weight:100,actions=load:3->xreg4[16..31],resubmit(,19)) reg0 = select(1, 2); formats as reg0 = select(1=100, 2=100); - encodes as group:5 - uses group: id(5), name(type=select,selection_method=dp_hash,bucket=bucket_id=0,weight:100,actions=load:1->xxreg0[96..127],resubmit(,19),bucket=bucket_id=1,weight:100,actions=load:2->xxreg0[96..127],resubmit(,19)) + encodes as group:7 + uses group: id(7), name(type=select,selection_method=dp_hash,bucket=bucket_id=0,weight:100,actions=load:1->xxreg0[96..127],resubmit(,19),bucket=bucket_id=1,weight:100,actions=load:2->xxreg0[96..127],resubmit(,19)) reg0 = select(1=, 2); Syntax error at `,' expecting weight. @@ -1542,12 +1557,12 @@ reg0[0..14] = select(1, 2, 3); cannot use 15-bit field reg0[0..14] for "select", which requires at least 16 bits. fwd_group(liveness="true", childports="eth0", "lsp1"); - encodes as group:6 - uses group: id(6), name(type=select,selection_method=dp_hash,bucket=watch_port:5,load=0x5->NXM_NX_REG15[0..15],resubmit(,64),bucket=watch_port:17,load=0x17->NXM_NX_REG15[0..15],resubmit(,64)) + encodes as group:8 + uses group: id(8), name(type=select,selection_method=dp_hash,bucket=watch_port:5,load=0x5->NXM_NX_REG15[0..15],resubmit(,64),bucket=watch_port:17,load=0x17->NXM_NX_REG15[0..15],resubmit(,64)) fwd_group(childports="eth0", "lsp1"); - encodes as group:7 - uses group: id(7), name(type=select,selection_method=dp_hash,bucket=load=0x5->NXM_NX_REG15[0..15],resubmit(,64),bucket=load=0x17->NXM_NX_REG15[0..15],resubmit(,64)) + encodes as group:9 + uses group: id(9), name(type=select,selection_method=dp_hash,bucket=load=0x5->NXM_NX_REG15[0..15],resubmit(,64),bucket=load=0x17->NXM_NX_REG15[0..15],resubmit(,64)) fwd_group(childports=eth0); Syntax error at `eth0' expecting logical switch port. @@ -18000,12 +18015,12 @@ service_monitor | sed '/^$/d' | wc -l`]) ovn-sbctl dump-flows sw0 | grep ct_lb | grep priority=120 > lflows.txt AT_CHECK([cat lflows.txt], [0], [dnl - table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(10.0.0.3:80,20.0.0.3:80);) + table=10(ls_in_stateful ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(ct_lb(backends=10.0.0.3:80-20.0.0.3:80);) ]) ovn-sbctl dump-flows lr0 | grep ct_lb | grep priority=120 > lflows.txt AT_CHECK([cat lflows.txt], [0], [dnl - table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80 && is_chassis_resident("cr-lr0-public")), action=(ct_lb(10.0.0.3:80,20.0.0.3:80);) + table=6 (lr_in_dnat ), priority=120 , match=(ct.new && ip && ip4.dst == 10.0.0.10 && tcp && tcp.dst == 80 && is_chassis_resident("cr-lr0-public")), action=(ct_lb(backends=10.0.0.3:80-20.0.0.3:80);) ]) # get the svc monitor mac.