On Wed, May 3, 2017 at 6:43 PM, Mickey Spiegel <mickeys....@gmail.com> wrote: > On Wed, May 3, 2017 at 8:45 AM, Ben Pfaff <b...@ovn.org> wrote: > >> Without this support, ovn-trace is not very useful with OpenStack, which >> uses connection tracking extensively. >> >> Signed-off-by: Ben Pfaff <b...@ovn.org> >> > > Acked-by: Mickey Spiegel <mickeys....@gmail.com> > > A couple of minor comments below. > > --- >> ovn/utilities/ovn-trace.8.xml | 50 ++++++++++++++++++++++++++++++ >> +++++++++++ >> ovn/utilities/ovn-trace.c | 52 ++++++++++++++++++++++++++++++ >> ++++++++++--- >> 2 files changed, 99 insertions(+), 3 deletions(-) >> >> diff --git a/ovn/utilities/ovn-trace.8.xml b/ovn/utilities/ovn-trace.8.xml >> index 8bb329bfbd71..b2d46ac3d50b 100644 >> --- a/ovn/utilities/ovn-trace.8.xml >> +++ b/ovn/utilities/ovn-trace.8.xml >> @@ -166,6 +166,56 @@ >> output; >> </pre> >> >> + <h2>Stateful Actions</h2> >> > > The flow is a little funny. At the beginning of the output section: > > <code>ovn-trace</code> supports the three different forms of output, > each > described in a separate section below. > > Now there is another h2 section in between the three sections describing > the different forms of output. > > Perhaps just use <h3>?
May be in its own section? > > + >> + <p> >> + Some OVN logical actions use or update state that is not available in >> the >> + southbound database. <code>ovn-trace</code> handles these actions as >> + described below: >> + </p> >> + >> + <dl> >> + <dt>ct_next</dt> >> + <dd> >> + By default <code>ovn-trace</code> treats flows as ``tracked'' and >> + ``established.'' The <code>--ct</code> option overrides this >> behavior; >> + refer to its description for more information. >> + </dd> >> + >> + <dt>ct_commit</dt> >> + <dd> >> + This action is treated as a no-op. >> + </dd> >> + >> + <dt>ct_dnat</dt> >> + <dt>ct_snat</dt> >> + <dd> >> + <p> >> + When one of these action is used without arguments, to ``un-NAT'' >> a >> > > s/action/actions > > >> + packet, <code>ovn-trace</code> assumes that no NAT state was >> available >> + and treats it as a no-op. >> + </p> >> + >> + <p> >> + With an argument, <code>ovn-trace</code> sets the IP destination >> or >> + source, as appropriate, to the given address. It also sets >> + <code>ct.dnat</code> or <code>ct.snat</code> to 1 to indicate >> that NAT >> + has taken place. >> + </p> >> + </dd> >> + >> + <dt>ct_lb</dt> >> + <dd> >> + Not yet implemented; currently implemented as a no-op. >> + </dd> >> + >> + <dt>put_arp</dt> >> + <dt>put_nd</dt> >> + <dd> >> + This action is treated as a no-op. >> + </dd> >> + </dl> >> + >> <h2>Summary Output</h2> >> >> <p> >> diff --git a/ovn/utilities/ovn-trace.c b/ovn/utilities/ovn-trace.c >> index 3a0780eb931e..860fd4b26be0 100644 >> --- a/ovn/utilities/ovn-trace.c >> +++ b/ovn/utilities/ovn-trace.c >> @@ -346,6 +346,8 @@ struct ovntrace_datapath { >> size_t n_flows, allocated_flows; >> >> struct hmap mac_bindings; /* Contains "struct >> ovntrace_mac_binding"s. */ >> + >> + bool has_local_l3gateway; >> }; >> >> struct ovntrace_port { >> @@ -570,6 +572,9 @@ read_ports(void) >> port->peer->peer = port; >> } >> } >> + } else if (!strcmp(sbpb->type, "l3gateway")) { >> + /* Treat all gateways as local for our purposes. */ >> + dp->has_local_l3gateway = true; >> } >> } >> >> @@ -1522,6 +1527,46 @@ execute_ct_next(const struct ovnact_ct_next >> *ct_next, >> } >> >> static void >> +execute_ct_nat(const struct ovnact_ct_nat *ct_nat, >> + const struct ovntrace_datapath *dp, struct flow *uflow, >> + enum ovnact_pipeline pipeline, struct ovs_list *super) >> +{ >> + bool is_dst = ct_nat->ovnact.type == OVNACT_CT_DNAT; >> + if (!is_dst && dp->has_local_l3gateway && !ct_nat->ip) { >> + /* "ct_snat;" has no visible effect in a gateway router. */ >> + return; >> + } >> + const char *direction = is_dst ? "dst" : "src"; >> + >> + /* Make a sub-node for attaching the next table, >> + * and figure out the changes if any. */ >> + struct flow ct_flow = *uflow; >> + struct ds s = DS_EMPTY_INITIALIZER; >> + ds_put_format(&s, "ct_%cnat", direction[0]); >> + if (ct_nat->ip) { >> + ds_put_format(&s, "(ip4.%s="IP_FMT")", direction, >> IP_ARGS(ct_nat->ip)); >> + ovs_be32 *ip = is_dst ? &ct_flow.nw_dst : &ct_flow.nw_src; >> + *ip = ct_nat->ip; >> + >> + uint8_t state = is_dst ? CS_DST_NAT : CS_SRC_NAT; >> + ct_flow.ct_state |= state; >> + } else { >> + ds_put_format(&s, " /* assuming no un-%cnat entry, so no change >> */", >> + direction[0]); >> + } >> + struct ovntrace_node *node = ovntrace_node_append( >> + super, OVNTRACE_NODE_TRANSFORMATION, "%s", ds_cstr(&s)); >> + ds_destroy(&s); >> + >> + /* Trace the actions in the next table. */ >> + trace__(dp, &ct_flow, ct_nat->ltable, pipeline, &node->subs); >> + >> + /* Upon return, we will trace the actions following the ct action in >> the >> + * original table. The pipeline forked, so we're using the original >> + * flow, not ct_flow. */ >> +} >> + >> +static void >> trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len, >> const struct ovntrace_datapath *dp, struct flow *uflow, >> uint8_t table_id, enum ovnact_pipeline pipeline, >> @@ -1585,10 +1630,11 @@ trace_actions(const struct ovnact *ovnacts, size_t >> ovnacts_len, >> break; >> >> case OVNACT_CT_DNAT: >> + execute_ct_nat(ovnact_get_CT_DNAT(a), dp, uflow, pipeline, >> super); >> + break; >> + >> case OVNACT_CT_SNAT: >> - ovntrace_node_append(super, OVNTRACE_NODE_ERROR, >> - "*** ct_dnat and ct_snat actions " >> - "not implemented"); >> + execute_ct_nat(ovnact_get_CT_SNAT(a), dp, uflow, pipeline, >> super); >> break; >> >> case OVNACT_CT_LB: >> -- >> 2.10.2 >> >> _______________________________________________ >> dev mailing list >> d...@openvswitch.org >> https://mail.openvswitch.org/mailman/listinfo/ovs-dev >> > _______________________________________________ > dev mailing list > d...@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev