> On 10 Aug 2026, at 7:01 PM, Dumitru Ceara <[email protected]> wrote:
> 
> !-------------------------------------------------------------------|
>  CAUTION: External Email
> 
> |-------------------------------------------------------------------!
> 
> On 8/4/26 4:31 AM, Naveen Yerramneni wrote:
>> This commit introduces two NF-related logical actions, nf_learn_orig_inport()
>> and nf_lookup_orig_inport(), used to store and retrieve a packet's original
>> ingress port.  These actions will be used by northd to identify and drop
>> post-NF loopback copies in logical pipeline stages.
>> 
>>  - "nf_learn_orig_inport(ipv6 = true|false)" installs a learned flow in
>>    a new OFTABLE_NF_ORIG_INPORT_LEARN table.  The learned flow is keyed
>>    on the logical datapath and the IP source and destination addresses
>>    and matches future packets whose logical output port equals the
>>    logical input port of the packet that created it, i.e. packets that
>>    are about to be sent back out of the port they entered on.  Matching
>>    packets get MLF_POST_NF_LOOP_BACK set.  The learned flow has a 30s idle
>>    timeout.
>> 
>>  - "R = nf_lookup_orig_inport()" resubmits to the learn table and stores
>>    the result of the lookup (MLF_POST_NF_LOOP_BACK) into the 1-bit field R.
>> 
> 
> Hi Naveen,

Hi Dumitru,

> 
> Thanks for the new version!

Thanks for the review!

>> Signed-off-by: Naveen Yerramneni <[email protected]>
>> Acked-by: Aditya Mehakare <[email protected]>
>> CC: Sragdhara Datta Chaudhuri <[email protected]>
>> Assisted-by: Claude Opus 4.7, Cursor
> Actually, being pedantic, your Signed-off-by should be the last tag in
> the commit message, it indicates that you "agree to the Developer's
> Certificate of Origin" (as mentioned in our docs in
> submitting-patches.rst) for the whole patch, including the AI-assisted
> changes.

Ack. Will address this and other comments in this patch.

> 
>> ---
>> controller/lflow.h           |   1 +
>> include/ovn/actions.h        |  14 +++
>> include/ovn/logical-fields.h |   4 +
>> lib/actions.c                | 190 +++++++++++++++++++++++++++++++++++
>> lib/ovn-util.c               |   2 +-
>> ovn-sb.xml                   |  57 +++++++++++
>> tests/ovn-macros.at          |   1 +
>> tests/ovn.at                 |  19 ++++
>> utilities/ovn-trace.c        |  18 ++++
>> 9 files changed, 305 insertions(+), 1 deletion(-)
>> 
>> diff --git a/controller/lflow.h b/controller/lflow.h
>> index c211fe195..fa206392f 100644
>> --- a/controller/lflow.h
>> +++ b/controller/lflow.h
>> @@ -105,6 +105,7 @@ struct uuid;
>> #define OFTABLE_GET_REMOTE_FDB            111
>> #define OFTABLE_LEARN_REMOTE_FDB          112
>> #define OFTABLE_EVPN_ARP_LOOKUP           113
>> +#define OFTABLE_NF_ORIG_INPORT_LEARN    114
> 
> Nit: alignment.
> 
>> 
>> /* Verify that table regions do not overlap. */
>> BUILD_ASSERT_DECL(OFTABLE_LOG_INGRESS_PIPELINE + LOG_PIPELINE_INGRESS_LEN
>> diff --git a/include/ovn/actions.h b/include/ovn/actions.h
>> index 2b81f3f05..6a394b16b 100644
>> --- a/include/ovn/actions.h
>> +++ b/include/ovn/actions.h
>> @@ -140,6 +140,8 @@ struct collector_set_ids;
>>     OVNACT(CT_STATE_SAVE,     ovnact_result)          \
>>     OVNACT(MIRROR,            ovnact_mirror)          \
>>     OVNACT(CHK_EVPN_ARP,      ovnact_chk_evpn_arp)    \
>> +    OVNACT(NF_LEARN_ORIG_INPORT,  ovnact_nf_learn)  \
>> +    OVNACT(NF_LOOKUP_ORIG_INPORT, ovnact_nf_lookup) \
> 
> Nit: indentation of \.
> 
>> 
>> /* enum ovnact_type, with a member OVNACT_<ENUM> for each action. */
>> enum OVS_PACKED_ENUM ovnact_type {
>> @@ -513,6 +515,18 @@ struct ovnact_lookup_fdb {
>>     struct expr_field dst;     /* 1-bit destination field. */
>> };
>> 
>> +/* OVNACT_NF_LEARN_ORIG_INPORT. */
>> +struct ovnact_nf_learn {
>> +    struct ovnact ovnact;
>> +    bool ipv6;
>> +};
>> +
>> +/* OVNACT_NF_LOOKUP_ORIG_INPORT. */
>> +struct ovnact_nf_lookup {
>> +    struct ovnact ovnact;
>> +    struct expr_field dst;     /* 1-bit destination field. */
>> +};
>> +
>> /* OVNACT_SAMPLE */
>> struct ovnact_sample {
>>     struct ovnact ovnact;
>> diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h
>> index 9694d105f..e95dee316 100644
>> --- a/include/ovn/logical-fields.h
>> +++ b/include/ovn/logical-fields.h
>> @@ -140,6 +140,7 @@ enum mff_log_flags_bits {
>>     MLF_PKT_SAMPLED_BIT = 23,
>>     MLF_RECIRC_BIT = 24,
>>     MLF_EVPN_LOOKUP_BIT = 25,
>> +    MLF_POST_NF_LOOP_BACK_BIT = 26,
>>     MLF_NETWORK_ID_START_BIT = 28,
>>     MLF_NETWORK_ID_END_BIT = 31,
>> };
>> @@ -219,6 +220,9 @@ enum mff_log_flags {
>>     /* Indicate that the lookup in the EVPN ARP table was successful. */
>>     MLF_EVPN_LOOKUP = (1 << MLF_EVPN_LOOKUP_BIT),
>> 
>> +    /* Set on a post-NF packet going back to the original ingress port. */
>> +    MLF_POST_NF_LOOP_BACK = (1 << MLF_POST_NF_LOOP_BACK_BIT),
>> +
>>     /* Assign network ID to packet to choose correct network for snat when
>>      * lb_force_snat_ip=router_ip. */
>>     MLF_NETWORK_ID = (OVN_MAX_NETWORK_ID << MLF_NETWORK_ID_START_BIT),
>> diff --git a/lib/actions.c b/lib/actions.c
>> index 93d7aefd2..0cdfc5efe 100644
>> --- a/lib/actions.c
>> +++ b/lib/actions.c
>> @@ -4717,6 +4717,189 @@ ovnact_lookup_fdb_free(struct ovnact_lookup_fdb 
>> *get_fdb OVS_UNUSED)
>> {
>> }
>> 
>> +static void
>> +format_NF_LEARN_ORIG_INPORT(const struct ovnact_nf_learn *nf_learn,
>> +                              struct ds *s)
> 
> Nit: alignment.
> 
>> +{
>> +    ds_put_format(s, "nf_learn_orig_inport(ipv6 = %s);",
>> +                  nf_learn->ipv6 ? "true" : "false");
>> +}
>> +
>> +/* Idle timeout, in seconds, of the flow installed by
>> + * nf_learn_orig_inport(). */
>> +#define NF_LEARN_ORIG_INPORT_IDLE_TIMEOUT_S 30
>> +
>> +/* Adds a NXAST_LEARN spec matching the value of field 'id' (as it is in the
>> + * packet that triggers the learn) on the same field of future packets. */
>> +static void
>> +nf_learn_put_match_field(struct ofpbuf *ofpacts, enum mf_field_id id)
>> +{
>> +    struct ofpact_learn_spec *ol_spec =
>> +        ofpbuf_put_zeros(ofpacts, sizeof *ol_spec);
>> +    ol_spec->dst.field = mf_from_id(id);
>> +    ol_spec->dst.ofs = 0;
>> +    ol_spec->dst.n_bits = ol_spec->dst.field->n_bits;
>> +    ol_spec->n_bits = ol_spec->dst.n_bits;
>> +    ol_spec->dst_type = NX_LEARN_DST_MATCH;
>> +    ol_spec->src_type = NX_LEARN_SRC_FIELD;
>> +    ol_spec->src.field = mf_from_id(id);
>> +}
>> +
>> +static void
>> +encode_NF_LEARN_ORIG_INPORT(const struct ovnact_nf_learn *nf_learn,
>> +                              const struct ovnact_encode_params *ep,
>> +                              struct ofpbuf *ofpacts)
> 
> Nit: alignment.
> 
>> +{
>> +    size_t ol_offset = ofpacts->size;
>> +    struct ofpact_learn *ol = ofpact_put_LEARN(ofpacts);
>> +    struct match match = MATCH_CATCHALL_INITIALIZER;
>> +    struct ofpact_learn_spec *ol_spec;
>> +    unsigned int imm_bytes;
>> +    uint8_t *src_imm;
>> +
>> +    ol->flags = NX_LEARN_F_DELETE_LEARNED;
>> +    ol->idle_timeout = NF_LEARN_ORIG_INPORT_IDLE_TIMEOUT_S;
>> +    ol->hard_timeout = OFP_FLOW_PERMANENT;
>> +    ol->priority = OFP_DEFAULT_PRIORITY;
>> +    ol->table_id = OFTABLE_NF_ORIG_INPORT_LEARN;
>> +    ol->cookie = htonll(ep->lflow_uuid.parts[0]);
>> +
>> +    /* Match on the logical datapath. */
>> +    nf_learn_put_match_field(ofpacts, MFF_METADATA);
>> +
>> +    /* Match on the same ETH type as the packet that created the flow. */
>> +    ol_spec = ofpbuf_put_zeros(ofpacts, sizeof *ol_spec);
>> +    ol_spec->dst.field = mf_from_id(MFF_ETH_TYPE);
>> +    ol_spec->dst.ofs = 0;
>> +    ol_spec->dst.n_bits = ol_spec->dst.field->n_bits;
>> +    ol_spec->n_bits = ol_spec->dst.n_bits;
>> +    ol_spec->dst_type = NX_LEARN_DST_MATCH;
>> +    ol_spec->src_type = NX_LEARN_SRC_IMMEDIATE;
>> +    union mf_value imm_eth_type = {
>> +        .be16 = nf_learn->ipv6 ? htons(ETH_TYPE_IPV6) : htons(ETH_TYPE_IP)
>> +    };
>> +    mf_write_subfield_value(&ol_spec->dst, &imm_eth_type, &match);
>> +    /* Push value last, as this may reallocate 'ol_spec'. */
>> +    imm_bytes = DIV_ROUND_UP(ol_spec->dst.n_bits, 8);
>> +    src_imm = ofpbuf_put_zeros(ofpacts, OFPACT_ALIGN(imm_bytes));
>> +    memcpy(src_imm, &imm_eth_type, imm_bytes);
>> +
>> +    /* Match on the IP source and destination addresses. */
>> +    nf_learn_put_match_field(ofpacts,
>> +                             nf_learn->ipv6 ? MFF_IPV6_SRC : MFF_IPV4_SRC);
>> +    nf_learn_put_match_field(ofpacts,
>> +                             nf_learn->ipv6 ? MFF_IPV6_DST : MFF_IPV4_DST);
>> +
>> +    /* Match future packets whose logical output port equals the logical
>> +     * input port of the packet that created this flow. */
>> +    ol_spec = ofpbuf_put_zeros(ofpacts, sizeof *ol_spec);
>> +    ol_spec->dst.field = mf_from_id(MFF_LOG_OUTPORT);
>> +    ol_spec->dst.ofs = 0;
>> +    ol_spec->dst.n_bits = ol_spec->dst.field->n_bits;
>> +    ol_spec->n_bits = ol_spec->dst.n_bits;
>> +    ol_spec->dst_type = NX_LEARN_DST_MATCH;
>> +    ol_spec->src_type = NX_LEARN_SRC_FIELD;
>> +    ol_spec->src.field = mf_from_id(MFF_LOG_INPORT);
>> +
>> +    /* Set MLF_POST_NF_LOOP_BACK on matching packets. */
>> +    ol_spec = ofpbuf_put_zeros(ofpacts, sizeof *ol_spec);
>> +    ol_spec->dst.field = mf_from_id(MFF_LOG_FLAGS);
>> +    ol_spec->dst.ofs = MLF_POST_NF_LOOP_BACK_BIT;
>> +    ol_spec->dst.n_bits = 1;
>> +    ol_spec->n_bits = ol_spec->dst.n_bits;
>> +    ol_spec->dst_type = NX_LEARN_DST_LOAD;
>> +    ol_spec->src_type = NX_LEARN_SRC_IMMEDIATE;
>> +    union mf_value imm_hit = { .u8 = 1 };
>> +    mf_write_subfield_value(&ol_spec->dst, &imm_hit, &match);
>> +    /* Push value last, as this may reallocate 'ol_spec'. */
>> +    imm_bytes = DIV_ROUND_UP(ol_spec->dst.n_bits, 8);
>> +    src_imm = ofpbuf_put_zeros(ofpacts, OFPACT_ALIGN(imm_bytes));
>> +    memcpy(src_imm, &imm_hit, imm_bytes);
>> +
>> +    ol = ofpbuf_at_assert(ofpacts, ol_offset, sizeof *ol);
>> +    ofpact_finish_LEARN(ofpacts, &ol);
>> +}
>> +
>> +static void
>> +parse_nf_learn_orig_inport(struct action_context *ctx,
>> +                             struct ovnact_nf_learn *nf_learn)
> 
> Nit: alignment.
> 
>> +{
>> +    lexer_force_match(ctx->lexer, LEX_T_LPAREN);
>> +    if (!lexer_match_id(ctx->lexer, "ipv6")) {
>> +        lexer_syntax_error(ctx->lexer, "invalid parameter");
>> +        return;
>> +    }
>> +    if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) {
>> +        return;
>> +    }
>> +    if (lexer_match_id(ctx->lexer, "true")) {
>> +        nf_learn->ipv6 = true;
>> +    } else if (lexer_match_id(ctx->lexer, "false")) {
>> +        nf_learn->ipv6 = false;
>> +    } else {
>> +        lexer_syntax_error(ctx->lexer, "expecting true or false");
>> +        return;
>> +    }
>> +    lexer_force_match(ctx->lexer, LEX_T_RPAREN);
>> +}
>> +
>> +static void
>> +ovnact_nf_learn_free(struct ovnact_nf_learn *nf_learn OVS_UNUSED)
>> +{
>> +}
>> +
>> +static void
>> +format_NF_LOOKUP_ORIG_INPORT(const struct ovnact_nf_lookup *nf_lookup,
>> +                               struct ds *s)
> 
> Nit: alignment.
> 
>> +{
>> +    expr_field_format(&nf_lookup->dst, s);
>> +    ds_put_cstr(s, " = nf_lookup_orig_inport();");
>> +}
>> +
>> +static void
>> +encode_NF_LOOKUP_ORIG_INPORT(
>> +    const struct ovnact_nf_lookup *nf_lookup,
>> +    const struct ovnact_encode_params *ep OVS_UNUSED,
>> +    struct ofpbuf *ofpacts)
>> +{
>> +    struct mf_subfield dst = expr_resolve_field(&nf_lookup->dst);
>> +    ovs_assert(dst.field);
>> +
>> +    put_load(0, MFF_LOG_FLAGS, MLF_POST_NF_LOOP_BACK_BIT, 1, ofpacts);
>> +    emit_resubmit(ofpacts, OFTABLE_NF_ORIG_INPORT_LEARN);
>> +
>> +    struct ofpact_reg_move *orm = ofpact_put_REG_MOVE(ofpacts);
>> +    orm->dst = dst;
>> +    orm->src.field = mf_from_id(MFF_LOG_FLAGS);
>> +    orm->src.ofs = MLF_POST_NF_LOOP_BACK_BIT;
>> +    orm->src.n_bits = 1;
>> +}
>> +
>> +static void
>> +parse_nf_lookup_orig_inport(struct action_context *ctx,
>> +                              struct expr_field *dst,
>> +                              struct ovnact_nf_lookup *nf_lookup)
> 
> Nit: alignment.
> 
>> +{
>> +    lexer_get(ctx->lexer);  /* Skip nf_lookup_orig_inport. */
>> +    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;
>> +    }
>> +    nf_lookup->dst = *dst;
>> +
>> +    lexer_force_match(ctx->lexer, LEX_T_RPAREN);
>> +}
>> +
>> +static void
>> +ovnact_nf_lookup_free(struct ovnact_nf_lookup *nf_lookup OVS_UNUSED)
>> +{
>> +}
>> +
>> static void
>> parse_check_in_port_sec(struct action_context *ctx,
>>                         const struct expr_field *dst,
>> @@ -5976,6 +6159,10 @@ parse_set_action(struct action_context *ctx)
>>                    && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) {
>>             parse_lookup_fdb(
>>                 ctx, &lhs, ovnact_put_LOOKUP_FDB(ctx->ovnacts));
>> +        } else if (!strcmp(ctx->lexer->token.s, "nf_lookup_orig_inport")
>> +                   && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) {
>> +            parse_nf_lookup_orig_inport(
>> +                ctx, &lhs, ovnact_put_NF_LOOKUP_ORIG_INPORT(ctx->ovnacts));
>>         } else if (!strcmp(ctx->lexer->token.s, "check_in_port_sec")
>>                    && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) {
>>             parse_check_in_port_sec(
>> @@ -6147,6 +6334,9 @@ parse_action(struct action_context *ctx)
>>         ovnact_put_FLOOD_REMOTE(ctx->ovnacts);
>>     } else if (lexer_match_id(ctx->lexer, "mirror")) {
>>         parse_MIRROR_action(ctx);
>> +    } else if (lexer_match_id(ctx->lexer, "nf_learn_orig_inport")) {
>> +        parse_nf_learn_orig_inport(
>> +            ctx, ovnact_put_NF_LEARN_ORIG_INPORT(ctx->ovnacts));
>>     } else {
>>         lexer_syntax_error(ctx->lexer, "expecting action");
>>     }
>> diff --git a/lib/ovn-util.c b/lib/ovn-util.c
>> index d9b78fbb6..35e085d99 100644
>> --- a/lib/ovn-util.c
>> +++ b/lib/ovn-util.c
>> @@ -1007,7 +1007,7 @@ ip_address_and_port_from_lb_key(const char *key, char 
>> **ip_address,
>>  *
>>  * NOTE: If OVN_NORTHD_PIPELINE_CSUM is updated make sure to double check
>>  * whether an update of OVN_INTERNAL_MINOR_VER is required. */
>> -#define OVN_NORTHD_PIPELINE_CSUM "118971668 11318"
>> +#define OVN_NORTHD_PIPELINE_CSUM "849109292 11426"
>> #define OVN_INTERNAL_MINOR_VER 15
> 
> This needs to be bumped too, see submitting-patches.rst.
> 
>> 
>> /* Returns the OVN version. The caller must free the returned value. */
>> diff --git a/ovn-sb.xml b/ovn-sb.xml
>> index e403eb360..a6c8b6c76 100644
>> --- a/ovn-sb.xml
>> +++ b/ovn-sb.xml
>> @@ -1832,6 +1832,63 @@
>>           </p>
>>         </dd>
>> 
>> +        <dt>
>> +          <code>nf_learn_orig_inport(ipv6 = <var>B</var>);</code>
>> +        </dt>
>> +
>> +        <dd>
>> +          <p>
>> +            Records the logical input port that the current IP packet
>> +            entered the logical switch on by learning a flow.  The learned
>> +            flow matches a later packet of the same flow (same logical
>> +            datapath and IP source and destination addresses) when its
>> +            logical output port equals that input port, that is, when the
>> +            packet is about to be sent back out of the port it originally
>> +            arrived on.
>> +          </p>
>> +
>> +          <p>
>> +            <var>B</var> must be <code>true</code> to learn an IPv6 flow or
>> +            <code>false</code> to learn an IPv4 flow.  The learned flow has 
>> a
>> +            30 second idle timeout.  This action is used together with
>> +            <code>nf_lookup_orig_inport()</code> to drop the duplicate
>> +            copies that a network function (NF) redirection can produce when
>> +            the destination MAC address is still unknown, which would
>> +            otherwise cause MAC address flaps or L2 loops.
>> +          </p>
>> +
>> +          <p>
>> +            <b>Example:</b>
>> +            <code>nf_learn_orig_inport(ipv6 = false);</code>
>> +          </p>
>> +        </dd>
>> +
>> +        <dt>
>> +          <code><var>R</var> = nf_lookup_orig_inport();</code>
>> +        </dt>
>> +
>> +        <dd>
>> +          <p>
>> +            <b>Result</b>: stored to a 1-bit subfield <var>R</var>.
>> +          </p>
>> +
>> +          <p>
>> +            Looks up the flow learned by
>> +            <code>nf_learn_orig_inport()</code>.  Stores <code>1</code> in
>> +            <var>R</var> if the current packet matches a learned flow, that 
>> is,
>> +            if it is an IP packet that, after network function redirection, 
>> is
>> +            about to be sent back out of the logical input port it 
>> originally
>> +            arrived on.  Otherwise stores <code>0</code>.
>> +          </p>
>> +
>> +          <p>
>> +            <b>Example:</b>
>> +            <code>
>> +              reg0[0] = nf_lookup_orig_inport();
>> +            </code>
>> +          </p>
>> +        </dd>
>> +
>>         <dt><code>nd_ns { <var>action</var>; </code>...<code> };</code></dt>
>>         <dd>
>>           <p>
>> diff --git a/tests/ovn-macros.at b/tests/ovn-macros.at
>> index ab14b65c6..2a1faf677 100644
>> --- a/tests/ovn-macros.at
>> +++ b/tests/ovn-macros.at
>> @@ -1655,5 +1655,6 @@ m4_define([OFTABLE_CT_ORIG_PROTO_LOAD], [110])
>> m4_define([OFTABLE_GET_REMOTE_FDB], [111])
>> m4_define([OFTABLE_LEARN_REMOTE_FDB], [112])
>> m4_define([OFTABLE_EVPN_ARP_LOOKUP], [113])
>> +m4_define([OFTABLE_NF_ORIG_INPORT_LEARN], [114])
>> 
>> m4_define([OFTABLE_SAVE_INPORT_HEX], [m4_eval(OFTABLE_SAVE_INPORT, 16)])
>> diff --git a/tests/ovn.at b/tests/ovn.at
>> index a88ea9650..47bf5f4ec 100644
>> --- a/tests/ovn.at
>> +++ b/tests/ovn.at
>> @@ -2129,6 +2129,25 @@ reg1[[1]] = lookup_fdb(outport, ip4.src);
>> reg1[[1]] = lookup_fdb(ip4.src, eth.src);
>>     Cannot use numeric field ip4.src where string field is required.
>> 
>> +# nf_learn_orig_inport / nf_lookup_orig_inport
>> +nf_learn_orig_inport(ipv6 = false);
>> +    encodes as 
>> learn(table=OFTABLE_NF_ORIG_INPORT_LEARN,idle_timeout=30,delete_learned,cookie=0xaaaaaaaa,OXM_OF_METADATA[[]],eth_type=0x800,NXM_OF_IP_SRC[[]],NXM_OF_IP_DST[[]],NXM_NX_REG15[[]]=NXM_NX_REG14[[0..-1]],load:0x1->NXM_NX_REG10[[26]])
>> +
>> +nf_learn_orig_inport(ipv6 = true);
>> +    encodes as 
>> learn(table=OFTABLE_NF_ORIG_INPORT_LEARN,idle_timeout=30,delete_learned,cookie=0xaaaaaaaa,OXM_OF_METADATA[[]],eth_type=0x86dd,NXM_NX_IPV6_SRC[[]],NXM_NX_IPV6_DST[[]],NXM_NX_REG15[[]]=NXM_NX_REG14[[0..-1]],load:0x1->NXM_NX_REG10[[26]])
>> +
>> +nf_learn_orig_inport();
>> +    Syntax error at `)' invalid parameter.
>> +
>> +nf_learn_orig_inport(ipv6 = maybe);
>> +    Syntax error at `maybe' expecting true or false.
>> +
>> +reg0[[0]] = nf_lookup_orig_inport();
>> +    encodes as 
>> set_field:0/0x4000000->reg10,resubmit(,OFTABLE_NF_ORIG_INPORT_LEARN),move:NXM_NX_REG10[[26]]->NXM_NX_XXREG0[[96]]
>> +
>> +reg0 = nf_lookup_orig_inport();
>> +    Cannot use 32-bit field reg0[[0..31]] where 1-bit field is required.
>> +
>> # check_in_port_sec
>> reg0[[0]] = check_in_port_sec();
>>     encodes as 
>> set_field:0/0x1000->reg10,resubmit(,OFTABLE_CHK_IN_PORT_SEC),move:NXM_NX_REG10[[12]]->NXM_NX_XXREG0[[96]]
>> diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c
>> index 0dcee89ac..535cbe9b5 100644
>> --- a/utilities/ovn-trace.c
>> +++ b/utilities/ovn-trace.c
>> @@ -3216,6 +3216,17 @@ execute_ct_save_state(const struct ovnact_result *dl, 
>> struct flow *uflow,
>>     ds_destroy(&s);
>> }
>> 
>> +static void
>> +execute_nf_lookup_orig_inport(const struct ovnact_nf_lookup *nf_lookup,
>> +                                struct flow *uflow, struct ovs_list *super)
> 
> Nit: alignment.
> 
>> +{
>> +    struct mf_subfield dst = expr_resolve_field(&nf_lookup->dst);
>> +    union mf_subvalue sv = { .u8_val = 0 };
>> +    mf_write_subfield_flow(&dst, &sv, uflow);
>> +    ovntrace_node_append(super, OVNTRACE_NODE_ACTION,
>> +                         "/* Assumed nf_lookup_orig_inport miss. */");
>> +}
>> +
>> static void
>> execute_ct_orig_tp_dst(const struct ovnact_result *res, struct flow *uflow,
>>                        struct ovs_list *super)
>> @@ -3641,6 +3652,13 @@ trace_actions(const struct ovnact *ovnacts, size_t 
>> ovnacts_len,
>>             execute_chk_evpn_arp(ovnact_get_CHK_EVPN_ARP(a), dp, uflow,
>>                                  super);
>>             break;
>> +        case OVNACT_NF_LEARN_ORIG_INPORT:
>> +            /* Nothing to do for tracing. */
>> +            break;
>> +        case OVNACT_NF_LOOKUP_ORIG_INPORT:
>> +            execute_nf_lookup_orig_inport(
>> +                ovnact_get_NF_LOOKUP_ORIG_INPORT(a), uflow, super);
>> +            break;
>>         }
>>     }
>>     ofpbuf_uninit(&stack);
> 
> Regards,
> Dumitru

Thanks,
Naveen


_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to