On Wed, Apr 24, 2024 at 5:56 AM Naveen Yerramneni <
naveen.yerramn...@nutanix.com> wrote:

> NEW OVN ACTIONS
> ---------------
>   1. dhcp_relay_req_chk(<relay-ip>, <server-ip>)
>        - This action executes on the source node on which the DHCP request
> originated.
>        - This action relays the DHCP request coming from client to the
> server.
>          Relay-ip is used to update GIADDR in the DHCP header.
>   2. dhcp_relay_resp_chk(<relay-ip>, <server-ip>)
>        - This action executes on the first node (RC node) which processes
>          the DHCP response from the server.
>        - This action updates  the destination MAC and destination IP so
> that the response
>          can be forwarded to the appropriate node from which request was
> originated.
>        - Relay-ip, server-ip are used to validate GIADDR and SERVER ID in
> the DHCP payload.
>
> Signed-off-by: Naveen Yerramneni <naveen.yerramn...@nutanix.com>
>

Thanks.

I applied this patch to main with the below changes.  Changes are mostly
cosmetic.

----------------------------------------------------------------------------
diff --git a/include/ovn/actions.h b/include/ovn/actions.h
index b30cb96b29..ae0864fdd7 100644
--- a/include/ovn/actions.h
+++ b/include/ovn/actions.h
@@ -396,7 +396,6 @@ struct ovnact_put_opts {
 /* OVNACT_DHCP_RELAY. */
 struct ovnact_dhcp_relay {
     struct ovnact ovnact;
-    int family;
     struct expr_field dst;      /* 1-bit destination field. */
     ovs_be32 relay_ipv4;
     ovs_be32 server_ipv4;
diff --git a/lib/actions.c b/lib/actions.c
index 940209a7b7..94751d0597 100644
--- a/lib/actions.c
+++ b/lib/actions.c
@@ -2692,12 +2692,10 @@ parse_dhcp_relay_chk(struct action_context *ctx,

     /* Parse relay ip and server ip. */
     if (ctx->lexer->token.format == LEX_F_IPV4) {
-        dhcp_relay->family = AF_INET;
         dhcp_relay->relay_ipv4 = ctx->lexer->token.value.ipv4;
         lexer_get(ctx->lexer);
         lexer_match(ctx->lexer, LEX_T_COMMA);
         if (ctx->lexer->token.format == LEX_F_IPV4) {
-            dhcp_relay->family = AF_INET;
             dhcp_relay->server_ipv4 = ctx->lexer->token.value.ipv4;
             lexer_get(ctx->lexer);
         } else {
@@ -2706,7 +2704,7 @@ parse_dhcp_relay_chk(struct action_context *ctx,
         }
     } else {
         lexer_syntax_error(ctx->lexer, "expecting IPv4 dhcp relay "
-            "and server ips");
+                           "and server ips");
         return;
     }
     lexer_force_match(ctx->lexer, LEX_T_RPAREN);
@@ -2726,9 +2724,9 @@ encode_dhcpv4_relay_chk(const struct
ovnact_dhcp_relay *dhcp_relay,
     ovs_be32 ofs = htonl(dst.ofs);
     ofpbuf_put(ofpacts, &ofs, sizeof ofs);
     ofpbuf_put(ofpacts, &dhcp_relay->relay_ipv4,
-        sizeof(dhcp_relay->relay_ipv4));
+               sizeof(dhcp_relay->relay_ipv4));
     ofpbuf_put(ofpacts, &dhcp_relay->server_ipv4,
-        sizeof(dhcp_relay->server_ipv4));
+               sizeof(dhcp_relay->server_ipv4));
     encode_finish_controller_op(oc_offset, ofpacts);
 }

@@ -2736,7 +2734,7 @@ static void
 format_DHCPV4_RELAY_REQ_CHK(const struct ovnact_dhcp_relay *dhcp_relay,
                             struct ds *s)
 {
-    format_dhcpv4_relay_chk("dhcp_relay_req_chk",dhcp_relay, s);
+    format_dhcpv4_relay_chk("dhcp_relay_req_chk", dhcp_relay, s);
 }

 static void
@@ -2752,7 +2750,7 @@ static void
 format_DHCPV4_RELAY_RESP_CHK(const struct ovnact_dhcp_relay *dhcp_relay,
                              struct ds *s)
 {
-    format_dhcpv4_relay_chk("dhcp_relay_resp_chk",dhcp_relay, s);
+    format_dhcpv4_relay_chk("dhcp_relay_resp_chk", dhcp_relay, s);
 }

 static void
@@ -2764,8 +2762,7 @@ encode_DHCPV4_RELAY_RESP_CHK(const struct
ovnact_dhcp_relay *dhcp_relay,
                             ACTION_OPCODE_DHCP_RELAY_RESP_CHK);
 }

-static void ovnact_dhcp_relay_free(
-          struct ovnact_dhcp_relay *dhcp_relay OVS_UNUSED)
+static void ovnact_dhcp_relay_free(struct ovnact_dhcp_relay *dr OVS_UNUSED)
 {
 }

@@ -5472,11 +5469,11 @@ parse_set_action(struct action_context *ctx)
             parse_chk_lb_aff(ctx, &lhs,
                     ovnact_put_CHK_LB_AFF(ctx->ovnacts));
         } else if (lexer_match_id(ctx->lexer, "dhcp_relay_req_chk")) {
-            parse_dhcp_relay_chk(ctx, &lhs,
-                ovnact_put_DHCPV4_RELAY_REQ_CHK(ctx->ovnacts));
+            parse_dhcp_relay_chk(
+                ctx, &lhs, ovnact_put_DHCPV4_RELAY_REQ_CHK(ctx->ovnacts));
         } else if (lexer_match_id(ctx->lexer, "dhcp_relay_resp_chk")) {
-            parse_dhcp_relay_chk(ctx, &lhs,
-                ovnact_put_DHCPV4_RELAY_RESP_CHK(ctx->ovnacts));
+            parse_dhcp_relay_chk(
+                ctx, &lhs, ovnact_put_DHCPV4_RELAY_RESP_CHK(ctx->ovnacts));
         } else {
             parse_assignment_action(ctx, false, &lhs);
         }
diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c
index 49b2ab9545..13a4ea490a 100644
--- a/utilities/ovn-trace.c
+++ b/utilities/ovn-trace.c
@@ -2360,9 +2360,9 @@ execute_dhcpv4_relay_resp_chk(const struct
ovnact_dhcp_relay *dr,
     ovntrace_node_append(
         super, OVNTRACE_NODE_ERROR,
         "/* We assume that this packet is DHCPOFFER or DHCPACK and "
-            "DHCP broadcast flag is set. Dest IP is set to broadcast. "
-            "Dest MAC is set to broadcast but in real network this is
unicast "
-            "which is extracted from DHCP header. */");
+        "DHCP broadcast flag is set. Dest IP is set to broadcast. "
+        "Dest MAC is set to broadcast but in real network this is unicast "
+        "which is extracted from DHCP header. */");

     /* Assume DHCP broadcast flag is set */
     uflow->nw_dst = htonl(0xFFFFFFFF);
----------------------------------------------------------------------------

Numan

---
>  include/ovn/actions.h |  27 ++++++++++
>  lib/actions.c         | 116 ++++++++++++++++++++++++++++++++++++++++++
>  ovn-sb.xml            |  62 ++++++++++++++++++++++
>  tests/ovn.at          |  34 +++++++++++++
>  utilities/ovn-trace.c |  67 ++++++++++++++++++++++++
>  5 files changed, 306 insertions(+)
>
> diff --git a/include/ovn/actions.h b/include/ovn/actions.h
> index f697dff39..ab2f3856c 100644
> --- a/include/ovn/actions.h
> +++ b/include/ovn/actions.h
> @@ -96,6 +96,8 @@ struct collector_set_ids;
>      OVNACT(LOOKUP_ND_IP,      ovnact_lookup_mac_bind_ip) \
>      OVNACT(PUT_DHCPV4_OPTS,   ovnact_put_opts)        \
>      OVNACT(PUT_DHCPV6_OPTS,   ovnact_put_opts)        \
> +    OVNACT(DHCPV4_RELAY_REQ_CHK,  ovnact_dhcp_relay)      \
> +    OVNACT(DHCPV4_RELAY_RESP_CHK, ovnact_dhcp_relay)      \
>      OVNACT(SET_QUEUE,         ovnact_set_queue)       \
>      OVNACT(DNS_LOOKUP,        ovnact_result)          \
>      OVNACT(LOG,               ovnact_log)             \
> @@ -389,6 +391,15 @@ struct ovnact_put_opts {
>      size_t n_options;
>  };
>
> +/* OVNACT_DHCP_RELAY. */
> +struct ovnact_dhcp_relay {
> +    struct ovnact ovnact;
> +    int family;
> +    struct expr_field dst;      /* 1-bit destination field. */
> +    ovs_be32 relay_ipv4;
> +    ovs_be32 server_ipv4;
> +};
> +
>  /* Valid arguments to SET_QUEUE action.
>   *
>   * QDISC_MIN_QUEUE_ID is the default queue, so user-defined queues should
> @@ -765,6 +776,22 @@ enum action_opcode {
>
>      /* multicast group split buffer action. */
>      ACTION_OPCODE_MG_SPLIT_BUF,
> +
> +    /* "dhcp_relay_req_chk(relay_ip, server_ip)".
> +     *
> +     * Arguments follow the action_header, in this format:
> +     *   - The 32-bit DHCP relay IP.
> +     *   - The 32-bit DHCP server IP.
> +     */
> +    ACTION_OPCODE_DHCP_RELAY_REQ_CHK,
> +
> +    /* "dhcp_relay_resp_chk(relay_ip, server_ip)".
> +     *
> +     * Arguments follow the action_header, in this format:
> +     *   - The 32-bit DHCP relay IP.
> +     *   - The 32-bit DHCP server IP.
> +     */
> +    ACTION_OPCODE_DHCP_RELAY_RESP_CHK,
>  };
>
>  /* Header. */
> diff --git a/lib/actions.c b/lib/actions.c
> index 361d55009..6cd60366a 100644
> --- a/lib/actions.c
> +++ b/lib/actions.c
> @@ -1869,6 +1869,8 @@ is_paused_nested_action(enum action_opcode opcode)
>      case ACTION_OPCODE_BFD_MSG:
>      case ACTION_OPCODE_ACTIVATION_STRATEGY_RARP:
>      case ACTION_OPCODE_MG_SPLIT_BUF:
> +    case ACTION_OPCODE_DHCP_RELAY_REQ_CHK:
> +    case ACTION_OPCODE_DHCP_RELAY_RESP_CHK:
>      default:
>          return false;
>      }
> @@ -2610,6 +2612,114 @@ ovnact_controller_event_free(struct
> ovnact_controller_event *event)
>      free_gen_options(event->options, event->n_options);
>  }
>
> +static void
> +format_dhcpv4_relay_chk(const char *name,
> +                        const struct ovnact_dhcp_relay *dhcp_relay,
> +                        struct ds *s)
> +{
> +    expr_field_format(&dhcp_relay->dst, s);
> +    ds_put_format(s, " = %s("IP_FMT", "IP_FMT");",
> +                  name,
> +                  IP_ARGS(dhcp_relay->relay_ipv4),
> +                  IP_ARGS(dhcp_relay->server_ipv4));
> +}
> +
> +static void
> +parse_dhcp_relay_chk(struct action_context *ctx,
> +                     const struct expr_field *dst,
> +                     struct ovnact_dhcp_relay *dhcp_relay)
> +{
> +    /* Skip dhcp_relay_req_chk/dhcp_relay_resp_chk( */
> +    lexer_force_match(ctx->lexer, LEX_T_LPAREN);
> +
> +    /* Validate that the destination is a 1-bit, modifiable field. */
> +    char *error = expr_type_check(dst, 1, true, ctx->scope);
> +    if (error) {
> +        lexer_error(ctx->lexer, "%s", error);
> +        free(error);
> +        return;
> +    }
> +    dhcp_relay->dst = *dst;
> +
> +    /* Parse relay ip and server ip. */
> +    if (ctx->lexer->token.format == LEX_F_IPV4) {
> +        dhcp_relay->family = AF_INET;
> +        dhcp_relay->relay_ipv4 = ctx->lexer->token.value.ipv4;
> +        lexer_get(ctx->lexer);
> +        lexer_match(ctx->lexer, LEX_T_COMMA);
> +        if (ctx->lexer->token.format == LEX_F_IPV4) {
> +            dhcp_relay->family = AF_INET;
> +            dhcp_relay->server_ipv4 = ctx->lexer->token.value.ipv4;
> +            lexer_get(ctx->lexer);
> +        } else {
> +            lexer_syntax_error(ctx->lexer, "expecting IPv4 dhcp server
> ip");
> +            return;
> +        }
> +    } else {
> +        lexer_syntax_error(ctx->lexer, "expecting IPv4 dhcp relay "
> +            "and server ips");
> +        return;
> +    }
> +    lexer_force_match(ctx->lexer, LEX_T_RPAREN);
> +}
> +
> +static void
> +encode_dhcpv4_relay_chk(const struct ovnact_dhcp_relay *dhcp_relay,
> +                        const struct ovnact_encode_params *ep,
> +                        struct ofpbuf *ofpacts,
> +                        enum action_opcode dhcp_relay_opcode)
> +{
> +    struct mf_subfield dst = expr_resolve_field(&dhcp_relay->dst);
> +    size_t oc_offset = encode_start_controller_op(dhcp_relay_opcode, true,
> +                                                  ep->ctrl_meter_id,
> +                                                  ofpacts);
> +    nx_put_header(ofpacts, dst.field->id, OFP15_VERSION, false);
> +    ovs_be32 ofs = htonl(dst.ofs);
> +    ofpbuf_put(ofpacts, &ofs, sizeof ofs);
> +    ofpbuf_put(ofpacts, &dhcp_relay->relay_ipv4,
> +        sizeof(dhcp_relay->relay_ipv4));
> +    ofpbuf_put(ofpacts, &dhcp_relay->server_ipv4,
> +        sizeof(dhcp_relay->server_ipv4));
> +    encode_finish_controller_op(oc_offset, ofpacts);
> +}
> +
> +static void
> +format_DHCPV4_RELAY_REQ_CHK(const struct ovnact_dhcp_relay *dhcp_relay,
> +                            struct ds *s)
> +{
> +    format_dhcpv4_relay_chk("dhcp_relay_req_chk",dhcp_relay, s);
> +}
> +
> +static void
> +encode_DHCPV4_RELAY_REQ_CHK(const struct ovnact_dhcp_relay *dhcp_relay,
> +                            const struct ovnact_encode_params *ep,
> +                            struct ofpbuf *ofpacts)
> +{
> +    encode_dhcpv4_relay_chk(dhcp_relay, ep, ofpacts,
> +                            ACTION_OPCODE_DHCP_RELAY_REQ_CHK);
> +}
> +
> +static void
> +format_DHCPV4_RELAY_RESP_CHK(const struct ovnact_dhcp_relay *dhcp_relay,
> +                             struct ds *s)
> +{
> +    format_dhcpv4_relay_chk("dhcp_relay_resp_chk",dhcp_relay, s);
> +}
> +
> +static void
> +encode_DHCPV4_RELAY_RESP_CHK(const struct ovnact_dhcp_relay *dhcp_relay,
> +                             const struct ovnact_encode_params *ep,
> +                             struct ofpbuf *ofpacts)
> +{
> +    encode_dhcpv4_relay_chk(dhcp_relay, ep, ofpacts,
> +                            ACTION_OPCODE_DHCP_RELAY_RESP_CHK);
> +}
> +
> +static void ovnact_dhcp_relay_free(
> +          struct ovnact_dhcp_relay *dhcp_relay OVS_UNUSED)
> +{
> +}
> +
>  static void
>  parse_put_opts(struct action_context *ctx, const struct expr_field *dst,
>                 struct ovnact_put_opts *po, const struct hmap *gen_opts,
> @@ -5312,6 +5422,12 @@ parse_set_action(struct action_context *ctx)
>                     lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) {
>              parse_chk_lb_aff(ctx, &lhs,
>                      ovnact_put_CHK_LB_AFF(ctx->ovnacts));
> +        } else if (lexer_match_id(ctx->lexer, "dhcp_relay_req_chk")) {
> +            parse_dhcp_relay_chk(ctx, &lhs,
> +                ovnact_put_DHCPV4_RELAY_REQ_CHK(ctx->ovnacts));
> +        } else if (lexer_match_id(ctx->lexer, "dhcp_relay_resp_chk")) {
> +            parse_dhcp_relay_chk(ctx, &lhs,
> +                ovnact_put_DHCPV4_RELAY_RESP_CHK(ctx->ovnacts));
>          } else {
>              parse_assignment_action(ctx, false, &lhs);
>          }
> diff --git a/ovn-sb.xml b/ovn-sb.xml
> index 4c26c6714..81ed824d0 100644
> --- a/ovn-sb.xml
> +++ b/ovn-sb.xml
> @@ -2801,6 +2801,68 @@ tcp.flags = RST;
>              use statistics of MAC cache.
>            </p>
>          </dd>
> +
> +        <dt><code><var>R</var> = dhcp_relay_req_chk(<var>relay-ip</var>,
> +                                      <var>server-ip</var>);</code></dt>
> +        <dd>
> +          <p>
> +            <b>Parameters</b>: Logical Router Port IP
> <var>relay-ip</var>, DHCP
> +            Server IP <var>server-ip</var>.
> +          </p>
> +
> +          <p>
> +            <b>Result</b>: stored to a 1-bit subfield <var>R</var>.
> +          </p>
> +
> +          <p>
> +            This action executes on the source node on which the DHCP
> request
> +            (DHCPDISCOVER or DHCPREQUEST) originated.
> +          </p>
> +
> +          <p>
> +            When this action applied successfully on the DHCP request
> packet,
> +            it updates GIADDR in the DHCP packet with <var>relay-ip</var>
> and
> +            stores 1 in R.
> +          </p>
> +
> +          <p>
> +            When this action failed to apply on the packet, it leaves the
> +            packet unchanged and stores 0 in R.
> +          </p>
> +        </dd>
> +
> +        <dt><code><var>R</var> = dhcp_relay_resp_chk(<var>relay-ip</var>,
> +                                      <var>server-ip</var>);</code></dt>
> +        <dd>
> +          <p>
> +            <b>Parameters</b>: Logical Router Port IP
> <var>relay-ip</var>, DHCP
> +            Server IP <var>server-ip</var>.
> +          </p>
> +
> +          <p>
> +            <b>Result</b>: stored to a 1-bit subfield <var>R</var>.
> +          </p>
> +
> +          <p>
> +            This action executes on the first node (Redirect Chassis node)
> +            which processes the DHCP response(DHCPOFFER, DHCPACK) from
> the DHCP
> +            server.
> +          </p>
> +
> +          <p>
> +            When this action applied successfully on the DHCP response
> packet,
> +            it updates the destination MAC and destination IP in the
> packet and
> +            stores 1 in R.
> +            <var>relay-ip</var> and <var>server-ip</var> are used to
> validate
> +            GIADDR and SERVER-ID in the DHCP response packet.
> +          </p>
> +
> +          <p>
> +            When this action failed to apply on the packet, it leaves the
> +            packet unchanged and stores 0 in R.
> +          </p>
> +        </dd>
> +
>        </dl>
>      </column>
>
> diff --git a/tests/ovn.at b/tests/ovn.at
> index dc6aafd53..1ad4159cf 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -1653,6 +1653,40 @@ reg1[[0]] = put_dhcp_opts(offerip=1.2.3.4,
> domain_name=1.2.3.4);
>  reg1[[0]] = put_dhcp_opts(offerip=1.2.3.4, domain_search_list=1.2.3.4);
>      DHCPv4 option domain_search_list requires string value.
>
> +#dhcp_relay_req_chk
> +reg9[[7]] = dhcp_relay_req_chk(192.168.1.1, 172.16.1.1);
> +    encodes as
> controller(userdata=00.00.00.1c.00.00.00.00.80.01.08.08.00.00.00.07.c0.a8.01.01.ac.10.01.01,pause)
> +
> +reg9[[7]] = dhcp_relay_req_chk(192.168.1.1,172.16.1.1);
> +    formats as reg9[[7]] = dhcp_relay_req_chk(192.168.1.1, 172.16.1.1);
> +    encodes as
> controller(userdata=00.00.00.1c.00.00.00.00.80.01.08.08.00.00.00.07.c0.a8.01.01.ac.10.01.01,pause)
> +
> +reg9[[7..8]] = dhcp_relay_req_chk(192.168.1.1, 172.16.1.1);
> +    Cannot use 2-bit field reg9[[7..8]] where 1-bit field is required.
> +
> +reg9[[7]] = dhcp_relay_req_chk("192.168.1.1", "172.16.1.1");
> +    Syntax error at `"192.168.1.1"' expecting IPv4 dhcp relay and server
> ips.
> +
> +reg9[[7]] = dhcp_relay_req_chk(192.168.1, 172.16.1.1);
> +    Invalid numeric constant.
> +
> +#dhcp_relay_resp_chk
> +reg9[[8]] = dhcp_relay_resp_chk(192.168.1.1, 172.16.1.1);
> +    encodes as
> controller(userdata=00.00.00.1d.00.00.00.00.80.01.08.08.00.00.00.08.c0.a8.01.01.ac.10.01.01,pause)
> +
> +reg9[[8]] = dhcp_relay_resp_chk(192.168.1.1,172.16.1.1);
> +    formats as reg9[[8]] = dhcp_relay_resp_chk(192.168.1.1, 172.16.1.1);
> +    encodes as
> controller(userdata=00.00.00.1d.00.00.00.00.80.01.08.08.00.00.00.08.c0.a8.01.01.ac.10.01.01,pause)
> +
> +reg9[[7..8]] = dhcp_relay_resp_chk(192.168.1.1, 172.16.1.1);
> +    Cannot use 2-bit field reg9[[7..8]] where 1-bit field is required.
> +
> +reg9[[8]] = dhcp_relay_resp_chk("192.168.1.1", "172.16.1.1");
> +    Syntax error at `"192.168.1.1"' expecting IPv4 dhcp relay and server
> ips.
> +
> +reg9[[8]] = dhcp_relay_resp_chk(192.168.1, 172.16.1.1);
> +    Invalid numeric constant.
> +
>  # nd_ns
>  nd_ns { nd.target = xxreg0; output; };
>      encodes as controller(userdata=00.00.00.09.00.00.00.00.00.1c.00.18.00.
> 80.00.00.00.00.00.00.00.01.de
> .10.80.00.3e.10.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.OFTABLE_SAVE_INPORT_HEX.00.00.00,pause)
> diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c
> index ee086a7ae..0103253e1 100644
> --- a/utilities/ovn-trace.c
> +++ b/utilities/ovn-trace.c
> @@ -2329,6 +2329,63 @@ execute_put_dhcp_opts(const struct ovnact_put_opts
> *pdo,
>      execute_put_opts(pdo, name, uflow, super);
>  }
>
> +static void
> +execute_dhcpv4_relay_req_chk(const struct ovnact_dhcp_relay *dr,
> +                             struct flow *uflow, struct ovs_list *super)
> +{
> +    ovntrace_node_append(
> +        super, OVNTRACE_NODE_ERROR,
> +        "/* We assume that this packet is DHCPDISCOVER or DHCPREQUEST.
> */");
> +
> +    struct ds s = DS_EMPTY_INITIALIZER;
> +    struct mf_subfield dst = expr_resolve_field(&dr->dst);
> +    if (!mf_is_register(dst.field->id)) {
> +        /* Format assignment. */
> +        ds_clear(&s);
> +        expr_field_format(&dr->dst, &s);
> +        ovntrace_node_append(super, OVNTRACE_NODE_MODIFY,
> +                             "%s = 1", ds_cstr(&s));
> +    }
> +    ds_destroy(&s);
> +
> +    struct mf_subfield sf = expr_resolve_field(&dr->dst);
> +    union mf_subvalue sv = { .u8_val = 1 };
> +    mf_write_subfield_flow(&sf, &sv, uflow);
> +}
> +
> +static void
> +execute_dhcpv4_relay_resp_chk(const struct ovnact_dhcp_relay *dr,
> +                              struct flow *uflow, struct ovs_list *super)
> +{
> +    ovntrace_node_append(
> +        super, OVNTRACE_NODE_ERROR,
> +        "/* We assume that this packet is DHCPOFFER or DHCPACK and "
> +            "DHCP broadcast flag is set. Dest IP is set to broadcast. "
> +            "Dest MAC is set to broadcast but in real network this is
> unicast "
> +            "which is extracted from DHCP header. */");
> +
> +    /* Assume DHCP broadcast flag is set */
> +    uflow->nw_dst = htonl(0xFFFFFFFF);
> +    /* Dest MAC is set to broadcast but in real network this is unicast */
> +    struct eth_addr bcast_mac = { .ea = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF}};
> +    uflow->dl_dst = bcast_mac;
> +
> +    struct ds s = DS_EMPTY_INITIALIZER;
> +    struct mf_subfield dst = expr_resolve_field(&dr->dst);
> +    if (!mf_is_register(dst.field->id)) {
> +        /* Format assignment. */
> +        ds_clear(&s);
> +        expr_field_format(&dr->dst, &s);
> +        ovntrace_node_append(super, OVNTRACE_NODE_MODIFY,
> +                             "%s = 1", ds_cstr(&s));
> +    }
> +    ds_destroy(&s);
> +
> +    struct mf_subfield sf = expr_resolve_field(&dr->dst);
> +    union mf_subvalue sv = { .u8_val = 1 };
> +    mf_write_subfield_flow(&sf, &sv, uflow);
> +}
> +
>  static void
>  execute_put_nd_ra_opts(const struct ovnact_put_opts *pdo,
>                         const char *name, struct flow *uflow,
> @@ -3215,6 +3272,16 @@ trace_actions(const struct ovnact *ovnacts, size_t
> ovnacts_len,
>                                    "put_dhcpv6_opts", uflow, super);
>              break;
>
> +        case OVNACT_DHCPV4_RELAY_REQ_CHK:
> +
> execute_dhcpv4_relay_req_chk(ovnact_get_DHCPV4_RELAY_REQ_CHK(a),
> +                                         uflow, super);
> +            break;
> +
> +        case OVNACT_DHCPV4_RELAY_RESP_CHK:
> +
> execute_dhcpv4_relay_resp_chk(ovnact_get_DHCPV4_RELAY_RESP_CHK(a),
> +                                          uflow, super);
> +            break;
> +
>          case OVNACT_PUT_ND_RA_OPTS:
>              execute_put_nd_ra_opts(ovnact_get_PUT_DHCPV6_OPTS(a),
>                                     "put_nd_ra_opts", uflow, super);
> --
> 2.36.6
>
> _______________________________________________
> dev mailing list
> d...@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
>
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to