[ovs-dev] [PATCH v5 5/6] ovn: Support OVS action 'check_pkt_larger' in OVN

nusiddiq at redhat.com nusiddiq at redhat.com
Mon Apr 22 19:23:55 UTC 2019


From: Numan Siddique <nusiddiq at redhat.com>

Previous commit added a new OVS action 'check_pkt_larger'. This
patch supports that action in OVN. The syntax to use this would be

reg0[0] = check_pkt_larger(LEN)

Upcoming commit will make use of this action in ovn-northd and
will generate an ICMPv4 packet if the packet length is greater than
the specified length.

Signed-off-by: Numan Siddique <nusiddiq at redhat.com>
Acked-by: Mark Michelson <mmichels at redhat.com>
---
 include/ovn/actions.h     | 10 +++++++-
 ovn/lib/actions.c         | 53 +++++++++++++++++++++++++++++++++++++++
 ovn/ovn-sb.xml            | 21 ++++++++++++++++
 ovn/utilities/ovn-trace.c |  4 ++-
 tests/ovn.at              | 13 ++++++++++
 5 files changed, 99 insertions(+), 2 deletions(-)

diff --git a/include/ovn/actions.h b/include/ovn/actions.h
index af8b0a4a0..e07ad9aa3 100644
--- a/include/ovn/actions.h
+++ b/include/ovn/actions.h
@@ -82,7 +82,8 @@ struct ovn_extend_table;
     OVNACT(PUT_ND_RA_OPTS,    ovnact_put_opts)        \
     OVNACT(ND_NS,             ovnact_nest)            \
     OVNACT(SET_METER,         ovnact_set_meter)       \
-    OVNACT(OVNFIELD_LOAD,     ovnact_load)
+    OVNACT(OVNFIELD_LOAD,     ovnact_load)            \
+    OVNACT(CHECK_PKT_LARGER,  ovnact_check_pkt_larger)
 
 /* enum ovnact_type, with a member OVNACT_<ENUM> for each action. */
 enum OVS_PACKED_ENUM ovnact_type {
@@ -310,6 +311,13 @@ struct ovnact_set_meter {
     uint64_t burst;                  /* burst rate field, in kbps. */
 };
 
+/* OVNACT_CHECK_IP_PKT_LARGER. */
+struct ovnact_check_pkt_larger {
+    struct ovnact ovnact;
+    uint16_t pkt_len;
+    struct expr_field dst;      /* 1-bit destination field. */
+};
+
 /* Internal use by the helpers below. */
 void ovnact_init(struct ovnact *, enum ovnact_type, size_t len);
 void *ovnact_put(struct ofpbuf *, enum ovnact_type, size_t len);
diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c
index f78e6ffcb..d5909911d 100644
--- a/ovn/lib/actions.c
+++ b/ovn/lib/actions.c
@@ -2359,6 +2359,55 @@ encode_OVNFIELD_LOAD(const struct ovnact_load *load,
     }
 }
 
+static void
+parse_check_pkt_larger(struct action_context *ctx,
+                       const struct expr_field *dst,
+                       struct ovnact_check_pkt_larger *cipl)
+{
+     /* Validate that the destination is a 1-bit, modifiable field. */
+    char *error = expr_type_check(dst, 1, true);
+    if (error) {
+        lexer_error(ctx->lexer, "%s", error);
+        free(error);
+        return;
+    }
+
+    int pkt_len;
+    lexer_get(ctx->lexer); /* Skip check_pkt_len. */
+    if (!lexer_force_match(ctx->lexer, LEX_T_LPAREN)
+        || !lexer_get_int(ctx->lexer, &pkt_len)
+        || !lexer_force_match(ctx->lexer, LEX_T_RPAREN)) {
+        return;
+    }
+
+    cipl->dst = *dst;
+    cipl->pkt_len = pkt_len;
+}
+
+static void
+format_CHECK_PKT_LARGER(const struct ovnact_check_pkt_larger *cipl,
+                        struct ds *s)
+{
+    expr_field_format(&cipl->dst, s);
+    ds_put_format(s, " = check_pkt_larger(%d);", cipl->pkt_len);
+}
+
+static void
+encode_CHECK_PKT_LARGER(const struct ovnact_check_pkt_larger *cipl,
+                        const struct ovnact_encode_params *ep OVS_UNUSED,
+                        struct ofpbuf *ofpacts)
+{
+    struct ofpact_check_pkt_larger *check_pkt_larger =
+        ofpact_put_CHECK_PKT_LARGER(ofpacts);
+    check_pkt_larger->pkt_len = cipl->pkt_len;
+    check_pkt_larger->dst = expr_resolve_field(&cipl->dst);
+}
+
+static void
+ovnact_check_pkt_larger_free(struct ovnact_check_pkt_larger *cipl OVS_UNUSED)
+{
+}
+
 /* Parses an assignment or exchange or put_dhcp_opts action. */
 static void
 parse_set_action(struct action_context *ctx)
@@ -2388,6 +2437,10 @@ parse_set_action(struct action_context *ctx)
                 && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) {
             parse_put_nd_ra_opts(ctx, &lhs,
                                  ovnact_put_PUT_ND_RA_OPTS(ctx->ovnacts));
+        } else if (!strcmp(ctx->lexer->token.s, "check_pkt_larger")
+                && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) {
+            parse_check_pkt_larger(ctx, &lhs,
+                                   ovnact_put_CHECK_PKT_LARGER(ctx->ovnacts));
         } else {
             parse_assignment_action(ctx, false, &lhs);
         }
diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml
index b95579881..625f79983 100644
--- a/ovn/ovn-sb.xml
+++ b/ovn/ovn-sb.xml
@@ -1799,6 +1799,27 @@
 
           <p><b>Example:</b> <code>set_meter(100, 1000);</code></p>
         </dd>
+
+        <dt><code><var>R</var> = check_pkt_larger(<var>L</var>)</code></dt>
+        <dd>
+          <p>
+            <b>Parameters</b>: packet length <var>L</var> to check for
+            in bytes.
+          </p>
+
+          <p>
+            <b>Result</b>: stored to a 1-bit subfield <var>R</var>.
+          </p>
+
+          <p>
+            This is a logical equivalent of the OpenFlow
+            <code>check_pkt_larger</code> action. If the packet is larger
+            than the length specified in <var>L</var>, it stores 1 in the
+            subfield <var>R</var>.
+          </p>
+
+          <p><b>Example: </b><code>reg0[6] = check_pkt_larger(1000);</code></p>
+        </dd>
       </dl>
 
       <dl>
diff --git a/ovn/utilities/ovn-trace.c b/ovn/utilities/ovn-trace.c
index 28e2bb075..9718077aa 100644
--- a/ovn/utilities/ovn-trace.c
+++ b/ovn/utilities/ovn-trace.c
@@ -2134,8 +2134,10 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len,
         case OVNACT_OVNFIELD_LOAD:
             execute_ovnfield_load(ovnact_get_OVNFIELD_LOAD(a), super);
             break;
-        }
 
+        case OVNACT_CHECK_PKT_LARGER:
+            break;
+        }
     }
     ds_destroy(&s);
 }
diff --git a/tests/ovn.at b/tests/ovn.at
index 9bc652195..b3d9dbdfc 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -1341,6 +1341,19 @@ ip4.src <-> ip6.src[0..31];
     encodes as push:NXM_NX_IPV6_SRC[0..31],push:NXM_OF_IP_SRC[],pop:NXM_NX_IPV6_SRC[0..31],pop:NXM_OF_IP_SRC[]
     has prereqs eth.type == 0x800 && eth.type == 0x86dd
 
+# check_pkt_larger
+reg0[0] = check_pkt_larger(1500);
+    encodes as check_pkt_larger(1500)->NXM_NX_XXREG0[96]
+
+reg0 = check_pkt_larger(1500);
+    Cannot use 32-bit field reg0[0..31] where 1-bit field is required.
+
+reg0 = check_pkt_larger(foo);
+    Cannot use 32-bit field reg0[0..31] where 1-bit field is required.
+
+reg0[0] = check_pkt_larger(foo);
+    Syntax error at `foo' expecting `;'.
+
 # Miscellaneous negative tests.
 ;
     Syntax error at `;'.
-- 
2.20.1



More information about the dev mailing list