diff --git a/include/dp_flow.h b/include/dp_flow.h index 93584e4ff..ec90bd6a3 100644 --- a/include/dp_flow.h +++ b/include/dp_flow.h @@ -156,6 +156,7 @@ void dp_free_flow(struct dp_ref *ref); void dp_free_network_nat_port(struct flow_value *cntrack); void dp_remove_nat_flows(uint16_t port_id, int nat_type); // TODO create proper enum! void dp_remove_neighnat_flows(uint32_t ipv4, uint32_t vni, uint16_t min_port, uint16_t max_port); +void dp_remove_vm_flows(uint16_t port_id, uint32_t ipv4, uint32_t vni); hash_sig_t dp_get_conntrack_flow_hash_value(struct flow_key *key); diff --git a/src/dp_flow.c b/src/dp_flow.c index 30113c24a..45e6ed250 100644 --- a/src/dp_flow.c +++ b/src/dp_flow.c @@ -425,6 +425,13 @@ void dp_process_aged_flows_non_offload(void) } } +static __rte_always_inline void dp_remove_flow(struct flow_value *flow_val) +{ + if (offload_mode_enabled) + dp_rte_flow_remove(flow_val); + dp_age_out_flow(flow_val); +} + void dp_remove_nat_flows(uint16_t port_id, int nat_type) { struct flow_value *flow_val = NULL; @@ -438,11 +445,8 @@ void dp_remove_nat_flows(uint16_t port_id, int nat_type) return; } // NAT/VIP are in 1:1 relation to a VM (port_id), no need to check IP:port - if (flow_val->created_port_id == port_id && flow_val->nf_info.nat_type == nat_type) { - if (offload_mode_enabled) - dp_rte_flow_remove(flow_val); - dp_age_out_flow(flow_val); - } + if (flow_val->created_port_id == port_id && flow_val->nf_info.nat_type == nat_type) + dp_remove_flow(flow_val); } } @@ -461,13 +465,32 @@ void dp_remove_neighnat_flows(uint32_t ipv4, uint32_t vni, uint16_t min_port, ui if (next_key->vni == vni && next_key->ip_dst == ipv4 && next_key->port_dst >= min_port && next_key->port_dst < max_port ) { - if (offload_mode_enabled) - dp_rte_flow_remove(flow_val); - dp_age_out_flow(flow_val); + dp_remove_flow(flow_val); + } + } +} + +void dp_remove_vm_flows(uint16_t port_id, uint32_t ipv4, uint32_t vni) +{ + struct flow_value *flow_val = NULL; + const struct flow_key *next_key; + uint32_t iter = 0; + int ret; + + while ((ret = rte_hash_iterate(ipv4_flow_tbl, (const void **)&next_key, (void **)&flow_val, &iter)) != -ENOENT) { + if (DP_FAILED(ret)) { + DPS_LOG_ERR("Iterating flow table failed while removing VM flows", DP_LOG_RET(ret)); + return; + } + if (flow_val->created_port_id == port_id + || (next_key->vni == vni && flow_val->flow_key[DP_FLOW_DIR_ORG].ip_dst == ipv4) + ) { + dp_remove_flow(flow_val); } } } + hash_sig_t dp_get_conntrack_flow_hash_value(struct flow_key *key) { //It is not necessary to first test if this key exists, since for now, this function diff --git a/src/grpc/dp_grpc_impl.c b/src/grpc/dp_grpc_impl.c index 0fcdd7350..54bc06d2d 100644 --- a/src/grpc/dp_grpc_impl.c +++ b/src/grpc/dp_grpc_impl.c @@ -555,12 +555,17 @@ static int dp_process_delete_interface(struct dp_grpc_responder *responder) struct dpgrpc_iface_id *request = &responder->request.del_iface; int port_id; + uint32_t ipv4; + uint32_t vni; int ret = DP_GRPC_OK; port_id = dp_get_portid_with_vm_handle(request->iface_id); if (DP_FAILED(port_id)) return DP_GRPC_ERR_NOT_FOUND; + ipv4 = dp_get_dhcp_range_ip4(port_id); + vni = dp_get_vm_vni(port_id); + dp_del_vnf_with_vnf_key(dp_get_vm_ul_ip6(port_id)); if (DP_FAILED(dp_port_stop(port_id))) ret = DP_GRPC_ERR_PORT_STOP; @@ -570,6 +575,7 @@ static int dp_process_delete_interface(struct dp_grpc_responder *responder) #ifdef ENABLE_VIRTSVC dp_virtsvc_del_vm(port_id); #endif + dp_remove_vm_flows(port_id, ipv4, vni); return ret; }