Message ID | a6debc28-b1db-42a3-b56f-11ee41445384@oracle.com |
---|---|
State | Superseded |
Headers | show |
Series | [ovs-dev] ovn-northd.c: Add proxy ARP support to OVN | expand |
On Wed, 2021-06-02 at 17:02 +0100, Brendan Doyle wrote: > From a9d3140845175edb7644b2d0d82a95bd6cf94662 Mon Sep 17 00:00:00 2001 > From: Brendan Doyle <brendan.doyle@oracle.com> > Date: Fri, 28 May 2021 10:01:17 -0700 > Subject: [PATCH ovn] ovn-northd.c: Add proxy ARP support to OVN > > This patch provides the ability to configure proxy ARP IPs on a Logical > Switch Router port. The IPs are added as Options for router ports. This > provides a useful feature where traffic for a service must be sent to > an > address in a logical network address space, but the service is provided > in a different network. For example an NFS service is provide to > Logical > networks at an address in their Logical network space, but the NFS > server resides in a physical network. A Logical switch Router port can > be configured to respond to ARP requests sent to the service "Logical > address", the Logical Router/Gateway can then be configured to forward > the traffic to the underlay/physical network. > > Signed-off-by: Brendan Doyle <brendan.doyle@oracle.com> > --- > northd/ovn-northd.c | 38 +++++++++++++++++++ > ovn-nb.xml | 9 +++++ > tests/ovn.at | 103 > ++++++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 150 insertions(+) > > diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c > index 0e5092a..a377e83 100644 > --- a/northd/ovn-northd.c > +++ b/northd/ovn-northd.c > @@ -6943,6 +6943,7 @@ build_lswitch_arp_nd_responder_known_ips(struct > ovn_port *op, > struct ds *match) > { > if (op->nbsp) { > + const char *arp_proxy; > if (!strcmp(op->nbsp->type, "virtual")) { > /* Handle > * - GARPs for virtual ip which belongs to a logical > port > @@ -7096,6 +7097,43 @@ build_lswitch_arp_nd_responder_known_ips(struct > ovn_port *op, > } > } > } > + > + /* > + * Add responses for ARP proxies. > + */ > + arp_proxy = smap_get(&op->nbsp->options,"arp_proxy"); > + if (arp_proxy && op->peer) { > + char *ips, *ip, *rest; > + > + ips = xstrdup(arp_proxy); > + rest = ips; > + > + while ((ip = strtok_r(rest,",", &rest))) { > + ds_clear(match); > + ds_put_format(match, "arp.tpa == %s && arp.op == 1", > ip); > + > + ds_clear(actions); > + ds_put_format(actions, > + "eth.dst = eth.src; " > + "eth.src = %s; " > + "arp.op = 2; /* ARP reply */ " > + "arp.tha = arp.sha; " > + "arp.sha = %s; " > + "arp.tpa = arp.spa; " > + "arp.spa = %s; " I think you can collapse the two lines above into: "arp.tpa <-> arp.spa; " and get rid of one %s. For an example, see build_lrouter_arp_flow(). In fact, you might be able to reduce the number of lflows down to one by doing something like the following, since now your action is constant due to the <->. int i = 0; ds_clear(&match); ds_put_cstr(match, "arp.op == 1 && ("); while ((ip = strtok_r(rest,",", &rest))) { if (i++ > 0) { ds_put_cstr(match, " || "); }; ds_put_format(match, "arp.tpa == %s", ip); } ds_put_cstr(match, ")"); An example of that is in build_port_security_ipv6_nd_flow(). --- General comment, this will need a ddlog counterpart too. I'm not an expert there, so I'll leave it to the OVN team to help. But you could use Ilya's lrouter arp flow patch as a reference: http://patchwork.ozlabs.org/project/ovn/patch/20210507162256.3661118-1-i.maximets@ovn.org/ Looking at that patch, you might need to update the ovn-northd.8 manpage as well? Thanks! Dan > + "outport = inport; " > + "flags.loopback = 1; " > + "output;", > + op->peer->lrp_networks.ea_s, > + op->peer->lrp_networks.ea_s, > + ip); > + > + ovn_lflow_add_with_hint(lflows, op->od, > S_SWITCH_IN_ARP_ND_RSP, > + 50, ds_cstr(match), ds_cstr(actions), > + &op->nbsp->header_); > + } > + free(ips); > + } > } > } > > diff --git a/ovn-nb.xml b/ovn-nb.xml > index 02fd216..4b6c183 100644 > --- a/ovn-nb.xml > +++ b/ovn-nb.xml > @@ -848,6 +848,15 @@ > </dd> > </dl> > </column> > + > + <column name="options" key="arp_proxy"> > + Optional. A comma separated list IPv4 addresses that this > + logical switch <code>router</code> port will reply to ARP > requests. > + Example: <code>169.254.239.254,169.254.239.2</code>. The > + <ref column="options" key="router-port"/>'s logical router > should > + have a route to forward packets sent to configured proxy ARP > IPs to > + an appropriate destination. > + </column> > </group> > > <group title="Options for localnet ports"> > diff --git a/tests/ovn.at b/tests/ovn.at > index 2c3c36d..c675cc9 100644 > --- a/tests/ovn.at > +++ b/tests/ovn.at > @@ -26527,3 +26527,106 @@ AT_CHECK([test $(ovn-appctl -t ovn-controller > coverage/read-counter lflow_run) = > OVN_CLEANUP([hv1]) > AT_CLEANUP > ]) > + > +OVN_FOR_EACH_NORTHD([ > +AT_SETUP([ovn -- proxy-arp: 1 HVs, 1 LSs, 1 lport/LS, 1 LR]) > +AT_KEYWORDS([proxy-arp]) > +ovn_start > + > +# Logical network: > +# One LR - lr1 has switch ls1 (192.16.1.0/24) connected to it, > +# and and one HV with IP 192.16.1.6. > + > +ovn-nbctl lr-add lr1 > +ovn-nbctl ls-add ls1 > + > +# Connect ls1 to lr1 > +ovn-nbctl lrp-add lr1 ls1 00:00:00:01:02:f1 192.16.1.1/24 > +ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \ > + type=router options:router-port=ls1 > addresses=\"00:00:00:01:02:f1\" > + > +# Create logical port ls1-lp1 in ls1 > +ovn-nbctl lsp-add ls1 ls1-lp1 \ > +-- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 192.16.1.6" > + > + > +# Create one hypervisor and create OVS ports corresponding to logical > ports. > +net_add n1 > + > +sim_add pa-hv > +as pa-hv > +ovs-vsctl add-br br-phys > +ovn_attach n1 br-phys 192.16.0.1 > + > +# Note: tx/rx are with respect to the LS port, so > +# tx on switch port is HV rx, etc. > +ovs-vsctl -- add-port br-int vif1 -- \ > + set interface vif1 external-ids:iface-id=ls1-lp1 \ > + options:tx_pcap=pa-hv/vif1-tx.pcap \ > + options:rxq_pcap=pa-hv/vif1-rx.pcap \ > + ofport-request=1 > + > +# And proxy ARP flows for 69.254.239.254 and 169.254.239.2 > +# and check that SB flows have been added. > +ovn-nbctl --wait=hv add Logical_Switch_Port rp-ls1 \ > +options arp_proxy='"169.254.239.254,169.254.239.2"' > +ovn-sbctl dump-flows > sbflows > +AT_CAPTURE_FILE([sbflows]) > + > +AT_CHECK([ovn-sbctl dump-flows | grep ls_in_arp_rsp | grep > "169.254.239.2" | wc -l], [0], [dnl > +2 > +]) > + > +# Remove and check that the flows have been removed > +ovn-nbctl --wait=hv remove Logical_Switch_Port rp-ls1 options > arp_proxy='"169.254.239.254,169.254.239.2"' > + > +AT_CHECK([ovn-sbctl dump-flows | grep ls_in_arp_rsp | grep > "169.254.239.2" | wc -l], [0], [dnl > +0 > +]) > + > +# Add the flows back send arp request and check we see an ARP response > +ovn-nbctl --wait=hv add Logical_Switch_Port rp-ls1 \ > +options arp_proxy='"169.254.239.254,169.254.239.2"' > + > +ls1_p1_mac=00:00:00:01:02:03 > +ls1_p1_ip=192.16.1.6 > + > +ls1_ro_mac=00:00:00:01:02:f1 > +ls1_ro_ip=192.168.1.1 > + > +proxy_ip1=169.254.239.254 > +proxy_ip2=169.254.239.2 > + > +bcast_mac=ff:ff:ff:ff:ff:ff > + > +# Send ARP request for 169.254.239.254 > +packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && > eth.dst==$bcast_mac && > + arp.op==1 && arp.sha==$ls1_p1_mac && arp.spa==$ls1_p1_ip && > + arp.tha==$bcast_mac && arp.tpa==$proxy_ip1" > + > +as pa-hv ovs-appctl -t ovn-controller inject-pkt "$packet" > + > +ovs-ofctl dump-flows br-int| grep 169.254.239.254 | grep priority=50 > > debug1 > +AT_CAPTURE_FILE([debug1]) > + > + > +# Check if packet hit the ARP reply ovs flow > +AT_CHECK([ovs-ofctl dump-flows br-int | \ > + grep "169.254.239.254" | \ > + grep "priority=50" | \ > + grep "arp_op=1" | \ > + grep "n_packets=1" | wc -l], [0], [dnl > +1 > +]) > + > +# Check that the HV gets an ARP reply > +expected="eth.src==$ls1_ro_mac && eth.dst==$ls1_p1_mac && > + arp.op==2 && arp.sha==$ls1_ro_mac && arp.spa==$proxy_ip1 && > + arp.tha==$ls1_p1_mac && arp.tpa==$ls1_p1_ip" > +echo $expected | ovstest test-ovn expr-to-packets > expected > + > +OVN_CHECK_PACKETS([pa-hv/vif1-tx.pcap], [expected]) > + > +OVN_CLEANUP([pa-hv]) > +AT_CLEANUP > +]) > -- > 1.8.3.1 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev >
On 03/06/2021 16:59, Dan Williams wrote: > On Wed, 2021-06-02 at 17:02 +0100, Brendan Doyle wrote: >> From a9d3140845175edb7644b2d0d82a95bd6cf94662 Mon Sep 17 00:00:00 2001 >> From: Brendan Doyle <brendan.doyle@oracle.com> >> Date: Fri, 28 May 2021 10:01:17 -0700 >> Subject: [PATCH ovn] ovn-northd.c: Add proxy ARP support to OVN >> >> This patch provides the ability to configure proxy ARP IPs on a Logical >> Switch Router port. The IPs are added as Options for router ports. This >> provides a useful feature where traffic for a service must be sent to >> an >> address in a logical network address space, but the service is provided >> in a different network. For example an NFS service is provide to >> Logical >> networks at an address in their Logical network space, but the NFS >> server resides in a physical network. A Logical switch Router port can >> be configured to respond to ARP requests sent to the service "Logical >> address", the Logical Router/Gateway can then be configured to forward >> the traffic to the underlay/physical network. >> >> Signed-off-by: Brendan Doyle <brendan.doyle@oracle.com> >> --- >> northd/ovn-northd.c | 38 +++++++++++++++++++ >> ovn-nb.xml | 9 +++++ >> tests/ovn.at | 103 >> ++++++++++++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 150 insertions(+) >> >> diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c >> index 0e5092a..a377e83 100644 >> --- a/northd/ovn-northd.c >> +++ b/northd/ovn-northd.c >> @@ -6943,6 +6943,7 @@ build_lswitch_arp_nd_responder_known_ips(struct >> ovn_port *op, >> struct ds *match) >> { >> if (op->nbsp) { >> + const char *arp_proxy; >> if (!strcmp(op->nbsp->type, "virtual")) { >> /* Handle >> * - GARPs for virtual ip which belongs to a logical >> port >> @@ -7096,6 +7097,43 @@ build_lswitch_arp_nd_responder_known_ips(struct >> ovn_port *op, >> } >> } >> } >> + >> + /* >> + * Add responses for ARP proxies. >> + */ >> + arp_proxy = smap_get(&op->nbsp->options,"arp_proxy"); >> + if (arp_proxy && op->peer) { >> + char *ips, *ip, *rest; >> + >> + ips = xstrdup(arp_proxy); >> + rest = ips; >> + >> + while ((ip = strtok_r(rest,",", &rest))) { >> + ds_clear(match); >> + ds_put_format(match, "arp.tpa == %s && arp.op == 1", >> ip); >> + >> + ds_clear(actions); >> + ds_put_format(actions, >> + "eth.dst = eth.src; " >> + "eth.src = %s; " >> + "arp.op = 2; /* ARP reply */ " >> + "arp.tha = arp.sha; " >> + "arp.sha = %s; " >> + "arp.tpa = arp.spa; " >> + "arp.spa = %s; " > I think you can collapse the two lines above into: > > "arp.tpa <-> arp.spa;" > > and get rid of one %s. For an example, see build_lrouter_arp_flow(). > > In fact, you might be able to reduce the number of lflows down to one > by doing something like the following, since now your action is > constant due to the <->. > > int i = 0; > ds_clear(&match); > ds_put_cstr(match, "arp.op == 1 && ("); > while ((ip = strtok_r(rest,",", &rest))) { > if (i++ > 0) { > ds_put_cstr(match, " || "); > }; > ds_put_format(match, "arp.tpa == %s", ip); > } > ds_put_cstr(match, ")"); > > An example of that is in build_port_security_ipv6_nd_flow(). > Yes, I can modify as above much more elegant. On a process point It seems the convention for updated patches is to resubmit with a v2, v3 etc make changes and resubmit as: [PATCH ovn v2] ovn-northd.c: Add proxy ARP support to OVN ? > --- > > General comment, this will need a ddlog counterpart too. I'm not an ddlog?? Not something I know about, I have seen other ovn-northd.c patches that do not have a reference to ddlog?? > expert there, so I'll leave it to the OVN team to help. But you could > use Ilya's lrouter arp flow patch as a reference: > > https://urldefense.com/v3/__http://patchwork.ozlabs.org/project/ovn/patch/20210507162256.3661118-1-i.maximets@ovn.org/__;!!GqivPVa7Brio!Nj575dWsjTnglWHVCkWMecpF2LWvS8PaWIQQvYmZbvYYgt1yjxGBBOoivhRao3nCZd0$ > > Looking at that patch, you might need to update the ovn-northd.8 > manpage as well? Not sure I'm not adding a new table, just an ability to add flows to an existing table. Not sure what I would add to that man page, I have made updates to ovn-nb.xml. I used: [ovs-dev,v4] Policy-based routing (PBR) in OVN. - Patchwork <https://patchwork.ozlabs.org/project/openvswitch/patch/1554334195-126528-2-git-send-email-mary.manohar@nutanix.com/> as a guide on what I should update. > Thanks! > Dan > >> + "outport = inport; " >> + "flags.loopback = 1; " >> + "output;", >> + op->peer->lrp_networks.ea_s, >> + op->peer->lrp_networks.ea_s, >> + ip); >> + >> + ovn_lflow_add_with_hint(lflows, op->od, >> S_SWITCH_IN_ARP_ND_RSP, >> + 50, ds_cstr(match), ds_cstr(actions), >> + &op->nbsp->header_); >> + } >> + free(ips); >> + } >> } >> } >> >> diff --git a/ovn-nb.xml b/ovn-nb.xml >> index 02fd216..4b6c183 100644 >> --- a/ovn-nb.xml >> +++ b/ovn-nb.xml >> @@ -848,6 +848,15 @@ >> </dd> >> </dl> >> </column> >> + >> + <column name="options" key="arp_proxy"> >> + Optional. A comma separated list IPv4 addresses that this >> + logical switch <code>router</code> port will reply to ARP >> requests. >> + Example: <code>169.254.239.254,169.254.239.2</code>. The >> + <ref column="options" key="router-port"/>'s logical router >> should >> + have a route to forward packets sent to configured proxy ARP >> IPs to >> + an appropriate destination. >> + </column> >> </group> >> >> <group title="Options for localnet ports"> >> diff --git a/tests/ovn.at b/tests/ovn.at >> index 2c3c36d..c675cc9 100644 >> --- a/tests/ovn.at >> +++ b/tests/ovn.at >> @@ -26527,3 +26527,106 @@ AT_CHECK([test $(ovn-appctl -t ovn-controller >> coverage/read-counter lflow_run) = >> OVN_CLEANUP([hv1]) >> AT_CLEANUP >> ]) >> + >> +OVN_FOR_EACH_NORTHD([ >> +AT_SETUP([ovn -- proxy-arp: 1 HVs, 1 LSs, 1 lport/LS, 1 LR]) >> +AT_KEYWORDS([proxy-arp]) >> +ovn_start >> + >> +# Logical network: >> +# One LR - lr1 has switch ls1 (192.16.1.0/24) connected to it, >> +# and and one HV with IP 192.16.1.6. >> + >> +ovn-nbctl lr-add lr1 >> +ovn-nbctl ls-add ls1 >> + >> +# Connect ls1 to lr1 >> +ovn-nbctl lrp-add lr1 ls1 00:00:00:01:02:f1 192.16.1.1/24 >> +ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \ >> + type=router options:router-port=ls1 >> addresses=\"00:00:00:01:02:f1\" >> + >> +# Create logical port ls1-lp1 in ls1 >> +ovn-nbctl lsp-add ls1 ls1-lp1 \ >> +-- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 192.16.1.6" >> + >> + >> +# Create one hypervisor and create OVS ports corresponding to logical >> ports. >> +net_add n1 >> + >> +sim_add pa-hv >> +as pa-hv >> +ovs-vsctl add-br br-phys >> +ovn_attach n1 br-phys 192.16.0.1 >> + >> +# Note: tx/rx are with respect to the LS port, so >> +# tx on switch port is HV rx, etc. >> +ovs-vsctl -- add-port br-int vif1 -- \ >> + set interface vif1 external-ids:iface-id=ls1-lp1 \ >> + options:tx_pcap=pa-hv/vif1-tx.pcap \ >> + options:rxq_pcap=pa-hv/vif1-rx.pcap \ >> + ofport-request=1 >> + >> +# And proxy ARP flows for 69.254.239.254 and 169.254.239.2 >> +# and check that SB flows have been added. >> +ovn-nbctl --wait=hv add Logical_Switch_Port rp-ls1 \ >> +options arp_proxy='"169.254.239.254,169.254.239.2"' >> +ovn-sbctl dump-flows > sbflows >> +AT_CAPTURE_FILE([sbflows]) >> + >> +AT_CHECK([ovn-sbctl dump-flows | grep ls_in_arp_rsp | grep >> "169.254.239.2" | wc -l], [0], [dnl >> +2 >> +]) >> + >> +# Remove and check that the flows have been removed >> +ovn-nbctl --wait=hv remove Logical_Switch_Port rp-ls1 options >> arp_proxy='"169.254.239.254,169.254.239.2"' >> + >> +AT_CHECK([ovn-sbctl dump-flows | grep ls_in_arp_rsp | grep >> "169.254.239.2" | wc -l], [0], [dnl >> +0 >> +]) >> + >> +# Add the flows back send arp request and check we see an ARP response >> +ovn-nbctl --wait=hv add Logical_Switch_Port rp-ls1 \ >> +options arp_proxy='"169.254.239.254,169.254.239.2"' >> + >> +ls1_p1_mac=00:00:00:01:02:03 >> +ls1_p1_ip=192.16.1.6 >> + >> +ls1_ro_mac=00:00:00:01:02:f1 >> +ls1_ro_ip=192.168.1.1 >> + >> +proxy_ip1=169.254.239.254 >> +proxy_ip2=169.254.239.2 >> + >> +bcast_mac=ff:ff:ff:ff:ff:ff >> + >> +# Send ARP request for 169.254.239.254 >> +packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && >> eth.dst==$bcast_mac && >> + arp.op==1 && arp.sha==$ls1_p1_mac && arp.spa==$ls1_p1_ip && >> + arp.tha==$bcast_mac && arp.tpa==$proxy_ip1" >> + >> +as pa-hv ovs-appctl -t ovn-controller inject-pkt "$packet" >> + >> +ovs-ofctl dump-flows br-int| grep 169.254.239.254 | grep priority=50 > >> debug1 >> +AT_CAPTURE_FILE([debug1]) >> + >> + >> +# Check if packet hit the ARP reply ovs flow >> +AT_CHECK([ovs-ofctl dump-flows br-int | \ >> + grep "169.254.239.254" | \ >> + grep "priority=50" | \ >> + grep "arp_op=1" | \ >> + grep "n_packets=1" | wc -l], [0], [dnl >> +1 >> +]) >> + >> +# Check that the HV gets an ARP reply >> +expected="eth.src==$ls1_ro_mac && eth.dst==$ls1_p1_mac && >> + arp.op==2 && arp.sha==$ls1_ro_mac && arp.spa==$proxy_ip1 && >> + arp.tha==$ls1_p1_mac && arp.tpa==$ls1_p1_ip" >> +echo $expected | ovstest test-ovn expr-to-packets > expected >> + >> +OVN_CHECK_PACKETS([pa-hv/vif1-tx.pcap], [expected]) >> + >> +OVN_CLEANUP([pa-hv]) >> +AT_CLEANUP >> +]) >> -- >> 1.8.3.1 >> >> _______________________________________________ >> dev mailing list >> dev@openvswitch.org >> https://urldefense.com/v3/__https://mail.openvswitch.org/mailman/listinfo/ovs-dev__;!!GqivPVa7Brio!Nj575dWsjTnglWHVCkWMecpF2LWvS8PaWIQQvYmZbvYYgt1yjxGBBOoivhRab1J-c-U$ >> >
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 0e5092a..a377e83 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -6943,6 +6943,7 @@ build_lswitch_arp_nd_responder_known_ips(struct ovn_port *op, struct ds *match) { if (op->nbsp) { + const char *arp_proxy; if (!strcmp(op->nbsp->type, "virtual")) { /* Handle * - GARPs for virtual ip which belongs to a logical port @@ -7096,6 +7097,43 @@ build_lswitch_arp_nd_responder_known_ips(struct ovn_port *op, } } } + + /* + * Add responses for ARP proxies. + */ + arp_proxy = smap_get(&op->nbsp->options,"arp_proxy"); + if (arp_proxy && op->peer) { + char *ips, *ip, *rest; + + ips = xstrdup(arp_proxy); + rest = ips; + + while ((ip = strtok_r(rest,",", &rest))) { + ds_clear(match); + ds_put_format(match, "arp.tpa == %s && arp.op == 1", ip); + + ds_clear(actions); + ds_put_format(actions, + "eth.dst = eth.src; " + "eth.src = %s; " + "arp.op = 2; /* ARP reply */ " + "arp.tha = arp.sha; " + "arp.sha = %s; " + "arp.tpa = arp.spa; " + "arp.spa = %s; " + "outport = inport; " + "flags.loopback = 1; " + "output;", + op->peer->lrp_networks.ea_s, + op->peer->lrp_networks.ea_s, + ip); + + ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_ARP_ND_RSP, + 50, ds_cstr(match), ds_cstr(actions), + &op->nbsp->header_); + } + free(ips); + } } } diff --git a/ovn-nb.xml b/ovn-nb.xml index 02fd216..4b6c183 100644 --- a/ovn-nb.xml +++ b/ovn-nb.xml @@ -848,6 +848,15 @@ </dd> </dl> </column> + + <column name="options" key="arp_proxy"> + Optional. A comma separated list IPv4 addresses that this + logical switch <code>router</code> port will reply to ARP requests. + Example: <code>169.254.239.254,169.254.239.2</code>. The + <ref column="options" key="router-port"/>'s logical router should + have a route to forward packets sent to configured proxy ARP IPs to + an appropriate destination. + </column> </group> <group title="Options for localnet ports"> diff --git a/tests/ovn.at b/tests/ovn.at index 2c3c36d..c675cc9 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -26527,3 +26527,106 @@ AT_CHECK([test $(ovn-appctl -t ovn-controller coverage/read-counter lflow_run) = OVN_CLEANUP([hv1]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([ovn -- proxy-arp: 1 HVs, 1 LSs, 1 lport/LS, 1 LR]) +AT_KEYWORDS([proxy-arp]) +ovn_start + +# Logical network: +# One LR - lr1 has switch ls1 (192.16.1.0/24) connected to it, +# and and one HV with IP 192.16.1.6. + +ovn-nbctl lr-add lr1 +ovn-nbctl ls-add ls1 + +# Connect ls1 to lr1 +ovn-nbctl lrp-add lr1 ls1 00:00:00:01:02:f1 192.16.1.1/24 +ovn-nbctl lsp-add ls1 rp-ls1 -- set Logical_Switch_Port rp-ls1 \ + type=router options:router-port=ls1 addresses=\"00:00:00:01:02:f1\" + +# Create logical port ls1-lp1 in ls1 +ovn-nbctl lsp-add ls1 ls1-lp1 \ +-- lsp-set-addresses ls1-lp1 "00:00:00:01:02:03 192.16.1.6" + + +# Create one hypervisor and create OVS ports corresponding to logical ports. +net_add n1 + +sim_add pa-hv +as pa-hv +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.16.0.1 + +# Note: tx/rx are with respect to the LS port, so +# tx on switch port is HV rx, etc. +ovs-vsctl -- add-port br-int vif1 -- \ + set interface vif1 external-ids:iface-id=ls1-lp1 \ + options:tx_pcap=pa-hv/vif1-tx.pcap \ + options:rxq_pcap=pa-hv/vif1-rx.pcap \ + ofport-request=1 + +# And proxy ARP flows for 69.254.239.254 and 169.254.239.2 +# and check that SB flows have been added. +ovn-nbctl --wait=hv add Logical_Switch_Port rp-ls1 \ +options arp_proxy='"169.254.239.254,169.254.239.2"' +ovn-sbctl dump-flows > sbflows +AT_CAPTURE_FILE([sbflows]) + +AT_CHECK([ovn-sbctl dump-flows | grep ls_in_arp_rsp | grep "169.254.239.2" | wc -l], [0], [dnl +2 +]) + +# Remove and check that the flows have been removed +ovn-nbctl --wait=hv remove Logical_Switch_Port rp-ls1 options arp_proxy='"169.254.239.254,169.254.239.2"' + +AT_CHECK([ovn-sbctl dump-flows | grep ls_in_arp_rsp | grep "169.254.239.2" | wc -l], [0], [dnl +0 +]) + +# Add the flows back send arp request and check we see an ARP response +ovn-nbctl --wait=hv add Logical_Switch_Port rp-ls1 \ +options arp_proxy='"169.254.239.254,169.254.239.2"' + +ls1_p1_mac=00:00:00:01:02:03 +ls1_p1_ip=192.16.1.6 + +ls1_ro_mac=00:00:00:01:02:f1 +ls1_ro_ip=192.168.1.1 + +proxy_ip1=169.254.239.254 +proxy_ip2=169.254.239.2 + +bcast_mac=ff:ff:ff:ff:ff:ff + +# Send ARP request for 169.254.239.254 +packet="inport==\"ls1-lp1\" && eth.src==$ls1_p1_mac && eth.dst==$bcast_mac && + arp.op==1 && arp.sha==$ls1_p1_mac && arp.spa==$ls1_p1_ip && + arp.tha==$bcast_mac && arp.tpa==$proxy_ip1" + +as pa-hv ovs-appctl -t ovn-controller inject-pkt "$packet" + +ovs-ofctl dump-flows br-int| grep 169.254.239.254 | grep priority=50 > debug1 +AT_CAPTURE_FILE([debug1]) + + +# Check if packet hit the ARP reply ovs flow +AT_CHECK([ovs-ofctl dump-flows br-int | \ + grep "169.254.239.254" | \ + grep "priority=50" | \ + grep "arp_op=1" | \ + grep "n_packets=1" | wc -l], [0], [dnl +1 +]) + +# Check that the HV gets an ARP reply +expected="eth.src==$ls1_ro_mac && eth.dst==$ls1_p1_mac && + arp.op==2 && arp.sha==$ls1_ro_mac && arp.spa==$proxy_ip1 && + arp.tha==$ls1_p1_mac && arp.tpa==$ls1_p1_ip" +echo $expected | ovstest test-ovn expr-to-packets > expected + +OVN_CHECK_PACKETS([pa-hv/vif1-tx.pcap], [expected]) + +OVN_CLEANUP([pa-hv]) +AT_CLEANUP +])