[ovs-dev] [PATCH v3 ovn 2/4] ovn-northd: Move NAT ARP/ND resolution to separate functions.
Dumitru Ceara
dceara at redhat.com
Thu Sep 17 12:51:09 UTC 2020
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);
}
More information about the dev
mailing list