datapath: Include OVS_KEY_ATTR_IPV4_TUNNEL in upstream range.
[sliver-openvswitch.git] / datapath / flow.c
index c70daee..2acdd05 100644 (file)
@@ -226,9 +226,7 @@ struct sw_flow *ovs_flow_alloc(void)
                return ERR_PTR(-ENOMEM);
 
        spin_lock_init(&flow->lock);
-       atomic_set(&flow->refcnt, 1);
        flow->sf_acts = NULL;
-       flow->dead = false;
 
        return flow;
 }
@@ -290,12 +288,6 @@ struct flow_table *ovs_flow_tbl_alloc(int new_size)
        return table;
 }
 
-static void flow_free(struct sw_flow *flow)
-{
-       flow->dead = true;
-       ovs_flow_put(flow);
-}
-
 void ovs_flow_tbl_destroy(struct flow_table *table)
 {
        int i;
@@ -314,7 +306,7 @@ void ovs_flow_tbl_destroy(struct flow_table *table)
 
                hlist_for_each_entry_safe(flow, node, n, head, hash_node[ver]) {
                        hlist_del_rcu(&flow->hash_node[ver]);
-                       flow_free(flow);
+                       ovs_flow_free(flow);
                }
        }
 
@@ -418,13 +410,21 @@ struct flow_table *ovs_flow_tbl_expand(struct flow_table *table)
        return __flow_tbl_rehash(table, table->n_buckets * 2);
 }
 
+void ovs_flow_free(struct sw_flow *flow)
+{
+       if (unlikely(!flow))
+               return;
+
+       kfree((struct sf_flow_acts __force *)flow->sf_acts);
+       kmem_cache_free(flow_cache, flow);
+}
+
 /* RCU callback used by ovs_flow_deferred_free. */
 static void rcu_free_flow_callback(struct rcu_head *rcu)
 {
        struct sw_flow *flow = container_of(rcu, struct sw_flow, rcu);
 
-       flow->dead = true;
-       ovs_flow_put(flow);
+       ovs_flow_free(flow);
 }
 
 /* Schedules 'flow' to be freed after the next RCU grace period.
@@ -434,22 +434,6 @@ void ovs_flow_deferred_free(struct sw_flow *flow)
        call_rcu(&flow->rcu, rcu_free_flow_callback);
 }
 
-void ovs_flow_hold(struct sw_flow *flow)
-{
-       atomic_inc(&flow->refcnt);
-}
-
-void ovs_flow_put(struct sw_flow *flow)
-{
-       if (unlikely(!flow))
-               return;
-
-       if (atomic_dec_and_test(&flow->refcnt)) {
-               kfree((struct sf_flow_acts __force *)flow->sf_acts);
-               kmem_cache_free(flow_cache, flow);
-       }
-}
-
 /* RCU callback used by ovs_flow_deferred_free_acts. */
 static void rcu_free_acts_callback(struct rcu_head *rcu)
 {
@@ -725,7 +709,8 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
                        }
                }
 
-       } else if (key->eth.type == htons(ETH_P_ARP) && arphdr_ok(skb)) {
+       } else if ((key->eth.type == htons(ETH_P_ARP) ||
+                  key->eth.type == htons(ETH_P_RARP)) && arphdr_ok(skb)) {
                struct arp_eth_header *arp;
 
                arp = (struct arp_eth_header *)skb_network_header(skb);
@@ -861,10 +846,10 @@ const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
        [OVS_KEY_ATTR_ICMPV6] = sizeof(struct ovs_key_icmpv6),
        [OVS_KEY_ATTR_ARP] = sizeof(struct ovs_key_arp),
        [OVS_KEY_ATTR_ND] = sizeof(struct ovs_key_nd),
+       [OVS_KEY_ATTR_IPV4_TUNNEL] = sizeof(struct ovs_key_ipv4_tunnel),
 
        /* Not upstream. */
        [OVS_KEY_ATTR_TUN_ID] = sizeof(__be64),
-       [OVS_KEY_ATTR_IPV4_TUNNEL] = sizeof(struct ovs_key_ipv4_tunnel),
 };
 
 static int ipv4_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_len,
@@ -1173,7 +1158,8 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
                        if (err)
                                return err;
                }
-       } else if (swkey->eth.type == htons(ETH_P_ARP)) {
+       } else if (swkey->eth.type == htons(ETH_P_ARP) ||
+                  swkey->eth.type == htons(ETH_P_RARP)) {
                const struct ovs_key_arp *arp_key;
 
                if (!(attrs & (1 << OVS_KEY_ATTR_ARP)))
@@ -1361,7 +1347,8 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
                ipv6_key->ipv6_tclass = swkey->ip.tos;
                ipv6_key->ipv6_hlimit = swkey->ip.ttl;
                ipv6_key->ipv6_frag = swkey->ip.frag;
-       } else if (swkey->eth.type == htons(ETH_P_ARP)) {
+       } else if (swkey->eth.type == htons(ETH_P_ARP) ||
+                  swkey->eth.type == htons(ETH_P_RARP)) {
                struct ovs_key_arp *arp_key;
 
                nla = nla_reserve(skb, OVS_KEY_ATTR_ARP, sizeof(*arp_key));