]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - include/net/ipv6.h
ipv6: add ipv6_addr_prefix_copy
[karo-tx-linux.git] / include / net / ipv6.h
index ea5a13ef85a6c4175f93db5abc45a761b19a8a5b..6570f379aba2eb744b0e8522349f0612b01b6814 100644 (file)
@@ -205,6 +205,7 @@ extern rwlock_t ip6_ra_lock;
  */
 
 struct ipv6_txoptions {
+       atomic_t                refcnt;
        /* Length of this structure */
        int                     tot_len;
 
@@ -217,7 +218,7 @@ struct ipv6_txoptions {
        struct ipv6_opt_hdr     *dst0opt;
        struct ipv6_rt_hdr      *srcrt; /* Routing Header */
        struct ipv6_opt_hdr     *dst1opt;
-
+       struct rcu_head         rcu;
        /* Option buffer, as read by IPV6_PKTOPTIONS, starts here. */
 };
 
@@ -252,6 +253,24 @@ struct ipv6_fl_socklist {
        struct rcu_head                 rcu;
 };
 
+static inline struct ipv6_txoptions *txopt_get(const struct ipv6_pinfo *np)
+{
+       struct ipv6_txoptions *opt;
+
+       rcu_read_lock();
+       opt = rcu_dereference(np->opt);
+       if (opt && !atomic_inc_not_zero(&opt->refcnt))
+               opt = NULL;
+       rcu_read_unlock();
+       return opt;
+}
+
+static inline void txopt_put(struct ipv6_txoptions *opt)
+{
+       if (opt && atomic_dec_and_test(&opt->refcnt))
+               kfree_rcu(opt, rcu);
+}
+
 struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, __be32 label);
 struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions *opt_space,
                                         struct ip6_flowlabel *fl,
@@ -382,6 +401,21 @@ static inline void ipv6_addr_prefix(struct in6_addr *pfx,
                pfx->s6_addr[o] = addr->s6_addr[o] & (0xff00 >> b);
 }
 
+static inline void ipv6_addr_prefix_copy(struct in6_addr *addr,
+                                        const struct in6_addr *pfx,
+                                        int plen)
+{
+       /* caller must guarantee 0 <= plen <= 128 */
+       int o = plen >> 3,
+           b = plen & 0x7;
+
+       memcpy(addr->s6_addr, pfx, o);
+       if (b != 0) {
+               addr->s6_addr[o] &= ~(0xff00 >> b);
+               addr->s6_addr[o] |= (pfx->s6_addr[o] & (0xff00 >> b));
+       }
+}
+
 static inline void __ipv6_addr_set_half(__be32 *addr,
                                        __be32 wh, __be32 wl)
 {