Skip to content

Commit

Permalink
resolve route instability issue by tracking if an incming offloading …
Browse files Browse the repository at this point in the history
…rule has been installed to arriving port
  • Loading branch information
byteocean committed Aug 1, 2023
1 parent 87e7c4b commit 5a55108
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 10 deletions.
4 changes: 4 additions & 0 deletions include/dp_flow.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ struct flow_value {
uint8_t orig : 4;
uint8_t reply : 4;
} offload_flags;
struct {
uint8_t pf0 : 4;
uint8_t pf1 : 4;
} incoming_flow_offloaded_flag;
struct dp_ref ref_count;
union {
enum dp_flow_tcp_state tcp_state;
Expand Down
35 changes: 26 additions & 9 deletions src/dp_cntrack.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,35 +70,52 @@ static __rte_always_inline void dp_cntrack_init_flow_offload_flags(struct flow_v
}


static __rte_always_inline void dp_cntrack_change_flow_offload_flags(struct flow_value *flow_val, struct dp_flow *df)
static __rte_always_inline void dp_cntrack_change_flow_offload_flags(struct rte_mbuf *m, struct flow_value *flow_val, struct dp_flow *df)
{
bool offload_check = false;

if (!offload_mode_enabled)
return;

if (df->flags.flow_type == DP_FLOW_TYPE_INCOMING) {
if (m->port == dp_port_get_pf0_id())
offload_check = flow_val->incoming_flow_offloaded_flag.pf0;
else
offload_check = flow_val->incoming_flow_offloaded_flag.pf1;
}

if (df->flags.dir == DP_FLOW_DIR_ORG) {

if (flow_val->offload_flags.orig == DP_FLOW_NON_OFFLOAD)
flow_val->offload_flags.orig = DP_FLOW_OFFLOAD_INSTALL;
else if (flow_val->offload_flags.orig == DP_FLOW_OFFLOAD_INSTALL)
else if (flow_val->offload_flags.orig == DP_FLOW_OFFLOAD_INSTALL) {
/* Despite the incoming flow is offloaded to one of the pf ports, pkts can arrive on another one */
/* So we need to check if the incoming flow is offloaded on the current port, if not, we hold the change of offload flags and do another offloading */
if (df->flags.flow_type == DP_FLOW_TYPE_INCOMING && !offload_check)
return;
flow_val->offload_flags.orig = DP_FLOW_OFFLOADED;
}
} else if (df->flags.dir == DP_FLOW_DIR_REPLY) {

if (flow_val->offload_flags.reply == DP_FLOW_NON_OFFLOAD)
flow_val->offload_flags.reply = DP_FLOW_OFFLOAD_INSTALL;
else if (flow_val->offload_flags.reply == DP_FLOW_OFFLOAD_INSTALL)
else if (flow_val->offload_flags.reply == DP_FLOW_OFFLOAD_INSTALL) {
if (df->flags.flow_type == DP_FLOW_TYPE_INCOMING && !offload_check)
return;
flow_val->offload_flags.reply = DP_FLOW_OFFLOADED;
}
}
}

static __rte_always_inline void dp_cntrack_set_timeout_tcp_flow(struct flow_value *flow_val, struct dp_flow *df)
static __rte_always_inline void dp_cntrack_set_timeout_tcp_flow(struct flow_value *flow_val, struct dp_flow *df, struct rte_mbuf *m)
{

if (flow_val->l4_state.tcp_state == DP_FLOW_TCP_STATE_ESTABLISHED) {
flow_val->timeout_value = DP_FLOW_TCP_EXTENDED_TIMEOUT;
dp_cntrack_change_flow_offload_flags(flow_val, df);
dp_cntrack_change_flow_offload_flags(m, flow_val, df);
} else if (flow_val->l4_state.tcp_state == DP_FLOW_TCP_STATE_FINWAIT
|| flow_val->l4_state.tcp_state == DP_FLOW_TCP_STATE_RST_FIN) {
dp_cntrack_change_flow_offload_flags(flow_val, df);
dp_cntrack_change_flow_offload_flags(m, flow_val, df);
flow_val->timeout_value = flow_timeout;
} else
flow_val->timeout_value = flow_timeout;
Expand Down Expand Up @@ -192,7 +209,7 @@ static __rte_always_inline void dp_set_flow_offload_flag(struct rte_mbuf *m, str
if (flow_val->nf_info.nat_type == DP_FLOW_NAT_TYPE_NETWORK_NEIGH
|| flow_val->nf_info.nat_type == DP_FLOW_LB_TYPE_FORWARD
|| flow_val->nf_info.nat_type == DP_FLOW_LB_TYPE_LOCAL_NEIGH_TRAFFIC) {
dp_cntrack_change_flow_offload_flags(flow_val, df);
dp_cntrack_change_flow_offload_flags(m, flow_val, df);
} else {

// recirc pkt shall not change flow's state because its ancestor has already done
Expand All @@ -201,7 +218,7 @@ static __rte_always_inline void dp_set_flow_offload_flag(struct rte_mbuf *m, str

// when to offload reply pkt of a tcp flow is determined in dp_cntrack_set_timeout_tcp_flow
if (df->l4_type != IPPROTO_TCP)
dp_cntrack_change_flow_offload_flags(flow_val, df);
dp_cntrack_change_flow_offload_flags(m, flow_val, df);
}
}

Expand Down Expand Up @@ -266,7 +283,7 @@ int dp_cntrack_handle(struct rte_node *node, struct rte_mbuf *m, struct dp_flow
if (df->l4_type == IPPROTO_TCP && !dp_get_pkt_mark(m)->flags.is_recirc) {
tcp_hdr = (struct rte_tcp_hdr *) (ipv4_hdr + 1);
dp_cntrack_tcp_state(flow_val, tcp_hdr);
dp_cntrack_set_timeout_tcp_flow(flow_val, df);
dp_cntrack_set_timeout_tcp_flow(flow_val, df, m);
}
df->conntrack = flow_val;
dp_cntrack_set_pkt_offload_decision(df);
Expand Down
10 changes: 9 additions & 1 deletion src/rte_flow/dp_rte_flow_traffic_forward.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,15 @@ static __rte_always_inline int dp_offload_handle_tunnel_encap_traffic(struct rte

static __rte_always_inline int dp_offload_handle_tunnel_decap_traffic(struct rte_mbuf *m, struct dp_flow *df)
{
bool cross_pf_port = m->port == dp_port_get_pf0_id() ? false : true;
bool cross_pf_port;

if (m->port == dp_port_get_pf0_id()) {
cross_pf_port = false;
df->conntrack->incoming_flow_offloaded_flag.pf0 = true;
} else {
cross_pf_port = true;
df->conntrack->incoming_flow_offloaded_flag.pf1 = true;
}

struct rte_flow_attr attr;
int hairpin_pattern_cnt = 0;
Expand Down

0 comments on commit 5a55108

Please sign in to comment.