Re: [ovs-dev] [PATCH v10 2/4] ovn-controller: Add a new action - 'put_nd_ra_opts'

2017-11-02 Thread Ben Pfaff
On Thu, Nov 02, 2017 at 06:19:24AM +0530, nusid...@redhat.com wrote:
> From: Numan Siddique 
> 
> This patch adds a new OVN action 'put_nd_ra_opts' to support native
> IPv6 Router Advertisement in OVN. This action can be used to respond
> to the IPv6 Router Solicitation requests.

Thanks for the patch!  I folded in the following changes because I
didn't think it made sense to mention the function name in error
messages; we don't do that elsewhere.

diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c
index 8cec5c7d0871..0df5edbaa51d 100644
--- a/ovn/lib/actions.c
+++ b/ovn/lib/actions.c
@@ -1851,69 +1851,57 @@ parse_put_nd_ra_opts(struct action_context *ctx, const 
struct expr_field *dst,
 o < &po->options[po->n_options]; o++) {
 const union expr_constant *c = o->value.values;
 if (o->value.n_values > 1) {
-lexer_error(ctx->lexer, "parse_put_nd_ra_opts -Invalid value for"
-" the option %s.", o->option->name);
+lexer_error(ctx->lexer, "Invalid value for \"%s\" option",
+o->option->name);
 return;
 }
 
+bool ok = true;
 switch (o->option->code) {
 case ND_RA_FLAG_ADDR_MODE:
-if (!c->string || (strcmp(c->string, "slaac") &&
-   strcmp(c->string, "dhcpv6_stateful") &&
-   strcmp(c->string, "dhcpv6_stateless"))) {
-lexer_error(ctx->lexer, "parse_put_nd_ra_opts -Invalid value "
-"for the option %s.", o->option->name);
-return;
-}
-
-if (!strcmp(c->string, "dhcpv6_stateful")) {
+ok = (c->string && (!strcmp(c->string, "slaac") ||
+!strcmp(c->string, "dhcpv6_stateful") ||
+!strcmp(c->string, "dhcpv6_stateless")));
+if (ok && !strcmp(c->string, "dhcpv6_stateful")) {
 addr_mode_stateful = true;
 }
 break;
 
 case ND_OPT_SOURCE_LINKADDR:
-if (c->format != LEX_F_ETHERNET) {
-lexer_error(ctx->lexer, "parse_put_nd_ra_opts -Invalid value "
-   "for the option %s.", o->option->name);
-}
+ok = c->format == LEX_F_ETHERNET;
 slla_present = true;
 break;
 
 case ND_OPT_PREFIX_INFORMATION:
-if (c->format != LEX_F_IPV6 || !c->masked) {
-lexer_error(ctx->lexer, "parse_put_nd_ra_opts -Invalid value "
-"for the option %s.", o->option->name);
-}
+ok = c->format == LEX_F_IPV6 && c->masked;
 prefix_set = true;
 break;
 
 case ND_OPT_MTU:
-if (c->format != LEX_F_DECIMAL) {
-lexer_error(ctx->lexer, "parse_put_nd_ra_opts -Invalid value "
-"for the option %s.", o->option->name);
-}
+ok = c->format == LEX_F_DECIMAL;
 break;
 }
-}
 
-if (ctx->lexer->error) {
-return;
+if (!ok) {
+lexer_error(ctx->lexer, "Invalid value for \"%s\" option",
+o->option->name);
+return;
+}
 }
 
 if (!slla_present) {
-lexer_error(ctx->lexer, "parse_put_nd_ra_opts - slla option not"
-" present.");
+lexer_error(ctx->lexer, "slla option not present");
 return;
 }
 
 if (addr_mode_stateful && prefix_set) {
-lexer_error(ctx->lexer, "parse_put_nd_ra_opts - prefix option can't be"
+lexer_error(ctx->lexer, "prefix option can't be"
 " set when address mode is dhcpv6_stateful.");
 return;
 }
 
 if (!addr_mode_stateful && !prefix_set) {
-lexer_error(ctx->lexer, "parse_put_nd_ra_opts - prefix option needs "
+lexer_error(ctx->lexer, "prefix option needs "
 "to be set when address mode is slaac/dhcpv6_stateless.");
 return;
 }
diff --git a/tests/ovn.at b/tests/ovn.at
index 320ec4bb2b72..93515aa329d1 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -1083,25 +1083,25 @@ reg1[0] = put_nd_ra_opts(addr_mode = 
"dhcpv6_stateless", slla = ae:01:02:03:04:0
 encodes as 
controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.40.ff.ff.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.06.03.04.40.c0.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00,pause)
 has prereqs ip6
 reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix = aef0::/64);
-parse_put_nd_ra_opts - slla option not present.
+slla option not present
 reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", mtu = 1450, prefix = 
aef0::/64, prefix = bef0::/64, slla = ae:01:02:03:04:10);
-parse_put_nd_ra_opts - prefix option can't be set when address mode is 
dhcpv6_statefu

[ovs-dev] [PATCH v10 2/4] ovn-controller: Add a new action - 'put_nd_ra_opts'

2017-11-01 Thread nusiddiq
From: Numan Siddique 

This patch adds a new OVN action 'put_nd_ra_opts' to support native
IPv6 Router Advertisement in OVN. This action can be used to respond
to the IPv6 Router Solicitation requests.

ovn-controller parses this action and adds a NXT_PACKET_IN2 OF flow
with 'pause' flag set and the RA options stored in 'userdata' field.
This action is similar to 'put_dhcp_opts' and 'put_dhcpv6_opts'.

When a valid IPv6 RS packet is received by the pinctrl module of
ovn-controller, it frames a new RA packet and sets the RA options
from the 'userdata' field and resumes the packet storing 1 in the
1-bit result sub-field. If the packet is invalid, it resumes the
packet without any modifications storing 0 in the 1-bit result
sub-field.

Eg. reg0[5] = put_nd_ra_opts(address_mode = "slaac", mtu = 1450,
 slla = 01:02:03:04:05:06, prefix = aef0::/64)

Note that unlike DHCPv4/v6, a new table to store the supported IPv6 ND RA
options is not added in SB DB since there are only 3 ND RA options.

Co-authored-by: Zongkai LI 
Signed-off-by: Zongkai LI 
Signed-off-by: Numan Siddique 
---
 include/ovn/actions.h |  14 +++-
 ovn/controller/lflow.c|  13 +++-
 ovn/controller/pinctrl.c  |  96 +++
 ovn/lib/actions.c | 194 +-
 ovn/lib/ovn-l7.h  |  48 
 ovn/ovn-sb.xml|  77 ++
 ovn/utilities/ovn-trace.c |  51 
 tests/ovn.at  |  31 
 tests/test-ovn.c  |  13 +++-
 9 files changed, 516 insertions(+), 21 deletions(-)

diff --git a/include/ovn/actions.h b/include/ovn/actions.h
index d13a3747b..15cee478d 100644
--- a/include/ovn/actions.h
+++ b/include/ovn/actions.h
@@ -72,7 +72,8 @@ struct simap;
 OVNACT(PUT_DHCPV6_OPTS,   ovnact_put_opts)\
 OVNACT(SET_QUEUE, ovnact_set_queue)   \
 OVNACT(DNS_LOOKUP,ovnact_dns_lookup)  \
-OVNACT(LOG,   ovnact_log)
+OVNACT(LOG,   ovnact_log) \
+OVNACT(PUT_ND_RA_OPTS,ovnact_put_opts)
 
 /* enum ovnact_type, with a member OVNACT_ for each action. */
 enum OVS_PACKED_ENUM ovnact_type {
@@ -418,6 +419,14 @@ enum action_opcode {
  *   - A variable length string containing the name.
  */
 ACTION_OPCODE_LOG,
+
+/* "result = put_nd_ra_opts(option, ...)".
+ * Arguments follow the action_header, in this format:
+ *   - A 32-bit or 64-bit OXM header designating the result field.
+ *   - A 32-bit integer specifying a bit offset within the result field.
+ *   - Any number of ICMPv6 options.
+ */
+ACTION_OPCODE_PUT_ND_RA_OPTS,
 };
 
 /* Header. */
@@ -438,6 +447,9 @@ struct ovnact_parse_params {
 /* hmap of 'struct gen_opts_map'  to support 'put_dhcpv6_opts' action */
 const struct hmap *dhcpv6_opts;
 
+/* hmap of 'struct gen_opts_map' to support 'put_nd_ra_opts' action */
+const struct hmap *nd_ra_opts;
+
 /* Each OVN flow exists in a logical table within a logical pipeline.
  * These parameters express this context for a set of OVN actions being
  * parsed:
diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c
index 6b6b91abc..a62ec6ebe 100644
--- a/ovn/controller/lflow.c
+++ b/ovn/controller/lflow.c
@@ -65,6 +65,7 @@ static void consider_logical_flow(struct controller_ctx *ctx,
   const struct sbrec_chassis *chassis,
   struct hmap *dhcp_opts,
   struct hmap *dhcpv6_opts,
+  struct hmap *nd_ra_opts,
   uint32_t *conj_id_ofs,
   const struct shash *addr_sets,
   struct hmap *flow_table,
@@ -167,17 +168,21 @@ add_logical_flows(struct controller_ctx *ctx,
 dhcpv6_opt_row->type);
 }
 
+struct hmap nd_ra_opts = HMAP_INITIALIZER(&nd_ra_opts);
+nd_ra_opts_init(&nd_ra_opts);
+
 SBREC_LOGICAL_FLOW_FOR_EACH (lflow, ctx->ovnsb_idl) {
 consider_logical_flow(ctx, chassis_index,
   lflow, local_datapaths,
   group_table, chassis,
-  &dhcp_opts, &dhcpv6_opts, &conj_id_ofs,
-  addr_sets, flow_table, active_tunnels,
-  local_lport_ids);
+  &dhcp_opts, &dhcpv6_opts, &nd_ra_opts,
+  &conj_id_ofs, addr_sets, flow_table,
+  active_tunnels, local_lport_ids);
 }
 
 dhcp_opts_destroy(&dhcp_opts);
 dhcp_opts_destroy(&dhcpv6_opts);
+nd_ra_opts_destroy(&nd_ra_opts);
 }
 
 static void
@@ -189,6 +194,7 @@ consider_logical_flow(struct controller_ctx *ctx,
   const struct sbrec_chassis *chassis,
   struct hmap *dhcp_opts,
   str