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

Ben Pfaff blp at ovn.org
Mon Aug 8 16:14:21 UTC 2016


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 at ovn.org>
---
 ovn/controller/lflow.c | 50 +++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 45 insertions(+), 5 deletions(-)

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];
-- 
2.1.3




More information about the dev mailing list