[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