OVS NAT currently cannot do snat and dnat in the same zone. So we need two zones per gateway router.
Signed-off-by: Gurucharan Shetty <g...@ovn.org> --- ovn/controller/ovn-controller.c | 52 +++++++++++++++++++++++++++++++---------- ovn/controller/ovn-controller.h | 2 ++ ovn/controller/patch.c | 6 +++-- ovn/controller/physical.c | 25 ++++++++++++++++++++ ovn/lib/logical-fields.h | 11 +++++---- 5 files changed, 78 insertions(+), 18 deletions(-) diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index a87937f..3b55e6c 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -254,29 +254,54 @@ get_ovnsb_remote_probe_interval(struct ovsdb_idl *ovs_idl, int *value) } static void -update_ct_zones(struct sset *lports, struct simap *ct_zones, - unsigned long *ct_zone_bitmap) +update_ct_zones(struct sset *lports, struct hmap *patched_datapaths, + struct simap *ct_zones, unsigned long *ct_zone_bitmap) { struct simap_node *ct_zone, *ct_zone_next; - const char *iface_id; int scan_start = 1; + struct patched_datapath *pd; + const char *user; + struct sset all_users = SSET_INITIALIZER(&all_users); - /* xxx This is wasteful to assign a zone to each port--even if no - * xxx security policy is applied. */ + SSET_FOR_EACH(user, lports) { + sset_add(&all_users, user); + } + + /* Local patched datapath (gateway routers) need zones assigned. */ + HMAP_FOR_EACH(pd, hmap_node, patched_datapaths) { + if (!pd->local) { + continue; + } - /* Delete any zones that are associated with removed ports. */ + char *dnat = xasprintf(UUID_FMT"_%s", + UUID_ARGS(&pd->port_binding->datapath->header_.uuid), + "dnat"); + char *snat = xasprintf(UUID_FMT"_%s", + UUID_ARGS(&pd->port_binding->datapath->header_.uuid), + "snat"); + sset_add(&all_users, dnat); + sset_add(&all_users, snat); + free(dnat); + free(snat); + } + + /* Delete zones that do not exist in above sset. */ SIMAP_FOR_EACH_SAFE(ct_zone, ct_zone_next, ct_zones) { - if (!sset_contains(lports, ct_zone->name)) { + if (!sset_contains(&all_users, ct_zone->name)) { bitmap_set0(ct_zone_bitmap, ct_zone->data); simap_delete(ct_zones, ct_zone); } } - /* Assign a unique zone id for each logical port. */ - SSET_FOR_EACH(iface_id, lports) { + /* xxx This is wasteful to assign a zone to each port--even if no + * xxx security policy is applied. */ + + /* Assign a unique zone id for each logical port and two zones + * to a gateway router. */ + SSET_FOR_EACH(user, &all_users) { size_t zone; - if (simap_contains(ct_zones, iface_id)) { + if (simap_contains(ct_zones, user)) { continue; } @@ -290,12 +315,14 @@ update_ct_zones(struct sset *lports, struct simap *ct_zones, scan_start = zone + 1; bitmap_set1(ct_zone_bitmap, zone); - simap_put(ct_zones, iface_id, zone); + simap_put(ct_zones, user, zone); /* xxx We should erase any old entries for this * xxx zone, but we need a generic interface to the conntrack * xxx table. */ } + + sset_destroy(&all_users); } int @@ -423,7 +450,8 @@ main(int argc, char *argv[]) enum mf_field_id mff_ovn_geneve = ofctrl_run(br_int); pinctrl_run(&ctx, &lports, br_int, chassis_id, &local_datapaths); - update_ct_zones(&all_lports, &ct_zones, ct_zone_bitmap); + update_ct_zones(&all_lports, &patched_datapaths, &ct_zones, + ct_zone_bitmap); struct hmap flow_table = HMAP_INITIALIZER(&flow_table); lflow_run(&ctx, &lports, &mcgroups, &local_datapaths, diff --git a/ovn/controller/ovn-controller.h b/ovn/controller/ovn-controller.h index 9af7959..ba50a98 100644 --- a/ovn/controller/ovn-controller.h +++ b/ovn/controller/ovn-controller.h @@ -48,6 +48,8 @@ struct local_datapath *get_local_datapath(const struct hmap *, * with at least one logical patch port binding. */ struct patched_datapath { struct hmap_node hmap_node; + bool local; /* 'True' if the datapath is for gateway router. */ + const struct sbrec_port_binding *port_binding; }; struct patched_datapath *get_patched_datapath(const struct hmap *, diff --git a/ovn/controller/patch.c b/ovn/controller/patch.c index e8abe30..652466b 100644 --- a/ovn/controller/patch.c +++ b/ovn/controller/patch.c @@ -230,7 +230,7 @@ add_bridge_mappings(struct controller_ctx *ctx, static void add_patched_datapath(struct hmap *patched_datapaths, - const struct sbrec_port_binding *binding_rec) + const struct sbrec_port_binding *binding_rec, bool local) { if (get_patched_datapath(patched_datapaths, binding_rec->datapath->tunnel_key)) { @@ -238,6 +238,8 @@ add_patched_datapath(struct hmap *patched_datapaths, } struct patched_datapath *pd = xzalloc(sizeof *pd); + pd->local = local; + pd->port_binding = binding_rec; hmap_insert(patched_datapaths, &pd->hmap_node, binding_rec->datapath->tunnel_key); } @@ -302,7 +304,7 @@ add_logical_patch_ports(struct controller_ctx *ctx, existing_ports); free(dst_name); free(src_name); - add_patched_datapath(patched_datapaths, binding); + add_patched_datapath(patched_datapaths, binding, local_port); if (local_port) { if (binding->chassis != chassis_rec && ctx->ovnsb_idl_txn) { sbrec_port_binding_set_chassis(binding, chassis_rec); diff --git a/ovn/controller/physical.c b/ovn/controller/physical.c index 576c695..b6e752c 100644 --- a/ovn/controller/physical.c +++ b/ovn/controller/physical.c @@ -367,6 +367,25 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, put_load(zone_id, MFF_LOG_CT_ZONE, 0, 32, &ofpacts); } + int zone_id_dnat, zone_id_snat; + char *dnat = xasprintf(UUID_FMT"_%s", + UUID_ARGS(&binding->datapath->header_.uuid), + "dnat"); + char *snat = xasprintf(UUID_FMT"_%s", + UUID_ARGS(&binding->datapath->header_.uuid), + "snat"); + zone_id_dnat = simap_get(ct_zones, dnat); + if (zone_id_dnat) { + put_load(zone_id_dnat, MFF_LOG_DNAT_ZONE, 0, 32, &ofpacts); + } + free(dnat); + + zone_id_snat = simap_get(ct_zones, snat); + if (zone_id_snat) { + put_load(zone_id_snat, MFF_LOG_SNAT_ZONE, 0, 32, &ofpacts); + } + free(snat); + /* Set MFF_LOG_DATAPATH and MFF_LOG_INPORT. */ put_load(dp_key, MFF_LOG_DATAPATH, 0, 64, &ofpacts); put_load(port_key, MFF_LOG_INPORT, 0, 32, &ofpacts); @@ -403,6 +422,12 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, if (zone_id) { put_load(zone_id, MFF_LOG_CT_ZONE, 0, 32, &ofpacts); } + if (zone_id_dnat) { + put_load(zone_id_dnat, MFF_LOG_DNAT_ZONE, 0, 32, &ofpacts); + } + if (zone_id_snat) { + put_load(zone_id_snat, MFF_LOG_SNAT_ZONE, 0, 32, &ofpacts); + } /* Resubmit to table 34. */ put_resubmit(OFTABLE_DROP_LOOPBACK, &ofpacts); diff --git a/ovn/lib/logical-fields.h b/ovn/lib/logical-fields.h index 59f1cee..f0f97a9 100644 --- a/ovn/lib/logical-fields.h +++ b/ovn/lib/logical-fields.h @@ -23,7 +23,12 @@ * These values are documented in ovn-architecture(7), please update the * documentation if you change any of them. */ #define MFF_LOG_DATAPATH MFF_METADATA /* Logical datapath (64 bits). */ -#define MFF_LOG_CT_ZONE MFF_REG5 /* Logical conntrack zone (32 bits). */ +#define MFF_LOG_DNAT_ZONE MFF_REG3 /* conntrack dnat zone for gateway router + * (32 bits). */ +#define MFF_LOG_SNAT_ZONE MFF_REG4 /* conntrack snat zone for gateway router + * (32 bits). */ +#define MFF_LOG_CT_ZONE MFF_REG5 /* Logical conntrack zone for lports + * (32 bits). */ #define MFF_LOG_INPORT MFF_REG6 /* Logical input port (32 bits). */ #define MFF_LOG_OUTPORT MFF_REG7 /* Logical output port (32 bits). */ @@ -33,8 +38,6 @@ #define MFF_LOG_REGS \ MFF_LOG_REG(MFF_REG0) \ MFF_LOG_REG(MFF_REG1) \ - MFF_LOG_REG(MFF_REG2) \ - MFF_LOG_REG(MFF_REG3) \ - MFF_LOG_REG(MFF_REG4) + MFF_LOG_REG(MFF_REG2) #endif /* ovn/lib/logical-fields.h */ -- 1.9.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev