[ovs-dev] [PATCH 9/9] ovn-controller: Drop most uses of OVS patch ports.
Ben Pfaff
blp at ovn.org
Thu Dec 15 18:14:30 UTC 2016
On Mon, Dec 05, 2016 at 12:58:24PM -0800, Mickey Spiegel wrote:
> On Sun, Dec 4, 2016 at 11:17 PM, Ben Pfaff <blp at ovn.org> wrote:
>
> > Until now, ovn-controller has implemented OVN logical patch ports and
> > l3gateway ports in terms of OVS patch ports. It is a hassle to create and
> > destroy ports, and it is also wasteful compared to what the patch ports
> > actually buy us: the ability to "save and restore" a packet around a
> > recursive trip through the flow table. The "clone" action can do that too,
> > without the need to create a port. This commit takes advantage of the
> > clone action for that purpose, getting rid of most of the patch ports
> > previously created by ovn-controller.
> >
>
> I like it. It took me a bit to change my mindset from most physical.c flows
> based on local ports with ofport values, splitting into some local ports
> with ofport values and other local ports accessing the same refactored
> code directly from a walk of sbrec_port_binding, based on port type.
>
> This will allow me to cut a bunch of code from the first chassisredirect
> patch in my distributed NAT patch set, similar to the way you cut
> add_logical_path_ports in patch.c. More importantly for the distributed
> NAT patch set, this solves most of my egress loopback open issue.
> The local_datapath changes earlier in the patch set probably solve
> my localnet issue. I need to look at that a little more carefully.
>
> A few comments below, mostly about code organization. One real
> technical issue.
>
> After this, I will go back to the first patch and work my way through
> patch by patch.
Thanks for the comments, and sorry it's taken me a while to get back to
them.
> > + /* Bind l3gateway ports to chassis.
> > + *
> > + * (It would make sense for ovn-northd to do this, but if it is ever
> > + * modified to do so, ovn-controller still needs to do the binding as
> > long
> > + * as OVN supports upgrades against older ovn-northd.) */
> > + if (ctx->ovnsb_idl_txn && chassis) {
> > + const struct sbrec_port_binding *binding;
> > + SBREC_PORT_BINDING_FOR_EACH (binding, ctx->ovnsb_idl) {
> > + if (!strcmp(binding->type, "l3gateway")) {
> > + const char *l3gw_chassis = smap_get(&binding->options,
> > + "l3gateway-chassis");
> > + if (!strcmp(l3gw_chassis, chassis->name)
> > + && binding->chassis != chassis) {
> > + sbrec_port_binding_set_chassis(binding, chassis);
> >
>
> I prefer that sbrec_port_binding_set_chassis be handled in binding.c
> rather than patch.c. For l2gateway, even though patch port creation
> is handled in patch.c, sbrec_port_binding_set_chassis is handled in
> binding.c. There is already l3gateway code in binding.c to trigger
> add_local_datapath. This code can go in right alongside that.
You're right that this code doesn't fit in here very well. I kept it
here only because it was previously handled in patch.c, but that's not a
good justification.
I'll move it.
> > + struct zone_ids zone_ids = { .ct = 0 };
> > + if (!strcmp(binding->type, "l3gateway")) {
> > + char *dnat = alloc_nat_zone_key(&binding->
> > datapath->header_.uuid,
> > + "dnat");
> > + zone_ids.dnat = simap_get(ct_zones, dnat);
> > + free(dnat);
> > +
> > + char *snat = alloc_nat_zone_key(&binding->
> > datapath->header_.uuid,
> > + "snat");
> > + zone_ids.snat = simap_get(ct_zones, snat);
> > + free(snat);
> > + }
> >
>
> For distributed NAT, most of the optimization above compared to
> get_zone_ids will go away. I will need dnat and snat zones for
> distributed routers as well as gateway routers.
...
> When I implement egress loopback for distributed NAT, while I will
> only need egress loopback for patch ports, I should probably code
> it up generically for all port types. In order to do that, I will need to
> access the code starting here, down to ofpact_finish_CLONE, from
> another place. I can take care of refactoring this chunk of code in
> that patch if you do not do it here. The difference will be that you
> are calling load_logical_ingress_metadata based on peer,
> whereas for egress loopback this will be based on binding itself.
> Alternatively, I could create my own copy just to optimize since I
> do not need to reset metadata (datapath) or any of the three
> zones.
I think that it's best to make these changes at the time they're
needed.
>
> > + size_t clone_ofs = ofpacts_p->size;
> > + struct ofpact_clone *clone = ofpact_put_CLONE(ofpacts_p);
> > + put_load(0, MFF_LOG_DNAT_ZONE, 0, 32, ofpacts_p);
> > + put_load(0, MFF_LOG_SNAT_ZONE, 0, 32, ofpacts_p);
> > + put_load(0, MFF_LOG_CT_ZONE, 0, 32, ofpacts_p);
> > + load_logical_ingress_metadata(peer, &zone_ids, ofpacts_p);
> >
>
> Don't you need to recompute the zone_ids based on the peer rather
> than based on binding?
> The peer is in a different datapath.
Thanks. I think that the following incremental fixes that:
diff --git a/ovn/controller/physical.c b/ovn/controller/physical.c
index 678b62d..f33750e 100644
--- a/ovn/controller/physical.c
+++ b/ovn/controller/physical.c
@@ -321,12 +321,12 @@ consider_port_binding(enum mf_field_id mff_ovn_geneve,
struct zone_ids zone_ids = { .ct = 0 };
if (!strcmp(binding->type, "l3gateway")) {
- char *dnat = alloc_nat_zone_key(&binding->datapath->header_.uuid,
+ char *dnat = alloc_nat_zone_key(&peer->datapath->header_.uuid,
"dnat");
zone_ids.dnat = simap_get(ct_zones, dnat);
free(dnat);
- char *snat = alloc_nat_zone_key(&binding->datapath->header_.uuid,
+ char *snat = alloc_nat_zone_key(&peer->datapath->header_.uuid,
"snat");
zone_ids.snat = simap_get(ct_zones, snat);
free(snat);
More information about the dev
mailing list