diff options
Diffstat (limited to 'include/net/ip6_route.h')
| -rw-r--r-- | include/net/ip6_route.h | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index ee7405e759ba..b69c16cbbf71 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h | |||
| @@ -27,6 +27,7 @@ struct route_info { | |||
| 27 | #include <linux/ip.h> | 27 | #include <linux/ip.h> |
| 28 | #include <linux/ipv6.h> | 28 | #include <linux/ipv6.h> |
| 29 | #include <linux/route.h> | 29 | #include <linux/route.h> |
| 30 | #include <net/nexthop.h> | ||
| 30 | 31 | ||
| 31 | #define RT6_LOOKUP_F_IFACE 0x00000001 | 32 | #define RT6_LOOKUP_F_IFACE 0x00000001 |
| 32 | #define RT6_LOOKUP_F_REACHABLE 0x00000002 | 33 | #define RT6_LOOKUP_F_REACHABLE 0x00000002 |
| @@ -35,6 +36,7 @@ struct route_info { | |||
| 35 | #define RT6_LOOKUP_F_SRCPREF_PUBLIC 0x00000010 | 36 | #define RT6_LOOKUP_F_SRCPREF_PUBLIC 0x00000010 |
| 36 | #define RT6_LOOKUP_F_SRCPREF_COA 0x00000020 | 37 | #define RT6_LOOKUP_F_SRCPREF_COA 0x00000020 |
| 37 | #define RT6_LOOKUP_F_IGNORE_LINKSTATE 0x00000040 | 38 | #define RT6_LOOKUP_F_IGNORE_LINKSTATE 0x00000040 |
| 39 | #define RT6_LOOKUP_F_DST_NOREF 0x00000080 | ||
| 38 | 40 | ||
| 39 | /* We do not (yet ?) support IPv6 jumbograms (RFC 2675) | 41 | /* We do not (yet ?) support IPv6 jumbograms (RFC 2675) |
| 40 | * Unlike IPv4, hdr->seg_len doesn't include the IPv6 header | 42 | * Unlike IPv4, hdr->seg_len doesn't include the IPv6 header |
| @@ -66,11 +68,14 @@ static inline bool rt6_need_strict(const struct in6_addr *daddr) | |||
| 66 | (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK); | 68 | (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK); |
| 67 | } | 69 | } |
| 68 | 70 | ||
| 71 | /* fib entries using a nexthop object can not be coalesced into | ||
| 72 | * a multipath route | ||
| 73 | */ | ||
| 69 | static inline bool rt6_qualify_for_ecmp(const struct fib6_info *f6i) | 74 | static inline bool rt6_qualify_for_ecmp(const struct fib6_info *f6i) |
| 70 | { | 75 | { |
| 71 | /* the RTF_ADDRCONF flag filters out RA's */ | 76 | /* the RTF_ADDRCONF flag filters out RA's */ |
| 72 | return !(f6i->fib6_flags & RTF_ADDRCONF) && | 77 | return !(f6i->fib6_flags & RTF_ADDRCONF) && !f6i->nh && |
| 73 | f6i->fib6_nh.fib_nh_gw_family; | 78 | f6i->fib6_nh->fib_nh_gw_family; |
| 74 | } | 79 | } |
| 75 | 80 | ||
| 76 | void ip6_route_input(struct sk_buff *skb); | 81 | void ip6_route_input(struct sk_buff *skb); |
| @@ -79,6 +84,10 @@ struct dst_entry *ip6_route_input_lookup(struct net *net, | |||
| 79 | struct flowi6 *fl6, | 84 | struct flowi6 *fl6, |
| 80 | const struct sk_buff *skb, int flags); | 85 | const struct sk_buff *skb, int flags); |
| 81 | 86 | ||
| 87 | struct dst_entry *ip6_route_output_flags_noref(struct net *net, | ||
| 88 | const struct sock *sk, | ||
| 89 | struct flowi6 *fl6, int flags); | ||
| 90 | |||
| 82 | struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk, | 91 | struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk, |
| 83 | struct flowi6 *fl6, int flags); | 92 | struct flowi6 *fl6, int flags); |
| 84 | 93 | ||
| @@ -89,6 +98,16 @@ static inline struct dst_entry *ip6_route_output(struct net *net, | |||
| 89 | return ip6_route_output_flags(net, sk, fl6, 0); | 98 | return ip6_route_output_flags(net, sk, fl6, 0); |
| 90 | } | 99 | } |
| 91 | 100 | ||
| 101 | /* Only conditionally release dst if flags indicates | ||
| 102 | * !RT6_LOOKUP_F_DST_NOREF or dst is in uncached_list. | ||
| 103 | */ | ||
| 104 | static inline void ip6_rt_put_flags(struct rt6_info *rt, int flags) | ||
| 105 | { | ||
| 106 | if (!(flags & RT6_LOOKUP_F_DST_NOREF) || | ||
| 107 | !list_empty(&rt->rt6i_uncached)) | ||
| 108 | ip6_rt_put(rt); | ||
| 109 | } | ||
| 110 | |||
| 92 | struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6, | 111 | struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6, |
| 93 | const struct sk_buff *skb, int flags); | 112 | const struct sk_buff *skb, int flags); |
| 94 | struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, | 113 | struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, |
| @@ -178,7 +197,7 @@ struct rt6_rtnl_dump_arg { | |||
| 178 | struct fib_dump_filter filter; | 197 | struct fib_dump_filter filter; |
| 179 | }; | 198 | }; |
| 180 | 199 | ||
| 181 | int rt6_dump_route(struct fib6_info *f6i, void *p_arg); | 200 | int rt6_dump_route(struct fib6_info *f6i, void *p_arg, unsigned int skip); |
| 182 | void rt6_mtu_change(struct net_device *dev, unsigned int mtu); | 201 | void rt6_mtu_change(struct net_device *dev, unsigned int mtu); |
| 183 | void rt6_remove_prefsrc(struct inet6_ifaddr *ifp); | 202 | void rt6_remove_prefsrc(struct inet6_ifaddr *ifp); |
| 184 | void rt6_clean_tohost(struct net *net, struct in6_addr *gateway); | 203 | void rt6_clean_tohost(struct net *net, struct in6_addr *gateway); |
| @@ -275,8 +294,13 @@ static inline const struct in6_addr *rt6_nexthop(const struct rt6_info *rt, | |||
| 275 | 294 | ||
| 276 | static inline bool rt6_duplicate_nexthop(struct fib6_info *a, struct fib6_info *b) | 295 | static inline bool rt6_duplicate_nexthop(struct fib6_info *a, struct fib6_info *b) |
| 277 | { | 296 | { |
| 278 | struct fib6_nh *nha = &a->fib6_nh, *nhb = &b->fib6_nh; | 297 | struct fib6_nh *nha, *nhb; |
| 298 | |||
| 299 | if (a->nh || b->nh) | ||
| 300 | return nexthop_cmp(a->nh, b->nh); | ||
| 279 | 301 | ||
| 302 | nha = a->fib6_nh; | ||
| 303 | nhb = b->fib6_nh; | ||
| 280 | return nha->fib_nh_dev == nhb->fib_nh_dev && | 304 | return nha->fib_nh_dev == nhb->fib_nh_dev && |
| 281 | ipv6_addr_equal(&nha->fib_nh_gw6, &nhb->fib_nh_gw6) && | 305 | ipv6_addr_equal(&nha->fib_nh_gw6, &nhb->fib_nh_gw6) && |
| 282 | !lwtunnel_cmp_encap(nha->fib_nh_lws, nhb->fib_nh_lws); | 306 | !lwtunnel_cmp_encap(nha->fib_nh_lws, nhb->fib_nh_lws); |
