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