This patch avoids explict push/pop actions surrounding ct_xxx actions,
which also unifies and simplifies the intermediate register usage in
those actions.

Signed-off-by: Han Zhou <hz...@ovn.org>
---
 controller/physical.c        | 32 +++++++--------
 include/ovn/logical-fields.h | 19 ++++-----
 lib/actions.c                | 78 +++++++++++++++++++++++++++++++++---
 northd/northd.c              | 19 +++------
 northd/ovn-northd.8.xml      | 15 +++----
 tests/ovn-northd.at          | 28 -------------
 tests/ovn.at                 | 31 ++++++++++++--
 7 files changed, 134 insertions(+), 88 deletions(-)

diff --git a/controller/physical.c b/controller/physical.c
index 9ec7d4d69333..15209318badb 100644
--- a/controller/physical.c
+++ b/controller/physical.c
@@ -3042,67 +3042,67 @@ physical_run(struct physical_ctx *p_ctx,
     ofpbuf_clear(&ofpacts);
 
     /* Add the flows:
-     * match = (ct.trk && ct.est), action = (reg8 = ct_tp_dst)
+     * match = (ct.trk && ct.est), action = (<reg_result> = ct_tp_dst)
      * table = 83
-     * match = (ct.trk && ct.new), action = (reg8 = ct_tp_dst)
+     * match = (ct.trk && ct.new), action = (<reg_result> = ct_tp_dst)
      * table = 83
      */
     match_set_ct_state_masked(&match, ct_state_est, ct_state_est);
-    put_move(MFF_CT_TP_DST, 0,  MFF_LOG_CT_ORIG_TP_DST_PORT, 0, 16, &ofpacts);
+    put_move(MFF_CT_TP_DST, 0,  MFF_LOG_RESULT_REG, 0, 16, &ofpacts);
     ofctrl_add_flow(flow_table, OFTABLE_CT_ORIG_TP_DST_LOAD, 100, 0, &match,
                     &ofpacts, hc_uuid);
 
     match_set_ct_state_masked(&match_new, ct_state_new, ct_state_new);
-    put_move(MFF_CT_TP_DST, 0,  MFF_LOG_CT_ORIG_TP_DST_PORT, 0, 16, &ofpacts);
+    put_move(MFF_CT_TP_DST, 0,  MFF_LOG_RESULT_REG, 0, 16, &ofpacts);
     ofctrl_add_flow(flow_table, OFTABLE_CT_ORIG_TP_DST_LOAD, 100, 0,
                     &match_new, &ofpacts, hc_uuid);
 
     /* Add the flows:
-     * match = (ct.trk && ct.est), action = (reg3[0..7] = ct_proto)
+     * match = (ct.trk && ct.est), action = (<reg_result> = ct_proto)
      * table = 86
-     * match = (ct.trk && ct.new), action = (reg3[0..7] = ct_proto)
+     * match = (ct.trk && ct.new), action = (<reg_result> = ct_proto)
      * table = 86
      */
      ofpbuf_clear(&ofpacts);
-     put_move(MFF_CT_NW_PROTO, 0,  MFF_LOG_CT_ORIG_PROTO, 0, 8, &ofpacts);
+     put_move(MFF_CT_NW_PROTO, 0,  MFF_LOG_RESULT_REG, 0, 8, &ofpacts);
      ofctrl_add_flow(flow_table, OFTABLE_CT_ORIG_PROTO_LOAD, 100, 0, &match,
                      &ofpacts, hc_uuid);
 
-     put_move(MFF_CT_NW_PROTO, 0,  MFF_LOG_CT_ORIG_PROTO, 0, 8, &ofpacts);
+     put_move(MFF_CT_NW_PROTO, 0,  MFF_LOG_RESULT_REG, 0, 8, &ofpacts);
      ofctrl_add_flow(flow_table, OFTABLE_CT_ORIG_PROTO_LOAD, 100, 0,
                      &match_new, &ofpacts, hc_uuid);
     /* Add the flows:
-     * match = (ct.trk && ct.est && ip4), action = (reg4 = ct_nw_dst)
+     * match = (ct.trk && ct.est && ip4), action = (<reg_result> = ct_nw_dst)
      * table = 81
-     * match = (ct.trk && ct.new && ip4), action = (reg4 = ct_nw_dst)
+     * match = (ct.trk && ct.new && ip4), action = (<reg_result> = ct_nw_dst)
      * table = 81
      */
     ofpbuf_clear(&ofpacts);
     match_set_dl_type(&match, htons(ETH_TYPE_IP));
-    put_move(MFF_CT_NW_DST, 0,  MFF_LOG_CT_ORIG_NW_DST_ADDR, 0, 32, &ofpacts);
+    put_move(MFF_CT_NW_DST, 0,  MFF_LOG_RESULT_REG, 0, 32, &ofpacts);
     ofctrl_add_flow(flow_table, OFTABLE_CT_ORIG_NW_DST_LOAD, 100, 0, &match,
                     &ofpacts, hc_uuid);
 
     match_set_dl_type(&match_new, htons(ETH_TYPE_IP));
-    put_move(MFF_CT_NW_DST, 0,  MFF_LOG_CT_ORIG_NW_DST_ADDR, 0, 32, &ofpacts);
+    put_move(MFF_CT_NW_DST, 0,  MFF_LOG_RESULT_REG, 0, 32, &ofpacts);
     ofctrl_add_flow(flow_table, OFTABLE_CT_ORIG_NW_DST_LOAD, 100, 0,
                     &match_new, &ofpacts, hc_uuid);
 
     /* Add the flows:
-     * match = (ct.trk && ct.est && ip6), action = (xxreg0 = ct_ip6_dst)
+     * match = (ct.trk && ct.est && ip6), action = (<reg_result> = ct_ip6_dst)
      * table = 82
-     * match = (ct.trk && ct.new && ip6), action = (xxreg0 = ct_ip6_dst)
+     * match = (ct.trk && ct.new && ip6), action = (<reg_result> = ct_ip6_dst)
      * table = 82
      */
     ofpbuf_clear(&ofpacts);
     match_set_dl_type(&match, htons(ETH_TYPE_IPV6));
-    put_move(MFF_CT_IPV6_DST, 0,  MFF_LOG_CT_ORIG_IP6_DST_ADDR, 0,
+    put_move(MFF_CT_IPV6_DST, 0,  MFF_LOG_RESULT_REG, 0,
              128, &ofpacts);
     ofctrl_add_flow(flow_table, OFTABLE_CT_ORIG_IP6_DST_LOAD, 100, 0, &match,
                     &ofpacts, hc_uuid);
 
     match_set_dl_type(&match_new, htons(ETH_TYPE_IPV6));
-    put_move(MFF_CT_IPV6_DST, 0,  MFF_LOG_CT_ORIG_IP6_DST_ADDR, 0,
+    put_move(MFF_CT_IPV6_DST, 0,  MFF_LOG_RESULT_REG, 0,
              128, &ofpacts);
     ofctrl_add_flow(flow_table, OFTABLE_CT_ORIG_IP6_DST_LOAD, 100, 0,
                     &match_new, &ofpacts, hc_uuid);
diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h
index 1130ee8d201d..8b1c1221e200 100644
--- a/include/ovn/logical-fields.h
+++ b/include/ovn/logical-fields.h
@@ -55,18 +55,13 @@ enum ovn_controller_event {
 
 #define MFF_N_LOG_REGS 10
 
-#define MFF_LOG_LB_AFF_MATCH_IP4_ADDR       MFF_REG4
-#define MFF_LOG_LB_AFF_MATCH_IP6_ADDR       MFF_XXREG1
-#define MFF_LOG_LB_AFF_MATCH_PORT           MFF_REG2
-
-#define MFF_LOG_CT_ORIG_NW_DST_ADDR         MFF_REG4   /* REG_LB_IPV4 */
-#define MFF_LOG_CT_ORIG_IP6_DST_ADDR        MFF_XXREG1 /* REG_LB_IPV6 */
-#define MFF_LOG_CT_ORIG_TP_DST_PORT         MFF_REG2   /* Used by
-                                                        * ct_tp_dst() */
-#define MFF_LOG_CT_ORIG_PROTO               MFF_REG3   /* Used by
-                                                        * ct_proto() */
-#define MFF_LOG_CT_SAVED_STATE              MFF_REG4   /* REG_CT_STATE
-                                                        * (bits 0..8). */
+#define MFF_LOG_LB_AFF_MATCH_IP4_ADDR MFF_REG4
+#define MFF_LOG_LB_AFF_MATCH_IP6_ADDR MFF_XXREG1
+#define MFF_LOG_LB_AFF_MATCH_PORT     MFF_REG2
+
+#define MFF_LOG_RESULT_REG            MFF_XXREG1
+
+#define MFF_LOG_CT_SAVED_STATE        MFF_REG4
 
 /* Logical registers that are needed for backwards
  * compatibility with older northd versions.
diff --git a/lib/actions.c b/lib/actions.c
index 41fd17522c6c..fa8aa20c273c 100644
--- a/lib/actions.c
+++ b/lib/actions.c
@@ -5445,13 +5445,60 @@ encode_MAC_CACHE_USE(const struct ovnact_null *null 
OVS_UNUSED,
     emit_resubmit(ofpacts, ep->mac_cache_use_table);
 }
 
+static bool
+encode_save_temp_reg(const struct ovnact_result *res,
+                     enum mf_field_id field_id, int ofs, int n_bits,
+                     struct ofpbuf *ofpacts)
+{
+    struct mf_subfield res_dst = expr_resolve_field(&res->dst);
+
+    if (res_dst.field->id == field_id) {
+        /* Check if the bits are the same */
+        if (res_dst.ofs == ofs && res_dst.n_bits == n_bits) {
+            return false;
+        } else {
+            /* Assert that the bits are non-overlapping */
+            ovs_assert(res_dst.ofs + res_dst.n_bits <= ofs ||
+                       ofs + n_bits <= res_dst.ofs);
+        }
+    }
+
+    struct ofpact_stack *push = ofpact_put_STACK_PUSH(ofpacts);
+    push->subfield = (struct mf_subfield) {
+        .field = mf_from_id(field_id),
+        .ofs = ofs,
+        .n_bits = n_bits
+    };
+
+    return true;
+}
+
+static void
+encode_restore_temp_reg(enum mf_field_id field_id, int ofs, int n_bits,
+                        struct ofpbuf *ofpacts)
+{
+    struct ofpact_stack *pop = ofpact_put_STACK_POP(ofpacts);
+    pop->subfield = (struct mf_subfield) {
+        .field = mf_from_id(field_id),
+        .ofs = ofs,
+        .n_bits = n_bits
+    };
+}
+
 static void
 encode_CT_ORIG_NW_DST(const struct ovnact_result *res,
                       const struct ovnact_encode_params *ep,
                       struct ofpbuf *ofpacts)
 {
+    bool protect_result_reg = encode_save_temp_reg(res, MFF_LOG_RESULT_REG, 0,
+                                                   32, ofpacts);
+
     encode_result_action___(res, ep->ct_nw_dst_load_table,
-                            MFF_LOG_CT_ORIG_NW_DST_ADDR, 0, 32, ofpacts);
+                            MFF_LOG_RESULT_REG, 0, 32, ofpacts);
+
+    if (protect_result_reg) {
+        encode_restore_temp_reg(MFF_LOG_RESULT_REG, 0, 32, ofpacts);
+    }
 }
 
 static void
@@ -5473,8 +5520,15 @@ encode_CT_ORIG_IP6_DST(const struct ovnact_result *res,
                        const struct ovnact_encode_params *ep,
                        struct ofpbuf *ofpacts)
 {
+    bool protect_reg = encode_save_temp_reg(res, MFF_LOG_RESULT_REG, 0, 128,
+                                            ofpacts);
+
     encode_result_action___(res, ep->ct_ip6_dst_load_table,
-                            MFF_LOG_CT_ORIG_IP6_DST_ADDR, 0, 128, ofpacts);
+                            MFF_LOG_RESULT_REG, 0, 128, ofpacts);
+
+    if (protect_reg) {
+        encode_restore_temp_reg(MFF_LOG_RESULT_REG, 0, 128, ofpacts);
+    }
 }
 
 static void
@@ -5493,11 +5547,18 @@ format_CT_ORIG_IP6_DST(const struct ovnact_result *res, 
struct ds *s)
 
 static void
 encode_CT_ORIG_TP_DST(const struct ovnact_result *res,
-                      const struct ovnact_encode_params *ep OVS_UNUSED,
+                      const struct ovnact_encode_params *ep,
                       struct ofpbuf *ofpacts)
 {
+    bool protect_reg = encode_save_temp_reg(res, MFF_LOG_RESULT_REG, 0, 16,
+                                            ofpacts);
+
     encode_result_action___(res, ep->ct_tp_dst_load_table,
-                            MFF_LOG_CT_ORIG_TP_DST_PORT, 0, 16, ofpacts);
+                            MFF_LOG_RESULT_REG, 0, 16, ofpacts);
+
+    if (protect_reg) {
+        encode_restore_temp_reg(MFF_LOG_RESULT_REG, 0, 16, ofpacts);
+    }
 }
 
 static void
@@ -5519,8 +5580,15 @@ encode_CT_ORIG_PROTO(const struct ovnact_result *res,
                      const struct ovnact_encode_params *ep,
                      struct ofpbuf *ofpacts)
 {
+    bool protect_reg = encode_save_temp_reg(res, MFF_LOG_RESULT_REG, 0, 8,
+                                            ofpacts);
+
     encode_result_action___(res, ep->ct_proto_load_table,
-                            MFF_LOG_CT_ORIG_PROTO, 0, 8, ofpacts);
+                            MFF_LOG_RESULT_REG, 0, 8, ofpacts);
+
+    if (protect_reg) {
+        encode_restore_temp_reg(MFF_LOG_RESULT_REG, 0, 8, ofpacts);
+    }
 }
 
 static void
diff --git a/northd/northd.c b/northd/northd.c
index 44c9b7721b7e..a7c7e267f090 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -16653,17 +16653,12 @@ build_lrouter_in_ct_extract_flows(struct lflow_table 
*lflows,
                                          const struct ovn_datapath *od,
                                          struct lflow_ref *lflow_ref)
 {
-    /* Ingress PRE_LB table: Extract connection tracking fields for new
-     * connections.
-     * XXX: use a more graceful way to push/pop reg2 and reg3 which are used
-     * as intermediate registers by the ct_proto() and ct_tp_dst() actions.
-     */
+    /* Ingress CT_EXTRACT table: Extract connection tracking fields for new
+     * connections. */
     ovn_lflow_add(lflows, od, S_ROUTER_IN_CT_EXTRACT, 100,
                   "ct.new && ip",
-                  "push(reg2); push(reg3); "
                   REG_CT_PROTO " = ct_proto(); "
-                  REG_CT_TP_DST " = ct_tp_dst(); "
-                  "pop(reg3); pop(reg2); next;",
+                  REG_CT_TP_DST " = ct_tp_dst(); next;",
                   lflow_ref);
 }
 
@@ -17947,16 +17942,12 @@ build_ls_stateful_flows(const struct 
ls_stateful_record *ls_stateful_rec,
                sbrec_acl_id_table);
 
     /* Build CT extraction flows - only needed if this datapath has load
-     * balancers.
-     * XXX: use a more graceful way to push/pop reg2 and reg3 which are used
-     * as intermediate registers by the ct_proto() and ct_tp_dst() actions.*/
+     * balancers. */
     if (ls_stateful_rec->has_lb_vip) {
         ovn_lflow_add(lflows, od, S_SWITCH_IN_CT_EXTRACT, 100,
                       "ct.new && ip",
-                      "push(reg2); push(reg3); "
                       REG_CT_PROTO " = ct_proto(); "
-                      REG_CT_TP_DST " = ct_tp_dst(); "
-                      "pop(reg3); pop(reg2); next;",
+                      REG_CT_TP_DST " = ct_tp_dst(); next;",
                       ls_stateful_rec->lflow_ref);
     }
 
diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
index e673c31c14d3..460a481d9af3 100644
--- a/northd/ovn-northd.8.xml
+++ b/northd/ovn-northd.8.xml
@@ -1046,8 +1046,7 @@
         extracts connection tracking protocol and destination port information
         into registers <code>reg1[16..23]</code> (protocol) and
         <code>reg1[0..15]</code> (destination port) using the actions
-        <code>push(reg2); push(reg3); reg1[16..23] = ct_proto();
-        reg1[0..15] = ct_tp_dst(); pop(reg3); pop(reg2); next;</code>.
+        <code>reg1[16..23] = ct_proto(); reg1[0..15] = ct_tp_dst(); 
next;</code>.
       </li>
 
       <li>
@@ -3873,19 +3872,15 @@ next;
         </p>
 
         <pre>
-push(reg2); push(reg3);
-reg2[0..15] = ct_tp_dst();
-reg3[16..23] = ct_proto();
-pop(reg3); pop(reg2);
+reg1[16..23] = ct_proto();
+reg1[0..15] = ct_tp_dst();
 next;
         </pre>
 
         <p>
           This stores the connection tracking destination port in
-          <code>REG_CT_TP_DST</code> (reg2[0..15]) and the protocol
-          in <code>REG_CT_PROTO</code> (reg3[16..23]). The push/pop
-          operations protect the existing register values from being
-          overwritten.
+          <code>REG_CT_TP_DST</code> (reg1[0..15]) and the protocol
+          in <code>REG_CT_PROTO</code> (reg1[16..23]).
         </p>
       </li>
 
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index b83330c501f8..25e850413a5e 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -3724,12 +3724,8 @@ flow="inport == \"lsp1\" && ${flow_eth} && ${flow_ip} && 
${flow_tcp}"
 ovn_trace --ct new --ct new ls "${flow}"
 AT_CHECK_UNQUOTED([ovn_trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
 ct_lb_mark {
-    push(reg2) -> 0x50;
-    push(reg3) -> 0;
     reg1[[16..23]] = 6;
     reg1[[0..15]] = 80;
-    pop(reg3) <- 0;
-    pop(reg2) <- 0x50;
     ct_lb_mark {
         reg0[[6]] = 0;
         reg0[[12]] = 0;
@@ -3744,12 +3740,8 @@ ct_lb_mark {
 flow="inport == \"lsp1\" && ${flow_eth} && ${flow_ip} && ${flow_udp}"
 AT_CHECK_UNQUOTED([ovn_trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
 ct_lb_mark {
-    push(reg2) -> 0x50;
-    push(reg3) -> 0;
     reg1[[16..23]] = 17;
     reg1[[0..15]] = 80;
-    pop(reg3) <- 0;
-    pop(reg2) <- 0x50;
     ct_lb_mark {
         reg0[[6]] = 0;
         reg0[[12]] = 0;
@@ -3776,12 +3768,8 @@ output("lsp2");
 flow="inport == \"lsp1\" && ${flow_eth} && ${flow_ip} && ${flow_udp}"
 AT_CHECK_UNQUOTED([ovn_trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
 ct_lb_mark {
-    push(reg2) -> 0x50;
-    push(reg3) -> 0;
     reg1[[16..23]] = 17;
     reg1[[0..15]] = 80;
-    pop(reg3) <- 0;
-    pop(reg2) <- 0x50;
     ct_lb_mark {
         reg0[[6]] = 0;
         reg0[[12]] = 0;
@@ -3878,12 +3866,8 @@ check ovn-nbctl --wait=sb sync
 flow="inport == \"lsp1\" && ${flow_eth} && ${flow_ip} && ${flow_tcp}"
 AT_CHECK_UNQUOTED([ovn_trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
 ct_lb_mark {
-    push(reg2) -> 0x50;
-    push(reg3) -> 0;
     reg1[[16..23]] = 6;
     reg1[[0..15]] = 80;
-    pop(reg3) <- 0;
-    pop(reg2) <- 0x50;
     ct_lb_mark {
         reg0[[6]] = 0;
         reg0[[12]] = 0;
@@ -3898,12 +3882,8 @@ ct_lb_mark {
 flow="inport == \"lsp1\" && ${flow_eth} && ${flow_ip} && ${flow_udp}"
 AT_CHECK_UNQUOTED([ovn_trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
 ct_lb_mark {
-    push(reg2) -> 0x50;
-    push(reg3) -> 0;
     reg1[[16..23]] = 17;
     reg1[[0..15]] = 80;
-    pop(reg3) <- 0;
-    pop(reg2) <- 0x50;
     ct_lb_mark {
         reg0[[6]] = 0;
         reg0[[12]] = 0;
@@ -3930,12 +3910,8 @@ output("lsp2");
 flow="inport == \"lsp1\" && ${flow_eth} && ${flow_ip} && ${flow_udp}"
 AT_CHECK_UNQUOTED([ovn_trace --ct new --ct new --minimal ls "${flow}"], [0], 
[dnl
 ct_lb_mark {
-    push(reg2) -> 0x50;
-    push(reg3) -> 0;
     reg1[[16..23]] = 17;
     reg1[[0..15]] = 80;
-    pop(reg3) <- 0;
-    pop(reg2) <- 0x50;
     ct_lb_mark {
         reg0[[6]] = 0;
         reg0[[12]] = 0;
@@ -7643,12 +7619,8 @@ flow="eth.dst == 00:00:00:00:01:00 && inport == 
\"rtr-ls\" && ip4.src == 42.42.4
 ovn_trace --ct new "${flow}" --lb-dst 42.42.42.42:4242
 AT_CHECK_UNQUOTED([ovn_trace --ct new --minimal "${flow}" --lb-dst 
42.42.42.42:4242], [0], [dnl
 ct_dnat /* assuming no un-dnat entry, so no change */ {
-    push(reg2) -> 0;
-    push(reg3) -> 0;
     reg1[[16..23]] = 6;
     reg1[[0..15]] = 4343;
-    pop(reg3) <- 0;
-    pop(reg2) <- 0;
     ct_lb_mark /* default (use --ct to customize) */ {
         ip.ttl--;
         eth.src = 00:00:00:00:01:00;
diff --git a/tests/ovn.at b/tests/ovn.at
index a47f82b4e13b..b44c4dd086a9 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -2236,10 +2236,16 @@ mac_cache_use;
 
 # ct_nw_dst()
 reg1 = ct_nw_dst();
-    encodes as 
set_field:0->reg4,resubmit(,OFTABLE_CT_ORIG_NW_DST_LOAD),move:NXM_NX_REG4[[]]->NXM_NX_XXREG0[[64..95]]
+    encodes as 
push:NXM_NX_XXREG1[[0..31]],set_field:0/0xffffffff->xxreg1,resubmit(,OFTABLE_CT_ORIG_NW_DST_LOAD),move:NXM_NX_XXREG1[[0..31]]->NXM_NX_XXREG0[[64..95]],pop:NXM_NX_XXREG1[[0..31]]
 
 xreg1[[3..34]] = ct_nw_dst();
-    encodes as 
set_field:0->reg4,resubmit(,OFTABLE_CT_ORIG_NW_DST_LOAD),move:NXM_NX_REG4[[]]->NXM_NX_XXREG0[[3..34]]
+    encodes as 
push:NXM_NX_XXREG1[[0..31]],set_field:0/0xffffffff->xxreg1,resubmit(,OFTABLE_CT_ORIG_NW_DST_LOAD),move:NXM_NX_XXREG1[[0..31]]->NXM_NX_XXREG0[[3..34]],pop:NXM_NX_XXREG1[[0..31]]
+
+reg4 = ct_nw_dst();
+    encodes as 
push:NXM_NX_XXREG1[[0..31]],set_field:0/0xffffffff->xxreg1,resubmit(,OFTABLE_CT_ORIG_NW_DST_LOAD),move:NXM_NX_XXREG1[[0..31]]->NXM_NX_XXREG1[[96..127]],pop:NXM_NX_XXREG1[[0..31]]
+
+reg7 = ct_nw_dst();
+    encodes as 
set_field:0/0xffffffff->xxreg1,resubmit(,OFTABLE_CT_ORIG_NW_DST_LOAD),move:NXM_NX_XXREG1[[0..31]]->NXM_NX_XXREG1[[0..31]]
 
 reg1[[3..34]] = ct_nw_dst();
     Cannot select bits 3 to 34 of 32-bit field reg1.
@@ -2271,7 +2277,10 @@ ct_ip6_dst();
 
 # ct_tp_dst()
 reg1[[0..15]] = ct_tp_dst();
-    encodes as 
set_field:0/0xffff->reg2,resubmit(,OFTABLE_CT_ORIG_TP_DST_LOAD),move:NXM_NX_REG2[[0..15]]->NXM_NX_XXREG0[[64..79]]
+    encodes as 
push:NXM_NX_XXREG1[[0..15]],set_field:0/0xffff->xxreg1,resubmit(,OFTABLE_CT_ORIG_TP_DST_LOAD),move:NXM_NX_XXREG1[[0..15]]->NXM_NX_XXREG0[[64..79]],pop:NXM_NX_XXREG1[[0..15]]
+
+reg4[[0..15]] = ct_tp_dst();
+    encodes as 
push:NXM_NX_XXREG1[[0..15]],set_field:0/0xffff->xxreg1,resubmit(,OFTABLE_CT_ORIG_TP_DST_LOAD),move:NXM_NX_XXREG1[[0..15]]->NXM_NX_XXREG1[[96..111]],pop:NXM_NX_XXREG1[[0..15]]
 
 reg1 = ct_tp_dst();
     Cannot use 32-bit field reg1[[0..31]] where 16-bit field is required.
@@ -2282,6 +2291,22 @@ ct_tp_dst;
 ct_tp_dst();
     Syntax error at `ct_tp_dst' expecting action.
 
+# ct_proto()
+reg1[[16..23]] = ct_proto();
+    encodes as 
push:NXM_NX_XXREG1[[0..7]],set_field:0/0xff->xxreg1,resubmit(,OFTABLE_CT_ORIG_PROTO_LOAD),move:NXM_NX_XXREG1[[0..7]]->NXM_NX_XXREG0[[80..87]],pop:NXM_NX_XXREG1[[0..7]]
+
+reg4[[0..7]] = ct_proto();
+    encodes as 
push:NXM_NX_XXREG1[[0..7]],set_field:0/0xff->xxreg1,resubmit(,OFTABLE_CT_ORIG_PROTO_LOAD),move:NXM_NX_XXREG1[[0..7]]->NXM_NX_XXREG1[[96..103]],pop:NXM_NX_XXREG1[[0..7]]
+
+reg1 = ct_proto();
+    Cannot use 32-bit field reg1[[0..31]] where 8-bit field is required.
+
+ct_proto;
+    Syntax error at `ct_proto' expecting action.
+
+ct_proto();
+    Syntax error at `ct_proto' expecting action.
+
 flood_remote;
     encodes as set_field:0x8000->reg6,resubmit(,OFTABLE_FLOOD_REMOTE_CHASSIS)
 
-- 
2.38.1

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to