Commit 20a96b9d2c3d used CT header fields for L4 matching, which caused HW offload problems for LB related traffic.
The root cause is, it added openflow rules with match ct_state=new and ct_nw_proto=xxx. The original consideration was that, although the ct_nw_proto is not supported by HW offload, it is only combined with ct_state=new, so it was assumed that it only affects the first packet of a new connection, which is not offloaded anyway. However, that's not the way how OVS is implemented. OVS generates megaflows not just according to what's matched in openflow tables, but also what's not matched. In this case, when a packet of an established connections comes, although it doesn't match the flow that has "ct_state=new && ct_nw_proto=xxx", just because it is examined against the rule, the megaflow unwildcards the ct_nw_proto field as exact match. So in the end the packet matches another flow "ct_state=est ..." that doesn't have ct_nw_proto in the mtach, but still generates a megaflow with ct_tuple4(proto=xxx) (which is a result of the ct_nw_proto condition of the openflow rule). And ct_tuple4... is not supported for HW offload, so all established connection packets are impacted and not offloaded. In theory OVS could be optimized so that when ct_state is not matched, then don't consider other ct fields of the same flow. However, this is challenging. So this patch introduces a separate stage CT_EXTRACT for both LS and LR pipelines, which jumps to a side-table to access the CT fields, only if the CT state is new. This way, the CT fields won't appear in the match conditions for established connections, thus won't generate megaflows with ct_tuple4(proto=xxx). Fixes: 20a96b9d2c3d ("northd: Allow fragmented traffic through LB.") Signed-off-by: Han Zhou <hz...@ovn.org> --- controller/lflow.c | 1 + controller/lflow.h | 1 + controller/physical.c | 18 +++- include/ovn/actions.h | 5 +- include/ovn/logical-fields.h | 6 +- lib/actions.c | 27 +++++ lib/logical-fields.c | 15 --- lib/ovn-util.c | 4 +- lib/ovn-util.h | 2 +- northd/northd.c | 100 ++++++++++++++++-- northd/northd.h | 76 +++++++------- northd/ovn-northd.8.xml | 189 ++++++++++++++++++++++----------- tests/ovn-macros.at | 1 + tests/ovn-northd.at | 196 +++++++++++++++++++++-------------- tests/ovn.at | 36 +++---- tests/system-ovn-kmod.at | 14 +++ tests/test-ovn.c | 1 + utilities/ovn-trace.c | 38 +++++++ 18 files changed, 503 insertions(+), 227 deletions(-) diff --git a/controller/lflow.c b/controller/lflow.c index 0a3bf1c1cc34..04d7748fe80f 100644 --- a/controller/lflow.c +++ b/controller/lflow.c @@ -892,6 +892,7 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, .ct_nw_dst_load_table = OFTABLE_CT_ORIG_NW_DST_LOAD, .ct_ip6_dst_load_table = OFTABLE_CT_ORIG_IP6_DST_LOAD, .ct_tp_dst_load_table = OFTABLE_CT_ORIG_TP_DST_LOAD, + .ct_proto_load_table = OFTABLE_CT_ORIG_PROTO_LOAD, .flood_remote_table = OFTABLE_FLOOD_REMOTE_CHASSIS, .ct_state_save_table = OFTABLE_CT_STATE_SAVE, .ctrl_meter_id = ctrl_meter_id, diff --git a/controller/lflow.h b/controller/lflow.h index 32549df90c6f..fa9e795e02c8 100644 --- a/controller/lflow.h +++ b/controller/lflow.h @@ -100,6 +100,7 @@ struct uuid; #define OFTABLE_CT_ORIG_TP_DST_LOAD 83 #define OFTABLE_FLOOD_REMOTE_CHASSIS 84 #define OFTABLE_CT_STATE_SAVE 85 +#define OFTABLE_CT_ORIG_PROTO_LOAD 86 /* Common defines shared between some controller components. */ #define CHASSIS_FLOOD_INDEX_START 0x8000 diff --git a/controller/physical.c b/controller/physical.c index 7b9b66ffe7f4..9ec7d4d69333 100644 --- a/controller/physical.c +++ b/controller/physical.c @@ -3033,8 +3033,8 @@ physical_run(struct physical_ctx *p_ctx, add_default_drop_flow(p_ctx, OFTABLE_LOG_TO_PHY, flow_table); /* Table 81, 82 and 83 - * Match on ct.trk and ct.est | ct.new and store the ct_nw_dst, ct_ip6_dst - * and ct_tp_dst in the registers. */ + * Match on ct.trk and ct.est | ct.new and store the ct_nw_dst, ct_ip6_dst, + * ct_tp_dst and ct_proto in the registers. */ uint32_t ct_state_est = OVS_CS_F_TRACKED | OVS_CS_F_ESTABLISHED; uint32_t ct_state_new = OVS_CS_F_TRACKED | OVS_CS_F_NEW; struct match match_new = MATCH_CATCHALL_INITIALIZER; @@ -3057,6 +3057,20 @@ physical_run(struct physical_ctx *p_ctx, 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) + * table = 86 + * match = (ct.trk && ct.new), action = (reg3[0..7] = ct_proto) + * table = 86 + */ + ofpbuf_clear(&ofpacts); + put_move(MFF_CT_NW_PROTO, 0, MFF_LOG_CT_ORIG_PROTO, 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); + 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) * table = 81 diff --git a/include/ovn/actions.h b/include/ovn/actions.h index 055d3b26cbf4..30e5e4229c55 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -134,6 +134,7 @@ struct collector_set_ids; OVNACT(CT_ORIG_NW_DST, ovnact_result) \ OVNACT(CT_ORIG_IP6_DST, ovnact_result) \ OVNACT(CT_ORIG_TP_DST, ovnact_result) \ + OVNACT(CT_ORIG_PROTO, ovnact_result) \ OVNACT(FLOOD_REMOTE, ovnact_null) \ OVNACT(CT_STATE_SAVE, ovnact_result) \ OVNACT(MIRROR, ovnact_mirror) \ @@ -423,7 +424,7 @@ struct ovnact_set_queue { }; /* OVNACT_DNS_LOOKUP, OVNACT_CHK_LB_HAIRPIN, OVNACT_CHK_LB_HAIRPIN_REPLY, - * OVNACT_CT_ORIG_NW_DST, CT_ORIG_IP6_DST, CT_ORIG_TP_DST */ + * OVNACT_CT_ORIG_NW_DST, CT_ORIG_IP6_DST, CT_ORIG_TP_DST, CT_ORIG_PROTO */ struct ovnact_result { struct ovnact ovnact; struct expr_field dst; /* destination field. */ @@ -973,6 +974,8 @@ struct ovnact_encode_params { * to resubmit. */ uint32_t ct_tp_dst_load_table; /* OpenFlow table for 'ct_tp_dst' * to resubmit. */ + uint32_t ct_proto_load_table; /* OpenFlow table for 'ct_proto' + * to resubmit. */ uint32_t flood_remote_table; /* OpenFlow table for 'chassis_flood' * to resubmit. */ uint32_t ct_state_save_table; /* OpenFlow table for saving ct_state to diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h index 61f5e7ae0a92..1130ee8d201d 100644 --- a/include/ovn/logical-fields.h +++ b/include/ovn/logical-fields.h @@ -61,8 +61,10 @@ enum ovn_controller_event { #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 /* REG_LB_PORT - * (bits 0..15). */ +#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). */ diff --git a/lib/actions.c b/lib/actions.c index cd969c684257..41fd17522c6c 100644 --- a/lib/actions.c +++ b/lib/actions.c @@ -5514,6 +5514,29 @@ format_CT_ORIG_TP_DST(const struct ovnact_result *res, struct ds *s) ds_put_cstr(s, " = ct_tp_dst();"); } +static void +encode_CT_ORIG_PROTO(const struct ovnact_result *res, + const struct ovnact_encode_params *ep, + struct ofpbuf *ofpacts) +{ + encode_result_action___(res, ep->ct_proto_load_table, + MFF_LOG_CT_ORIG_PROTO, 0, 8, ofpacts); +} + +static void +parse_CT_ORIG_PROTO(struct action_context *ctx, const struct expr_field *dst, + struct ovnact_result *res) +{ + parse_ovnact_result__(ctx, "ct_proto", NULL, dst, res, 8); +} + +static void +format_CT_ORIG_PROTO(const struct ovnact_result *res, struct ds *s) +{ + expr_field_format(&res->dst, s); + ds_put_cstr(s, " = ct_proto();"); +} + static void format_FLOOD_REMOTE(const struct ovnact_null *null OVS_UNUSED, struct ds *s) { @@ -5728,6 +5751,10 @@ parse_set_action(struct action_context *ctx) lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) { parse_CT_ORIG_TP_DST(ctx, &lhs, ovnact_put_CT_ORIG_TP_DST(ctx->ovnacts)); + } else if (!strcmp(ctx->lexer->token.s, "ct_proto") && + lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) { + parse_CT_ORIG_PROTO(ctx, &lhs, + ovnact_put_CT_ORIG_PROTO(ctx->ovnacts)); } else if (!strcmp(ctx->lexer->token.s, "ct_state_save") && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) { parse_CT_STATE_SAVE(ctx, &lhs, diff --git a/lib/logical-fields.c b/lib/logical-fields.c index efbc75b720e1..e479a78c1037 100644 --- a/lib/logical-fields.c +++ b/lib/logical-fields.c @@ -359,21 +359,6 @@ ovn_init_symtab(struct shash *symtab) expr_symtab_add_ovn_field(symtab, "icmp4.frag_mtu", OVN_ICMP4_FRAG_MTU); expr_symtab_add_ovn_field(symtab, "icmp6.frag_mtu", OVN_ICMP6_FRAG_MTU); - - expr_symtab_add_field(symtab, "ct_proto", MFF_CT_NW_PROTO, - "ct.trk", false); - - expr_symtab_add_predicate(symtab, "ct_udp", "ct_proto == 17"); - expr_symtab_add_field(symtab, "ct_udp.dst", MFF_CT_TP_DST, - "ct_udp", false); - - expr_symtab_add_predicate(symtab, "ct_tcp", "ct_proto == 6"); - expr_symtab_add_field(symtab, "ct_tcp.dst", MFF_CT_TP_DST, - "ct_tcp", false); - - expr_symtab_add_predicate(symtab, "ct_sctp", "ct_proto == 132"); - expr_symtab_add_field(symtab, "ct_sctp.dst", MFF_CT_TP_DST, - "ct_sctp", false); } const char * diff --git a/lib/ovn-util.c b/lib/ovn-util.c index 9f0bc99ba185..d7e236059766 100644 --- a/lib/ovn-util.c +++ b/lib/ovn-util.c @@ -901,8 +901,8 @@ 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 "1166037917 10535" -#define OVN_INTERNAL_MINOR_VER 8 +#define OVN_NORTHD_PIPELINE_CSUM "1158333617 10744" +#define OVN_INTERNAL_MINOR_VER 9 /* Returns the OVN version. The caller must free the returned value. */ char * diff --git a/lib/ovn-util.h b/lib/ovn-util.h index 2468a6de4249..c05bfc53b2ae 100644 --- a/lib/ovn-util.h +++ b/lib/ovn-util.h @@ -315,7 +315,7 @@ BUILD_ASSERT_DECL( #define SCTP_ABORT_CHUNK_FLAG_T (1 << 0) /* The number of tables for the ingress and egress pipelines. */ -#define LOG_PIPELINE_INGRESS_LEN 31 +#define LOG_PIPELINE_INGRESS_LEN 32 #define LOG_PIPELINE_EGRESS_LEN 14 static inline uint32_t diff --git a/northd/northd.c b/northd/northd.c index 6bfccf5da5c0..44c9b7721b7e 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -154,6 +154,8 @@ static bool vxlan_ic_mode; #define REG_LB_IPV4 "reg4" #define REG_LB_IPV6 "xxreg1" #define REG_LB_PORT "reg2[0..15]" +#define REG_CT_TP_DST "reg1[0..15]" +#define REG_CT_PROTO "reg1[16..23]" /* Registers for ACL evaluation */ #define REGBIT_ACL_VERDICT_ALLOW "reg8[16]" @@ -254,8 +256,10 @@ static const char *reg_ct_state[] = { * | | REGBIT_ACL_HINT_{ALLOW_NEW/ALLOW/DROP/BLOCK} | | | * | | REGBIT_ACL_{LABEL/STATELESS} | X | | * +----+----------------------------------------------+ X | | - * | R1 | UNUSED | R | | - * +----+----------------------------------------------+ E | | + * | R1 | REG_CT_TP_DST (0..15) | R | | + * | | REG_CT_PROTO (16..23) | E | | + * | | (>= IN_CT_EXTRACT && <= IN_LB_AFF_LEARN) | G | | + * +----+----------------------------------------------+ 0 | | * | R2 | REG_LB_PORT | G | | * | | (>= IN_PRE_STATEFUL && <= IN_LB_AFF_LEARN) | 0 | | * | | REG_ACL_ID | | | @@ -289,9 +293,11 @@ static const char *reg_ct_state[] = { * | | NEXT_HOP_IPV4 | R | | | | * | | (>= IN_IP_ROUTING) | E | INPORT_ETH_ADDR | X | | * +-----+---------------------------+ G | (< IP_INPUT) | X | | - * | R1 | UNUSED | 0 | | R | | - * | | | | | E | NEXT_HOP_IPV6 (>= IN_IP_ROUTING) | - * +-----+---------------------------+---+-----------------+ G | | + * | R1 | REG_CT_TP_DST (0..15) | 0 | | R | | + * | | REG_CT_PROTO (16..23) | | | E | NEXT_HOP_IPV6 (>= IN_IP_ROUTING) | + * | | (>= IN_CT_EXTRACT && | | | G | | + * | | <= IN_LB_AFF_LEARN) | | | | | + * +-----+---------------------------+---+-----------------+---+------------------------------------+ * | R2 | REG_DHCP_RELAY_DIP_IPV4 | | | 0 | | * | | REG_LB_PORT | X | | 0 | | * | | (>= IN_LB_AFF_CHECK | R | | | | @@ -470,6 +476,29 @@ ovn_datapath_name(const struct sbrec_datapath_binding *sb) return smap_get_def(&sb->external_ids, "name", ""); } +/* Convert protocol string to protocol number string. + * Returns the protocol number as a string for use in logical flows. + * Valid protocol strings are "tcp", "udp", and "sctp". + */ +static const char * +get_protocol_number_str(const char *proto_str) +{ + if (!proto_str) { + return "0"; + } + + if (!strcmp(proto_str, "tcp")) { + return "6"; /* IPPROTO_TCP */ + } else if (!strcmp(proto_str, "udp")) { + return "17"; /* IPPROTO_UDP */ + } else if (!strcmp(proto_str, "sctp")) { + return "132"; /* IPPROTO_SCTP */ + } + + /* Default to 0 for unknown protocols */ + return "0"; +} + /* A group of logical router datapaths which are connected - either * directly or indirectly. * Each logical router can belong to only one group. */ @@ -8427,8 +8456,9 @@ build_lb_affinity_ls_flows(struct lflow_table *lflows, ip_match, ip_match, lb_vip->vip_str); if (lb_vip->port_str) { - ds_put_format(&new_lb_match, " && ct_%s && ct_%s.dst == %s", - lb->proto, lb->proto, lb_vip->port_str); + ds_put_format(&new_lb_match, " && "REG_CT_PROTO" == %s && " + REG_CT_TP_DST" == %s", + get_protocol_number_str(lb->proto), lb_vip->port_str); } static char *aff_check = REGBIT_KNOWN_LB_SESSION" = chk_lb_aff(); next;"; @@ -8551,6 +8581,8 @@ build_lswitch_lb_affinity_default_flows(struct ovn_datapath *od, lflow_ref); } + + static void build_lrouter_lb_affinity_default_flows(struct ovn_datapath *od, struct lflow_table *lflows, @@ -8591,7 +8623,8 @@ build_lb_rules(struct lflow_table *lflows, struct ovn_lb_datapaths *lb_dps, lb_vip->vip_str); int priority = 110; if (lb_vip->port_str) { - ds_put_format(match, " && ct_%s.dst == %s", lb->proto, + ds_put_format(match, " && "REG_CT_PROTO" == %s && "REG_CT_TP_DST + " == %s", get_protocol_number_str(lb->proto), lb_vip->port_str); priority = 120; } @@ -12570,8 +12603,9 @@ build_lrouter_nat_flows_for_lb( ip_match, ip_match, lb_vip->vip_str); if (lb_vip->port_str) { prio = 120; - ds_put_format(match, " && ct_%s && ct_%s.dst == %s", - lb->proto, lb->proto, lb_vip->port_str); + ds_put_format(match, + " && "REG_CT_PROTO" == %s && "REG_CT_TP_DST" == %s", + get_protocol_number_str(lb->proto), lb_vip->port_str); } /* Add logical flows to UNDNAT the load balanced reverse traffic in @@ -16614,6 +16648,25 @@ build_lrouter_in_dnat_flow(struct lflow_table *lflows, &nat->header_, lflow_ref); } +static void +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. + */ + 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;", + lflow_ref); +} + static void build_lrouter_out_undnat_flow(struct lflow_table *lflows, const struct ovn_datapath *od, @@ -17051,6 +17104,8 @@ static void build_lr_nat_defrag_and_lb_default_flows( ovn_lflow_add(lflows, od, S_ROUTER_OUT_CHECK_DNAT_LOCAL, 0, "1", REGBIT_DST_NAT_IP_LOCAL" = 0; next;", lflow_ref); ovn_lflow_add(lflows, od, S_ROUTER_OUT_SNAT, 0, "1", "next;", lflow_ref); + ovn_lflow_add(lflows, od, S_ROUTER_IN_CT_EXTRACT, 0, "1", "next;", + lflow_ref); ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 0, "1", "next;", lflow_ref); ovn_lflow_add(lflows, od, S_ROUTER_OUT_UNDNAT, 0, "1", "next;", lflow_ref); ovn_lflow_add(lflows, od, S_ROUTER_OUT_POST_UNDNAT, 0, "1", "next;", @@ -17271,6 +17326,10 @@ build_lrouter_nat_defrag_and_lb( ds_truncate(match, match_len); ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 50, ds_cstr(match), "next;", lflow_ref); + + /* Add connection tracking field extraction flows for ct.new packets. + */ + build_lrouter_in_ct_extract_flows(lflows, od, lflow_ref); } /* NAT rules are only valid on Gateway routers and routers with @@ -17886,6 +17945,21 @@ build_ls_stateful_flows(const struct ls_stateful_record *ls_stateful_rec, build_acls(ls_stateful_rec, od, lflows, ls_pgs, meter_groups, sampling_apps, features, ls_stateful_rec->lflow_ref, 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.*/ + 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;", + ls_stateful_rec->lflow_ref); + } + build_lb_hairpin(ls_stateful_rec, od, lflows, ls_stateful_rec->lflow_ref); } @@ -17940,6 +18014,10 @@ build_lswitch_and_lrouter_iterate_by_ls(struct ovn_datapath *od, build_lswitch_destination_lookup_bmcast(od, lsi->lflows, &lsi->actions, lsi->meter_groups, NULL); build_lswitch_output_port_sec_od(od, lsi->lflows, NULL); + /* CT extraction flows are built with stateful flows, but default rule is + * always needed */ + ovn_lflow_add(lsi->lflows, od, S_SWITCH_IN_CT_EXTRACT, 0, "1", "next;", + NULL); build_lswitch_lb_affinity_default_flows(od, lsi->lflows, NULL); build_lswitch_lflows_l2_unknown(od, lsi->lflows, NULL); build_mcast_flood_lswitch(od, lsi->lflows, &lsi->actions, NULL); @@ -18540,7 +18618,7 @@ void build_lflows(struct ovsdb_idl_txn *ovnsb_txn, /* Parallel build may result in a suboptimal hash. Resize the * lflow map to a correct size before doing lookups */ lflow_table_expand(lflows); - + stopwatch_start(LFLOWS_TO_SB_STOPWATCH_NAME, time_msec()); lflow_table_sync_to_sb(lflows, ovnsb_txn, input_data->ls_datapaths, input_data->lr_datapaths, diff --git a/northd/northd.h b/northd/northd.h index eacff73eb0d3..ac00c4ec46d9 100644 --- a/northd/northd.h +++ b/northd/northd.h @@ -482,27 +482,28 @@ enum ovn_stage { PIPELINE_STAGE(SWITCH, IN, ACL_SAMPLE, 10, "ls_in_acl_sample") \ PIPELINE_STAGE(SWITCH, IN, ACL_ACTION, 11, "ls_in_acl_action") \ PIPELINE_STAGE(SWITCH, IN, QOS, 12, "ls_in_qos") \ - PIPELINE_STAGE(SWITCH, IN, LB_AFF_CHECK, 13, "ls_in_lb_aff_check") \ - PIPELINE_STAGE(SWITCH, IN, LB, 14, "ls_in_lb") \ - PIPELINE_STAGE(SWITCH, IN, LB_AFF_LEARN, 15, "ls_in_lb_aff_learn") \ - PIPELINE_STAGE(SWITCH, IN, PRE_HAIRPIN, 16, "ls_in_pre_hairpin") \ - PIPELINE_STAGE(SWITCH, IN, NAT_HAIRPIN, 17, "ls_in_nat_hairpin") \ - PIPELINE_STAGE(SWITCH, IN, HAIRPIN, 18, "ls_in_hairpin") \ - PIPELINE_STAGE(SWITCH, IN, ACL_AFTER_LB_EVAL, 19, \ + PIPELINE_STAGE(SWITCH, IN, CT_EXTRACT, 13, "ls_in_ct_extract") \ + PIPELINE_STAGE(SWITCH, IN, LB_AFF_CHECK, 14, "ls_in_lb_aff_check") \ + PIPELINE_STAGE(SWITCH, IN, LB, 15, "ls_in_lb") \ + PIPELINE_STAGE(SWITCH, IN, LB_AFF_LEARN, 16, "ls_in_lb_aff_learn") \ + PIPELINE_STAGE(SWITCH, IN, PRE_HAIRPIN, 17, "ls_in_pre_hairpin") \ + PIPELINE_STAGE(SWITCH, IN, NAT_HAIRPIN, 18, "ls_in_nat_hairpin") \ + PIPELINE_STAGE(SWITCH, IN, HAIRPIN, 19, "ls_in_hairpin") \ + PIPELINE_STAGE(SWITCH, IN, ACL_AFTER_LB_EVAL, 20, \ "ls_in_acl_after_lb_eval") \ - PIPELINE_STAGE(SWITCH, IN, ACL_AFTER_LB_SAMPLE, 20, \ + PIPELINE_STAGE(SWITCH, IN, ACL_AFTER_LB_SAMPLE, 21, \ "ls_in_acl_after_lb_sample") \ - PIPELINE_STAGE(SWITCH, IN, ACL_AFTER_LB_ACTION, 21, \ + PIPELINE_STAGE(SWITCH, IN, ACL_AFTER_LB_ACTION, 22, \ "ls_in_acl_after_lb_action") \ - PIPELINE_STAGE(SWITCH, IN, STATEFUL, 22, "ls_in_stateful") \ - PIPELINE_STAGE(SWITCH, IN, ARP_ND_RSP, 23, "ls_in_arp_rsp") \ - PIPELINE_STAGE(SWITCH, IN, DHCP_OPTIONS, 24, "ls_in_dhcp_options") \ - PIPELINE_STAGE(SWITCH, IN, DHCP_RESPONSE, 25, "ls_in_dhcp_response") \ - PIPELINE_STAGE(SWITCH, IN, DNS_LOOKUP, 26, "ls_in_dns_lookup") \ - PIPELINE_STAGE(SWITCH, IN, DNS_RESPONSE, 27, "ls_in_dns_response") \ - PIPELINE_STAGE(SWITCH, IN, EXTERNAL_PORT, 28, "ls_in_external_port") \ - PIPELINE_STAGE(SWITCH, IN, L2_LKUP, 29, "ls_in_l2_lkup") \ - PIPELINE_STAGE(SWITCH, IN, L2_UNKNOWN, 30, "ls_in_l2_unknown") \ + PIPELINE_STAGE(SWITCH, IN, STATEFUL, 23, "ls_in_stateful") \ + PIPELINE_STAGE(SWITCH, IN, ARP_ND_RSP, 24, "ls_in_arp_rsp") \ + PIPELINE_STAGE(SWITCH, IN, DHCP_OPTIONS, 25, "ls_in_dhcp_options") \ + PIPELINE_STAGE(SWITCH, IN, DHCP_RESPONSE, 26, "ls_in_dhcp_response") \ + PIPELINE_STAGE(SWITCH, IN, DNS_LOOKUP, 27, "ls_in_dns_lookup") \ + PIPELINE_STAGE(SWITCH, IN, DNS_RESPONSE, 28, "ls_in_dns_response") \ + PIPELINE_STAGE(SWITCH, IN, EXTERNAL_PORT, 29, "ls_in_external_port") \ + PIPELINE_STAGE(SWITCH, IN, L2_LKUP, 30, "ls_in_l2_lkup") \ + PIPELINE_STAGE(SWITCH, IN, L2_UNKNOWN, 31, "ls_in_l2_unknown") \ \ /* Logical switch egress stages. */ \ PIPELINE_STAGE(SWITCH, OUT, LOOKUP_FDB, 0, "ls_out_lookup_fdb") \ @@ -529,27 +530,28 @@ enum ovn_stage { PIPELINE_STAGE(ROUTER, IN, UNSNAT, 5, "lr_in_unsnat") \ PIPELINE_STAGE(ROUTER, IN, POST_UNSNAT, 6, "lr_in_post_unsnat") \ PIPELINE_STAGE(ROUTER, IN, DEFRAG, 7, "lr_in_defrag") \ - PIPELINE_STAGE(ROUTER, IN, LB_AFF_CHECK, 8, "lr_in_lb_aff_check") \ - PIPELINE_STAGE(ROUTER, IN, DNAT, 9, "lr_in_dnat") \ - PIPELINE_STAGE(ROUTER, IN, LB_AFF_LEARN, 10, "lr_in_lb_aff_learn") \ - PIPELINE_STAGE(ROUTER, IN, ECMP_STATEFUL, 11, "lr_in_ecmp_stateful") \ - PIPELINE_STAGE(ROUTER, IN, ND_RA_OPTIONS, 12, "lr_in_nd_ra_options") \ - PIPELINE_STAGE(ROUTER, IN, ND_RA_RESPONSE, 13, "lr_in_nd_ra_response") \ - PIPELINE_STAGE(ROUTER, IN, IP_ROUTING_PRE, 14, "lr_in_ip_routing_pre") \ - PIPELINE_STAGE(ROUTER, IN, IP_ROUTING, 15, "lr_in_ip_routing") \ - PIPELINE_STAGE(ROUTER, IN, IP_ROUTING_ECMP, 16, "lr_in_ip_routing_ecmp") \ - PIPELINE_STAGE(ROUTER, IN, POLICY, 17, "lr_in_policy") \ - PIPELINE_STAGE(ROUTER, IN, POLICY_ECMP, 18, "lr_in_policy_ecmp") \ - PIPELINE_STAGE(ROUTER, IN, DHCP_RELAY_RESP_CHK, 19, \ + PIPELINE_STAGE(ROUTER, IN, CT_EXTRACT, 8, "lr_in_ct_extract") \ + PIPELINE_STAGE(ROUTER, IN, LB_AFF_CHECK, 9, "lr_in_lb_aff_check") \ + PIPELINE_STAGE(ROUTER, IN, DNAT, 10, "lr_in_dnat") \ + PIPELINE_STAGE(ROUTER, IN, LB_AFF_LEARN, 11, "lr_in_lb_aff_learn") \ + PIPELINE_STAGE(ROUTER, IN, ECMP_STATEFUL, 12, "lr_in_ecmp_stateful") \ + PIPELINE_STAGE(ROUTER, IN, ND_RA_OPTIONS, 13, "lr_in_nd_ra_options") \ + PIPELINE_STAGE(ROUTER, IN, ND_RA_RESPONSE, 14, "lr_in_nd_ra_response") \ + PIPELINE_STAGE(ROUTER, IN, IP_ROUTING_PRE, 15, "lr_in_ip_routing_pre") \ + PIPELINE_STAGE(ROUTER, IN, IP_ROUTING, 16, "lr_in_ip_routing") \ + PIPELINE_STAGE(ROUTER, IN, IP_ROUTING_ECMP, 17, "lr_in_ip_routing_ecmp") \ + PIPELINE_STAGE(ROUTER, IN, POLICY, 18, "lr_in_policy") \ + PIPELINE_STAGE(ROUTER, IN, POLICY_ECMP, 19, "lr_in_policy_ecmp") \ + PIPELINE_STAGE(ROUTER, IN, DHCP_RELAY_RESP_CHK, 20, \ "lr_in_dhcp_relay_resp_chk") \ - PIPELINE_STAGE(ROUTER, IN, DHCP_RELAY_RESP, 20, \ + PIPELINE_STAGE(ROUTER, IN, DHCP_RELAY_RESP, 21, \ "lr_in_dhcp_relay_resp") \ - PIPELINE_STAGE(ROUTER, IN, ARP_RESOLVE, 21, "lr_in_arp_resolve") \ - PIPELINE_STAGE(ROUTER, IN, CHK_PKT_LEN, 22, "lr_in_chk_pkt_len") \ - PIPELINE_STAGE(ROUTER, IN, LARGER_PKTS, 23, "lr_in_larger_pkts") \ - PIPELINE_STAGE(ROUTER, IN, GW_REDIRECT, 24, "lr_in_gw_redirect") \ - PIPELINE_STAGE(ROUTER, IN, NETWORK_ID, 25, "lr_in_network_id") \ - PIPELINE_STAGE(ROUTER, IN, ARP_REQUEST, 26, "lr_in_arp_request") \ + PIPELINE_STAGE(ROUTER, IN, ARP_RESOLVE, 22, "lr_in_arp_resolve") \ + PIPELINE_STAGE(ROUTER, IN, CHK_PKT_LEN, 23, "lr_in_chk_pkt_len") \ + PIPELINE_STAGE(ROUTER, IN, LARGER_PKTS, 24, "lr_in_larger_pkts") \ + PIPELINE_STAGE(ROUTER, IN, GW_REDIRECT, 25, "lr_in_gw_redirect") \ + PIPELINE_STAGE(ROUTER, IN, NETWORK_ID, 26, "lr_in_network_id") \ + PIPELINE_STAGE(ROUTER, IN, ARP_REQUEST, 27, "lr_in_arp_request") \ \ /* Logical router egress stages. */ \ PIPELINE_STAGE(ROUTER, OUT, CHECK_DNAT_LOCAL, 0, \ diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml index 8cf31849aea4..e673c31c14d3 100644 --- a/northd/ovn-northd.8.xml +++ b/northd/ovn-northd.8.xml @@ -1033,7 +1033,29 @@ </li> </ul> - <h3>Ingress Table 13: Load balancing affinity check</h3> + <h3>Ingress Table 13: Connection Tracking Field Extraction</h3> + + <p> + This table extracts connection tracking fields for new connections + to be used by subsequent load balancing stages. + </p> + + <ul> + <li> + A priority-100 flow matches <code>ct.new && ip</code> and + 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>. + </li> + + <li> + A priority-0 flow matches all packets and advances to the next table. + </li> + </ul> + + <h3>Ingress Table 14: Load balancing affinity check</h3> <p> Load balancing affinity check table contains the following @@ -1048,11 +1070,12 @@ <var>PORT</var> of protocol <var>P</var> and IP address <var>VIP</var>, a priority-100 flow is added. For IPv4 <var>VIPs</var>, the flow matches <code>ct.new && ip && ip4.dst == <var>VIP</var> - && <var>P</var>.dst == <var>PORT</var></code>. For IPv6 + && reg1[16..23] == <var>PROTO_NUM</var> && + reg1[0..15] == <var>PORT</var></code>. For IPv6 <var>VIPs</var>, the flow matches <code>ct.new && ip && - ip6.dst == <var>VIP</var>&& <var>P</var> && - <var>P</var>.dst == <var> PORT</var></code>. The flow's action is - <code>reg9[6] = chk_lb_aff(); next;</code>. + ip6.dst == <var>VIP</var> && reg1[16..23] == + <var>PROTO_NUM</var> && reg1[0..15] == <var>PORT</var></code>. + The flow's action is <code>reg9[6] = chk_lb_aff(); next;</code>. </li> <li> @@ -1061,7 +1084,7 @@ </li> </ul> - <h3>Ingress Table 14: LB</h3> + <h3>Ingress Table 15: LB</h3> <ul> <li> @@ -1089,11 +1112,13 @@ <var>PORT</var> of protocol <var>P</var> and IP address <var>VIP</var>, a priority-120 flow is added. For IPv4 <var>VIPs </var>, the flow matches <code>ct.new && ip && - ip4.dst == <var>VIP</var> && - <var>P</var>.dst == <var>PORT</var></code>. For IPv6 <var>VIPs</var>, + ip4.dst == <var>VIP</var> && reg1[16..23] == + <var>PROTO_NUM</var> && reg1[0..15] == <var>PORT</var></code>. + For IPv6 <var>VIPs</var>, the flow matches <code>ct.new && ip && ip6.dst == <var> - VIP </var>&& <var>P</var> && <var>P</var>.dst == <var> - PORT</var></code>. The flow's action is <code>ct_lb_mark(<var>args</var>) + VIP </var>&& reg1[16..23] == <var>PROTO_NUM</var> && + reg1[0..15] == <var>PORT</var></code>. The flow's action is + <code>ct_lb_mark(<var>args</var>) </code>, where <var>args</var> contains comma separated IP addresses (and optional port numbers) to load balance to. The address family of the IP addresses of <var>args</var> is the same as the address family @@ -1141,7 +1166,7 @@ </li> </ul> - <h3>Ingress Table 15: Load balancing affinity learn</h3> + <h3>Ingress Table 16: Load balancing affinity learn</h3> <p> Load balancing affinity learn table contains the following @@ -1172,7 +1197,7 @@ </li> </ul> - <h3>Ingress Table 16: Pre-Hairpin</h3> + <h3>Ingress Table 17: Pre-Hairpin</h3> <ul> <li> If the logical switch has load balancer(s) configured, then a @@ -1190,7 +1215,7 @@ </li> </ul> - <h3>Ingress Table 17: Nat-Hairpin</h3> + <h3>Ingress Table 18: Nat-Hairpin</h3> <ul> <li> If the logical switch has load balancer(s) configured, then a @@ -1225,7 +1250,7 @@ </li> </ul> - <h3>Ingress Table 18: Hairpin</h3> + <h3>Ingress Table 19: Hairpin</h3> <ul> <li> <p> @@ -1263,7 +1288,7 @@ </li> </ul> - <h3>Ingress table 19: <code>from-lport</code> ACL evaluation after LB</h3> + <h3>Ingress table 20: <code>from-lport</code> ACL evaluation after LB</h3> <p> Logical flows in this table closely reproduce those in the @@ -1348,7 +1373,7 @@ </li> </ul> - <h3>Ingress Table 20: <code>from-lport</code> ACL sampling after LB</h3> + <h3>Ingress Table 21: <code>from-lport</code> ACL sampling after LB</h3> <p> Logical flows in this table sample traffic matched by @@ -1388,7 +1413,7 @@ </li> </ul> - <h3>Ingress Table 21: <code>from-lport</code> ACL action after LB</h3> + <h3>Ingress Table 22: <code>from-lport</code> ACL action after LB</h3> <p> Logical flows in this table decide how to proceed based on the values of @@ -1428,7 +1453,7 @@ </li> </ul> - <h3>Ingress Table 22: Stateful</h3> + <h3>Ingress Table 23: Stateful</h3> <ul> <li> @@ -1451,7 +1476,7 @@ </li> </ul> - <h3>Ingress Table 23: ARP/ND responder</h3> + <h3>Ingress Table 24: ARP/ND responder</h3> <p> This table implements ARP/ND responder in a logical switch for known @@ -1786,7 +1811,7 @@ output; </li> </ul> - <h3>Ingress Table 24: DHCP option processing</h3> + <h3>Ingress Table 25: DHCP option processing</h3> <p> This table adds the DHCPv4 options to a DHCPv4 packet from the @@ -1847,7 +1872,7 @@ next; </li> </ul> - <h3>Ingress Table 25: DHCP responses</h3> + <h3>Ingress Table 26: DHCP responses</h3> <p> This table implements DHCP responder for the DHCP replies generated by @@ -1928,7 +1953,7 @@ output; </li> </ul> - <h3>Ingress Table 26 DNS Lookup</h3> + <h3>Ingress Table 27 DNS Lookup</h3> <p> This table looks up and resolves the DNS names to the corresponding @@ -1957,7 +1982,7 @@ reg0[4] = dns_lookup(); next; </li> </ul> - <h3>Ingress Table 27 DNS Responses</h3> + <h3>Ingress Table 28 DNS Responses</h3> <p> This table implements DNS responder for the DNS replies generated by @@ -1992,7 +2017,7 @@ output; </li> </ul> - <h3>Ingress table 28 External ports</h3> + <h3>Ingress table 29 External ports</h3> <p> Traffic from the <code>external</code> logical ports enter the ingress @@ -2035,7 +2060,7 @@ output; </li> </ul> - <h3>Ingress Table 29 Destination Lookup</h3> + <h3>Ingress Table 30 Destination Lookup</h3> <p> This table implements switching behavior. It contains these logical @@ -2261,7 +2286,7 @@ output; </li> </ul> - <h3>Ingress Table 30 Destination unknown</h3> + <h3>Ingress Table 31 Destination unknown</h3> <p> This table handles the packets whose destination was not found or @@ -2464,7 +2489,7 @@ output; A priority 34000 logical flow is added for each logical port which has DHCPv4 options defined to allow the DHCPv4 reply packet and which has DHCPv6 options defined to allow the DHCPv6 reply packet from the - <code>Ingress Table 18: DHCP responses</code>. This is indicated by + <code>Ingress Table 26: DHCP responses</code>. This is indicated by setting the allow bit. </li> @@ -2472,7 +2497,7 @@ output; A priority 34000 logical flow is added for each logical switch datapath configured with DNS records with the match <code>udp.dst = 53</code> to allow the DNS reply packet from the - <code>Ingress Table 20: DNS responses</code>. This is indicated by + <code>Ingress Table 28: DNS responses</code>. This is indicated by setting the allow bit. </li> @@ -3831,7 +3856,46 @@ next; <code>inport == DGP && is_chassis_resident(CHASSIS)</code>. </p> - <h3>Ingress Table 8: Load balancing affinity check</h3> + <h3>Ingress Table 8: Connection tracking field extraction</h3> + + <p> + This table extracts connection tracking fields for new connections + and stores them in registers for use by subsequent load balancing + stages. + </p> + + <ul> + <li> + <p> + For all new connections (<code>ct.new</code>), a priority-100 flow + extracts the connection tracking protocol and destination port + information into registers: + </p> + + <pre> +push(reg2); push(reg3); +reg2[0..15] = ct_tp_dst(); +reg3[16..23] = ct_proto(); +pop(reg3); pop(reg2); +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. + </p> + </li> + + <li> + A priority-0 flow that matches all packets and advances to the + next table with action <code>next;</code>. + </li> + </ul> + + <h3>Ingress Table 9: Load balancing affinity check</h3> <p> Load balancing affinity check table contains the following @@ -3845,11 +3909,13 @@ next; column, that includes a L4 port <var>PORT</var> of protocol <var>P</var> and IPv4 or IPv6 address <var>VIP</var>, a priority-100 flow that matches on <code>ct.new && ip && - ip.dst == <var>VIP</var> && <var>P</var> && P.dst - == </code> <code><var>PORT</var></code> (<code>xxreg0 == <var>VIP - </var></code> in the IPv6 case) with an action of <code>reg0 = ip.dst; - reg9[16..31] = P.dst; reg9[6] = chk_lb_aff(); next;</code> - (<code>xxreg0 == <var>ip6.dst</var> </code> in the IPv6 case) + ip.dst == <var>VIP</var> && REG_CT_PROTO == <var>P_NUM</var> + && REG_CT_TP_DST == <var>PORT</var></code> (<code>xxreg0 == + <var>VIP</var></code> in the IPv6 case) with an action of + <code>reg0 = ip.dst; reg9[16..31] = P.dst; reg9[6] = chk_lb_aff(); + next;</code> (<code>xxreg0 == <var>ip6.dst</var> </code> in the IPv6 + case), where <var>P_NUM</var> is the protocol number (6 for TCP, 17 + for UDP, 132 for SCTP). </li> <li> @@ -3858,7 +3924,7 @@ next; </li> </ul> - <h3>Ingress Table 9: DNAT</h3> + <h3>Ingress Table 10: DNAT</h3> <p> Packets enter the pipeline with destination IP address that needs to @@ -3882,12 +3948,15 @@ next; column, that includes a L4 port <var>PORT</var> of protocol <var>P</var> and IPv4 or IPv6 address <var>VIP</var>, a priority-150 flow that matches on <code>reg9[6] == 1 && ct.new && - ip && ip.dst == <var>VIP</var> && <var>P</var> && - P.dst == </code> <code><var>PORT</var></code> with an action of + ip && ip.dst == <var>VIP</var> && REG_CT_PROTO == + <var>P_NUM</var> && + REG_CT_TP_DST == <var>PORT</var></code> with an action of <code>ct_lb_mark(<var>args</var>) </code>, where <var>args</var> contains comma separated IP addresses (and optional port numbers) - to load balance to. The address family of the IP addresses of - <var>args</var> is the same as the address family of <var>VIP</var>. + to load balance to, and <var>P_NUM</var> is the protocol number + (6 for TCP, 17 for UDP, 132 for SCTP). The address family of the IP + addresses of <var>args</var> is the same as the address family of + <var>VIP</var>. </li> <li> @@ -3907,11 +3976,13 @@ next; includes a L4 port <var>PORT</var> of protocol <var>P</var> and IPv4 or IPv6 address <var>VIP</var>, a priority-120 flow that matches on <code>ct.new && !ct.rel && ip && ip.dst == - <var>VIP</var> && <var>P</var> && P.dst == - </code> <code><var>PORT</var></code> with an action of + <var>VIP</var> && REG_CT_PROTO == <var>P_NUM</var> && + REG_CT_TP_DST == <var>PORT</var></code> with an action of <code>ct_lb_mark(<var>args</var>)</code>, where <var>args</var> contains comma separated IPv4 or IPv6 addresses (and optional port numbers) to - load balance to. If the router is configured to force SNAT any + load balance to, and <var>P_NUM</var> is the protocol number + (6 for TCP, 17 for UDP, 132 for SCTP). If the router is configured + to force SNAT any load-balanced packets, the above action will be replaced by <code>flags.force_snat_for_lb = 1; ct_lb_mark(<var>args</var>; force_snat);</code>. @@ -4117,7 +4188,7 @@ next; </li> </ul> - <h3>Ingress Table 10: Load balancing affinity learn</h3> + <h3>Ingress Table 11: Load balancing affinity learn</h3> <p> Load balancing affinity learn table contains the following @@ -4145,7 +4216,7 @@ next; </li> </ul> - <h3>Ingress Table 11: ECMP symmetric reply processing</h3> + <h3>Ingress Table 12: ECMP symmetric reply processing</h3> <ul> <li> If ECMP routes with symmetric reply are configured in the @@ -4164,7 +4235,7 @@ next; </li> </ul> - <h3>Ingress Table 12: IPv6 ND RA option processing</h3> + <h3>Ingress Table 13: IPv6 ND RA option processing</h3> <ul> <li> @@ -4194,7 +4265,7 @@ reg0[5] = put_nd_ra_opts(<var>options</var>);next; </li> </ul> - <h3>Ingress Table 13: IPv6 ND RA responder</h3> + <h3>Ingress Table 14: IPv6 ND RA responder</h3> <p> This table implements IPv6 ND RA responder for the IPv6 ND RA replies @@ -4239,7 +4310,7 @@ output; </li> </ul> - <h3>Ingress Table 14: IP Routing Pre</h3> + <h3>Ingress Table 15: IP Routing Pre</h3> <p> If a packet arrived at this table from Logical Router Port <var>P</var> @@ -4269,7 +4340,7 @@ output; </li> </ul> - <h3>Ingress Table 15: IP Routing</h3> + <h3>Ingress Table 16: IP Routing</h3> <p> A packet that arrives at this table is an IP packet that should be @@ -4486,7 +4557,7 @@ reg8[16..31] = <var>MID1</var>); </li> </ul> - <h3>Ingress Table 16: IP_ROUTING_ECMP</h3> + <h3>Ingress Table 17: IP_ROUTING_ECMP</h3> <p> This table implements the second part of IP routing for ECMP routes @@ -4543,7 +4614,7 @@ outport = <var>P</var>; </li> </ul> - <h3>Ingress Table 17: Router policies</h3> + <h3>Ingress Table 18: Router policies</h3> <p> This table adds flows for the logical router policies configured on the logical router. Please see the @@ -4615,7 +4686,7 @@ next; </li> </ul> - <h3>Ingress Table 18: ECMP handling for router policies</h3> + <h3>Ingress Table 19: ECMP handling for router policies</h3> <p> This table handles the ECMP for the router policies configured with multiple nexthops. @@ -4664,7 +4735,7 @@ outport = <var>P</var> </li> </ul> - <h3>Ingress Table 19: DHCP Relay Response Check</h3> + <h3>Ingress Table 20: DHCP Relay Response Check</h3> <p> This stage process the DHCP response packets coming from the DHCP server. </p> @@ -4698,7 +4769,7 @@ outport = <var>P</var> </li> </ul> - <h3>Ingress Table 20: DHCP Relay Response</h3> + <h3>Ingress Table 21: DHCP Relay Response</h3> <p> This stage process the DHCP response packets on which <code>dhcp_relay_resp_chk</code> action is applied in the previous stage. @@ -4741,7 +4812,7 @@ output; </li> </ul> - <h3>Ingress Table 21: ARP/ND Resolution</h3> + <h3>Ingress Table 22: ARP/ND Resolution</h3> <p> Any packet that reaches this table is an IP packet whose next-hop @@ -4955,7 +5026,7 @@ output; </ul> - <h3>Ingress Table 22: Check packet length</h3> + <h3>Ingress Table 23: Check packet length</h3> <p> For distributed logical routers or gateway routers with gateway @@ -4994,7 +5065,7 @@ next; and advances to the next table. </p> - <h3>Ingress Table 23: Handle larger packets</h3> + <h3>Ingress Table 24: Handle larger packets</h3> <p> For distributed logical routers or gateway routers with gateway port @@ -5057,7 +5128,7 @@ icmp6 { and advances to the next table. </p> - <h3>Ingress Table 24: Gateway Redirect</h3> + <h3>Ingress Table 25: Gateway Redirect</h3> <p> For distributed logical routers where one or more of the logical router @@ -5141,7 +5212,7 @@ icmp6 { </li> </ul> - <h3>Ingress Table 25: Network ID</h3> + <h3>Ingress Table 26: Network ID</h3> <p> This table contains flows that set <code>flags.network_id</code> for @@ -5196,7 +5267,7 @@ icmp6 { </li> </ul> - <h3>Ingress Table 26: ARP Request</h3> + <h3>Ingress Table 27: ARP Request</h3> <p> In the common case where the Ethernet destination has been resolved, this diff --git a/tests/ovn-macros.at b/tests/ovn-macros.at index d0f1c0bf4fed..9986449ff61c 100644 --- a/tests/ovn-macros.at +++ b/tests/ovn-macros.at @@ -1495,5 +1495,6 @@ m4_define([OFTABLE_CT_ORIG_IP6_DST_LOAD], [82]) m4_define([OFTABLE_CT_ORIG_TP_DST_LOAD], [83]) m4_define([OFTABLE_FLOOD_REMOTE_CHASSIS], [84]) m4_define([OFTABLE_CT_STATE_SAVE], [85]) +m4_define([OFTABLE_CT_ORIG_PROTO_LOAD], [86]) m4_define([OFTABLE_SAVE_INPORT_HEX], [m4_eval(OFTABLE_SAVE_INPORT, 16)]) diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index c191b142e60a..b83330c501f8 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -1475,7 +1475,7 @@ check ovn-nbctl --wait=sb ls-lb-add sw0 lb1 AT_CAPTURE_FILE([sbflows]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows sw0 | tee sbflows | grep 'priority=120.*backends' | ovn_strip_lflows], 0, [dnl - table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) ]) # disabled LSPs should not be a backend of Load Balancer @@ -1484,7 +1484,7 @@ check ovn-nbctl lsp-set-enabled sw0-p1 disabled AT_CAPTURE_FILE([sbflows]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows sw0 | tee sbflows | grep 'priority=120.*backends' | ovn_strip_lflows], 0, [dnl - table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=20.0.0.3:80);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=20.0.0.3:80);) ]) wait_row_count Service_Monitor 1 @@ -1493,7 +1493,7 @@ check ovn-nbctl lsp-set-enabled sw0-p1 enabled AT_CAPTURE_FILE([sbflows]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows sw0 | tee sbflows | grep 'priority=120.*backends' | ovn_strip_lflows], 0, [dnl - table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) ]) wait_row_count Service_Monitor 2 @@ -1504,7 +1504,7 @@ wait_row_count Service_Monitor 0 AT_CAPTURE_FILE([sbflows2]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows sw0 | tee sbflows2 | grep 'priority=120.*backends' | ovn_strip_lflows], [0], -[ table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) +[ table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) ]) AS_BOX([Create the Load_Balancer_Health_Check again.]) @@ -1516,7 +1516,7 @@ check ovn-nbctl --wait=sb sync ovn-sbctl dump-flows sw0 | grep backends | grep priority=120 > lflows.txt AT_CHECK([cat lflows.txt | ovn_strip_lflows], [0], [dnl - table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) ]) AS_BOX([Get the uuid of both the service_monitor]) @@ -1525,8 +1525,8 @@ sm_sw1_p1=$(fetch_column Service_Monitor _uuid logical_port=sw1-p1) AT_CAPTURE_FILE([sbflows3]) OVS_WAIT_FOR_OUTPUT( - [ovn-sbctl dump-flows sw0 | tee sbflows 3 | grep 'priority=120.*backends' | ovn_strip_lflows], [0], -[ table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) + [ovn-sbctl dump-flows sw0 | tee sbflows3 | grep 'priority=120.*backends' | ovn_strip_lflows], [0], +[ table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) ]) AS_BOX([Set the service monitor for sw1-p1 to offline]) @@ -1537,7 +1537,7 @@ check ovn-nbctl --wait=sb sync AT_CAPTURE_FILE([sbflows4]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows sw0 | tee sbflows4 | grep 'priority=120.*backends' | ovn_strip_lflows], [0], -[ table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80);) +[ table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80);) ]) AS_BOX([Set the service monitor for sw0-p1 to offline]) @@ -1552,8 +1552,8 @@ OVS_WAIT_FOR_OUTPUT( AT_CAPTURE_FILE([sbflows6]) OVS_WAIT_FOR_OUTPUT( - [ovn-sbctl dump-flows sw0 | tee sbflows6 | grep "ip4.dst == 10.0.0.10 && ct_tcp.dst == 80" | grep priority=120 | grep ls_in_lb | ovn_strip_lflows], [0], [dnl - table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80), action=(drop;) + [ovn-sbctl dump-flows sw0 | tee sbflows6 | grep "ip4.dst == 10.0.0.10.*reg1.*== 6.*reg1.*== 80" | grep priority=120 | grep ls_in_lb | ovn_strip_lflows], [0], [dnl + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(drop;) ]) AS_BOX([Set the service monitor for sw0-p1 and sw1-p1 to online]) @@ -1566,7 +1566,7 @@ check ovn-nbctl --wait=sb sync AT_CAPTURE_FILE([sbflows7]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows sw0 | tee sbflows7 | grep backends | grep priority=120 | ovn_strip_lflows], 0, -[ table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) +[ table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) ]) AS_BOX([Set the service monitor for sw1-p1 to error]) @@ -1574,10 +1574,10 @@ check ovn-sbctl set service_monitor $sm_sw1_p1 status=error wait_row_count Service_Monitor 1 logical_port=sw1-p1 status=error check ovn-nbctl --wait=sb sync -ovn-sbctl dump-flows sw0 | grep "ip4.dst == 10.0.0.10 && ct_tcp.dst == 80" \ +ovn-sbctl dump-flows sw0 | grep "ip4.dst == 10.0.0.10.*reg1.*== 6.*reg1.*== 80" \ | grep priority=120 > lflows.txt AT_CHECK([cat lflows.txt | grep ls_in_lb | ovn_strip_lflows], [0], [dnl - table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80);) ]) AS_BOX([Add one more vip to lb1]) @@ -1603,8 +1603,8 @@ AT_CAPTURE_FILE([sbflows9]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows sw0 | tee sbflows9 | grep backends | grep priority=120 | ovn_strip_lflows], 0, -[ table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80);) - table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && ct_tcp.dst == 1000), action=(reg4 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb_mark(backends=10.0.0.3:1000);) +[ table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && reg1[[16..23]] == 6 && reg1[[0..15]] == 1000), action=(reg4 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb_mark(backends=10.0.0.3:1000);) ]) AS_BOX([Set the service monitor for sw1-p1 to online]) @@ -1617,8 +1617,8 @@ AT_CAPTURE_FILE([sbflows10]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows sw0 | tee sbflows10 | grep backends | grep priority=120 | ovn_strip_lflows], 0, -[ table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) - table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && ct_tcp.dst == 1000), action=(reg4 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb_mark(backends=10.0.0.3:1000,20.0.0.3:80);) +[ table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && reg1[[16..23]] == 6 && reg1[[0..15]] == 1000), action=(reg4 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb_mark(backends=10.0.0.3:1000,20.0.0.3:80);) ]) AS_BOX([Associate lb1 to sw1]) @@ -1627,8 +1627,8 @@ AT_CAPTURE_FILE([sbflows11]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows sw1 | tee sbflows11 | grep backends | grep priority=120 | ovn_strip_lflows], 0, [dnl - table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) - table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && ct_tcp.dst == 1000), action=(reg4 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb_mark(backends=10.0.0.3:1000,20.0.0.3:80);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.40 && reg1[[16..23]] == 6 && reg1[[0..15]] == 1000), action=(reg4 = 10.0.0.40; reg2[[0..15]] = 1000; ct_lb_mark(backends=10.0.0.3:1000,20.0.0.3:80);) ]) AS_BOX([Now create lb2 same as lb1 but udp protocol.]) @@ -1684,8 +1684,8 @@ check ovn-sbctl set service_monitor $sm_sw1_p1 status=offline AT_CAPTURE_FILE([sbflows12]) OVS_WAIT_FOR_OUTPUT( - [ovn-sbctl dump-flows sw0 | tee sbflows12 | grep "ip4.dst == 10.0.0.10 && ct_tcp.dst == 80" | grep priority=120 | grep ls_in_lb | ovn_strip_lflows], [0], [dnl - table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80), action=(reg0 = 0; reject { outport <-> inport; next(pipeline=egress,table=??);};) + [ovn-sbctl dump-flows sw0 | tee sbflows12 | grep "ip4.dst == 10.0.0.10.*reg1.*== 6.*reg1.*== 80" | grep priority=120 | grep ls_in_lb | ovn_strip_lflows], [0], [dnl + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg0 = 0; reject { outport <-> inport; next(pipeline=egress,table=??);};) ]) AT_CLEANUP @@ -3721,8 +3721,15 @@ check ovn-nbctl --wait=sb sync # TCP packets should go to conntrack. 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; @@ -3737,6 +3744,12 @@ 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; @@ -3763,6 +3776,12 @@ 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; @@ -3859,6 +3878,12 @@ 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; @@ -3873,6 +3898,12 @@ 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; @@ -3899,6 +3930,12 @@ 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; @@ -4405,8 +4442,8 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | ovn_strip_lflows], [0], [dnl AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80), action=(ct_lb_mark(backends=10.0.0.4:8080);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.100 && ct_tcp && ct_tcp.dst == 80), action=(ct_lb_mark(backends=10.0.0.40:8080);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(ct_lb_mark(backends=10.0.0.4:8080);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.100 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(ct_lb_mark(backends=10.0.0.40:8080);) table=??(lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted), action=(next;) table=??(lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new && !ct.rpl), action=(ct_commit_nat;) table=??(lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) @@ -4436,8 +4473,8 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | ovn_strip_lflows], [0], [dnl AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.100 && ct_tcp && ct_tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.100 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; force_snat);) table=??(lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted), action=(next;) table=??(lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new && !ct.rpl), action=(ct_commit_nat;) table=??(lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) @@ -4487,8 +4524,8 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | ovn_strip_lflows], [0], [dnl AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.100 && ct_tcp && ct_tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.100 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; force_snat);) table=??(lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted), action=(next;) table=??(lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new && !ct.rpl), action=(ct_commit_nat;) table=??(lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) @@ -4555,8 +4592,8 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | ovn_strip_lflows], [0], [dnl AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.100 && ct_tcp && ct_tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.100 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; force_snat);) table=??(lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted), action=(next;) table=??(lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new && !ct.rpl), action=(ct_commit_nat;) table=??(lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) @@ -4610,7 +4647,7 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | ovn_strip_lflows], [0], [dnl ]) AT_CHECK([grep "lr_in_dnat" lr0flows | grep skip_snat_for_lb | ovn_strip_lflows], [0], [dnl - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.20 && ct_tcp && ct_tcp.dst == 80), action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; skip_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.20 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.40:8080; skip_snat);) table=??(lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; next;) table=??(lr_in_dnat ), priority=70 , match=(ct.rel && !ct.est && !ct.new && !ct.rpl && ct_mark.skip_snat == 1), action=(flags.skip_snat_for_lb = 1; ct_commit_nat;) ]) @@ -4791,8 +4828,8 @@ check_stateful_flows() { table=??(ls_in_lb ), priority=0 , match=(1), action=(next;) table=??(ls_in_lb ), priority=110 , match=(ct.trk && ct.est && !ct.rpl && reg0[[19]] == 1 && ip4), action=(reg4 = ct_nw_dst(); reg2[[0..15]] = ct_tp_dst(); next;) table=??(ls_in_lb ), priority=110 , match=(ct.trk && ct.est && !ct.rpl && reg0[[19]] == 1 && ip6), action=(xxreg1 = ct_ip6_dst(); reg2[[0..15]] = ct_tp_dst(); next;) - table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.4:8080);) - table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.20 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.20; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.40:8080);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.4:8080);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.20 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 10.0.0.20; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.40:8080);) ]) AT_CHECK([grep "ls_in_stateful" sw0flows | ovn_strip_lflows], [0], [dnl @@ -6046,9 +6083,9 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) table=??(lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat_in_czone(10.0.0.3);) table=??(lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.200 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.80,10.0.0.81);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.4:8080);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && ct_tcp && ct_tcp.dst == 8082 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && ct_udp && ct_udp.dst == 60 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.4:8080);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && reg1[[16..23]] == 6 && reg1[[0..15]] == 8082 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && reg1[[16..23]] == 17 && reg1[[0..15]] == 60 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062);) table=??(lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted), action=(next;) table=??(lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new && !ct.rpl), action=(ct_commit_nat;) table=??(lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) @@ -6116,9 +6153,9 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) table=??(lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20 && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_dnat(10.0.0.3);) table=??(lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.200 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.80,10.0.0.81);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.4:8080);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && ct_tcp && ct_tcp.dst == 8082 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && ct_udp && ct_udp.dst == 60 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.4:8080);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && reg1[[16..23]] == 6 && reg1[[0..15]] == 8082 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && reg1[[16..23]] == 17 && reg1[[0..15]] == 60 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062);) table=??(lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted), action=(next;) table=??(lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new && !ct.rpl), action=(ct_commit_nat;) table=??(lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) @@ -6190,9 +6227,9 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) table=??(lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20), action=(flags.loopback = 1; ct_dnat(10.0.0.3);) table=??(lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.200), action=(ct_lb_mark(backends=10.0.0.80,10.0.0.81);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80), action=(ct_lb_mark(backends=10.0.0.4:8080);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && ct_tcp && ct_tcp.dst == 8082), action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && ct_udp && ct_udp.dst == 60), action=(ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(ct_lb_mark(backends=10.0.0.4:8080);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && reg1[[16..23]] == 6 && reg1[[0..15]] == 8082), action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && reg1[[16..23]] == 17 && reg1[[0..15]] == 60), action=(ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062);) table=??(lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted), action=(next;) table=??(lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new && !ct.rpl), action=(ct_commit_nat;) table=??(lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) @@ -6253,9 +6290,9 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) table=??(lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20), action=(flags.loopback = 1; ct_dnat(10.0.0.3);) table=??(lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.200), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.80,10.0.0.81; force_snat);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && ct_tcp && ct_tcp.dst == 8082), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && ct_udp && ct_udp.dst == 60), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && reg1[[16..23]] == 6 && reg1[[0..15]] == 8082), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && reg1[[16..23]] == 17 && reg1[[0..15]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);) table=??(lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted), action=(next;) table=??(lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new && !ct.rpl), action=(ct_commit_nat;) table=??(lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) @@ -6321,10 +6358,10 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) table=??(lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20), action=(flags.loopback = 1; ct_dnat(10.0.0.3);) table=??(lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.200), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.80,10.0.0.81; force_snat);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.10 && ct_tcp && ct_tcp.dst == 9082), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && ct_tcp && ct_tcp.dst == 8082), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && ct_udp && ct_udp.dst == 60), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 9082), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && reg1[[16..23]] == 6 && reg1[[0..15]] == 8082), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && reg1[[16..23]] == 17 && reg1[[0..15]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);) table=??(lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted), action=(next;) table=??(lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new && !ct.rpl), action=(ct_commit_nat;) table=??(lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) @@ -6401,11 +6438,11 @@ AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) table=??(lr_in_dnat ), priority=100 , match=(ip && ip4.dst == 172.168.0.20), action=(flags.loopback = 1; ct_dnat(10.0.0.3);) table=??(lr_in_dnat ), priority=110 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.200), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.80,10.0.0.81; force_snat);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.10 && ct_tcp && ct_tcp.dst == 9082), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && ct_tcp && ct_tcp.dst == 8082), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && ct_udp && ct_udp.dst == 60), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip6 && ip6.dst == def0::2 && ct_tcp && ct_tcp.dst == 8000), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=[[aef0::2]]:80,[[aef0::3]]:80; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.4:8080; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 9082), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && reg1[[16..23]] == 6 && reg1[[0..15]] == 8082), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && reg1[[16..23]] == 17 && reg1[[0..15]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip6 && ip6.dst == def0::2 && reg1[[16..23]] == 6 && reg1[[0..15]] == 8000), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=[[aef0::2]]:80,[[aef0::3]]:80; force_snat);) table=??(lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted), action=(next;) table=??(lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new && !ct.rpl), action=(ct_commit_nat;) table=??(lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) @@ -6470,8 +6507,8 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | ovn_strip_lflows], [0], [dnl AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && ct_tcp && ct_tcp.dst == 60), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && ct_udp && ct_udp.dst == 60), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && reg1[[16..23]] == 17 && reg1[[0..15]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.210 && reg1[[16..23]] == 6 && reg1[[0..15]] == 60), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.50:6062,10.0.0.60:6062; force_snat);) table=??(lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted), action=(next;) table=??(lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new && !ct.rpl), action=(ct_commit_nat;) table=??(lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) @@ -7603,8 +7640,15 @@ check ovn-nbctl --wait=sb sync flow="eth.dst == 00:00:00:00:01:00 && inport == \"rtr-ls\" && ip4.src == 42.42.42.42 && ip4.dst == 43.43.43.43 && ip.ttl == 64 && tcp && tcp.dst == 4343" +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; @@ -9664,13 +9708,13 @@ AT_CAPTURE_FILE([S1flows]) AT_CHECK([grep "ls_in_lb " S0flows | ovn_strip_lflows], [0], [dnl table=??(ls_in_lb ), priority=0 , match=(1), action=(next;) - table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 172.16.0.10 && ct_tcp.dst == 80), action=(reg4 = 172.16.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80);) - table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 172.16.0.11 && ct_tcp.dst == 8080), action=(reg4 = 172.16.0.11; reg2[[0..15]] = 8080; ct_lb_mark(backends=10.0.0.2:8080);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 172.16.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 172.16.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 172.16.0.11 && reg1[[16..23]] == 6 && reg1[[0..15]] == 8080), action=(reg4 = 172.16.0.11; reg2[[0..15]] = 8080; ct_lb_mark(backends=10.0.0.2:8080);) ]) AT_CHECK([grep "ls_in_lb " S1flows | ovn_strip_lflows], [0], [dnl table=??(ls_in_lb ), priority=0 , match=(1), action=(next;) - table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 172.16.0.10 && ct_tcp.dst == 80), action=(reg4 = 172.16.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80);) - table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 172.16.0.11 && ct_tcp.dst == 8080), action=(reg4 = 172.16.0.11; reg2[[0..15]] = 8080; ct_lb_mark(backends=10.0.0.2:8080);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 172.16.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 172.16.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 172.16.0.11 && reg1[[16..23]] == 6 && reg1[[0..15]] == 8080), action=(reg4 = 172.16.0.11; reg2[[0..15]] = 8080; ct_lb_mark(backends=10.0.0.2:8080);) ]) ovn-sbctl get datapath S0 _uuid > dp_uuids @@ -9796,13 +9840,13 @@ AT_CAPTURE_FILE([S0flows]) AT_CHECK([grep "ls_in_lb_aff_check" S0flows | ovn_strip_lflows], [0], [dnl table=??(ls_in_lb_aff_check ), priority=0 , match=(1), action=(next;) - table=??(ls_in_lb_aff_check ), priority=100 , match=(ct.new && ip4 && ip4.dst == 172.16.0.10 && ct_tcp && ct_tcp.dst == 80), action=(reg9[[6]] = chk_lb_aff(); next;) + table=??(ls_in_lb_aff_check ), priority=100 , match=(ct.new && ip4 && ip4.dst == 172.16.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg9[[6]] = chk_lb_aff(); next;) ]) AT_CHECK([grep "ls_in_lb " S0flows | ovn_strip_lflows], [0], [dnl table=??(ls_in_lb ), priority=0 , match=(1), action=(next;) table=??(ls_in_lb ), priority=110 , match=(ct.trk && ct.est && !ct.rpl && reg0[[19]] == 1 && ip4), action=(reg4 = ct_nw_dst(); reg2[[0..15]] = ct_tp_dst(); next;) table=??(ls_in_lb ), priority=110 , match=(ct.trk && ct.est && !ct.rpl && reg0[[19]] == 1 && ip6), action=(xxreg1 = ct_ip6_dst(); reg2[[0..15]] = ct_tp_dst(); next;) - table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 172.16.0.10 && ct_tcp.dst == 80), action=(reg4 = 172.16.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80);) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 172.16.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 172.16.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80);) table=??(ls_in_lb ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4.dst == 172.16.0.10 && reg4 == 10.0.0.2 && reg2[[0..15]] == 80), action=(reg4 = 172.16.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80);) table=??(ls_in_lb ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4.dst == 172.16.0.10 && reg4 == 20.0.0.2 && reg2[[0..15]] == 80), action=(reg4 = 172.16.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=20.0.0.2:80);) ]) @@ -9818,11 +9862,11 @@ AT_CAPTURE_FILE([R1flows]) AT_CHECK([grep "lr_in_lb_aff_check" R1flows | ovn_strip_lflows], [0], [dnl table=??(lr_in_lb_aff_check ), priority=0 , match=(1), action=(next;) - table=??(lr_in_lb_aff_check ), priority=100 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.16.0.10 && ct_tcp && ct_tcp.dst == 80), action=(reg9[[6]] = chk_lb_aff(); next;) + table=??(lr_in_lb_aff_check ), priority=100 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.16.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg9[[6]] = chk_lb_aff(); next;) ]) AT_CHECK([grep "lr_in_dnat " R1flows | ovn_strip_lflows], [0], [dnl table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.16.0.10 && ct_tcp && ct_tcp.dst == 80), action=(reg4 = 172.16.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.16.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 172.16.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80);) table=??(lr_in_dnat ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4.dst == 172.16.0.10 && reg4 == 10.0.0.2 && reg2[[0..15]] == 80), action=(ct_lb_mark(backends=10.0.0.2:80);) table=??(lr_in_dnat ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4.dst == 172.16.0.10 && reg4 == 20.0.0.2 && reg2[[0..15]] == 80), action=(ct_lb_mark(backends=20.0.0.2:80);) table=??(lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted), action=(next;) @@ -9846,7 +9890,7 @@ AT_CAPTURE_FILE([R1flows_skip_snat]) AT_CHECK([grep "lr_in_dnat " R1flows_skip_snat | ovn_strip_lflows], [0], [dnl table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.16.0.10 && ct_tcp && ct_tcp.dst == 80), action=(flags.skip_snat_for_lb = 1; reg4 = 172.16.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; skip_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.16.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(flags.skip_snat_for_lb = 1; reg4 = 172.16.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; skip_snat);) table=??(lr_in_dnat ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4.dst == 172.16.0.10 && reg4 == 10.0.0.2 && reg2[[0..15]] == 80), action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.2:80; skip_snat);) table=??(lr_in_dnat ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4.dst == 172.16.0.10 && reg4 == 20.0.0.2 && reg2[[0..15]] == 80), action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=20.0.0.2:80; skip_snat);) table=??(lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted), action=(next;) @@ -9867,7 +9911,7 @@ AT_CAPTURE_FILE([R1flows_force_snat]) AT_CHECK([grep "lr_in_dnat " R1flows_force_snat | ovn_strip_lflows], [0], [dnl table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.16.0.10 && ct_tcp && ct_tcp.dst == 80), action=(flags.force_snat_for_lb = 1; reg4 = 172.16.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.16.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(flags.force_snat_for_lb = 1; reg4 = 172.16.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; force_snat);) table=??(lr_in_dnat ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4.dst == 172.16.0.10 && reg4 == 10.0.0.2 && reg2[[0..15]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.2:80; force_snat);) table=??(lr_in_dnat ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4.dst == 172.16.0.10 && reg4 == 20.0.0.2 && reg2[[0..15]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=20.0.0.2:80; force_snat);) table=??(lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted), action=(next;) @@ -9887,7 +9931,7 @@ AT_CAPTURE_FILE([R1flows_force_skip_snat]) AT_CHECK([grep "lr_in_dnat " R1flows_force_skip_snat | ovn_strip_lflows], [0], [dnl table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.16.0.10 && ct_tcp && ct_tcp.dst == 80), action=(flags.skip_snat_for_lb = 1; reg4 = 172.16.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; skip_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.16.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(flags.skip_snat_for_lb = 1; reg4 = 172.16.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; skip_snat);) table=??(lr_in_dnat ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4.dst == 172.16.0.10 && reg4 == 10.0.0.2 && reg2[[0..15]] == 80), action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.2:80; skip_snat);) table=??(lr_in_dnat ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4.dst == 172.16.0.10 && reg4 == 20.0.0.2 && reg2[[0..15]] == 80), action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=20.0.0.2:80; skip_snat);) table=??(lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted), action=(next;) @@ -9911,8 +9955,8 @@ AT_CAPTURE_FILE([R1flows_2lbs]) AT_CHECK([grep "lr_in_dnat " R1flows_2lbs | ovn_strip_lflows], [0], [dnl table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.16.0.10 && ct_tcp && ct_tcp.dst == 80), action=(flags.skip_snat_for_lb = 1; reg4 = 172.16.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; skip_snat);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.16.0.20 && ct_tcp && ct_tcp.dst == 80), action=(flags.force_snat_for_lb = 1; reg4 = 172.16.0.20; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; force_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.16.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(flags.skip_snat_for_lb = 1; reg4 = 172.16.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; skip_snat);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.16.0.20 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(flags.force_snat_for_lb = 1; reg4 = 172.16.0.20; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.2:80,20.0.0.2:80; force_snat);) table=??(lr_in_dnat ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4.dst == 172.16.0.10 && reg4 == 10.0.0.2 && reg2[[0..15]] == 80), action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.2:80; skip_snat);) table=??(lr_in_dnat ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4.dst == 172.16.0.10 && reg4 == 20.0.0.2 && reg2[[0..15]] == 80), action=(flags.skip_snat_for_lb = 1; ct_lb_mark(backends=20.0.0.2:80; skip_snat);) table=??(lr_in_dnat ), priority=150 , match=(reg9[[6]] == 1 && ct.new && ip4.dst == 172.16.0.20 && reg4 == 10.0.0.2 && reg2[[0..15]] == 80), action=(flags.force_snat_for_lb = 1; ct_lb_mark(backends=10.0.0.2:80; force_snat);) @@ -12370,7 +12414,7 @@ check ovn-nbctl --wait=sb ls-lb-add sw0 lb1 check_engine_stats lflow norecompute compute CHECK_NO_CHANGE_AFTER_RECOMPUTE -lb_lflow_uuid=$(fetch_column Logical_flow _uuid match='"ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80"') +lb_lflow_uuid=$(fetch_column Logical_flow _uuid match='"ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80"') sw0_uuid=$(fetch_column Datapath_Binding _uuid external_ids:name=sw0) lb_lflow_dp=$(ovn-sbctl --bare --columns logical_datapath list logical_flow $lb_lflow_uuid) @@ -12408,7 +12452,7 @@ check ovn-nbctl --wait=sb set load_balancer lb1 options:foo=bar check_engine_stats lflow recompute nocompute CHECK_NO_CHANGE_AFTER_RECOMPUTE -lb_lflow_uuid=$(fetch_column Logical_flow _uuid match='"ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80"') +lb_lflow_uuid=$(fetch_column Logical_flow _uuid match='"ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80"') check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats check ovn-nbctl --wait=sb clear load_balancer lb2 vips @@ -12489,7 +12533,7 @@ check ovn-nbctl --wait=sb clear load_balancer lb1 vips AT_CHECK([ovn-sbctl --bare --columns logical_datapath list logical_flow $lb_lflow_uuid], [1], [ignore], [ignore]) -lb_lflow_uuid=$(fetch_column Logical_flow _uuid match='"ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80"') +lb_lflow_uuid=$(fetch_column Logical_flow _uuid match='"ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80"') AT_CHECK([test "$lb_lflow_uuid" = ""]) @@ -12506,7 +12550,7 @@ check ovn-nbctl --wait=sb ls-lb-add sw1 lb3 check_engine_stats lflow norecompute compute CHECK_NO_CHANGE_AFTER_RECOMPUTE -lb_lflow_uuid=$(fetch_column Logical_flow _uuid match='"ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80"') +lb_lflow_uuid=$(fetch_column Logical_flow _uuid match='"ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80"') lb_lflow_dp=$(ovn-sbctl --bare --columns logical_datapath list logical_flow $lb_lflow_uuid) AT_CHECK([test "$lb_lflow_dp" = ""]) @@ -15983,7 +16027,7 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | ovn_strip_lflows], [0], [dnl AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) table=??(lr_in_dnat ), priority=10 , match=(ip && ct.new && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_commit_to_zone(dnat);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && ct_tcp && ct_tcp.dst == 8082 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && reg1[[16..23]] == 6 && reg1[[0..15]] == 8082 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);) table=??(lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted), action=(next;) table=??(lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new && !ct.rpl), action=(ct_commit_nat;) table=??(lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) @@ -16027,7 +16071,7 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | ovn_strip_lflows], [0], [dnl AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) table=??(lr_in_dnat ), priority=10 , match=(ip && ct.new && inport == "lr0-public" && is_chassis_resident("cr-lr0-public")), action=(ct_commit_to_zone(dnat);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && ct_tcp && ct_tcp.dst == 8082 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && reg1[[16..23]] == 6 && reg1[[0..15]] == 8082 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);) table=??(lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted), action=(next;) table=??(lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new && !ct.rpl), action=(ct_commit_nat;) table=??(lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) @@ -16073,7 +16117,7 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | ovn_strip_lflows], [0], [dnl AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) table=??(lr_in_dnat ), priority=10 , match=(ip && ct.new), action=(ct_commit_to_zone(dnat);) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && ct_tcp && ct_tcp.dst == 8082), action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && reg1[[16..23]] == 6 && reg1[[0..15]] == 8082), action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);) table=??(lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted), action=(next;) table=??(lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new && !ct.rpl), action=(ct_commit_nat;) table=??(lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) @@ -16114,7 +16158,7 @@ AT_CHECK([grep "lr_in_defrag" lr0flows | ovn_strip_lflows], [0], [dnl AT_CHECK([grep "lr_in_dnat" lr0flows | ovn_strip_lflows], [0], [dnl table=??(lr_in_dnat ), priority=0 , match=(1), action=(next;) - table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && ct_tcp && ct_tcp.dst == 8082), action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);) + table=??(lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 172.168.0.100 && reg1[[16..23]] == 6 && reg1[[0..15]] == 8082), action=(ct_lb_mark(backends=10.0.0.50:82,10.0.0.60:82);) table=??(lr_in_dnat ), priority=50 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted), action=(next;) table=??(lr_in_dnat ), priority=50 , match=(ct.rel && !ct.est && !ct.new && !ct.rpl), action=(ct_commit_nat;) table=??(lr_in_dnat ), priority=70 , match=(ct.est && !ct.rel && !ct.new && !ct.rpl && ct_mark.natted && ct_mark.force_snat == 1), action=(flags.force_snat_for_lb = 1; next;) diff --git a/tests/ovn.at b/tests/ovn.at index 2986f421648c..a47f82b4e13b 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -154,14 +154,7 @@ ct_mark.natted = ct_mark[1] ct_mark.obs_collector_id = ct_mark[16..23] ct_mark.obs_stage = ct_mark[4..5] ct_mark.skip_snat = ct_mark[2] -ct_proto = NXM_NX_CT_NW_PROTO -ct_sctp = ct_proto == 132 -ct_sctp.dst = NXM_NX_CT_TP_DST ct_state = NXM_NX_CT_STATE -ct_tcp = ct_proto == 6 -ct_tcp.dst = NXM_NX_CT_TP_DST -ct_udp = ct_proto == 17 -ct_udp.dst = NXM_NX_CT_TP_DST ]]) AT_CLEANUP @@ -840,8 +833,8 @@ next(); Syntax error at `)' expecting "pipeline" or "table". next(10; Syntax error at `;' expecting `)'. -#next(30); -# "next" action cannot advance beyond table 29. +next(32); + "next" action cannot advance beyond table 32. next(table=lflow_table); formats as next; @@ -26700,14 +26693,14 @@ OVS_WAIT_FOR_OUTPUT( ovn-sbctl dump-flows sw0 | grep ct_lb_mark | grep priority=120 | sed 's/table=..//'], 0, [dnl (ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark;) - (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80; hash_fields="ip_dst,ip_src,tcp_dst,tcp_src");) + (ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80; hash_fields="ip_dst,ip_src,tcp_dst,tcp_src");) ]) AT_CAPTURE_FILE([sbflows2]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows > sbflows2 ovn-sbctl dump-flows lr0 | grep ct_lb_mark | grep priority=120 | sed 's/table=..//'], 0, - [ (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80; hash_fields="ip_dst,ip_src,tcp_dst,tcp_src");) + [ (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=10.0.0.3:80,20.0.0.3:80; hash_fields="ip_dst,ip_src,tcp_dst,tcp_src");) ]) # get the svc monitor mac. @@ -26743,14 +26736,14 @@ ovn-sbctl dump-flows sw0 > sbflows3 AT_CHECK( [grep "ip4.dst == 10.0.0.10" sbflows3 | grep priority=120 |\ ovn_strip_lflows], [0], [dnl - table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && ct_tcp.dst == 80), action=(drop;) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(drop;) table=??(ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && ip4.dst == 10.0.0.10 && tcp.dst == 80), action=(reg4 = 10.0.0.10; reg2[[0..15]] = 80; ct_lb_mark;) ]) AT_CAPTURE_FILE([sbflows4]) ovn-sbctl dump-flows lr0 > sbflows4 AT_CHECK([grep lr_in_dnat sbflows4 | grep priority=120 | sed 's/table=..//' | sort], [0], [dnl - (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && ct_tcp && ct_tcp.dst == 80 && is_chassis_resident("cr-lr0-public")), action=(drop;) + (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip4 && ip4.dst == 10.0.0.10 && reg1[[16..23]] == 6 && reg1[[0..15]] == 80 && is_chassis_resident("cr-lr0-public")), action=(drop;) ]) # Delete sw0-p1 @@ -26906,14 +26899,14 @@ OVS_WAIT_FOR_OUTPUT( ovn-sbctl dump-flows sw0 | grep ct_lb_mark | grep priority=120 | sed 's/table=..//'], 0, [dnl (ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && ip6.dst == 2002::a && tcp.dst == 80), action=(xxreg1 = 2002::a; reg2[[0..15]] = 80; ct_lb_mark;) - (ls_in_lb ), priority=120 , match=(ct.new && ip6.dst == 2002::a && ct_tcp.dst == 80), action=(xxreg1 = 2002::a; reg2[[0..15]] = 80; ct_lb_mark(backends=[[2001::3]]:80,[[2002::3]]:80; hash_fields="ipv6_dst,ipv6_src,tcp_dst,tcp_src");) + (ls_in_lb ), priority=120 , match=(ct.new && ip6.dst == 2002::a && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(xxreg1 = 2002::a; reg2[[0..15]] = 80; ct_lb_mark(backends=[[2001::3]]:80,[[2002::3]]:80; hash_fields="ipv6_dst,ipv6_src,tcp_dst,tcp_src");) ]) AT_CAPTURE_FILE([sbflows2]) OVS_WAIT_FOR_OUTPUT( [ovn-sbctl dump-flows > sbflows2 ovn-sbctl dump-flows lr0 | grep ct_lb_mark | grep priority=120 | sed 's/table=..//'], 0, - [ (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip6 && ip6.dst == 2002::a && ct_tcp && ct_tcp.dst == 80 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=[[2001::3]]:80,[[2002::3]]:80; hash_fields="ipv6_dst,ipv6_src,tcp_dst,tcp_src");) + [ (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip6 && ip6.dst == 2002::a && reg1[[16..23]] == 6 && reg1[[0..15]] == 80 && is_chassis_resident("cr-lr0-public")), action=(ct_lb_mark(backends=[[2001::3]]:80,[[2002::3]]:80; hash_fields="ipv6_dst,ipv6_src,tcp_dst,tcp_src");) ]) # get the svc monitor mac. @@ -26948,14 +26941,14 @@ ovn-sbctl dump-flows sw0 > sbflows3 AT_CHECK( [grep "ip6.dst == 2002::a" sbflows3 | grep priority=120 |\ ovn_strip_lflows], [0], [dnl - table=??(ls_in_lb ), priority=120 , match=(ct.new && ip6.dst == 2002::a && ct_tcp.dst == 80), action=(drop;) + table=??(ls_in_lb ), priority=120 , match=(ct.new && ip6.dst == 2002::a && reg1[[16..23]] == 6 && reg1[[0..15]] == 80), action=(drop;) table=??(ls_in_pre_stateful ), priority=120 , match=(reg0[[2]] == 1 && ip6.dst == 2002::a && tcp.dst == 80), action=(xxreg1 = 2002::a; reg2[[0..15]] = 80; ct_lb_mark;) ]) AT_CAPTURE_FILE([sbflows4]) ovn-sbctl dump-flows lr0 > sbflows4 AT_CHECK([grep lr_in_dnat sbflows4 | grep priority=120 | sed 's/table=..//' | sort], [0], [dnl - (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip6 && ip6.dst == 2002::a && ct_tcp && ct_tcp.dst == 80 && is_chassis_resident("cr-lr0-public")), action=(drop;) + (lr_in_dnat ), priority=120 , match=(ct.new && !ct.rel && ip6 && ip6.dst == 2002::a && reg1[[16..23]] == 6 && reg1[[0..15]] == 80 && is_chassis_resident("cr-lr0-public")), action=(drop;) ]) # Delete sw0-p1 @@ -37334,10 +37327,10 @@ check_default_flows() { # Tables OFTABLE_CHK_LB_HAIRPIN and OFTABLE_CT_SNAT_HAIRPIN are part # of the chk_lb_hairpin and ct_snat_to_vip actions respectively and # it's OK if they don't have a default action. - # Tables OFTABLE_CT_ORIG_NW_DST_LOAD, OFTABLE_CT_ORIG_IP6_DST_LOAD and - # OFTABLE_CT_ORIG_TP_DST_LOAD are part of ct_nw_dst(), ct_ip6_dst() - # and ct_tp_dst() actions respectively and it's OK for them to not - # have default flows. + # Tables OFTABLE_CT_ORIG_NW_DST_LOAD, OFTABLE_CT_ORIG_IP6_DST_LOAD, + # OFTABLE_CT_ORIG_TP_DST_LOAD and OFTABLE_CT_ORIG_PROTO_LOAD are part + # of ct_nw_dst(), ct_ip6_dst(), ct_tp_dst() and ct_proto() actions + # respectively and it's OK for them to not have default flows. # Table OFTABLE_FLOOD_REMOTE_CHASSIS is part of flood_remote action # and it's OK for it to not have default flows. # Table OFTABLE_CT_STATE_SAVE is the implementation of the @@ -37348,6 +37341,7 @@ check_default_flows() { OFTABLE_CT_ORIG_NW_DST_LOAD | \ OFTABLE_CT_ORIG_IP6_DST_LOAD | \ OFTABLE_CT_ORIG_TP_DST_LOAD | \ + OFTABLE_CT_ORIG_PROTO_LOAD | \ OFTABLE_FLOOD_REMOTE_CHASSIS | \ OFTABLE_CT_STATE_SAVE) continue ;; diff --git a/tests/system-ovn-kmod.at b/tests/system-ovn-kmod.at index 48d7e86f4cfa..e9a4eece6493 100644 --- a/tests/system-ovn-kmod.at +++ b/tests/system-ovn-kmod.at @@ -193,6 +193,10 @@ tcp,orig=(src=172.16.1.2,dst=172.16.1.101,sport=<cleared>,dport=<cleared>),reply ]) NS_CHECK_EXEC([alice1], [nc -z 172.16.1.101 8081]) +dnl There shouldn't be any DP flow with both +est and ct_tuple4. Otherwise HW +dnl offload may not work. +AT_CHECK([ovs-appctl dpctl/dump-flows | grep 'ct_tuple4' | grep '+est'], [1], [ignore]) + # Flush conntrack entries for easier output parsing of next test. AT_CHECK([ovs-appctl dpctl/flush-conntrack]) @@ -283,6 +287,10 @@ tcp,orig=(src=192.168.1.200,dst=192.168.1.2,sport=<cleared>,dport=<cleared>),rep ]) NS_CHECK_EXEC([foo1], [nc -z 192.168.1.100 8081]) +dnl There shouldn't be any DP flow with both +est and ct_tuple4. Otherwise HW +dnl offload may not work. +AT_CHECK([ovs-appctl dpctl/dump-flows | grep 'ct_tuple4' | grep '+est'], [1], [ignore]) + OVN_CLEANUP_CONTROLLER([hv1]) as ovn-sb OVS_APP_EXIT_AND_WAIT([ovsdb-server]) @@ -1737,6 +1745,12 @@ ovs-appctl dpctl/dump-flows -m \ check_flow_assured "$flow" done +ovs-ofctl dump-flows br-int > oflow +ovn-sbctl lflow-list > lflow +dnl There shouldn't be any DP flow with both +est and ct_tuple4. Otherwise HW +dnl offload may not work. +AT_CHECK([ovs-appctl dpctl/dump-flows | grep 'ct_tuple4' | grep '+est'], [1], [ignore]) + ovs-appctl revalidator/resume OVS_APP_EXIT_AND_WAIT([ovn-controller]) diff --git a/tests/test-ovn.c b/tests/test-ovn.c index 1b63c05d2cfa..1580f44c4739 100644 --- a/tests/test-ovn.c +++ b/tests/test-ovn.c @@ -1388,6 +1388,7 @@ test_parse_actions(struct ovs_cmdl_context *ctx OVS_UNUSED) .ct_nw_dst_load_table = OFTABLE_CT_ORIG_NW_DST_LOAD, .ct_ip6_dst_load_table = OFTABLE_CT_ORIG_IP6_DST_LOAD, .ct_tp_dst_load_table = OFTABLE_CT_ORIG_TP_DST_LOAD, + .ct_proto_load_table = OFTABLE_CT_ORIG_PROTO_LOAD, .flood_remote_table = OFTABLE_FLOOD_REMOTE_CHASSIS, .ct_state_save_table = OFTABLE_CT_STATE_SAVE, .lflow_uuid.parts = diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c index 08a22e7c2108..a63a3be198c9 100644 --- a/utilities/ovn-trace.c +++ b/utilities/ovn-trace.c @@ -3172,6 +3172,40 @@ execute_ct_save_state(const struct ovnact_result *dl, struct flow *uflow, ds_destroy(&s); } +static void +execute_ct_orig_tp_dst(const struct ovnact_result *res, struct flow *uflow, + struct ovs_list *super) +{ + /* For ovn-trace, we simulate ct_tp_dst() by returning the current + * packet's destination port. */ + struct mf_subfield sf = expr_resolve_field(&res->dst); + union mf_subvalue sv = { .be16_int = uflow->tp_dst }; + mf_write_subfield_flow(&sf, &sv, uflow); + + struct ds s = DS_EMPTY_INITIALIZER; + expr_field_format(&res->dst, &s); + ovntrace_node_append(super, OVNTRACE_NODE_MODIFY, "%s = %"PRIu16, + ds_cstr(&s), ntohs(uflow->tp_dst)); + ds_destroy(&s); +} + +static void +execute_ct_orig_proto(const struct ovnact_result *res, struct flow *uflow, + struct ovs_list *super) +{ + /* For ovn-trace, we simulate ct_proto() by returning the current + * packet's protocol. */ + struct mf_subfield sf = expr_resolve_field(&res->dst); + union mf_subvalue sv = { .u8_val = uflow->nw_proto }; + mf_write_subfield_flow(&sf, &sv, uflow); + + struct ds s = DS_EMPTY_INITIALIZER; + expr_field_format(&res->dst, &s); + ovntrace_node_append(super, OVNTRACE_NODE_MODIFY, "%s = %"PRIu8, + ds_cstr(&s), uflow->nw_proto); + ds_destroy(&s); +} + static void execute_mirror(const struct ovnact_mirror *mirror, const struct ovntrace_datapath *dp, @@ -3539,6 +3573,10 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len, case OVNACT_CT_ORIG_IP6_DST: break; case OVNACT_CT_ORIG_TP_DST: + execute_ct_orig_tp_dst(ovnact_get_CT_ORIG_TP_DST(a), uflow, super); + break; + case OVNACT_CT_ORIG_PROTO: + execute_ct_orig_proto(ovnact_get_CT_ORIG_PROTO(a), uflow, super); break; case OVNACT_FLOOD_REMOTE: ovntrace_node_append(super, OVNTRACE_NODE_OUTPUT, -- 2.38.1 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev