From b37f8c15ca6ee079541b0c02ee77ce9d392b18fc Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: References: From: Lorenzo Bianconi Date: Thu, 20 Sep 2018 16:46:02 +0200 Subject: [PATCH] OVN: add CT_LB action to ovn-trace Add CT_LB action to ovn-trace utility in order to fix the following ovn-trace error if a load balancer rule is added to OVN configuration ct_next(ct_state=est|trk /* default (use --ct to customize) */) { *** ct_lb action not implemented; }; Add '--lb_dst' option in order to specify the ip address to use in VIP pool. If --lb_dst is not provided the destination ip will be randomly choosen Signed-off-by: Lorenzo Bianconi Signed-off-by: Ben Pfaff --- ovn/utilities/ovn-trace.8.xml | 18 ++++++- ovn/utilities/ovn-trace.c | 98 +++++++++++++++++++++++++++++++++-- 2 files changed, 111 insertions(+), 5 deletions(-) --- a/ovn/utilities/ovn-trace.8.xml +++ b/ovn/utilities/ovn-trace.8.xml @@ -253,9 +253,17 @@ ct_snat) action. -
ct_lb
+
ct_lb;
+
ct_lb(ip[:port]...);
- Not yet implemented; currently implemented as a no-op. + Forks the pipeline. In one fork, sets ip4.dst (or + ip6.dst) to one of the load-balancer addresses and the + destination port to its associated port, if any, and sets + ct.dnat to 1. With one or more arguments, gives preference + to the address specified on --lb-dst, if any; without + arguments, uses the address and port specified on --lb-dst. + In the other fork, the pipeline continues without change after the + ct_lb action.
ct_commit
@@ -424,6 +432,12 @@

+
--lb-dst=ip[:port]
+
+ Sets the IP from VIP pool to use as destination of the packet. + --lb-dst is not available in daemon mode. +
+
--friendly-names
--no-friendly-names
--- a/ovn/utilities/ovn-trace.c +++ b/ovn/utilities/ovn-trace.c @@ -46,6 +46,7 @@ #include "stream.h" #include "unixctl.h" #include "util.h" +#include "random.h" VLOG_DEFINE_THIS_MODULE(ovntrace); @@ -77,6 +78,9 @@ static uint32_t *ct_states; static size_t n_ct_states; static size_t ct_state_idx; +/* --lb-dst: load balancer destination info. */ +static struct ovnact_ct_lb_dst lb_dst; + /* --friendly-names, --no-friendly-names: Whether to substitute human-friendly * port and datapath names for the awkward UUIDs typically used in the actual * logical flows. */ @@ -187,6 +191,24 @@ parse_ct_option(const char *state_s_) } static void +parse_lb_option(const char *s) +{ + struct sockaddr_storage ss; + if (!inet_parse_active(s, 0, &ss)) { + ovs_fatal(0, "%s: bad address", s); + } + + lb_dst.family = ss.ss_family; + struct in6_addr a = ss_get_address(&ss); + if (ss.ss_family == AF_INET) { + lb_dst.ipv4 = in6_addr_get_mapped_ipv4(&a); + } else { + lb_dst.ipv6 = a; + } + lb_dst.port = ss_get_port(&ss); +} + +static void parse_options(int argc, char *argv[]) { enum { @@ -202,7 +224,8 @@ parse_options(int argc, char *argv[]) OPT_NO_FRIENDLY_NAMES, DAEMON_OPTION_ENUMS, SSL_OPTION_ENUMS, - VLOG_OPTION_ENUMS + VLOG_OPTION_ENUMS, + OPT_LB_DST }; static const struct option long_options[] = { {"db", required_argument, NULL, OPT_DB}, @@ -217,6 +240,7 @@ parse_options(int argc, char *argv[]) {"no-friendly-names", no_argument, NULL, OPT_NO_FRIENDLY_NAMES}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, + {"lb-dst", required_argument, NULL, OPT_LB_DST}, DAEMON_LONG_OPTIONS, VLOG_LONG_OPTIONS, STREAM_SSL_LONG_OPTIONS, @@ -274,6 +298,10 @@ parse_options(int argc, char *argv[]) use_friendly_names = false; break; + case OPT_LB_DST: + parse_lb_option(optarg); + break; + case 'h': usage(); @@ -1823,6 +1851,71 @@ execute_ct_nat(const struct ovnact_ct_na } static void +execute_ct_lb(const struct ovnact_ct_lb *ct_lb, + const struct ovntrace_datapath *dp, struct flow *uflow, + enum ovnact_pipeline pipeline, struct ovs_list *super) +{ + struct flow ct_lb_flow = *uflow; + + int family = (ct_lb_flow.dl_type == htons(ETH_TYPE_IP) ? AF_INET + : ct_lb_flow.dl_type == htons(ETH_TYPE_IPV6) ? AF_INET6 + : AF_UNSPEC); + if (family != AF_UNSPEC) { + const struct ovnact_ct_lb_dst *dst = NULL; + if (ct_lb->n_dsts) { + /* For ct_lb with addresses, choose one of the addresses. */ + int n = 0; + for (int i = 0; i < ct_lb->n_dsts; i++) { + const struct ovnact_ct_lb_dst *d = &ct_lb->dsts[i]; + if (d->family != family) { + continue; + } + + /* Check for the destination specified by --lb-dst, if any. */ + if (lb_dst.family == family + && (family == AF_INET + ? d->ipv4 == lb_dst.ipv4 + : ipv6_addr_equals(&d->ipv6, &lb_dst.ipv6))) { + lb_dst.family = AF_UNSPEC; + dst = d; + break; + } + + /* Select a random destination as a fallback. */ + if (!random_range(++n)) { + dst = d; + } + } + + if (!dst) { + ovntrace_node_append(super, OVNTRACE_NODE_ERROR, + "*** no load balancing destination " + "(use --lb-dst)"); + } + } else if (lb_dst.family == family) { + /* For ct_lb without addresses, use user-specified address. */ + dst = &lb_dst; + } + + if (dst) { + if (family == AF_INET6) { + ct_lb_flow.ipv6_dst = dst->ipv6; + } else { + ct_lb_flow.nw_dst = dst->ipv4; + } + if (dst->port) { + ct_lb_flow.tp_dst = htons(dst->port); + } + ct_lb_flow.ct_state |= CS_DST_NAT; + } + } + + struct ovntrace_node *node = ovntrace_node_append( + super, OVNTRACE_NODE_TRANSFORMATION, "ct_lb"); + trace__(dp, &ct_lb_flow, ct_lb->ltable, pipeline, &node->subs); +} + +static void execute_log(const struct ovnact_log *log, struct flow *uflow, struct ovs_list *super) { @@ -1910,8 +2003,7 @@ trace_actions(const struct ovnact *ovnac break; case OVNACT_CT_LB: - ovntrace_node_append(super, OVNTRACE_NODE_ERROR, - "*** ct_lb action not implemented"); + execute_ct_lb(ovnact_get_CT_LB(a), dp, uflow, pipeline, super); break; case OVNACT_CT_CLEAR: