On 5/19/23 20:18, Vladislav Odintsov wrote:
> This patch fixes a situation, where logical flow with incorrect syntax could
> be generated.  If a logical switch has two attached logical router ports and
> one of them has configured gateway chassis, then incorrect flow can have the
> match like:
> `reg0[14] == 1 && (is_chassis_resident("cr-lrp2") || ` or
> `is_chassis_resident("cr-lrp1"))`
> 
> The flow's match was reworked to have at maximum one 'is_chassis_resident()'
> part.  For each cr-lport a new lflow is created.  There should not be many
> cr-lports within one datapath (normally there is just one), so the lflows
> count shouldn't increase dramatically.
> 
> Now the match looks like:
> `reg0[14] == 1 && is_chassis_resident("cr-lrp2")`
> 
> As an additional enhancement, the code became easier and tests were also
> simplified.
> 
> Documentation and relevant testcases were updated.
> 
> Fixes: 4e90bcf55c2e ("controller, northd, vtep: support routed networks with 
> HW VTEP")
> Signed-off-by: Vladislav Odintsov <[email protected]>
> ---
>  northd/northd.c         | 35 ++++++++++++++---------------------
>  northd/ovn-northd.8.xml | 13 +++++++------
>  tests/ovn.at            | 17 +++--------------
>  3 files changed, 24 insertions(+), 41 deletions(-)
> 
> diff --git a/northd/northd.c b/northd/northd.c
> index 07b127cdf..d6c26735d 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -7819,37 +7819,30 @@ static void
>  build_vtep_hairpin(struct ovn_datapath *od, struct hmap *lflows)
>  {
>      /* Ingress Pre-ARP flows for VTEP hairpining traffic. Priority 1000:
> -     * Packets that received from non-VTEP ports should continue processing. 
> */
> -
> +     * Packets that received from VTEP ports must go directly to L2LKP table.
> +     */

I changed this to:

"Packets received from VTEP ports must go directly to L2LKP table."

and applied it to main and backported to all stable branches down to 22.06.

Regards,
Dumitru

>      char *action = xasprintf("next(pipeline=ingress, table=%d);",
>                               ovn_stage_get_table(S_SWITCH_IN_L2_LKUP));
> -    /* send all traffic from VTEP directly to L2LKP table. */
>      ovn_lflow_add(lflows, od, S_SWITCH_IN_HAIRPIN, 1000,
>                    REGBIT_FROM_RAMP" == 1", action);
>      free(action);
>  
> -    struct ds match = DS_EMPTY_INITIALIZER;
> -    size_t n_ports = od->n_router_ports;
> -    bool dp_has_l3dgw_ports = false;
> -    for (int i = 0; i < n_ports; i++) {
> -        if (is_l3dgw_port(od->router_ports[i]->peer)) {
> -            ds_put_format(&match, "%sis_chassis_resident(%s)%s",
> -                          i == 0 ? REGBIT_FROM_RAMP" == 1 && (" : "",
> -                          od->router_ports[i]->peer->cr_port->json_key,
> -                          i < n_ports - 1 ? " || " : ")");
> -            dp_has_l3dgw_ports = true;
> -        }
> -    }
> -
>      /* Ingress pre-arp flow for traffic from VTEP (ramp) switch.
>      * Priority 2000: Packets, that were received from VTEP (ramp) switch and
>      * router ports of current datapath are l3dgw ports and they reside on
>      * current chassis, should be passed to next table for ARP/ND hairpin
> -    * processing.
> -    */
> -    if (dp_has_l3dgw_ports) {
> -        ovn_lflow_add(lflows, od, S_SWITCH_IN_HAIRPIN, 2000, ds_cstr(&match),
> -                      "next;");
> +    * processing. */
> +    struct ds match = DS_EMPTY_INITIALIZER;
> +    for (int i = 0; i < od->n_router_ports; i++) {
> +        struct ovn_port *op = od->router_ports[i]->peer;
> +        if (is_l3dgw_port(op)) {
> +            ds_clear(&match);
> +            ds_put_format(&match,
> +                          REGBIT_FROM_RAMP" == 1 && is_chassis_resident(%s)",
> +                          op->cr_port->json_key);
> +            ovn_lflow_add(lflows, od, S_SWITCH_IN_HAIRPIN, 2000,
> +                          ds_cstr(&match), "next;");
> +        }
>      }
>      ds_destroy(&match);
>  }
> diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
> index 540fe03bd..a8ef00a28 100644
> --- a/northd/ovn-northd.8.xml
> +++ b/northd/ovn-northd.8.xml
> @@ -1144,16 +1144,17 @@
>        <li>
>          <p>
>            For each distributed gateway router port <var>RP</var> attached to
> -          the logical switch, a priority-2000 flow is added with the match
> -          <code>reg0[14] == 1 &amp;&amp; is_chassis_resident(<var>RP</var>)
> -          </code> and action <code>next;</code> to pass the traffic to the
> -          next table to respond to the ARP requests for the router port IPs.
> +          the logical switch and has chassis redirect port <var>cr-RP</var>, 
> a
> +          priority-2000 flow is added with the match
> +          <pre>
> +<code>reg0[14] == 1 &amp;&amp; is_chassis_resident(<var>cr-RP</var>)</code>
> +          </pre>
> +          and action <code>next;</code>.
>          </p>
>  
>          <p>
>            <code>reg0[14]</code> register bit is set in the ingress L2 port
> -           security check table for traffic received from HW VTEP (ramp)
> -           ports.
> +          security check table for traffic received from HW VTEP (ramp) 
> ports.
>          </p>
>        </li>
>  
> diff --git a/tests/ovn.at b/tests/ovn.at
> index 9e6e8a14a..53349530b 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -4432,24 +4432,13 @@ 
> response=${sha}${lrpmac}08060001080006040002${lrpmac}${tpa}${sha}${spa}
>  echo $response >> 3.expected
>  
>  # First ensure basic flow contents are as we expect.
> -AT_CHECK([ovn-sbctl lflow-list lsw0 | grep 'reg0[\[14\]]' | sort | sed 
> 's/table=../table=??/g' | sed 
> 's/is_chassis_resident([[^)]]*)/is_chassis_resident("??")/g'], [0], [dnl
> +AT_CHECK([ovn-sbctl lflow-list lsw0 | grep 'reg0[\[14\]]' | sort | sed 
> 's/table=../table=??/g'], [0], [dnl
>    table=??(ls_in_check_port_sec), priority=70   , match=(inport == 
> "lp-vtep"), action=(reg0[[14]] = 1; next(pipeline=ingress, table=??);)
>    table=??(ls_in_hairpin      ), priority=1000 , match=(reg0[[14]] == 1), 
> action=(next(pipeline=ingress, table=??);)
> -  table=??(ls_in_hairpin      ), priority=2000 , match=(reg0[[14]] == 1 && 
> (is_chassis_resident("??") || is_chassis_resident("??"))), action=(next;)
> +  table=??(ls_in_hairpin      ), priority=2000 , match=(reg0[[14]] == 1 && 
> is_chassis_resident("cr-lrp1")), action=(next;)
> +  table=??(ls_in_hairpin      ), priority=2000 , match=(reg0[[14]] == 1 && 
> is_chassis_resident("cr-lrp2")), action=(next;)
>  ])
>  
> -# We've ensured that the expected hairpin flows are present
> -# and that the expected number of "is_chassis_resident" fields are in
> -# the flow. Now we need to ensure the contents are correct.
> -# Unfortunately, the order of the "is_chassis_resident" fields is
> -# unpredictable. Therefore we sort them so the order is predictable.
> -actual_chassis=$(ovn-sbctl lflow-list lsw0 | grep 'ls_in_hairpin' | grep 
> 'priority=2000' | grep -o 'is_chassis_resident([[^)]]*)' | sort)
> -
> -expected_chassis='is_chassis_resident("cr-lrp1")
> -is_chassis_resident("cr-lrp2")'
> -
> -check test "$expected_chassis" = "$actual_chassis"
> -
>  # dump information with counters
>  echo "------ OVN dump ------"
>  ovn-nbctl show

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to