static struct rt6_info *rt6_multipath_select(struct rt6_info *match,
                                             struct flowi6 *fl6, int oif,
+                                            const struct sk_buff *skb,
                                             int strict)
 {
        struct rt6_info *sibling, *next_sibling;
         * case it will always be non-zero. Otherwise now is the time to do it.
         */
        if (!fl6->mp_hash)
-               fl6->mp_hash = rt6_multipath_hash(fl6, NULL, NULL);
+               fl6->mp_hash = rt6_multipath_hash(fl6, skb, NULL);
 
        if (fl6->mp_hash <= atomic_read(&match->rt6i_nh_upper_bound))
                return match;
 
 static struct rt6_info *ip6_pol_route_lookup(struct net *net,
                                             struct fib6_table *table,
-                                            struct flowi6 *fl6, int flags)
+                                            struct flowi6 *fl6,
+                                            const struct sk_buff *skb,
+                                            int flags)
 {
        struct rt6_info *rt, *rt_cache;
        struct fib6_node *fn;
                rt = rt6_device_match(net, rt, &fl6->saddr,
                                      fl6->flowi6_oif, flags);
                if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0)
-                       rt = rt6_multipath_select(rt, fl6,
-                                                 fl6->flowi6_oif, flags);
+                       rt = rt6_multipath_select(rt, fl6, fl6->flowi6_oif,
+                                                 skb, flags);
        }
        if (rt == net->ipv6.ip6_null_entry) {
                fn = fib6_backtrack(fn, &fl6->saddr);
 }
 
 struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6,
-                                   int flags)
+                                  const struct sk_buff *skb, int flags)
 {
-       return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_lookup);
+       return fib6_rule_lookup(net, fl6, skb, flags, ip6_pol_route_lookup);
 }
 EXPORT_SYMBOL_GPL(ip6_route_lookup);
 
 struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr,
-                           const struct in6_addr *saddr, int oif, int strict)
+                           const struct in6_addr *saddr, int oif,
+                           const struct sk_buff *skb, int strict)
 {
        struct flowi6 fl6 = {
                .flowi6_oif = oif,
                flags |= RT6_LOOKUP_F_HAS_SADDR;
        }
 
-       dst = fib6_rule_lookup(net, &fl6, flags, ip6_pol_route_lookup);
+       dst = fib6_rule_lookup(net, &fl6, skb, flags, ip6_pol_route_lookup);
        if (dst->error == 0)
                return (struct rt6_info *) dst;
 
 }
 
 struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
-                              int oif, struct flowi6 *fl6, int flags)
+                              int oif, struct flowi6 *fl6,
+                              const struct sk_buff *skb, int flags)
 {
        struct fib6_node *fn, *saved_fn;
        struct rt6_info *rt, *rt_cache;
 redo_rt6_select:
        rt = rt6_select(net, fn, oif, strict);
        if (rt->rt6i_nsiblings)
-               rt = rt6_multipath_select(rt, fl6, oif, strict);
+               rt = rt6_multipath_select(rt, fl6, oif, skb, strict);
        if (rt == net->ipv6.ip6_null_entry) {
                fn = fib6_backtrack(fn, &fl6->saddr);
                if (fn)
 }
 EXPORT_SYMBOL_GPL(ip6_pol_route);
 
-static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table,
-                                           struct flowi6 *fl6, int flags)
+static struct rt6_info *ip6_pol_route_input(struct net *net,
+                                           struct fib6_table *table,
+                                           struct flowi6 *fl6,
+                                           const struct sk_buff *skb,
+                                           int flags)
 {
-       return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags);
+       return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, skb, flags);
 }
 
 struct dst_entry *ip6_route_input_lookup(struct net *net,
                                         struct net_device *dev,
-                                        struct flowi6 *fl6, int flags)
+                                        struct flowi6 *fl6,
+                                        const struct sk_buff *skb,
+                                        int flags)
 {
        if (rt6_need_strict(&fl6->daddr) && dev->type != ARPHRD_PIMREG)
                flags |= RT6_LOOKUP_F_IFACE;
 
-       return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_input);
+       return fib6_rule_lookup(net, fl6, skb, flags, ip6_pol_route_input);
 }
 EXPORT_SYMBOL_GPL(ip6_route_input_lookup);
 
        if (unlikely(fl6.flowi6_proto == IPPROTO_ICMPV6))
                fl6.mp_hash = rt6_multipath_hash(&fl6, skb, flkeys);
        skb_dst_drop(skb);
-       skb_dst_set(skb, ip6_route_input_lookup(net, skb->dev, &fl6, flags));
+       skb_dst_set(skb,
+                   ip6_route_input_lookup(net, skb->dev, &fl6, skb, flags));
 }
 
-static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table,
-                                            struct flowi6 *fl6, int flags)
+static struct rt6_info *ip6_pol_route_output(struct net *net,
+                                            struct fib6_table *table,
+                                            struct flowi6 *fl6,
+                                            const struct sk_buff *skb,
+                                            int flags)
 {
-       return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags);
+       return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, skb, flags);
 }
 
 struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk,
        else if (sk)
                flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs);
 
-       return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_output);
+       return fib6_rule_lookup(net, fl6, NULL, flags, ip6_pol_route_output);
 }
 EXPORT_SYMBOL_GPL(ip6_route_output_flags);
 
 static struct rt6_info *__ip6_route_redirect(struct net *net,
                                             struct fib6_table *table,
                                             struct flowi6 *fl6,
+                                            const struct sk_buff *skb,
                                             int flags)
 {
        struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6;
 };
 
 static struct dst_entry *ip6_route_redirect(struct net *net,
-                                       const struct flowi6 *fl6,
-                                       const struct in6_addr *gateway)
+                                           const struct flowi6 *fl6,
+                                           const struct sk_buff *skb,
+                                           const struct in6_addr *gateway)
 {
        int flags = RT6_LOOKUP_F_HAS_SADDR;
        struct ip6rd_flowi rdfl;
        rdfl.fl6 = *fl6;
        rdfl.gateway = *gateway;
 
-       return fib6_rule_lookup(net, &rdfl.fl6,
+       return fib6_rule_lookup(net, &rdfl.fl6, skb,
                                flags, __ip6_route_redirect);
 }
 
        fl6.flowlabel = ip6_flowinfo(iph);
        fl6.flowi6_uid = uid;
 
-       dst = ip6_route_redirect(net, &fl6, &ipv6_hdr(skb)->saddr);
+       dst = ip6_route_redirect(net, &fl6, skb, &ipv6_hdr(skb)->saddr);
        rt6_do_redirect(dst, NULL, skb);
        dst_release(dst);
 }
        fl6.saddr = iph->daddr;
        fl6.flowi6_uid = sock_net_uid(net, NULL);
 
-       dst = ip6_route_redirect(net, &fl6, &iph->saddr);
+       dst = ip6_route_redirect(net, &fl6, skb, &iph->saddr);
        rt6_do_redirect(dst, NULL, skb);
        dst_release(dst);
 }
                flags |= RT6_LOOKUP_F_HAS_SADDR;
 
        flags |= RT6_LOOKUP_F_IGNORE_LINKSTATE;
-       rt = ip6_pol_route(net, table, cfg->fc_ifindex, &fl6, flags);
+       rt = ip6_pol_route(net, table, cfg->fc_ifindex, &fl6, NULL, flags);
 
        /* if table lookup failed, fall back to full lookup */
        if (rt == net->ipv6.ip6_null_entry) {
        }
 
        if (!grt)
-               grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, 1);
+               grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, NULL, 1);
 
        if (!grt)
                goto out;
                if (!ipv6_addr_any(&fl6.saddr))
                        flags |= RT6_LOOKUP_F_HAS_SADDR;
 
-               dst = ip6_route_input_lookup(net, dev, &fl6, flags);
+               dst = ip6_route_input_lookup(net, dev, &fl6, NULL, flags);
 
                rcu_read_unlock();
        } else {