[ovs-dev] [PATCH v3 ovn 2/4] ovn-northd: Move NAT ARP/ND resolution to separate functions.
Han Zhou
hzhou at ovn.org
Mon Sep 21 06:53:00 UTC 2020
On Thu, Sep 17, 2020 at 5:51 AM Dumitru Ceara <dceara at redhat.com> wrote:
>
> To avoid duplicating code later on, move out the code that generates
ARP/ND
> replies for NAT external IPs to separate functions.
>
> Signed-off-by: Dumitru Ceara <dceara at redhat.com>
> ---
> northd/ovn-northd.c | 172
++++++++++++++++++++++++++++-----------------------
> 1 file changed, 94 insertions(+), 78 deletions(-)
>
> diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
> index d5d7631..f79ed99 100644
> --- a/northd/ovn-northd.c
> +++ b/northd/ovn-northd.c
> @@ -8636,6 +8636,94 @@ build_lrouter_nd_flow(struct ovn_datapath *od,
struct ovn_port *op,
> }
>
> static void
> +build_lrouter_nat_arp_nd_flow(struct ovn_datapath *od,
> + struct ovn_nat *nat_entry,
> + struct hmap *lflows)
> +{
> + struct lport_addresses *ext_addrs = &nat_entry->ext_addrs;
> + const struct nbrec_nat *nat = nat_entry->nb;
> +
> + if (nat_entry_is_v6(nat_entry)) {
> + build_lrouter_nd_flow(od, NULL, "nd_na",
> + ext_addrs->ipv6_addrs[0].addr_s,
> + ext_addrs->ipv6_addrs[0].sn_addr_s,
> + REG_INPORT_ETH_ADDR, NULL, false, 90,
> + &nat->header_, lflows);
> + } else {
> + build_lrouter_arp_flow(od, NULL,
> + ext_addrs->ipv4_addrs[0].addr_s,
> + REG_INPORT_ETH_ADDR, NULL, false, 90,
> + &nat->header_, lflows);
> + }
> +}
> +
> +static void
> +build_lrouter_port_nat_arp_nd_flow(struct ovn_port *op,
> + struct ovn_nat *nat_entry,
> + struct hmap *lflows)
> +{
> + struct lport_addresses *ext_addrs = &nat_entry->ext_addrs;
> + const struct nbrec_nat *nat = nat_entry->nb;
> + struct ds match = DS_EMPTY_INITIALIZER;
> +
> + /* Mac address to use when replying to ARP/NS. */
> + const char *mac_s = REG_INPORT_ETH_ADDR;
> + struct eth_addr mac;
> +
> + if (nat->external_mac &&
> + eth_addr_from_string(nat->external_mac, &mac)
> + && nat->logical_port) {
> + /* distributed NAT case, use nat->external_mac */
> + mac_s = nat->external_mac;
> + /* Traffic with eth.src = nat->external_mac should only be
> + * sent from the chassis where nat->logical_port is
> + * resident, so that upstream MAC learning points to the
> + * correct chassis. Also need to avoid generation of
> + * multiple ARP responses from different chassis. */
> + ds_put_format(&match, "is_chassis_resident(\"%s\")",
> + nat->logical_port);
> + } else {
> + mac_s = REG_INPORT_ETH_ADDR;
> + /* Traffic with eth.src = l3dgw_port->lrp_networks.ea_s
> + * should only be sent from the "redirect-chassis", so that
> + * upstream MAC learning points to the "redirect-chassis".
> + * Also need to avoid generation of multiple ARP responses
> + * from different chassis. */
> + if (op->od->l3redirect_port) {
> + ds_put_format(&match, "is_chassis_resident(%s)",
> + op->od->l3redirect_port->json_key);
> + }
> + }
> +
> + /* Respond to ARP/NS requests on the chassis that binds the gw
> + * port. Drop the ARP/NS requests on other chassis.
> + */
> + if (nat_entry_is_v6(nat_entry)) {
> + build_lrouter_nd_flow(op->od, op, "nd_na",
> + ext_addrs->ipv6_addrs[0].addr_s,
> + ext_addrs->ipv6_addrs[0].sn_addr_s,
> + mac_s, &match, false, 92,
> + &nat->header_, lflows);
> + build_lrouter_nd_flow(op->od, op, "nd_na",
> + ext_addrs->ipv6_addrs[0].addr_s,
> + ext_addrs->ipv6_addrs[0].sn_addr_s,
> + mac_s, NULL, true, 91,
> + &nat->header_, lflows);
> + } else {
> + build_lrouter_arp_flow(op->od, op,
> + ext_addrs->ipv4_addrs[0].addr_s,
> + mac_s, &match, false, 92,
> + &nat->header_, lflows);
> + build_lrouter_arp_flow(op->od, op,
> + ext_addrs->ipv4_addrs[0].addr_s,
> + mac_s, NULL, true, 91,
> + &nat->header_, lflows);
> + }
> +
> + ds_destroy(&match);
> +}
> +
> +static void
> build_lrouter_force_snat_flows(struct hmap *lflows, struct ovn_datapath
*od,
> const char *ip_version, const char
*ip_addr,
> const char *context)
> @@ -8869,6 +8957,10 @@ build_lrouter_flows(struct hmap *datapaths, struct
hmap *ports,
> /* Priority-90-92 flows handle ARP requests and ND packets. Most
are
> * per logical port but DNAT addresses can be handled per
datapath
> * for non gateway router ports.
> + *
> + * Priority 91 and 92 flows are added for each gateway router
> + * port to handle the special cases. In case we get the packet
> + * on a regular port, just reply with the port's ETH address.
> */
> struct sset snat_ips = SSET_INITIALIZER(&snat_ips);
> for (int i = 0; i < od->nbr->n_nat; i++) {
> @@ -8890,23 +8982,7 @@ build_lrouter_flows(struct hmap *datapaths, struct
hmap *ports,
> continue;
> }
> }
> -
> - /* Priority 91 and 92 flows are added for each gateway router
> - * port to handle the special cases. In case we get the
packet
> - * on a regular port, just reply with the port's ETH address.
> - */
> - if (nat_entry_is_v6(nat_entry)) {
> - build_lrouter_nd_flow(od, NULL, "nd_na",
> - ext_addrs->ipv6_addrs[0].addr_s,
> - ext_addrs->ipv6_addrs[0].sn_addr_s,
> - REG_INPORT_ETH_ADDR, NULL, false,
90,
> - &nat->header_, lflows);
> - } else {
> - build_lrouter_arp_flow(od, NULL,
> - ext_addrs->ipv4_addrs[0].addr_s,
> - REG_INPORT_ETH_ADDR, NULL, false,
90,
> - &nat->header_, lflows);
> - }
> + build_lrouter_nat_arp_nd_flow(od, nat_entry, lflows);
> }
> sset_destroy(&snat_ips);
>
> @@ -9212,67 +9288,7 @@ build_lrouter_flows(struct hmap *datapaths, struct
hmap *ports,
> continue;
> }
> }
> -
> - /* Mac address to use when replying to ARP/NS. */
> - const char *mac_s = REG_INPORT_ETH_ADDR;
> -
> - /* ARP / ND handling for external IP addresses.
> - *
> - * DNAT IP addresses are external IP addresses that need ARP
> - * handling. */
> -
> - struct eth_addr mac;
> -
> - ds_clear(&match);
> - if (nat->external_mac &&
> - eth_addr_from_string(nat->external_mac, &mac)
> - && nat->logical_port) {
> - /* distributed NAT case, use nat->external_mac */
> - mac_s = nat->external_mac;
> - /* Traffic with eth.src = nat->external_mac should only
be
> - * sent from the chassis where nat->logical_port is
> - * resident, so that upstream MAC learning points to the
> - * correct chassis. Also need to avoid generation of
> - * multiple ARP responses from different chassis. */
> - ds_put_format(&match, "is_chassis_resident(\"%s\")",
> - nat->logical_port);
> - } else {
> - mac_s = REG_INPORT_ETH_ADDR;
> - /* Traffic with eth.src = l3dgw_port->lrp_networks.ea_s
> - * should only be sent from the "redirect-chassis", so
that
> - * upstream MAC learning points to the
"redirect-chassis".
> - * Also need to avoid generation of multiple ARP
responses
> - * from different chassis. */
> - if (op->od->l3redirect_port) {
> - ds_put_format(&match, "is_chassis_resident(%s)",
> - op->od->l3redirect_port->json_key);
> - }
> - }
> -
> - /* Respond to ARP/NS requests on the chassis that binds the
gw
> - * port. Drop the ARP/NS requests on other chassis.
> - */
> - if (nat_entry_is_v6(nat_entry)) {
> - build_lrouter_nd_flow(op->od, op, "nd_na",
> - ext_addrs->ipv6_addrs[0].addr_s,
> - ext_addrs->ipv6_addrs[0].sn_addr_s,
> - mac_s, &match, false, 92,
> - &nat->header_, lflows);
> - build_lrouter_nd_flow(op->od, op, "nd_na",
> - ext_addrs->ipv6_addrs[0].addr_s,
> - ext_addrs->ipv6_addrs[0].sn_addr_s,
> - mac_s, NULL, true, 91,
> - &nat->header_, lflows);
> - } else {
> - build_lrouter_arp_flow(op->od, op,
> - ext_addrs->ipv4_addrs[0].addr_s,
> - mac_s, &match, false, 92,
> - &nat->header_, lflows);
> - build_lrouter_arp_flow(op->od, op,
> - ext_addrs->ipv4_addrs[0].addr_s,
> - mac_s, NULL, true, 91,
> - &nat->header_, lflows);
> - }
> + build_lrouter_port_nat_arp_nd_flow(op, nat_entry, lflows);
> }
> sset_destroy(&sset_snat_ips);
> }
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Acked-by: Han Zhou <hzhou at ovn.org>
More information about the dev
mailing list