On Thu, Jul 2, 2020 at 7:53 AM Dumitru Ceara <[email protected]> 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 <[email protected]> > --- > 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 <[email protected]> > + * | 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 > _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
