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
