Following patch make sure that BH is disabled while running
execute_actions() on packets from userspace. RCU annotation for BH is
used to fix false positive warning message.

Signed-off-by: Pravin B Shelar <[email protected]>
Bug #7621
---
 datapath/actions.c                             |    5 +++--
 datapath/datapath.c                            |    6 ++++--
 datapath/linux/compat/include/linux/rcupdate.h |    4 +++-
 datapath/tunnel.c                              |    8 ++++----
 datapath/vport-patch.c                         |    2 +-
 5 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/datapath/actions.c b/datapath/actions.c
index 36437a4..76d378f 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -234,7 +234,7 @@ static int do_output(struct datapath *dp, struct sk_buff 
*skb, int out_port)
        if (unlikely(!skb))
                return -ENOMEM;
 
-       vport = rcu_dereference(dp->ports[out_port]);
+       vport = rcu_dereference_bh(dp->ports[out_port]);
        if (unlikely(!vport)) {
                kfree_skb(skb);
                return -ENODEV;
@@ -383,10 +383,11 @@ static int do_execute_actions(struct datapath *dp, struct 
sk_buff *skb,
 /* Execute a list of actions against 'skb'. */
 int execute_actions(struct datapath *dp, struct sk_buff *skb)
 {
-       struct sw_flow_actions *acts = 
rcu_dereference(OVS_CB(skb)->flow->sf_acts);
+       struct sw_flow_actions *acts;
        struct loop_counter *loop;
        int error;
 
+       acts = rcu_dereference_bh(OVS_CB(skb)->flow->sf_acts);
        /* Check whether we've looped too much. */
        loop = loop_get_counter();
        if (unlikely(++loop->count > MAX_LOOPS))
diff --git a/datapath/datapath.c b/datapath/datapath.c
index 15c1e33..b912ee3 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -304,7 +304,8 @@ void dp_process_received_packet(struct vport *p, struct 
sk_buff *skb)
                }
 
                /* Look up flow. */
-               flow = flow_tbl_lookup(rcu_dereference(dp->table), &key, 
key_len);
+               flow = flow_tbl_lookup(rcu_dereference_bh(dp->table),
+                                        &key, key_len);
                if (unlikely(!flow)) {
                        struct dp_upcall_info upcall;
 
@@ -705,8 +706,9 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, 
struct genl_info *info)
        if (flow->key.eth.in_port < DP_MAX_PORTS)
                OVS_CB(packet)->vport = get_vport_protected(dp,
                                                        flow->key.eth.in_port);
-
+       local_bh_disable();
        err = execute_actions(dp, packet);
+       local_bh_enable();
        rcu_read_unlock();
 
        flow_put(flow);
diff --git a/datapath/linux/compat/include/linux/rcupdate.h 
b/datapath/linux/compat/include/linux/rcupdate.h
index 99459ea..6c9a0a6 100644
--- a/datapath/linux/compat/include/linux/rcupdate.h
+++ b/datapath/linux/compat/include/linux/rcupdate.h
@@ -17,5 +17,7 @@ static inline int rcu_read_lock_held(void)
        return 1;
 }
 #endif
-
+#ifndef rcu_dereference_bh
+#define rcu_dereference_bh(p) rcu_dereference(p)
+#endif
 #endif /* linux/rcupdate.h wrapper */
diff --git a/datapath/tunnel.c b/datapath/tunnel.c
index 3576df8..176c5c6 100644
--- a/datapath/tunnel.c
+++ b/datapath/tunnel.c
@@ -898,7 +898,7 @@ static struct tnl_cache *build_cache(struct vport *vport,
                if (err || is_frag)
                        goto done;
 
-               flow = flow_tbl_lookup(rcu_dereference(dst_vport->dp->table),
+               flow = flow_tbl_lookup(rcu_dereference_bh(dst_vport->dp->table),
                                         &flow_key, flow_key_len);
                if (flow) {
                        cache->flow = flow;
@@ -920,7 +920,7 @@ static struct rtable *find_route(struct vport *vport,
                                 u8 tos, struct tnl_cache **cache)
 {
        struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
-       struct tnl_cache *cur_cache = rcu_dereference(tnl_vport->cache);
+       struct tnl_cache *cur_cache = rcu_dereference_bh(tnl_vport->cache);
 
        *cache = NULL;
        tos = RT_TOS(tos);
@@ -1074,8 +1074,7 @@ free_frags:
 int tnl_send(struct vport *vport, struct sk_buff *skb)
 {
        struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
-       const struct tnl_mutable_config *mutable = 
rcu_dereference(tnl_vport->mutable);
-
+       const struct tnl_mutable_config *mutable;
        enum vport_err_type err = VPORT_E_TX_ERROR;
        struct rtable *rt;
        struct dst_entry *unattached_dst = NULL;
@@ -1119,6 +1118,7 @@ int tnl_send(struct vport *vport, struct sk_buff *skb)
        else
                inner_tos = 0;
 
+       mutable = rcu_dereference_bh(tnl_vport->mutable);
        if (mutable->flags & TNL_F_TOS_INHERIT)
                tos = inner_tos;
        else
diff --git a/datapath/vport-patch.c b/datapath/vport-patch.c
index 9554f12..c18b59d 100644
--- a/datapath/vport-patch.c
+++ b/datapath/vport-patch.c
@@ -271,7 +271,7 @@ static int patch_get_options(const struct vport *vport, 
struct sk_buff *skb)
 static int patch_send(struct vport *vport, struct sk_buff *skb)
 {
        struct patch_vport *patch_vport = patch_vport_priv(vport);
-       struct vport *peer = rcu_dereference(patch_vport->peer);
+       struct vport *peer = rcu_dereference_bh(patch_vport->peer);
        int skb_len = skb->len;
 
        if (!peer) {
-- 
1.7.1

_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev

Reply via email to