datapath: handle recirculation loop detection
[sliver-openvswitch.git] / datapath / datapath.c
index aa4c109..0611dad 100644 (file)
@@ -187,6 +187,7 @@ static void destroy_dp_rcu(struct rcu_head *rcu)
 {
        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);
@@ -240,7 +241,8 @@ void ovs_dp_detach_port(struct vport *p)
 }
 
 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;
@@ -252,7 +254,8 @@ void ovs_dp_process_packet_with_key(struct sk_buff *skb,
        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;
 
@@ -270,7 +273,7 @@ void ovs_dp_process_packet_with_key(struct sk_buff *skb,
        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:
@@ -296,7 +299,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
                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,
@@ -599,7 +602,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
        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();
 
@@ -1447,7 +1450,7 @@ err_destroy_ports_array:
 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);
@@ -1479,8 +1482,6 @@ static void __dp_destroy(struct datapath *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);
 }