[ovs-dev] [PATCH v3 ovn 2/5] ovn-northd: Store ETH address of router inport in xreg0.

Han Zhou hzhou at ovn.org
Fri Jul 3 05:55:08 UTC 2020


On Thu, Jul 2, 2020 at 7:53 AM Dumitru Ceara <dceara at redhat.com> wrote:
>
> This helps simplifying logical flows that need to use the port's
> configured ETH address:
> - ARP responders for owned IPs
> - NS responders for owned IPs
>
> Signed-off-by: Dumitru Ceara <dceara at redhat.com>
> ---
>  northd/ovn-northd.8.xml |   22 ++++---
>  northd/ovn-northd.c     |  148
++++++++++++++++++++++++++---------------------
>  tests/ovn-northd.at     |  140
++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 233 insertions(+), 77 deletions(-)
>
> diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
> index a7639f3..78e2a71 100644
> --- a/northd/ovn-northd.8.xml
> +++ b/northd/ovn-northd.8.xml
> @@ -1487,7 +1487,9 @@ output;
>            For each enabled router port <var>P</var> with Ethernet address
>            <var>E</var>, a priority-50 flow that matches <code>inport ==
>            <var>P</var> && (eth.mcast || eth.dst ==
> -          <var>E</var></code>), with action <code>next;</code>.
> +          <var>E</var></code>), stores the router port ethernet address
> +          and advances to next table, with action
> +          <code>xreg0[0..47]=E; next;</code>.
>          </p>
>
>          <p>
> @@ -1507,7 +1509,7 @@ output;
>            a priority-50 flow that matches <code>inport == <var>GW</var>
>            && eth.dst == <var>E</var></code>, where <var>GW</var>
>            is the logical router gateway port, with action
> -          <code>next;</code>.
> +          <code>xreg0[0..47]=E; next;</code>.
>          </p>
>
>          <p>
> @@ -1770,10 +1772,10 @@ next;
>
>          <pre>
>  eth.dst = eth.src;
> -eth.src = <var>E</var>;
> +eth.src = xreg0[0..47];
>  arp.op = 2; /* ARP reply. */
>  arp.tha = arp.sha;
> -arp.sha = <var>E</var>;
> +arp.sha = xreg0[0..47];
>  arp.tpa = arp.spa;
>  arp.spa = <var>A</var>;
>  outport = <var>P</var>;
> @@ -1822,10 +1824,10 @@ output;
>
>          <pre>
>  nd_na_router {
> -    eth.src = <var>E</var>;
> +    eth.src = xreg0[0..47];
>      ip6.src = <var>A</var>;
>      nd.target = <var>A</var>;
> -    nd.tll = <var>E</var>;
> +    nd.tll = xreg0[0..47];
>      outport = inport;
>      flags.loopback = 1;
>      output;
> @@ -1862,10 +1864,10 @@ nd_na_router {
>
>          <pre>
>  eth.dst = eth.src;
> -eth.src = <var>E</var>;
> +eth.src = xreg0[0..47];
>  arp.op = 2; /* ARP reply. */
>  arp.tha = arp.sha;
> -arp.sha = <var>E</var>;
> +arp.sha = xreg0[0..47];
>  arp.tpa = arp.spa;
>  arp.spa = <var>A</var>;
>  outport = <var>P</var>;
> @@ -1894,8 +1896,8 @@ output;
>          <pre>
>  eth.dst = eth.src;
>  nd_na {
> -    eth.src = <var>E</var>;
> -    nd.tll = <var>E</var>;
> +    eth.src = xreg0[0..47];
> +    nd.tll = xreg0[0..47];
>      ip6.src = <var>A</var>;
>      nd.target = <var>A</var>;
>      outport = <var>P</var>;
> diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
> index 85d73ff..7c92436 100644
> --- a/northd/ovn-northd.c
> +++ b/northd/ovn-northd.c
> @@ -223,6 +223,11 @@ enum ovn_stage {
>  #define REGBIT_LOOKUP_NEIGHBOR_RESULT "reg9[2]"
>  #define REGBIT_SKIP_LOOKUP_NEIGHBOR "reg9[3]"
>
> +/* Register to store the eth address associated to a router port for
packets
> + * received in S_ROUTER_IN_ADMISSION.
> + */
> +#define REG_INPORT_ETH_ADDR "xreg0[0..47]"
> +
>  /* Register for ECMP bucket selection. */
>  #define REG_ECMP_GROUP_ID       "reg8[0..15]"
>  #define REG_ECMP_MEMBER_ID      "reg8[16..31]"
> @@ -246,33 +251,40 @@ enum ovn_stage {
>   * +---------+-------------------------------------+
>   *
>   * Logical Router pipeline:
> - * +-----+--------------------------+---+-------------+
> - * | R0  | REGBIT_ND_RA_OPTS_RESULT |   |             |
> - * |     |    IPv4-NEXT-HOP         | X |             |
> - * +-----+--------------------------+ X |             |
> - * | R1  | IPv4-SRC-IP for ARP-REQ  | R |    IPv6     |
> - * +-----+--------------------------+ E |  NEXT-HOP   |
> - * | R2  |        UNUSED            | G |             |
> - * +-----+--------------------------+ 0 |             |
> - * | R3  |        UNUSED            |   |             |
> - * +-----+--------------------------+---+-------------+
> - * | R4  |        UNUSED            |   |             |
> - * +-----+--------------------------+ X |             |
> - * | R5  |        UNUSED            | X | IPv6-SRC-IP |
> - * +-----+--------------------------+ R |   for NS    |
> - * | R6  |        UNUSED            | E |             |
> - * +-----+--------------------------+ G |             |
> - * | R7  |        UNUSED            | 1 |             |
> - * +-----+--------------------------+---+-------------+
> - * | R8  |     ECMP_GROUP_ID        |
> - * |     |     ECMP_MEMBER_ID       |
> - * +-----+--------------------------+
> - * |     | REGBIT_{                 |
> - * |     |   EGRESS_LOOPBACK/       |
> - * | R9  |   PKT_LARGER/            |
> - * |     |   LOOKUP_NEIGHBOR_RESULT/|
> - * |     |   SKIP_LOOKUP_NEIGHBOR}  |
> - * +-----+--------------------------+
> + *
+-----+--------------------------+---+-----------------+---+-------------+
> + * | R0  | REGBIT_ND_RA_OPTS_RESULT | X |                 |   |
    |
> + * |     |    IPv4-NEXT-HOP         | R |                 |   |
    |
> + * +-----+--------------------------+ E | INPORT_ETH_ADDR | X |
    |
> + * | R1  | IPv4-SRC-IP for ARP-REQ  | G |   (< IP_INPUT)  | X |    IPv6
    |
> + * |     |                          | 0 |                 | R |
 NEXT-HOP   |
> + * +-----+--------------------------+---+-----------------+ E |(>=
IP_INPUT)|

It is a good idea to mention the stage "< IP_INPUT" or ">= IP_INPUT".
However, sInce R0 and R1 are overlapping with xreg0 and xxreg0, it might be
better to mention the stage of R0 and R1 usage as well.
Otherwise:

Acked-by: Han Zhou <hzhou at ovn.org>


> + * | R2  |        UNUSED            | X |                 | G |
    |
> + * |     |                          | R |                 | 0 |
    |
> + * +-----+--------------------------+ E |     UNUSED      |   |
    |
> + * | R3  |        UNUSED            | G |                 |   |
    |
> + * |     |                          | 1 |                 |   |
    |
> + *
+-----+--------------------------+---+-----------------+---+-------------+
> + * | R4  |        UNUSED            | X |                 |   |
    |
> + * |     |                          | R |                 |   |
    |
> + * +-----+--------------------------+ E |     UNUSED      | X |
    |
> + * | R5  |        UNUSED            | G |                 | X |
IPv6-SRC-IP |
> + * |     |                          | 2 |                 | R |   for NS
   |
> + * +-----+--------------------------+---+-----------------+ E |(>=
IP_INPUT)|
> + * | R6  |        UNUSED            | X |                 | G |
    |
> + * |     |                          | R |                 | 1 |
    |
> + * +-----+--------------------------+ E |     UNUSED      |   |
    |
> + * | R7  |        UNUSED            | G |                 |   |
    |
> + * |     |                          | 3 |                 |   |
    |
> + *
+-----+--------------------------+---+-----------------+---+-------------+
> + * | R8  |     ECMP_GROUP_ID        |   |                 |
> + * |     |     ECMP_MEMBER_ID       | X |                 |
> + * +-----+--------------------------+ R |                 |
> + * |     | REGBIT_{                 | E |                 |
> + * |     |   EGRESS_LOOPBACK/       | G |     UNUSED      |
> + * | R9  |   PKT_LARGER/            | 4 |                 |
> + * |     |   LOOKUP_NEIGHBOR_RESULT/|   |                 |
> + * |     |   SKIP_LOOKUP_NEIGHBOR}  |   |                 |
> + * +-----+--------------------------+---+-----------------+
>   *
>   */
>
> @@ -8007,10 +8019,19 @@ build_lrouter_flows(struct hmap *datapaths,
struct hmap *ports,
>              continue;
>          }
>
> +        /* Store the ethernet address of the port receiving the packet.
> +         * This will save us from having to match on inport further down
in
> +         * the pipeline.
> +         */
> +        ds_clear(&actions);
> +        ds_put_format(&actions, REG_INPORT_ETH_ADDR " = %s; next;",
> +                      op->lrp_networks.ea_s);
> +
>          ds_clear(&match);
>          ds_put_format(&match, "eth.mcast && inport == %s", op->json_key);
>          ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_ADMISSION,
50,
> -                                ds_cstr(&match), "next;",
&op->nbrp->header_);
> +                                ds_cstr(&match), ds_cstr(&actions),
> +                                &op->nbrp->header_);
>
>          ds_clear(&match);
>          ds_put_format(&match, "eth.dst == %s && inport == %s",
> @@ -8023,7 +8044,8 @@ build_lrouter_flows(struct hmap *datapaths, struct
hmap *ports,
>                            op->od->l3redirect_port->json_key);
>          }
>          ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_ADMISSION,
50,
> -                                ds_cstr(&match), "next;",
&op->nbrp->header_);
> +                                ds_cstr(&match),  ds_cstr(&actions),
> +                                &op->nbrp->header_);
>      }
>
>      /* Logical router ingress table 1: LOOKUP_NEIGHBOR and
> @@ -8290,17 +8312,15 @@ build_lrouter_flows(struct hmap *datapaths,
struct hmap *ports,
>              ds_clear(&actions);
>              ds_put_format(&actions,
>                  "eth.dst = eth.src; "
> -                "eth.src = %s; "
> +                "eth.src = " REG_INPORT_ETH_ADDR "; "
>                  "arp.op = 2; /* ARP reply */ "
>                  "arp.tha = arp.sha; "
> -                "arp.sha = %s; "
> +                "arp.sha = " REG_INPORT_ETH_ADDR "; "
>                  "arp.tpa = arp.spa; "
>                  "arp.spa = %s; "
>                  "outport = %s; "
>                  "flags.loopback = 1; "
>                  "output;",
> -                op->lrp_networks.ea_s,
> -                op->lrp_networks.ea_s,
>                  op->lrp_networks.ipv4_addrs[i].addr_s,
>                  op->json_key);
>              ovn_lflow_add_with_hint(lflows, op->od,
S_ROUTER_IN_IP_INPUT, 90,
> @@ -8327,17 +8347,15 @@ build_lrouter_flows(struct hmap *datapaths,
struct hmap *ports,
>              ds_clear(&actions);
>              ds_put_format(&actions,
>                            "eth.dst = eth.src; "
> -                          "eth.src = %s; "
> +                          "eth.src = " REG_INPORT_ETH_ADDR "; "
>                            "arp.op = 2; /* ARP reply */ "
>                            "arp.tha = arp.sha; "
> -                          "arp.sha = %s; "
> +                          "arp.sha = " REG_INPORT_ETH_ADDR "; "
>                            "arp.tpa = arp.spa; "
>                            "arp.spa = %s; "
>                            "outport = %s; "
>                            "flags.loopback = 1; "
>                            "output;",
> -                          op->lrp_networks.ea_s,
> -                          op->lrp_networks.ea_s,
>                            ip_address,
>                            op->json_key);
>
> @@ -8358,18 +8376,16 @@ build_lrouter_flows(struct hmap *datapaths,
struct hmap *ports,
>              ds_clear(&actions);
>              ds_put_format(&actions,
>                            "nd_na { "
> -                          "eth.src = %s; "
> +                          "eth.src = " REG_INPORT_ETH_ADDR "; "
>                            "ip6.src = %s; "
>                            "nd.target = %s; "
> -                          "nd.tll = %s; "
> +                          "nd.tll = " REG_INPORT_ETH_ADDR "; "
>                            "outport = inport; "
>                            "flags.loopback = 1; "
>                            "output; "
>                            "};",
> -                          op->lrp_networks.ea_s,
>                            ip_address,
> -                          ip_address,
> -                          op->lrp_networks.ea_s);
> +                          ip_address);
>
>              ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 90,
>                            ds_cstr(&match), ds_cstr(&actions));
> @@ -8492,18 +8508,14 @@ build_lrouter_flows(struct hmap *datapaths,
struct hmap *ports,
>                                    nat->logical_port);
>                  } else {
>                      if (is_v6) {
> -                        ds_put_format(&actions,
> -                            "eth.src = %s; "
> -                            "nd.tll = %s; ",
> -                            op->lrp_networks.ea_s,
> -                            op->lrp_networks.ea_s);
> +                        ds_put_cstr(&actions,
> +                                    "eth.src = " REG_INPORT_ETH_ADDR "; "
> +                                    "nd.tll = " REG_INPORT_ETH_ADDR ";
");
>
>                      } else {
> -                        ds_put_format(&actions,
> -                            "eth.src = %s; "
> -                            "arp.sha = %s; ",
> -                            op->lrp_networks.ea_s,
> -                            op->lrp_networks.ea_s);
> +                        ds_put_cstr(&actions,
> +                                    "eth.src = "REG_INPORT_ETH_ADDR "; "
> +                                    "arp.sha = " REG_INPORT_ETH_ADDR ";
");
>                      }
>                      /* Traffic with eth.src =
l3dgw_port->lrp_networks.ea_s
>                       * should only be sent from the "redirect-chassis",
so that
> @@ -8517,17 +8529,13 @@ build_lrouter_flows(struct hmap *datapaths,
struct hmap *ports,
>                  }
>              } else {
>                  if (is_v6) {
> -                    ds_put_format(&actions,
> -                        "eth.src = %s; "
> -                        "nd.tll = %s; ",
> -                        op->lrp_networks.ea_s,
> -                        op->lrp_networks.ea_s);
> +                    ds_put_cstr(&actions,
> +                                "eth.src = " REG_INPORT_ETH_ADDR "; "
> +                                "nd.tll = " REG_INPORT_ETH_ADDR "; ");
>                  } else {
>                      ds_put_format(&actions,
> -                        "eth.src = %s; "
> -                        "arp.sha = %s; ",
> -                        op->lrp_networks.ea_s,
> -                        op->lrp_networks.ea_s);
> +                                  "eth.src = " REG_INPORT_ETH_ADDR "; "
> +                                  "arp.sha = " REG_INPORT_ETH_ADDR "; ");
>                  }
>              }
>              if (is_v6) {
> @@ -8745,18 +8753,16 @@ build_lrouter_flows(struct hmap *datapaths,
struct hmap *ports,
>              ds_clear(&actions);
>              ds_put_format(&actions,
>                            "nd_na_router { "
> -                          "eth.src = %s; "
> +                          "eth.src = " REG_INPORT_ETH_ADDR "; "
>                            "ip6.src = %s; "
>                            "nd.target = %s; "
> -                          "nd.tll = %s; "
> +                          "nd.tll = " REG_INPORT_ETH_ADDR "; "
>                            "outport = inport; "
>                            "flags.loopback = 1; "
>                            "output; "
>                            "};",
> -                          op->lrp_networks.ea_s,
> -                          op->lrp_networks.ipv6_addrs[i].addr_s,
>                            op->lrp_networks.ipv6_addrs[i].addr_s,
> -                          op->lrp_networks.ea_s);
> +                          op->lrp_networks.ipv6_addrs[i].addr_s);
>              ovn_lflow_add_with_hint(lflows, op->od,
S_ROUTER_IN_IP_INPUT, 90,
>                                      ds_cstr(&match), ds_cstr(&actions),
>                                      &op->nbrp->header_);
> @@ -9258,6 +9264,14 @@ build_lrouter_flows(struct hmap *datapaths, struct
hmap *ports,
>               * on the l3dgw_port instance where nat->logical_port is
>               * resident. */
>              if (distributed) {
> +                /* Store the ethernet address of the port receiving the
packet.
> +                 * This will save us from having to match on inport
further
> +                 * down in the pipeline.
> +                 */
> +                ds_clear(&actions);
> +                ds_put_format(&actions, REG_INPORT_ETH_ADDR " = %s;
next;",
> +                              od->l3dgw_port->lrp_networks.ea_s);
> +
>                  ds_clear(&match);
>                  ds_put_format(&match,
>                                "eth.dst == "ETH_ADDR_FMT" && inport == %s"
> @@ -9266,7 +9280,7 @@ build_lrouter_flows(struct hmap *datapaths, struct
hmap *ports,
>                                od->l3dgw_port->json_key,
>                                nat->logical_port);
>                  ovn_lflow_add_with_hint(lflows, od,
S_ROUTER_IN_ADMISSION, 50,
> -                                        ds_cstr(&match), "next;",
> +                                        ds_cstr(&match),
ds_cstr(&actions),
>                                          &nat->header_);
>              }
>
> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> index d7a940f..ef1ac04 100644
> --- a/tests/ovn-northd.at
> +++ b/tests/ovn-northd.at
> @@ -1551,3 +1551,143 @@ lsp2
>  ])
>
>  AT_CLEANUP
> +
> +AT_SETUP([ovn -- check router ARP/NS responder])
> +ovn_start
> +
> +ovn-sbctl chassis-add ch geneve 127.0.0.1
> +
> +ovn-nbctl lr-add lr
> +ovn-nbctl lrp-add lr lrp-public 00:00:00:00:01:00 43.43.43.1/24
> +ovn-nbctl lrp-add lr lrp 00:00:00:00:00:01 42.42.42.1/24
> +
> +ovn-nbctl ls-add ls
> +ovn-nbctl lsp-add ls ls-rp
> +ovn-nbctl lsp-set-type ls-rp router
> +ovn-nbctl lsp-set-addresses ls-rp router
> +ovn-nbctl lsp-set-options ls-rp router-port=lrp
> +ovn-nbctl lsp-add ls ls-vm
> +
> +ovn-nbctl set logical_router lr options:chassis=ch
> +ovn-nbctl lr-nat-add lr dnat_and_snat 43.43.43.2 42.42.42.2
> +ovn-nbctl lr-nat-add lr dnat 43.43.43.3 42.42.42.3
> +ovn-nbctl lr-nat-add lr dnat_and_snat 43.43.43.4 42.42.42.4 ls-vm
00:00:00:00:00:02
> +
> +ovn-nbctl --wait=sb sync
> +
> +# Ingress router port ETH address is stored in lr_in_admission.
> +AT_CHECK([ovn-sbctl lflow-list | grep -E
"lr_in_admission.*xreg0\[[0..47\]]" | sort], [0], [dnl
> +  table=0 (lr_in_admission    ), priority=50   , dnl
> +match=(eth.dst == 00:00:00:00:00:01 && inport == "lrp"), dnl
> +action=(xreg0[[0..47]] = 00:00:00:00:00:01; next;)
> +  table=0 (lr_in_admission    ), priority=50   , dnl
> +match=(eth.dst == 00:00:00:00:01:00 && inport == "lrp-public"), dnl
> +action=(xreg0[[0..47]] = 00:00:00:00:01:00; next;)
> +  table=0 (lr_in_admission    ), priority=50   , dnl
> +match=(eth.mcast && inport == "lrp"), dnl
> +action=(xreg0[[0..47]] = 00:00:00:00:00:01; next;)
> +  table=0 (lr_in_admission    ), priority=50   , dnl
> +match=(eth.mcast && inport == "lrp-public"), dnl
> +action=(xreg0[[0..47]] = 00:00:00:00:01:00; next;)
> +])
> +
> +# Ingress router port ETH address is used for ARP reply/NA in
lr_in_ip_input.
> +AT_CHECK([ovn-sbctl lflow-list | grep -E "lr_in_ip_input.*priority=90" |
grep "arp\|nd" | sort], [0], [dnl
> +  table=3 (lr_in_ip_input     ), priority=90   , dnl
> +match=(inport == "lrp" && arp.spa == 42.42.42.0/24 && arp.tpa ==
42.42.42.1 && arp.op == 1), dnl
> +action=(eth.dst = eth.src; eth.src = xreg0[[0..47]]; arp.op = 2; /* ARP
reply */ arp.tha = arp.sha; arp.sha = xreg0[[0..47]]; arp.tpa = arp.spa;
arp.spa = 42.42.42.1; outport = "lrp"; flags.loopback = 1; output;)
> +  table=3 (lr_in_ip_input     ), priority=90   , dnl
> +match=(inport == "lrp" && arp.tpa == 43.43.43.2 && arp.op == 1), dnl
> +action=(eth.dst = eth.src; arp.op = 2; /* ARP reply */ arp.tha =
arp.sha; eth.src = xreg0[[0..47]]; arp.sha = xreg0[[0..47]]; arp.tpa =
arp.spa; arp.spa = 43.43.43.2; outport = "lrp"; flags.loopback = 1; output;)
> +  table=3 (lr_in_ip_input     ), priority=90   , dnl
> +match=(inport == "lrp" && arp.tpa == 43.43.43.3 && arp.op == 1), dnl
> +action=(eth.dst = eth.src; arp.op = 2; /* ARP reply */ arp.tha =
arp.sha; eth.src = xreg0[[0..47]]; arp.sha = xreg0[[0..47]]; arp.tpa =
arp.spa; arp.spa = 43.43.43.3; outport = "lrp"; flags.loopback = 1; output;)
> +  table=3 (lr_in_ip_input     ), priority=90   , dnl
> +match=(inport == "lrp" && arp.tpa == 43.43.43.4 && arp.op == 1), dnl
> +action=(eth.dst = eth.src; arp.op = 2; /* ARP reply */ arp.tha =
arp.sha; eth.src = xreg0[[0..47]]; arp.sha = xreg0[[0..47]]; arp.tpa =
arp.spa; arp.spa = 43.43.43.4; outport = "lrp"; flags.loopback = 1; output;)
> +  table=3 (lr_in_ip_input     ), priority=90   , dnl
> +match=(inport == "lrp" && nd_ns && ip6.dst == {fe80::200:ff:fe00:1,
ff02::1:ff00:1} && nd.target == fe80::200:ff:fe00:1), dnl
> +action=(nd_na_router { eth.src = xreg0[[0..47]]; ip6.src =
fe80::200:ff:fe00:1; nd.target = fe80::200:ff:fe00:1; nd.tll =
xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };)
> +  table=3 (lr_in_ip_input     ), priority=90   , dnl
> +match=(inport == "lrp-public" && arp.spa == 43.43.43.0/24 && arp.tpa ==
43.43.43.1 && arp.op == 1), dnl
> +action=(eth.dst = eth.src; eth.src = xreg0[[0..47]]; arp.op = 2; /* ARP
reply */ arp.tha = arp.sha; arp.sha = xreg0[[0..47]]; arp.tpa = arp.spa;
arp.spa = 43.43.43.1; outport = "lrp-public"; flags.loopback = 1; output;)
> +  table=3 (lr_in_ip_input     ), priority=90   , dnl
> +match=(inport == "lrp-public" && arp.tpa == 43.43.43.2 && arp.op == 1),
dnl
> +action=(eth.dst = eth.src; arp.op = 2; /* ARP reply */ arp.tha =
arp.sha; eth.src = xreg0[[0..47]]; arp.sha = xreg0[[0..47]]; arp.tpa =
arp.spa; arp.spa = 43.43.43.2; outport = "lrp-public"; flags.loopback = 1;
output;)
> +  table=3 (lr_in_ip_input     ), priority=90   , dnl
> +match=(inport == "lrp-public" && arp.tpa == 43.43.43.3 && arp.op == 1),
dnl
> +action=(eth.dst = eth.src; arp.op = 2; /* ARP reply */ arp.tha =
arp.sha; eth.src = xreg0[[0..47]]; arp.sha = xreg0[[0..47]]; arp.tpa =
arp.spa; arp.spa = 43.43.43.3; outport = "lrp-public"; flags.loopback = 1;
output;)
> +  table=3 (lr_in_ip_input     ), priority=90   , dnl
> +match=(inport == "lrp-public" && arp.tpa == 43.43.43.4 && arp.op == 1),
dnl
> +action=(eth.dst = eth.src; arp.op = 2; /* ARP reply */ arp.tha =
arp.sha; eth.src = xreg0[[0..47]]; arp.sha = xreg0[[0..47]]; arp.tpa =
arp.spa; arp.spa = 43.43.43.4; outport = "lrp-public"; flags.loopback = 1;
output;)
> +  table=3 (lr_in_ip_input     ), priority=90   , dnl
> +match=(inport == "lrp-public" && nd_ns && ip6.dst ==
{fe80::200:ff:fe00:100, ff02::1:ff00:100} && nd.target ==
fe80::200:ff:fe00:100), dnl
> +action=(nd_na_router { eth.src = xreg0[[0..47]]; ip6.src =
fe80::200:ff:fe00:100; nd.target = fe80::200:ff:fe00:100; nd.tll =
xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };)
> +])
> +
> +# xreg0[0..47] isn't used anywhere else.
> +AT_CHECK([ovn-sbctl lflow-list | grep "xreg0\[[0..47\]]" | grep -vE
'lr_in_admission|lr_in_ip_input'], [1], [])
> +
> +# Test chassis redirect port.
> +ovn-nbctl remove logical_router lr options chassis
> +ovn-nbctl lrp-set-gateway-chassis lrp-public ch
> +ovn-nbctl --wait=sb sync
> +
> +# Ingress router port ETH address is stored in lr_in_admission.
> +AT_CHECK([ovn-sbctl lflow-list | grep -E
"lr_in_admission.*xreg0\[[0..47\]]" | sort], [0], [dnl
> +  table=0 (lr_in_admission    ), priority=50   , dnl
> +match=(eth.dst == 00:00:00:00:00:01 && inport == "lrp"), dnl
> +action=(xreg0[[0..47]] = 00:00:00:00:00:01; next;)
> +  table=0 (lr_in_admission    ), priority=50   , dnl
> +match=(eth.dst == 00:00:00:00:00:02 && inport == "lrp-public" &&
is_chassis_resident("ls-vm")), dnl
> +action=(xreg0[[0..47]] = 00:00:00:00:01:00; next;)
> +  table=0 (lr_in_admission    ), priority=50   , dnl
> +match=(eth.dst == 00:00:00:00:01:00 && inport == "lrp-public" &&
is_chassis_resident("cr-lrp-public")), dnl
> +action=(xreg0[[0..47]] = 00:00:00:00:01:00; next;)
> +  table=0 (lr_in_admission    ), priority=50   , dnl
> +match=(eth.mcast && inport == "lrp"), dnl
> +action=(xreg0[[0..47]] = 00:00:00:00:00:01; next;)
> +  table=0 (lr_in_admission    ), priority=50   , dnl
> +match=(eth.mcast && inport == "lrp-public"), dnl
> +action=(xreg0[[0..47]] = 00:00:00:00:01:00; next;)
> +])
> +
> +# Ingress router port is used for ARP reply/NA in lr_in_ip_input.
> +# xxreg0[0..47] is used unless external_mac is set.
> +AT_CHECK([ovn-sbctl lflow-list | grep -E "lr_in_ip_input.*priority=90" |
grep "arp\|nd" | sort], [0], [dnl
> +  table=3 (lr_in_ip_input     ), priority=90   , dnl
> +match=(inport == "lrp" && arp.spa == 42.42.42.0/24 && arp.tpa ==
42.42.42.1 && arp.op == 1), dnl
> +action=(eth.dst = eth.src; eth.src = xreg0[[0..47]]; arp.op = 2; /* ARP
reply */ arp.tha = arp.sha; arp.sha = xreg0[[0..47]]; arp.tpa = arp.spa;
arp.spa = 42.42.42.1; outport = "lrp"; flags.loopback = 1; output;)
> +  table=3 (lr_in_ip_input     ), priority=90   , dnl
> +match=(inport == "lrp" && arp.tpa == 43.43.43.2 && arp.op == 1), dnl
> +action=(eth.dst = eth.src; arp.op = 2; /* ARP reply */ arp.tha =
arp.sha; eth.src = xreg0[[0..47]]; arp.sha = xreg0[[0..47]]; arp.tpa =
arp.spa; arp.spa = 43.43.43.2; outport = "lrp"; flags.loopback = 1; output;)
> +  table=3 (lr_in_ip_input     ), priority=90   , dnl
> +match=(inport == "lrp" && arp.tpa == 43.43.43.3 && arp.op == 1), dnl
> +action=(eth.dst = eth.src; arp.op = 2; /* ARP reply */ arp.tha =
arp.sha; eth.src = xreg0[[0..47]]; arp.sha = xreg0[[0..47]]; arp.tpa =
arp.spa; arp.spa = 43.43.43.3; outport = "lrp"; flags.loopback = 1; output;)
> +  table=3 (lr_in_ip_input     ), priority=90   , dnl
> +match=(inport == "lrp" && arp.tpa == 43.43.43.4 && arp.op == 1), dnl
> +action=(eth.dst = eth.src; arp.op = 2; /* ARP reply */ arp.tha =
arp.sha; eth.src = xreg0[[0..47]]; arp.sha = xreg0[[0..47]]; arp.tpa =
arp.spa; arp.spa = 43.43.43.4; outport = "lrp"; flags.loopback = 1; output;)
> +  table=3 (lr_in_ip_input     ), priority=90   , dnl
> +match=(inport == "lrp" && nd_ns && ip6.dst == {fe80::200:ff:fe00:1,
ff02::1:ff00:1} && nd.target == fe80::200:ff:fe00:1), dnl
> +action=(nd_na_router { eth.src = xreg0[[0..47]]; ip6.src =
fe80::200:ff:fe00:1; nd.target = fe80::200:ff:fe00:1; nd.tll =
xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };)
> +  table=3 (lr_in_ip_input     ), priority=90   , dnl
> +match=(inport == "lrp-public" && arp.spa == 43.43.43.0/24 && arp.tpa ==
43.43.43.1 && arp.op == 1), dnl
> +action=(eth.dst = eth.src; eth.src = xreg0[[0..47]]; arp.op = 2; /* ARP
reply */ arp.tha = arp.sha; arp.sha = xreg0[[0..47]]; arp.tpa = arp.spa;
arp.spa = 43.43.43.1; outport = "lrp-public"; flags.loopback = 1; output;)
> +  table=3 (lr_in_ip_input     ), priority=90   , dnl
> +match=(inport == "lrp-public" && arp.tpa == 43.43.43.2 && arp.op == 1 &&
is_chassis_resident("cr-lrp-public")), dnl
> +action=(eth.dst = eth.src; arp.op = 2; /* ARP reply */ arp.tha =
arp.sha; eth.src = xreg0[[0..47]]; arp.sha = xreg0[[0..47]]; arp.tpa =
arp.spa; arp.spa = 43.43.43.2; outport = "lrp-public"; flags.loopback = 1;
output;)
> +  table=3 (lr_in_ip_input     ), priority=90   , dnl
> +match=(inport == "lrp-public" && arp.tpa == 43.43.43.3 && arp.op == 1 &&
is_chassis_resident("cr-lrp-public")), dnl
> +action=(eth.dst = eth.src; arp.op = 2; /* ARP reply */ arp.tha =
arp.sha; eth.src = xreg0[[0..47]]; arp.sha = xreg0[[0..47]]; arp.tpa =
arp.spa; arp.spa = 43.43.43.3; outport = "lrp-public"; flags.loopback = 1;
output;)
> +  table=3 (lr_in_ip_input     ), priority=90   , dnl
> +match=(inport == "lrp-public" && arp.tpa == 43.43.43.4 && arp.op == 1 &&
is_chassis_resident("ls-vm")), dnl
> +action=(eth.dst = eth.src; arp.op = 2; /* ARP reply */ arp.tha =
arp.sha; eth.src = 00:00:00:00:00:02; arp.sha = 00:00:00:00:00:02; arp.tpa
= arp.spa; arp.spa = 43.43.43.4; outport = "lrp-public"; flags.loopback =
1; output;)
> +  table=3 (lr_in_ip_input     ), priority=90   , dnl
> +match=(inport == "lrp-public" && nd_ns && ip6.dst ==
{fe80::200:ff:fe00:100, ff02::1:ff00:100} && nd.target ==
fe80::200:ff:fe00:100 && is_chassis_resident("cr-lrp-public")), dnl
> +action=(nd_na_router { eth.src = xreg0[[0..47]]; ip6.src =
fe80::200:ff:fe00:100; nd.target = fe80::200:ff:fe00:100; nd.tll =
xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };)
> +])
> +
> +# xreg0[0..47] isn't used anywhere else.
> +AT_CHECK([ovn-sbctl lflow-list | grep "xreg0\[[0..47\]]" | grep -vE
'lr_in_admission|lr_in_ip_input'], [1], [])
> +
> +AT_CLEANUP
>


More information about the dev mailing list