diff mbox series

[ovs-dev] northd: Avoid looking up port peers when not needed.

Message ID 20220412152624.3541-1-dceara@redhat.com
State Changes Requested
Headers show
Series [ovs-dev] northd: Avoid looking up port peers when not needed. | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success

Commit Message

Dumitru Ceara April 12, 2022, 3:26 p.m. UTC
There's no need to call ovn_port_get_peer() to find the peer port of a
logical switch port that's connected to a logical router.  We already
store those in op->peer.

Also, factor out addition of router ports to a logical switch's
ovn_datapath and use x2nrealloc().

Signed-off-by: Dumitru Ceara <dceara@redhat.com>
---
Spotted during code inspection.  I don't really think it will improve
performance but it can't hurt and it should make the code a bit more
clear.
---
 northd/northd.c | 42 +++++++++++++++++++++++-------------------
 1 file changed, 23 insertions(+), 19 deletions(-)

Comments

Mark Michelson April 18, 2022, 5:32 p.m. UTC | #1
Hi Dumitru,

This change makes it so that ovn_port_get_peer() is only relevant before 
op->peer is set; otherwise, you just use op->peer directly. This means 
that there is only one place in the code now that calls 
ovn_port_get_peer(). I have a few ideas here. In order of preference:

1) Instead of removing all the calls to ovn_port_get_peer(), modify 
ovn_port_get_peer() to attempt to return op->peer if it is non-NULL. 
Otherwise, it can fall back to looking up by router-port. This way 
developers always call ovn_port_get_peer() no matter the circumstances, 
lessening the cognitive load.

2) Get rid of ovn_port_get_peer() and put its logic in-line in 
join_logical_ports(). This gets rid of a single-use function and keeps 
other developers from calling it unnecessarily.

3) Leave your code as-is but add a comment to ovn_port_get_peer() to 
explain that it is unnecessary the vast majority of the time.

What do you think?

Mark

On 4/12/22 11:26, Dumitru Ceara wrote:
> There's no need to call ovn_port_get_peer() to find the peer port of a
> logical switch port that's connected to a logical router.  We already
> store those in op->peer.
> 
> Also, factor out addition of router ports to a logical switch's
> ovn_datapath and use x2nrealloc().
> 
> Signed-off-by: Dumitru Ceara <dceara@redhat.com>
> ---
> Spotted during code inspection.  I don't really think it will improve
> performance but it can't hurt and it should make the code a bit more
> clear.
> ---
>   northd/northd.c | 42 +++++++++++++++++++++++-------------------
>   1 file changed, 23 insertions(+), 19 deletions(-)
> 
> diff --git a/northd/northd.c b/northd/northd.c
> index 01ae7d7fd7..6308259159 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -601,6 +601,7 @@ struct ovn_datapath {
>       /* Logical switch data. */
>       struct ovn_port **router_ports;
>       size_t n_router_ports;
> +    size_t n_allocated_router_ports;
>   
>       struct hmap port_tnlids;
>       uint32_t port_key_hint;
> @@ -1081,6 +1082,17 @@ ovn_datapath_from_sbrec(const struct hmap *datapaths,
>       return NULL;
>   }
>   
> +static void
> +ovn_datapath_add_router_port(struct ovn_datapath *od, struct ovn_port *op)
> +{
> +    if (od->n_router_ports == od->n_allocated_router_ports) {
> +        od->router_ports = x2nrealloc(od->router_ports,
> +                                      &od->n_allocated_router_ports,
> +                                      sizeof *od->router_ports);
> +    }
> +    od->router_ports[od->n_router_ports++] = op;
> +}
> +
>   static bool
>   lrouter_is_enabled(const struct nbrec_logical_router *lrouter)
>   {
> @@ -2657,12 +2669,9 @@ join_logical_ports(struct northd_input *input_data,
>                   continue;
>               }
>   
> +            ovn_datapath_add_router_port(op->od, op);
>               peer->peer = op;
>               op->peer = peer;
> -            op->od->router_ports = xrealloc(
> -                op->od->router_ports,
> -                sizeof *op->od->router_ports * (op->od->n_router_ports + 1));
> -            op->od->router_ports[op->od->n_router_ports++] = op;
>   
>               /* Fill op->lsp_addrs for op->nbsp->addresses[] with
>                * contents "router", which was skipped in the loop above. */
> @@ -11142,8 +11151,8 @@ build_ip_routing_pre_flows_for_lrouter(struct ovn_datapath *od,
>    * REG_NEXT_HOP_IPV4/REG_NEXT_HOP_IPV6 for the selected ECMP member.
>    */
>   static void
> -build_ip_routing_flows_for_lrouter_port(
> -        struct ovn_port *op, const struct hmap *ports, struct hmap *lflows)
> +build_ip_routing_flows_for_lrouter_port(struct ovn_port *op,
> +                                        struct hmap *lflows)
>   {
>       if (op->nbrp) {
>   
> @@ -11161,14 +11170,13 @@ build_ip_routing_flows_for_lrouter_port(
>                         &op->nbrp->header_, false, ROUTE_PRIO_OFFSET_CONNECTED);
>           }
>       } else if (lsp_is_router(op->nbsp)) {
> -        struct ovn_port *peer = ovn_port_get_peer(ports, op);
> +        struct ovn_port *peer = op->peer;
>           if (!peer || !peer->nbrp || !peer->lrp_networks.n_ipv4_addrs) {
>               return;
>           }
>   
>           for (int i = 0; i < op->od->n_router_ports; i++) {
> -            struct ovn_port *router_port = ovn_port_get_peer(
> -                    ports, op->od->router_ports[i]);
> +            struct ovn_port *router_port = op->od->router_ports[i]->peer;
>               if (!router_port || !router_port->nbrp || router_port == peer) {
>                   continue;
>               }
> @@ -11547,8 +11555,7 @@ build_arp_resolve_flows_for_lrouter_port(
>                       /* Get the Logical_Router_Port that the
>                        * Logical_Switch_Port is connected to, as
>                        * 'peer'. */
> -                    struct ovn_port *peer = ovn_port_get_peer(
> -                            ports, op->od->router_ports[k]);
> +                    struct ovn_port *peer = op->od->router_ports[k]->peer;
>                       if (!peer || !peer->nbrp) {
>                           continue;
>                       }
> @@ -11578,8 +11585,7 @@ build_arp_resolve_flows_for_lrouter_port(
>                       /* Get the Logical_Router_Port that the
>                        * Logical_Switch_Port is connected to, as
>                        * 'peer'. */
> -                    struct ovn_port *peer = ovn_port_get_peer(
> -                            ports, op->od->router_ports[k]);
> +                    struct ovn_port *peer = op->od->router_ports[k]->peer;
>                       if (!peer || !peer->nbrp) {
>                           continue;
>                       }
> @@ -11639,8 +11645,7 @@ build_arp_resolve_flows_for_lrouter_port(
>               !op->sb->chassis) {
>               /* The virtual port is not claimed yet. */
>               for (size_t i = 0; i < op->od->n_router_ports; i++) {
> -                struct ovn_port *peer = ovn_port_get_peer(
> -                        ports, op->od->router_ports[i]);
> +                struct ovn_port *peer = op->od->router_ports[i]->peer;
>                   if (!peer || !peer->nbrp) {
>                       continue;
>                   }
> @@ -11675,8 +11680,7 @@ build_arp_resolve_flows_for_lrouter_port(
>                       /* Get the Logical_Router_Port that the
>                       * Logical_Switch_Port is connected to, as
>                       * 'peer'. */
> -                    struct ovn_port *peer =
> -                        ovn_port_get_peer(ports, vp->od->router_ports[j]);
> +                    struct ovn_port *peer = vp->od->router_ports[j]->peer;
>                       if (!peer || !peer->nbrp) {
>                           continue;
>                       }
> @@ -11713,7 +11717,7 @@ build_arp_resolve_flows_for_lrouter_port(
>            * we need to add logical flows such that it can resolve
>            * ARP entries for all the other router ports connected to
>            * the switch in question. */
> -        struct ovn_port *peer = ovn_port_get_peer(ports, op);
> +        struct ovn_port *peer = op->peer;
>           if (!peer || !peer->nbrp) {
>               return;
>           }
> @@ -13626,7 +13630,7 @@ build_lswitch_and_lrouter_iterate_by_op(struct ovn_port *op,
>                                             &lsi->actions);
>       build_neigh_learning_flows_for_lrouter_port(op, lsi->lflows, &lsi->match,
>                                                   &lsi->actions);
> -    build_ip_routing_flows_for_lrouter_port(op, lsi->ports, lsi->lflows);
> +    build_ip_routing_flows_for_lrouter_port(op, lsi->lflows);
>       build_ND_RA_flows_for_lrouter_port(op, lsi->lflows, &lsi->match,
>                                          &lsi->actions, lsi->meter_groups);
>       build_arp_resolve_flows_for_lrouter_port(op, lsi->lflows, lsi->ports,
>
Dumitru Ceara April 19, 2022, 8:21 a.m. UTC | #2
On 4/18/22 19:32, Mark Michelson wrote:
> Hi Dumitru,
> 

Hi Mark,

Thanks for reviewing this patch!

> This change makes it so that ovn_port_get_peer() is only relevant before
> op->peer is set; otherwise, you just use op->peer directly. This means
> that there is only one place in the code now that calls
> ovn_port_get_peer(). I have a few ideas here. In order of preference:
> 
> 1) Instead of removing all the calls to ovn_port_get_peer(), modify
> ovn_port_get_peer() to attempt to return op->peer if it is non-NULL.
> Otherwise, it can fall back to looking up by router-port. This way
> developers always call ovn_port_get_peer() no matter the circumstances,
> lessening the cognitive load.

I will do this.

> 
> 2) Get rid of ovn_port_get_peer() and put its logic in-line in
> join_logical_ports(). This gets rid of a single-use function and keeps
> other developers from calling it unnecessarily.
> 

I don't really like this option because join_logical_ports() is really
long and complex already.

> 3) Leave your code as-is but add a comment to ovn_port_get_peer() to
> explain that it is unnecessary the vast majority of the time.

Normally, I'd prefer this solution, but that's because the code
populating ovn_port and ovn_datapath structures should be, in my
opinion, separated modules, distinct from the code that uses ovn_port
and ovn_datapath.  That's not currently the case though.

> 
> What do you think?
> 

I'll post v2, implementing option "1)".

> Mark
> 

Thanks,
Dumitru

> On 4/12/22 11:26, Dumitru Ceara wrote:
>> There's no need to call ovn_port_get_peer() to find the peer port of a
>> logical switch port that's connected to a logical router.  We already
>> store those in op->peer.
>>
>> Also, factor out addition of router ports to a logical switch's
>> ovn_datapath and use x2nrealloc().
>>
>> Signed-off-by: Dumitru Ceara <dceara@redhat.com>
>> ---
>> Spotted during code inspection.  I don't really think it will improve
>> performance but it can't hurt and it should make the code a bit more
>> clear.
>> ---
>>   northd/northd.c | 42 +++++++++++++++++++++++-------------------
>>   1 file changed, 23 insertions(+), 19 deletions(-)
>>
>> diff --git a/northd/northd.c b/northd/northd.c
>> index 01ae7d7fd7..6308259159 100644
>> --- a/northd/northd.c
>> +++ b/northd/northd.c
>> @@ -601,6 +601,7 @@ struct ovn_datapath {
>>       /* Logical switch data. */
>>       struct ovn_port **router_ports;
>>       size_t n_router_ports;
>> +    size_t n_allocated_router_ports;
>>         struct hmap port_tnlids;
>>       uint32_t port_key_hint;
>> @@ -1081,6 +1082,17 @@ ovn_datapath_from_sbrec(const struct hmap
>> *datapaths,
>>       return NULL;
>>   }
>>   +static void
>> +ovn_datapath_add_router_port(struct ovn_datapath *od, struct ovn_port
>> *op)
>> +{
>> +    if (od->n_router_ports == od->n_allocated_router_ports) {
>> +        od->router_ports = x2nrealloc(od->router_ports,
>> +                                      &od->n_allocated_router_ports,
>> +                                      sizeof *od->router_ports);
>> +    }
>> +    od->router_ports[od->n_router_ports++] = op;
>> +}
>> +
>>   static bool
>>   lrouter_is_enabled(const struct nbrec_logical_router *lrouter)
>>   {
>> @@ -2657,12 +2669,9 @@ join_logical_ports(struct northd_input
>> *input_data,
>>                   continue;
>>               }
>>   +            ovn_datapath_add_router_port(op->od, op);
>>               peer->peer = op;
>>               op->peer = peer;
>> -            op->od->router_ports = xrealloc(
>> -                op->od->router_ports,
>> -                sizeof *op->od->router_ports *
>> (op->od->n_router_ports + 1));
>> -            op->od->router_ports[op->od->n_router_ports++] = op;
>>                 /* Fill op->lsp_addrs for op->nbsp->addresses[] with
>>                * contents "router", which was skipped in the loop
>> above. */
>> @@ -11142,8 +11151,8 @@ build_ip_routing_pre_flows_for_lrouter(struct
>> ovn_datapath *od,
>>    * REG_NEXT_HOP_IPV4/REG_NEXT_HOP_IPV6 for the selected ECMP member.
>>    */
>>   static void
>> -build_ip_routing_flows_for_lrouter_port(
>> -        struct ovn_port *op, const struct hmap *ports, struct hmap
>> *lflows)
>> +build_ip_routing_flows_for_lrouter_port(struct ovn_port *op,
>> +                                        struct hmap *lflows)
>>   {
>>       if (op->nbrp) {
>>   @@ -11161,14 +11170,13 @@ build_ip_routing_flows_for_lrouter_port(
>>                         &op->nbrp->header_, false,
>> ROUTE_PRIO_OFFSET_CONNECTED);
>>           }
>>       } else if (lsp_is_router(op->nbsp)) {
>> -        struct ovn_port *peer = ovn_port_get_peer(ports, op);
>> +        struct ovn_port *peer = op->peer;
>>           if (!peer || !peer->nbrp || !peer->lrp_networks.n_ipv4_addrs) {
>>               return;
>>           }
>>             for (int i = 0; i < op->od->n_router_ports; i++) {
>> -            struct ovn_port *router_port = ovn_port_get_peer(
>> -                    ports, op->od->router_ports[i]);
>> +            struct ovn_port *router_port =
>> op->od->router_ports[i]->peer;
>>               if (!router_port || !router_port->nbrp || router_port ==
>> peer) {
>>                   continue;
>>               }
>> @@ -11547,8 +11555,7 @@ build_arp_resolve_flows_for_lrouter_port(
>>                       /* Get the Logical_Router_Port that the
>>                        * Logical_Switch_Port is connected to, as
>>                        * 'peer'. */
>> -                    struct ovn_port *peer = ovn_port_get_peer(
>> -                            ports, op->od->router_ports[k]);
>> +                    struct ovn_port *peer =
>> op->od->router_ports[k]->peer;
>>                       if (!peer || !peer->nbrp) {
>>                           continue;
>>                       }
>> @@ -11578,8 +11585,7 @@ build_arp_resolve_flows_for_lrouter_port(
>>                       /* Get the Logical_Router_Port that the
>>                        * Logical_Switch_Port is connected to, as
>>                        * 'peer'. */
>> -                    struct ovn_port *peer = ovn_port_get_peer(
>> -                            ports, op->od->router_ports[k]);
>> +                    struct ovn_port *peer =
>> op->od->router_ports[k]->peer;
>>                       if (!peer || !peer->nbrp) {
>>                           continue;
>>                       }
>> @@ -11639,8 +11645,7 @@ build_arp_resolve_flows_for_lrouter_port(
>>               !op->sb->chassis) {
>>               /* The virtual port is not claimed yet. */
>>               for (size_t i = 0; i < op->od->n_router_ports; i++) {
>> -                struct ovn_port *peer = ovn_port_get_peer(
>> -                        ports, op->od->router_ports[i]);
>> +                struct ovn_port *peer = op->od->router_ports[i]->peer;
>>                   if (!peer || !peer->nbrp) {
>>                       continue;
>>                   }
>> @@ -11675,8 +11680,7 @@ build_arp_resolve_flows_for_lrouter_port(
>>                       /* Get the Logical_Router_Port that the
>>                       * Logical_Switch_Port is connected to, as
>>                       * 'peer'. */
>> -                    struct ovn_port *peer =
>> -                        ovn_port_get_peer(ports,
>> vp->od->router_ports[j]);
>> +                    struct ovn_port *peer =
>> vp->od->router_ports[j]->peer;
>>                       if (!peer || !peer->nbrp) {
>>                           continue;
>>                       }
>> @@ -11713,7 +11717,7 @@ build_arp_resolve_flows_for_lrouter_port(
>>            * we need to add logical flows such that it can resolve
>>            * ARP entries for all the other router ports connected to
>>            * the switch in question. */
>> -        struct ovn_port *peer = ovn_port_get_peer(ports, op);
>> +        struct ovn_port *peer = op->peer;
>>           if (!peer || !peer->nbrp) {
>>               return;
>>           }
>> @@ -13626,7 +13630,7 @@ build_lswitch_and_lrouter_iterate_by_op(struct
>> ovn_port *op,
>>                                             &lsi->actions);
>>       build_neigh_learning_flows_for_lrouter_port(op, lsi->lflows,
>> &lsi->match,
>>                                                   &lsi->actions);
>> -    build_ip_routing_flows_for_lrouter_port(op, lsi->ports,
>> lsi->lflows);
>> +    build_ip_routing_flows_for_lrouter_port(op, lsi->lflows);
>>       build_ND_RA_flows_for_lrouter_port(op, lsi->lflows, &lsi->match,
>>                                          &lsi->actions,
>> lsi->meter_groups);
>>       build_arp_resolve_flows_for_lrouter_port(op, lsi->lflows,
>> lsi->ports,
>>
>
diff mbox series

Patch

diff --git a/northd/northd.c b/northd/northd.c
index 01ae7d7fd7..6308259159 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -601,6 +601,7 @@  struct ovn_datapath {
     /* Logical switch data. */
     struct ovn_port **router_ports;
     size_t n_router_ports;
+    size_t n_allocated_router_ports;
 
     struct hmap port_tnlids;
     uint32_t port_key_hint;
@@ -1081,6 +1082,17 @@  ovn_datapath_from_sbrec(const struct hmap *datapaths,
     return NULL;
 }
 
+static void
+ovn_datapath_add_router_port(struct ovn_datapath *od, struct ovn_port *op)
+{
+    if (od->n_router_ports == od->n_allocated_router_ports) {
+        od->router_ports = x2nrealloc(od->router_ports,
+                                      &od->n_allocated_router_ports,
+                                      sizeof *od->router_ports);
+    }
+    od->router_ports[od->n_router_ports++] = op;
+}
+
 static bool
 lrouter_is_enabled(const struct nbrec_logical_router *lrouter)
 {
@@ -2657,12 +2669,9 @@  join_logical_ports(struct northd_input *input_data,
                 continue;
             }
 
+            ovn_datapath_add_router_port(op->od, op);
             peer->peer = op;
             op->peer = peer;
-            op->od->router_ports = xrealloc(
-                op->od->router_ports,
-                sizeof *op->od->router_ports * (op->od->n_router_ports + 1));
-            op->od->router_ports[op->od->n_router_ports++] = op;
 
             /* Fill op->lsp_addrs for op->nbsp->addresses[] with
              * contents "router", which was skipped in the loop above. */
@@ -11142,8 +11151,8 @@  build_ip_routing_pre_flows_for_lrouter(struct ovn_datapath *od,
  * REG_NEXT_HOP_IPV4/REG_NEXT_HOP_IPV6 for the selected ECMP member.
  */
 static void
-build_ip_routing_flows_for_lrouter_port(
-        struct ovn_port *op, const struct hmap *ports, struct hmap *lflows)
+build_ip_routing_flows_for_lrouter_port(struct ovn_port *op,
+                                        struct hmap *lflows)
 {
     if (op->nbrp) {
 
@@ -11161,14 +11170,13 @@  build_ip_routing_flows_for_lrouter_port(
                       &op->nbrp->header_, false, ROUTE_PRIO_OFFSET_CONNECTED);
         }
     } else if (lsp_is_router(op->nbsp)) {
-        struct ovn_port *peer = ovn_port_get_peer(ports, op);
+        struct ovn_port *peer = op->peer;
         if (!peer || !peer->nbrp || !peer->lrp_networks.n_ipv4_addrs) {
             return;
         }
 
         for (int i = 0; i < op->od->n_router_ports; i++) {
-            struct ovn_port *router_port = ovn_port_get_peer(
-                    ports, op->od->router_ports[i]);
+            struct ovn_port *router_port = op->od->router_ports[i]->peer;
             if (!router_port || !router_port->nbrp || router_port == peer) {
                 continue;
             }
@@ -11547,8 +11555,7 @@  build_arp_resolve_flows_for_lrouter_port(
                     /* Get the Logical_Router_Port that the
                      * Logical_Switch_Port is connected to, as
                      * 'peer'. */
-                    struct ovn_port *peer = ovn_port_get_peer(
-                            ports, op->od->router_ports[k]);
+                    struct ovn_port *peer = op->od->router_ports[k]->peer;
                     if (!peer || !peer->nbrp) {
                         continue;
                     }
@@ -11578,8 +11585,7 @@  build_arp_resolve_flows_for_lrouter_port(
                     /* Get the Logical_Router_Port that the
                      * Logical_Switch_Port is connected to, as
                      * 'peer'. */
-                    struct ovn_port *peer = ovn_port_get_peer(
-                            ports, op->od->router_ports[k]);
+                    struct ovn_port *peer = op->od->router_ports[k]->peer;
                     if (!peer || !peer->nbrp) {
                         continue;
                     }
@@ -11639,8 +11645,7 @@  build_arp_resolve_flows_for_lrouter_port(
             !op->sb->chassis) {
             /* The virtual port is not claimed yet. */
             for (size_t i = 0; i < op->od->n_router_ports; i++) {
-                struct ovn_port *peer = ovn_port_get_peer(
-                        ports, op->od->router_ports[i]);
+                struct ovn_port *peer = op->od->router_ports[i]->peer;
                 if (!peer || !peer->nbrp) {
                     continue;
                 }
@@ -11675,8 +11680,7 @@  build_arp_resolve_flows_for_lrouter_port(
                     /* Get the Logical_Router_Port that the
                     * Logical_Switch_Port is connected to, as
                     * 'peer'. */
-                    struct ovn_port *peer =
-                        ovn_port_get_peer(ports, vp->od->router_ports[j]);
+                    struct ovn_port *peer = vp->od->router_ports[j]->peer;
                     if (!peer || !peer->nbrp) {
                         continue;
                     }
@@ -11713,7 +11717,7 @@  build_arp_resolve_flows_for_lrouter_port(
          * we need to add logical flows such that it can resolve
          * ARP entries for all the other router ports connected to
          * the switch in question. */
-        struct ovn_port *peer = ovn_port_get_peer(ports, op);
+        struct ovn_port *peer = op->peer;
         if (!peer || !peer->nbrp) {
             return;
         }
@@ -13626,7 +13630,7 @@  build_lswitch_and_lrouter_iterate_by_op(struct ovn_port *op,
                                           &lsi->actions);
     build_neigh_learning_flows_for_lrouter_port(op, lsi->lflows, &lsi->match,
                                                 &lsi->actions);
-    build_ip_routing_flows_for_lrouter_port(op, lsi->ports, lsi->lflows);
+    build_ip_routing_flows_for_lrouter_port(op, lsi->lflows);
     build_ND_RA_flows_for_lrouter_port(op, lsi->lflows, &lsi->match,
                                        &lsi->actions, lsi->meter_groups);
     build_arp_resolve_flows_for_lrouter_port(op, lsi->lflows, lsi->ports,