Message ID | 1383661738-6083-2-git-send-email-florent.fourcot@enst-bretagne.fr |
---|---|
State | Changes Requested, archived |
Delegated to: | David Miller |
Headers | show |
On Tue, Nov 05, 2013 at 03:28:56PM +0100, Florent Fourcot wrote: > + spin_lock_bh(&ip6_fl_lock); > + rcu_read_lock_bh(); > + > + for_each_sk_fl_rcu(np, sfl) { > + if (sfl->fl->label == (np->flow_label & IPV6_FLOWLABEL_MASK)) { The iteration is protected by rcu, so need to take the ip6_fl_lock. We should lock the smallest region which needs to be protected. This is only the body of the if. Using fl->label without lock is fine, because it is immutable after interning. > + freq->flr_label = sfl->fl->label; > + freq->flr_dst = sfl->fl->dst; > + freq->flr_share = sfl->fl->share; > + freq->flr_expires = (sfl->fl->expires - jiffies) / HZ; > + freq->flr_linger = sfl->fl->linger / HZ; > + > + rcu_read_unlock_bh(); > + spin_unlock_bh(&ip6_fl_lock); Please reverse these two lines then. Could you take a look at your patch regarding fl6_renew, too? Can we push locking into the function there, too? Greetings, Hannes -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tue, Nov 05, 2013 at 05:08:38PM +0100, Hannes Frederic Sowa wrote: > On Tue, Nov 05, 2013 at 03:28:56PM +0100, Florent Fourcot wrote: > > + spin_lock_bh(&ip6_fl_lock); > > + rcu_read_lock_bh(); > > + > > + for_each_sk_fl_rcu(np, sfl) { > > + if (sfl->fl->label == (np->flow_label & IPV6_FLOWLABEL_MASK)) { > > The iteration is protected by rcu, so need to take the ip6_fl_lock. We should ^no ^ here. Sorry, Hannes -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index dd96638..2a5f668 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -250,6 +250,7 @@ struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions *opt_space, struct ipv6_txoptions *fopt); void fl6_free_socklist(struct sock *sk); int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen); +int ipv6_flowlabel_opt_get(struct sock *sk, struct in6_flowlabel_req *freq); int ip6_flowlabel_init(void); void ip6_flowlabel_cleanup(void); diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 819578e..76e62a1 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -475,6 +475,33 @@ static inline void fl_link(struct ipv6_pinfo *np, struct ipv6_fl_socklist *sfl, spin_unlock_bh(&ip6_sk_fl_lock); } +int ipv6_flowlabel_opt_get(struct sock *sk, struct in6_flowlabel_req *freq) +{ + struct ipv6_pinfo *np = inet6_sk(sk); + struct ipv6_fl_socklist *sfl; + + spin_lock_bh(&ip6_fl_lock); + rcu_read_lock_bh(); + + for_each_sk_fl_rcu(np, sfl) { + if (sfl->fl->label == (np->flow_label & IPV6_FLOWLABEL_MASK)) { + freq->flr_label = sfl->fl->label; + freq->flr_dst = sfl->fl->dst; + freq->flr_share = sfl->fl->share; + freq->flr_expires = (sfl->fl->expires - jiffies) / HZ; + freq->flr_linger = sfl->fl->linger / HZ; + + rcu_read_unlock_bh(); + spin_unlock_bh(&ip6_fl_lock); + return 0; + } + } + rcu_read_unlock_bh(); + spin_unlock_bh(&ip6_fl_lock); + + return -ENOENT; +} + int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) { int uninitialized_var(err); diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 4919a8e..1c6ce31 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -1212,6 +1212,34 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, val = np->sndflow; break; + case IPV6_FLOWLABEL_MGR: + { + struct in6_flowlabel_req freq; + + if (len < sizeof(freq)) + return -EINVAL; + + if (copy_from_user(&freq, optval, sizeof(freq))) + return -EFAULT; + + if (freq.flr_action != IPV6_FL_A_GET) + return -EINVAL; + + len = sizeof(freq); + memset(&freq, 0, sizeof(freq)); + + val = ipv6_flowlabel_opt_get(sk, &freq); + if (val < 0) + return val; + + if (put_user(len, optlen)) + return -EFAULT; + if (copy_to_user(optval, &freq, len)) + return -EFAULT; + + return 0; + } + case IPV6_ADDR_PREFERENCES: val = 0;
It is already possible to set/put/renew a label with IPV6_FLOWLABEL_MGR and setsockopt. This patch add the possibility to get information about this label (current value, time before expiration, etc). It helps application to take decision for a renew or a release of the label. v2: * Add spin_lock to prevent race condition * return -ENOENT if no result found * check if flr_action is GET Signed-off-by: Florent Fourcot <florent.fourcot@enst-bretagne.fr> --- include/net/ipv6.h | 1 + net/ipv6/ip6_flowlabel.c | 27 +++++++++++++++++++++++++++ net/ipv6/ipv6_sockglue.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+)