diff mbox

[ovs-dev,v2,10/21] lflow: Correct register definitions to use subfields for overlaps.

Message ID 1470672872-19450-11-git-send-email-blp@ovn.org
State Accepted
Headers show

Commit Message

Ben Pfaff Aug. 8, 2016, 4:14 p.m. UTC
OVN expressions need to know what fields overlap or alias one another.
This is supposed to be done via subfields: if two fields overlap, then the
smaller one should be defined as a subfield of the larger one.  For
example, reg0 should be defined as xxreg0[96..127].  The symbol table in
lflow didn't do this, so it's possible for confusion to result.  (I don't
have evidence of this actually happening, because it would only occur
in a case where the same bits of a field were referred to with different
names.)

This commit fixes the problem.  It deserves a test, but that's somewhat
difficult at this point, so it will actually happen in a future commit.

Signed-off-by: Ben Pfaff <blp@ovn.org>
---
 ovn/controller/lflow.c | 50 +++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 45 insertions(+), 5 deletions(-)

Comments

Ryan Moats Aug. 8, 2016, 5:12 p.m. UTC | #1
"dev" <dev-bounces@openvswitch.org> wrote on 08/08/2016 11:14:21 AM:

> From: Ben Pfaff <blp@ovn.org>
> To: dev@openvswitch.org
> Cc: Ben Pfaff <blp@ovn.org>
> Date: 08/08/2016 11:16 AM
> Subject: [ovs-dev] [PATCH v2 10/21] lflow: Correct register
> definitions to use subfields for overlaps.
> Sent by: "dev" <dev-bounces@openvswitch.org>
>
> OVN expressions need to know what fields overlap or alias one another.
> This is supposed to be done via subfields: if two fields overlap, then
the
> smaller one should be defined as a subfield of the larger one.  For
> example, reg0 should be defined as xxreg0[96..127].  The symbol table in
> lflow didn't do this, so it's possible for confusion to result.  (I don't
> have evidence of this actually happening, because it would only occur
> in a case where the same bits of a field were referred to with different
> names.)
>
> This commit fixes the problem.  It deserves a test, but that's somewhat
> difficult at this point, so it will actually happen in a future commit.
>
> Signed-off-by: Ben Pfaff <blp@ovn.org>
> ---

Yes, we do really need a test for this - add it to the pile of debt...

Acked-by: Ryan Moats <rmoats@us.ibm.com>
Ben Pfaff Aug. 8, 2016, 5:54 p.m. UTC | #2
On Mon, Aug 08, 2016 at 12:12:53PM -0500, Ryan Moats wrote:
> "dev" <dev-bounces@openvswitch.org> wrote on 08/08/2016 11:14:21 AM:
> 
> > From: Ben Pfaff <blp@ovn.org>
> > To: dev@openvswitch.org
> > Cc: Ben Pfaff <blp@ovn.org>
> > Date: 08/08/2016 11:16 AM
> > Subject: [ovs-dev] [PATCH v2 10/21] lflow: Correct register
> > definitions to use subfields for overlaps.
> > Sent by: "dev" <dev-bounces@openvswitch.org>
> >
> > OVN expressions need to know what fields overlap or alias one another.
> > This is supposed to be done via subfields: if two fields overlap, then
> the
> > smaller one should be defined as a subfield of the larger one.  For
> > example, reg0 should be defined as xxreg0[96..127].  The symbol table in
> > lflow didn't do this, so it's possible for confusion to result.  (I don't
> > have evidence of this actually happening, because it would only occur
> > in a case where the same bits of a field were referred to with different
> > names.)
> >
> > This commit fixes the problem.  It deserves a test, but that's somewhat
> > difficult at this point, so it will actually happen in a future commit.
> >
> > Signed-off-by: Ben Pfaff <blp@ovn.org>
> > ---
> 
> Yes, we do really need a test for this - add it to the pile of debt...
> 
> Acked-by: Ryan Moats <rmoats@us.ibm.com>

Oh, the test is added one or two commits later, so it's only a very
short-term debt.
diff mbox

Patch

diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c
index 9eb92c8..71d42a7 100644
--- a/ovn/controller/lflow.c
+++ b/ovn/controller/lflow.c
@@ -52,6 +52,20 @@  lflow_reset_processing(void)
     physical_reset_processing();
 }
 
+static void
+add_subregister(const char *name,
+                const char *parent_name, int parent_idx,
+                int width, int idx,
+                struct shash *symtab)
+{
+    int lsb = width * idx;
+    int msb = lsb + (width - 1);
+    char *expansion = xasprintf("%s%d[%d..%d]",
+                                parent_name, parent_idx, lsb, msb);
+    expr_symtab_add_subfield(symtab, name, NULL, expansion);
+    free(expansion);
+}
+
 void
 lflow_init(void)
 {
@@ -64,16 +78,42 @@  lflow_init(void)
     expr_symtab_add_string(&symtab, "inport", MFF_LOG_INPORT, NULL);
     expr_symtab_add_string(&symtab, "outport", MFF_LOG_OUTPORT, NULL);
 
-    /* Logical registers. */
+    /* Logical registers:
+     *     128-bit xxregs
+     *     64-bit xregs
+     *     32-bit regs
+     *
+     * The expression language doesn't handle overlapping fields properly
+     * unless they're formally defined as subfields.  It's a little awkward. */
+    for (int xxi = 0; xxi < MFF_N_LOG_REGS / 4; xxi++) {
+        char *xxname = xasprintf("xxreg%d", xxi);
+        expr_symtab_add_field(&symtab, xxname, MFF_XXREG0 + xxi, NULL, false);
+        free(xxname);
+    }
+    for (int xi = 0; xi < MFF_N_LOG_REGS / 2; xi++) {
+        char *xname = xasprintf("xreg%d", xi);
+        int xxi = xi / 2;
+        if (xxi < MFF_N_LOG_REGS / 4) {
+            add_subregister(xname, "xxreg", xxi, 64, 1 - xi % 2, &symtab);
+        } else {
+            expr_symtab_add_field(&symtab, xname, MFF_XREG0 + xi, NULL, false);
+        }
+        free(xname);
+    }
     for (int i = 0; i < MFF_N_LOG_REGS; i++) {
         char *name = xasprintf("reg%d", i);
-        expr_symtab_add_field(&symtab, name, MFF_LOG_REG0 + i, NULL, false);
+        int xxi = i / 4;
+        int xi = i / 2;
+        if (xxi < MFF_N_LOG_REGS / 4) {
+            add_subregister(name, "xxreg", xxi, 32, 3 - i % 4, &symtab);
+        } else if (xi < MFF_N_LOG_REGS / 2) {
+            add_subregister(name, "xreg", xi, 32, 1 - i % 2, &symtab);
+        } else {
+            expr_symtab_add_field(&symtab, name, MFF_REG0 + i, NULL, false);
+        }
         free(name);
     }
 
-    expr_symtab_add_field(&symtab, "xxreg0", MFF_XXREG0, NULL, false);
-    expr_symtab_add_field(&symtab, "xxreg1", MFF_XXREG1, NULL, false);
-
     /* Flags used in logical to physical transformation. */
     expr_symtab_add_field(&symtab, "flags", MFF_LOG_FLAGS, NULL, false);
     char flags_str[16];