diff --git a/include/dp_error.h b/include/dp_error.h index a3b99e0b3..c82762c3c 100644 --- a/include/dp_error.h +++ b/include/dp_error.h @@ -11,6 +11,9 @@ extern "C" { #include #include +#define DP_RETURN_REF_COUNT_REDUCE_DROP(var, X) \ + do { dp_ref_dec(&(var)->ref_count); return X; } while (0) + #define DP_OK 0 #define DP_ERROR (-RTE_MAX_ERRNO) #define _DP_GRPC_ERRCODES (DP_ERROR-1) diff --git a/src/dp_cntrack.c b/src/dp_cntrack.c index bf911576f..bcef91394 100644 --- a/src/dp_cntrack.c +++ b/src/dp_cntrack.c @@ -305,6 +305,7 @@ int dp_cntrack_handle(struct rte_mbuf *m, struct dp_flow *df) return DP_ERROR; df->conntrack = flow_val; + dp_ref_inc(&flow_val->ref_count); dp_cntrack_set_pkt_offload_decision(df); return DP_OK; diff --git a/src/nodes/conntrack_node.c b/src/nodes/conntrack_node.c index 59d665508..c1d1db047 100644 --- a/src/nodes/conntrack_node.c +++ b/src/nodes/conntrack_node.c @@ -80,10 +80,10 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod case DP_VNF_TYPE_ALIAS_PFX: return CONNTRACK_NEXT_FIREWALL; case DP_VNF_TYPE_UNDEFINED: - return CONNTRACK_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(df->conntrack, CONNTRACK_NEXT_DROP); } - return CONNTRACK_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(df->conntrack, CONNTRACK_NEXT_DROP); } static uint16_t conntrack_node_process(struct rte_graph *graph, diff --git a/src/nodes/dnat_node.c b/src/nodes/dnat_node.c index 26c1383b3..c67b76eff 100644 --- a/src/nodes/dnat_node.c +++ b/src/nodes/dnat_node.c @@ -68,7 +68,7 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod // then it is a premature dnat pkt for network nat (sent before any outgoing traffic from VM, // and it cannot be a standalone new incoming flow for network NAT), // silently drop it now. - return DNAT_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(cntrack, DNAT_NEXT_DROP); } ipv4_hdr = dp_get_ipv4_hdr(m); @@ -84,7 +84,7 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod dp_delete_flow(&cntrack->flow_key[DP_FLOW_DIR_REPLY], cntrack); dp_set_ipaddr4(&cntrack->flow_key[DP_FLOW_DIR_REPLY].l3_src, ntohl(ipv4_hdr->dst_addr)); if (DP_FAILED(dp_add_flow(&cntrack->flow_key[DP_FLOW_DIR_REPLY], cntrack))) - return DNAT_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(cntrack, DNAT_NEXT_DROP); dp_ref_inc(&cntrack->ref_count); } return DNAT_NEXT_IPV4_LOOKUP; @@ -102,7 +102,7 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod if (DP_FLOW_HAS_FLAG_DST_NAT(cntrack->flow_flags) && df->flow_dir == DP_FLOW_DIR_ORG) { if (cntrack->flow_key[DP_FLOW_DIR_REPLY].l3_src.is_v6) - return DNAT_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(cntrack, DNAT_NEXT_DROP); ipv4_hdr = dp_get_ipv4_hdr(m); ipv4_hdr->dst_addr = htonl(cntrack->flow_key[DP_FLOW_DIR_REPLY].l3_src.ipv4); df->nat_type = DP_NAT_CHG_DST_IP; @@ -114,7 +114,7 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod /* We already know what to do */ if (DP_FLOW_HAS_FLAG_SRC_NAT(cntrack->flow_flags) && df->flow_dir == DP_FLOW_DIR_REPLY) { if (cntrack->flow_key[DP_FLOW_DIR_ORG].l3_src.is_v6) - return DNAT_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(cntrack, DNAT_NEXT_DROP); ipv4_hdr = dp_get_ipv4_hdr(m); ipv4_hdr->dst_addr = htonl(cntrack->flow_key[DP_FLOW_DIR_ORG].l3_src.ipv4); if (cntrack->nf_info.nat_type == DP_FLOW_NAT_TYPE_NETWORK_LOCAL) { @@ -125,7 +125,7 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod memset(&icmp_err_ip_info, 0, sizeof(icmp_err_ip_info)); dp_get_icmp_err_ip_hdr(m, &icmp_err_ip_info); if (!icmp_err_ip_info.err_ipv4_hdr || !icmp_err_ip_info.l4_src_port || !icmp_err_ip_info.l4_dst_port) - return DNAT_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(cntrack, DNAT_NEXT_DROP); icmp_err_ip_info.err_ipv4_hdr->src_addr = htonl(cntrack->flow_key[DP_FLOW_DIR_ORG].l3_src.ipv4); icmp_err_ip_info.err_ipv4_hdr->hdr_checksum = cntrack->nf_info.icmp_err_ip_cksum; dp_change_icmp_err_l4_src_port(m, &icmp_err_ip_info, cntrack->flow_key[DP_FLOW_DIR_ORG].src.port_src); @@ -155,7 +155,7 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod } if (DP_FAILED(dp_ipv6_from_ipaddr(&nat_ipv6, &cntrack->flow_key[DP_FLOW_DIR_ORG].l3_src)) || DP_FAILED(dp_nat_chg_ipv4_to_ipv6_hdr(df, m, &nat_ipv6))) - return DNAT_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(cntrack, DNAT_NEXT_DROP); return DNAT_NEXT_IPV6_LOOKUP; } @@ -166,7 +166,7 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod else if (df->l3_type == RTE_ETHER_TYPE_IPV6) return DNAT_NEXT_IPV6_LOOKUP; else - return DNAT_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(cntrack, DNAT_NEXT_DROP); } static uint16_t dnat_node_process(struct rte_graph *graph, diff --git a/src/nodes/ipip_encap_node.c b/src/nodes/ipip_encap_node.c index 9aca9a3fb..2e0b54541 100644 --- a/src/nodes/ipip_encap_node.c +++ b/src/nodes/ipip_encap_node.c @@ -76,6 +76,7 @@ static __rte_always_inline rte_edge_t get_next_index(struct rte_node *node, stru m->ol_flags |= RTE_MBUF_F_TX_TUNNEL_IP; if (df->nat_type == DP_LB_RECIRC) { + dp_ref_dec(&df->conntrack->ref_count); dp_get_pkt_mark(m)->flags.is_recirc = true; return IPIP_ENCAP_NEXT_CLS; } diff --git a/src/nodes/ipv4_lookup_node.c b/src/nodes/ipv4_lookup_node.c index c25ca39ee..ca86e7889 100644 --- a/src/nodes/ipv4_lookup_node.c +++ b/src/nodes/ipv4_lookup_node.c @@ -37,11 +37,11 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod out_port = dp_get_ip4_out_port(in_port, df->tun_info.dst_vni, df, &route, &ip); if (!out_port) - return IPV4_LOOKUP_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(df->conntrack, IPV4_LOOKUP_NEXT_DROP); if (out_port->is_pf) { if (in_port->is_pf) - return IPV4_LOOKUP_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(df->conntrack, IPV4_LOOKUP_NEXT_DROP); dp_copy_ipv6(&df->tun_info.ul_dst_addr6, &route.nh_ipv6); out_port = dp_multipath_get_pf(df->dp_flow_hash); } else { diff --git a/src/nodes/ipv6_lookup_node.c b/src/nodes/ipv6_lookup_node.c index 83be15bb6..50b969c41 100644 --- a/src/nodes/ipv6_lookup_node.c +++ b/src/nodes/ipv6_lookup_node.c @@ -32,11 +32,11 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod out_port = dp_get_ip6_out_port(in_port, t_vni, df, &route, &ip); if (!out_port) - return IPV6_LOOKUP_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(df->conntrack, IPV6_LOOKUP_NEXT_DROP); if (out_port->is_pf) { if (in_port->is_pf) - return IPV6_LOOKUP_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(df->conntrack, IPV6_LOOKUP_NEXT_DROP); dp_copy_ipv6(&df->tun_info.ul_dst_addr6, &route.nh_ipv6); } else { // next hop is known, fill in Ether header diff --git a/src/nodes/lb_node.c b/src/nodes/lb_node.c index b0636912a..20acd749e 100644 --- a/src/nodes/lb_node.c +++ b/src/nodes/lb_node.c @@ -64,12 +64,12 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod } /* ICMP error types conntrack keys are built from original TCP/UDP header, so let them slip */ if (df->l4_info.icmp_field.icmp_type != DP_IP_ICMP_TYPE_ERROR) - return LB_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(df->conntrack, LB_NEXT_DROP); } target_ip6 = dp_lb_get_backend_ip(&cntrack->flow_key[DP_FLOW_DIR_ORG], vni); if (!target_ip6) - return LB_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(df->conntrack, LB_NEXT_DROP); dp_copy_ipv6(&df->tun_info.ul_src_addr6, &df->tun_info.ul_dst_addr6); // same trick as in packet_relay_node.c dp_copy_ipv6(&df->tun_info.ul_dst_addr6, target_ip6); diff --git a/src/nodes/packet_relay_node.c b/src/nodes/packet_relay_node.c index 50c80104e..fb6936c03 100644 --- a/src/nodes/packet_relay_node.c +++ b/src/nodes/packet_relay_node.c @@ -24,7 +24,7 @@ static __rte_always_inline rte_edge_t lb_nnat_icmp_reply(struct dp_flow *df, str uint32_t cksum; if (icmp_hdr->icmp_type != RTE_IP_ICMP_ECHO_REQUEST) - return PACKET_RELAY_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(df->conntrack, PACKET_RELAY_NEXT_DROP); // rewrite the packet and send it back icmp_hdr->icmp_type = RTE_IP_ICMP_ECHO_REPLY; @@ -53,7 +53,7 @@ static __rte_always_inline rte_edge_t lb_nnat_icmpv6_reply(struct dp_flow *df, s union dp_ipv6 temp_addr; if (icmp6_hdr->icmp_type != DP_ICMPV6_ECHO_REQUEST) - return PACKET_RELAY_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(df->conntrack, PACKET_RELAY_NEXT_DROP); icmp6_hdr->icmp_type = DP_ICMPV6_ECHO_REPLY; @@ -92,7 +92,7 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod if (df->l4_type == IPPROTO_ICMPV6) return lb_nnat_icmpv6_reply(df, m); - return PACKET_RELAY_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(df->conntrack, PACKET_RELAY_NEXT_DROP); } static uint16_t packet_relay_node_process(struct rte_graph *graph, diff --git a/src/nodes/snat_node.c b/src/nodes/snat_node.c index 94018e5b3..f6cce0748 100644 --- a/src/nodes/snat_node.c +++ b/src/nodes/snat_node.c @@ -156,7 +156,7 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod && (df->l3_type == RTE_ETHER_TYPE_IPV4 || df->l3_type == RTE_ETHER_TYPE_IPV6)) { color = rte_meter_srtcm_color_blind_check(&in_port->port_srtcm, &in_port->port_srtcm_profile, rte_rdtsc(), df->l3_payload_length); if (color == RTE_COLOR_RED) - return SNAT_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(df->conntrack, SNAT_NEXT_DROP); } if (!cntrack) @@ -173,7 +173,7 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod if (snat_data && (snat_data->vip_ip != 0 || snat_data->nat_ip != 0) && df->flow_type == DP_FLOW_SOUTH_NORTH) { if (DP_FAILED(dp_process_ipv4_snat(m, df, cntrack, port, snat_data))) - return SNAT_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(df->conntrack, SNAT_NEXT_DROP); } if (df->l3_type == RTE_ETHER_TYPE_IPV6 @@ -182,7 +182,7 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod && dp_is_ipv6_nat64(&df->dst.dst_addr6) ) { if (DP_FAILED(dp_process_ipv6_nat64(m, df, cntrack, port))) - return SNAT_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(df->conntrack, SNAT_NEXT_DROP); return SNAT_NEXT_FIREWALL; } @@ -191,7 +191,7 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod /* We already know what to do */ if (DP_FLOW_HAS_FLAG_SRC_NAT(cntrack->flow_flags) && df->flow_dir == DP_FLOW_DIR_ORG) { if (cntrack->flow_key[DP_FLOW_DIR_REPLY].l3_dst.is_v6) - return SNAT_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(df->conntrack, SNAT_NEXT_DROP); ipv4_hdr = dp_get_ipv4_hdr(m); ipv4_hdr->src_addr = htonl(cntrack->flow_key[DP_FLOW_DIR_REPLY].l3_dst.ipv4); @@ -212,7 +212,7 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod && (df->flow_dir == DP_FLOW_DIR_REPLY) ) { if (cntrack->flow_key[DP_FLOW_DIR_ORG].l3_dst.is_v6) - return SNAT_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(df->conntrack, SNAT_NEXT_DROP); ipv4_hdr = dp_get_ipv4_hdr(m); df->src.src_addr = ipv4_hdr->src_addr; ipv4_hdr->src_addr = htonl(cntrack->flow_key[DP_FLOW_DIR_ORG].l3_dst.ipv4); @@ -223,7 +223,7 @@ static __rte_always_inline rte_edge_t get_next_index(__rte_unused struct rte_nod if (DP_FLOW_HAS_FLAG_SRC_NAT64(cntrack->flow_flags) && df->flow_dir == DP_FLOW_DIR_ORG) { if (DP_FAILED(dp_nat_chg_ipv6_to_ipv4_hdr(df, m, port->iface.nat_ip, &dest_ip4))) - return SNAT_NEXT_DROP; + DP_RETURN_REF_COUNT_REDUCE_DROP(df->conntrack, SNAT_NEXT_DROP); if (cntrack->nf_info.nat_type == DP_FLOW_NAT_TYPE_NETWORK_LOCAL) { df->nat_port = cntrack->flow_key[DP_FLOW_DIR_REPLY].port_dst; diff --git a/src/nodes/tx_node.c b/src/nodes/tx_node.c index a6eece307..ae8d1532c 100644 --- a/src/nodes/tx_node.c +++ b/src/nodes/tx_node.c @@ -98,6 +98,7 @@ static uint16_t tx_node_process(struct rte_graph *graph, if (df->offload_state == DP_FLOW_OFFLOAD_INSTALL) if (DP_FAILED(dp_offload_handler(m, df))) DPNODE_LOG_WARNING(node, "Offloading handler failed"); + dp_ref_dec(&df->conntrack->ref_count); } }