On Fri, Jul 1, 2022 at 1:41 PM Mark Michelson <[email protected]> wrote:
>
> Thanks for this Lorenzo,
>
> Acked-by: Mark Michelson <[email protected]>

Thanks.  I applied this patch to the main branch.

Numan

>
> On 6/30/22 09:22, Lorenzo Bianconi wrote:
> > Add chk_lb_hairpin_reply and ct_snat_to_vip implementations for ovn-trace
> > utility in order to simulate hairpin traffic
> >
> > Rreported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2099311
> > Signed-off-by: Lorenzo Bianconi <[email protected]>
> > ---
> >   tests/ovn-northd.at   |   8 ---
> >   utilities/ovn-trace.c | 126 ++++++++++++++++++++++++++++++++----------
> >   2 files changed, 97 insertions(+), 37 deletions(-)
> >
> > diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> > index fe97bedad..2f293bfc8 100644
> > --- a/tests/ovn-northd.at
> > +++ b/tests/ovn-northd.at
> > @@ -2936,7 +2936,6 @@ AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new 
> > --minimal ls "${flow}"], [0], [dn
> >   ct_lb_mark {
> >       ct_lb_mark {
> >           reg0[[6]] = 0;
> > -        *** chk_lb_hairpin_reply action not implemented;
> >           reg0[[12]] = 0;
> >           ct_lb_mark /* default (use --ct to customize) */ {
> >               output("lsp2");
> > @@ -2952,7 +2951,6 @@ AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new 
> > --minimal ls "${flow}"], [0], [dn
> >   ct_lb_mark {
> >       ct_lb_mark {
> >           reg0[[6]] = 0;
> > -        *** chk_lb_hairpin_reply action not implemented;
> >           reg0[[12]] = 0;
> >           ct_lb_mark /* default (use --ct to customize) */ {
> >               output("lsp2");
> > @@ -2974,7 +2972,6 @@ AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new 
> > --minimal ls "${flow}"], [0], [dn
> >   ct_lb_mark {
> >       ct_lb_mark {
> >           reg0[[6]] = 0;
> > -        *** chk_lb_hairpin_reply action not implemented;
> >           reg0[[12]] = 0;
> >           ct_lb_mark /* default (use --ct to customize) */ {
> >               output("lsp2");
> > @@ -2990,7 +2987,6 @@ AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new 
> > --minimal ls "${flow}"], [0], [dn
> >   ct_lb_mark {
> >       ct_lb_mark {
> >           reg0[[6]] = 0;
> > -        *** chk_lb_hairpin_reply action not implemented;
> >           reg0[[12]] = 0;
> >           ct_lb_mark /* default (use --ct to customize) */ {
> >               output("lsp2");
> > @@ -3092,7 +3088,6 @@ AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new 
> > --minimal ls "${flow}"], [0], [dn
> >   ct_lb_mark {
> >       ct_lb_mark {
> >           reg0[[6]] = 0;
> > -        *** chk_lb_hairpin_reply action not implemented;
> >           reg0[[12]] = 0;
> >           ct_lb_mark /* default (use --ct to customize) */ {
> >               output("lsp2");
> > @@ -3108,7 +3103,6 @@ AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new 
> > --minimal ls "${flow}"], [0], [dn
> >   ct_lb_mark {
> >       ct_lb_mark {
> >           reg0[[6]] = 0;
> > -        *** chk_lb_hairpin_reply action not implemented;
> >           reg0[[12]] = 0;
> >           ct_lb_mark /* default (use --ct to customize) */ {
> >               output("lsp2");
> > @@ -3130,7 +3124,6 @@ AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new 
> > --minimal ls "${flow}"], [0], [dn
> >   ct_lb_mark {
> >       ct_lb_mark {
> >           reg0[[6]] = 0;
> > -        *** chk_lb_hairpin_reply action not implemented;
> >           reg0[[12]] = 0;
> >           ct_lb_mark /* default (use --ct to customize) */ {
> >               output("lsp2");
> > @@ -3146,7 +3139,6 @@ AT_CHECK_UNQUOTED([ovn-trace --ct new --ct new 
> > --minimal ls "${flow}"], [0], [dn
> >   ct_lb_mark {
> >       ct_lb_mark {
> >           reg0[[6]] = 0;
> > -        *** chk_lb_hairpin_reply action not implemented;
> >           reg0[[12]] = 0;
> >           ct_lb_mark /* default (use --ct to customize) */ {
> >               output("lsp2");
> > diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c
> > index c4110de0a..baf489202 100644
> > --- a/utilities/ovn-trace.c
> > +++ b/utilities/ovn-trace.c
> > @@ -2488,10 +2488,13 @@ execute_ct_lb(const struct ovnact_ct_lb *ct_lb,
> >
> >           if (dst) {
> >               if (family == AF_INET6) {
> > +                ct_lb_flow.ct_ipv6_dst = ct_lb_flow.ipv6_dst;
> >                   ct_lb_flow.ipv6_dst = dst->ipv6;
> >               } else {
> > +                ct_lb_flow.ct_nw_dst = ct_lb_flow.nw_dst;
> >                   ct_lb_flow.nw_dst = dst->ipv4;
> >               }
> > +            ct_lb_flow.ct_tp_dst = ct_lb_flow.tp_dst;
> >               if (dst->port) {
> >                   ct_lb_flow.tp_dst = htons(dst->port);
> >               }
> > @@ -2588,15 +2591,65 @@ execute_ovnfield_load(const struct ovnact_load 
> > *load,
> >       }
> >   }
> >
> > +static bool
> > +get_lb_vip_data(struct flow *uflow, struct in6_addr *vip,
> > +                char **vip_str, uint16_t *port)
> > +{
> > +    int family;
> > +
> > +    const struct sbrec_load_balancer *sbdb;
> > +    SBREC_LOAD_BALANCER_FOR_EACH (sbdb, ovnsb_idl) {
> > +        struct smap_node *node;
> > +        SMAP_FOR_EACH (node, &sbdb->vips) {
> > +            if (!ip_address_and_port_from_lb_key(node->key, vip_str,
> > +                                                 port, &family)) {
> > +                continue;
> > +            }
> > +
> > +            if (family == AF_INET) {
> > +                ovs_be32 vip4;
> > +                ip_parse(*vip_str, &vip4);
> > +                in6_addr_set_mapped_ipv4(vip, vip4);
> > +                if (vip4 == uflow->ct_nw_dst) {
> > +                    return true;
> > +                }
> > +            } else {
> > +                ipv6_parse(*vip_str, vip);
> > +                if (ipv6_addr_equals(vip, &uflow->ct_ipv6_dst)) {
> > +                    return true;
> > +                }
> > +            }
> > +            free(*vip_str);
> > +        }
> > +    }
> > +
> > +    return false;
> > +}
> > +
> >   static void
> >   execute_chk_lb_hairpin(const struct ovnact_result *dl, struct flow *uflow,
> > -                       struct ovs_list *super)
> > +                       struct ovs_list *super, bool dir_orig)
> >   {
> > -    int family = (uflow->dl_type == htons(ETH_TYPE_IP) ? AF_INET
> > -                  : uflow->dl_type == htons(ETH_TYPE_IPV6) ? AF_INET6
> > -                  : AF_UNSPEC);
> > +    struct mf_subfield sf = expr_resolve_field(&dl->dst);
> > +    union mf_subvalue sv = { .u8_val = 0 };
> > +    struct in6_addr vip;
> > +    uint16_t vip_port;
> >       uint8_t res = 0;
> > -    if (family != AF_UNSPEC && uflow->ct_state & CS_DST_NAT) {
> > +    char *vip_str;
> > +
> > +    if (!get_lb_vip_data(uflow, &vip, &vip_str, &vip_port)) {
> > +        goto out;
> > +    }
> > +    free(vip_str);
> > +
> > +    int family = (uflow->dl_type == htons(ETH_TYPE_IP) ? AF_INET
> > +                 : uflow->dl_type == htons(ETH_TYPE_IPV6) ? AF_INET6
> > +                 : AF_UNSPEC);
> > +    if (family == AF_UNSPEC) {
> > +        goto out;
> > +    }
> > +
> > +    if (uflow->ct_state & CS_DST_NAT) {
> >           if (family == AF_INET) {
> >               res = (uflow->nw_src == uflow->nw_dst) ? 1 : 0;
> >           } else {
> > @@ -2604,8 +2657,14 @@ execute_chk_lb_hairpin(const struct ovnact_result 
> > *dl, struct flow *uflow,
> >           }
> >       }
> >
> > -    struct mf_subfield sf = expr_resolve_field(&dl->dst);
> > -    union mf_subvalue sv = { .u8_val = res };
> > +    if (dir_orig) {
> > +        res &= (vip_port == ntohs(uflow->ct_tp_dst));
> > +    } else {
> > +        res &= (vip_port == ntohs(uflow->tp_dst));
> > +    }
> > +
> > +    sv.u8_val = res;
> > +out:
> >       mf_write_subfield_flow(&sf, &sv, uflow);
> >
> >       struct ds s = DS_EMPTY_INITIALIZER;
> > @@ -2616,27 +2675,35 @@ execute_chk_lb_hairpin(const struct ovnact_result 
> > *dl, struct flow *uflow,
> >   }
> >
> >   static void
> > -execute_chk_lb_hairpin_reply(const struct ovnact_result *dl,
> > -                             struct flow *uflow,
> > -                             struct ovs_list *super)
> > +execute_ct_snat_to_vip(struct flow *uflow, struct ovs_list *super)
> >   {
> > -    struct mf_subfield sf = expr_resolve_field(&dl->dst);
> > -    union mf_subvalue sv = { .u8_val = 0 };
> > -    mf_write_subfield_flow(&sf, &sv, uflow);
> > -    ovntrace_node_append(super, OVNTRACE_NODE_ERROR,
> > -                         "*** chk_lb_hairpin_reply action not 
> > implemented");
> > -    struct ds s = DS_EMPTY_INITIALIZER;
> > -    expr_field_format(&dl->dst, &s);
> > -    ovntrace_node_append(super, OVNTRACE_NODE_MODIFY,
> > -                         "%s = 0", ds_cstr(&s));
> > -    ds_destroy(&s);
> > -}
> > +    struct in6_addr vip;
> > +    uint16_t vip_port;
> > +    char *vip_str;
> >
> > -static void
> > -execute_ct_snat_to_vip(struct flow *uflow OVS_UNUSED, struct ovs_list 
> > *super)
> > -{
> > -    ovntrace_node_append(super, OVNTRACE_NODE_ERROR,
> > -                         "*** ct_snat_to_vip action not implemented");
> > +    if (!get_lb_vip_data(uflow, &vip, &vip_str, &vip_port)) {
> > +        return;
> > +    }
> > +
> > +    if (IN6_IS_ADDR_V4MAPPED(&vip)) {
> > +        ovs_be32 vip4 = in6_addr_get_mapped_ipv4(&vip);
> > +        if (vip4 != uflow->ct_nw_dst) {
> > +            goto out;
> > +        }
> > +    } else {
> > +        if (!ipv6_addr_equals(&vip, &uflow->ct_ipv6_dst)) {
> > +            goto out;
> > +        }
> > +    }
> > +
> > +    if (vip_port != ntohs(uflow->ct_tp_dst)) {
> > +        goto out;
> > +    }
> > +
> > +    ovntrace_node_append(super, OVNTRACE_NODE_ACTION, "/* nat(src=%s) */",
> > +                         vip_str);
> > +out:
> > +    free(vip_str);
> >   }
> >
> >   static bool
> > @@ -3173,12 +3240,13 @@ trace_actions(const struct ovnact *ovnacts, size_t 
> > ovnacts_len,
> >               break;
> >
> >           case OVNACT_CHK_LB_HAIRPIN:
> > -            execute_chk_lb_hairpin(ovnact_get_CHK_LB_HAIRPIN(a), uflow, 
> > super);
> > +            execute_chk_lb_hairpin(ovnact_get_CHK_LB_HAIRPIN(a), uflow, 
> > super,
> > +                                   true);
> >               break;
> >
> >           case OVNACT_CHK_LB_HAIRPIN_REPLY:
> > -            
> > execute_chk_lb_hairpin_reply(ovnact_get_CHK_LB_HAIRPIN_REPLY(a),
> > -                                         uflow, super);
> > +            execute_chk_lb_hairpin(ovnact_get_CHK_LB_HAIRPIN_REPLY(a), 
> > uflow,
> > +                                   super, false);
> >               break;
> >           case OVNACT_CT_SNAT_TO_VIP:
> >               execute_ct_snat_to_vip(uflow, super);
> >
>
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to