{
struct datapath *dp = container_of(rcu, struct datapath, rcu);
+ ovs_flow_tbl_destroy(&dp->table);
free_percpu(dp->stats_percpu);
release_net(ovs_dp_get_net(dp));
kfree(dp->ports);
}
void ovs_dp_process_packet_with_key(struct sk_buff *skb,
- struct sw_flow_key *pkt_key)
+ struct sw_flow_key *pkt_key,
+ bool recirc)
{
const struct vport *p = OVS_CB(skb)->input_vport;
struct datapath *dp = p->dp;
stats = this_cpu_ptr(dp->stats_percpu);
/* Look up flow. */
- flow = ovs_flow_tbl_lookup_stats(&dp->table, pkt_key, &n_mask_hit);
+ flow = ovs_flow_tbl_lookup_stats(&dp->table, pkt_key, skb_get_rxhash(skb),
+ &n_mask_hit);
if (unlikely(!flow)) {
struct dp_upcall_info upcall;
OVS_CB(skb)->flow = flow;
ovs_flow_stats_update(OVS_CB(skb)->flow, pkt_key->tp.flags, skb);
- ovs_execute_actions(dp, skb);
+ ovs_execute_actions(dp, skb, recirc);
stats_counter = &stats->n_hit;
out:
return;
}
- ovs_dp_process_packet_with_key(skb, &key);
+ ovs_dp_process_packet_with_key(skb, &key, false);
}
int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb,
OVS_CB(packet)->input_vport = input_vport;
local_bh_disable();
- err = ovs_execute_actions(dp, packet);
+ err = ovs_execute_actions(dp, packet, false);
local_bh_enable();
rcu_read_unlock();
err_destroy_percpu:
free_percpu(dp->stats_percpu);
err_destroy_table:
- ovs_flow_tbl_destroy(&dp->table, false);
+ ovs_flow_tbl_destroy(&dp->table);
err_free_dp:
release_net(ovs_dp_get_net(dp));
kfree(dp);
ovs_dp_detach_port(ovs_vport_ovsl(dp, OVSP_LOCAL));
/* RCU destroy the flow table */
- ovs_flow_tbl_destroy(&dp->table, true);
-
call_rcu(&dp->rcu, destroy_dp_rcu);
}