route.c (db3fedee0cb7a0ea52450137d48b9e41be53ec14) route.c (0d16158149ab6b02fcd945b2f5a5cf31262a445b)
1/*
2 * Linux INET6 implementation
3 * FIB front-end.
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * This program is free software; you can redistribute it and/or

--- 857 unchanged lines hidden (view full) ---

866}
867#endif
868
869/*
870 * Misc support functions
871 */
872
873/* called with rcu_lock held */
1/*
2 * Linux INET6 implementation
3 * FIB front-end.
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * This program is free software; you can redistribute it and/or

--- 857 unchanged lines hidden (view full) ---

866}
867#endif
868
869/*
870 * Misc support functions
871 */
872
873/* called with rcu_lock held */
874static struct net_device *ip6_rt_get_dev_rcu(struct fib6_info *rt)
874static struct net_device *ip6_rt_get_dev_rcu(const struct fib6_result *res)
875{
875{
876 struct net_device *dev = rt->fib6_nh.fib_nh_dev;
876 struct net_device *dev = res->nh->fib_nh_dev;
877 const struct fib6_info *f6i = res->f6i;
877
878
878 if (rt->fib6_flags & (RTF_LOCAL | RTF_ANYCAST)) {
879 if (f6i->fib6_flags & (RTF_LOCAL | RTF_ANYCAST)) {
879 /* for copies of local routes, dst->dev needs to be the
880 * device if it is a master device, the master device if
881 * device is enslaved, and the loopback as the default
882 */
883 if (netif_is_l3_slave(dev) &&
880 /* for copies of local routes, dst->dev needs to be the
881 * device if it is a master device, the master device if
882 * device is enslaved, and the loopback as the default
883 */
884 if (netif_is_l3_slave(dev) &&
884 !rt6_need_strict(&rt->fib6_dst.addr))
885 !rt6_need_strict(&f6i->fib6_dst.addr))
885 dev = l3mdev_master_dev_rcu(dev);
886 else if (!netif_is_l3_master(dev))
887 dev = dev_net(dev)->loopback_dev;
888 /* last case is netif_is_l3_master(dev) is true in which
889 * case we want dev returned to be dev
890 */
891 }
892

--- 51 unchanged lines hidden (view full) ---

944 case RTN_UNREACHABLE:
945 default:
946 rt->dst.output = ip6_pkt_discard_out;
947 rt->dst.input = ip6_pkt_discard;
948 break;
949 }
950}
951
886 dev = l3mdev_master_dev_rcu(dev);
887 else if (!netif_is_l3_master(dev))
888 dev = dev_net(dev)->loopback_dev;
889 /* last case is netif_is_l3_master(dev) is true in which
890 * case we want dev returned to be dev
891 */
892 }
893

--- 51 unchanged lines hidden (view full) ---

945 case RTN_UNREACHABLE:
946 default:
947 rt->dst.output = ip6_pkt_discard_out;
948 rt->dst.input = ip6_pkt_discard;
949 break;
950 }
951}
952
952static void ip6_rt_init_dst(struct rt6_info *rt, struct fib6_info *ort)
953static void ip6_rt_init_dst(struct rt6_info *rt, const struct fib6_result *res)
953{
954{
955 struct fib6_info *ort = res->f6i;
956
954 if (ort->fib6_flags & RTF_REJECT) {
955 ip6_rt_init_dst_reject(rt, ort);
956 return;
957 }
958
959 rt->dst.error = 0;
960 rt->dst.output = ip6_output;
961
962 if (ort->fib6_type == RTN_LOCAL || ort->fib6_type == RTN_ANYCAST) {
963 rt->dst.input = ip6_input;
964 } else if (ipv6_addr_type(&ort->fib6_dst.addr) & IPV6_ADDR_MULTICAST) {
965 rt->dst.input = ip6_mc_input;
966 } else {
967 rt->dst.input = ip6_forward;
968 }
969
957 if (ort->fib6_flags & RTF_REJECT) {
958 ip6_rt_init_dst_reject(rt, ort);
959 return;
960 }
961
962 rt->dst.error = 0;
963 rt->dst.output = ip6_output;
964
965 if (ort->fib6_type == RTN_LOCAL || ort->fib6_type == RTN_ANYCAST) {
966 rt->dst.input = ip6_input;
967 } else if (ipv6_addr_type(&ort->fib6_dst.addr) & IPV6_ADDR_MULTICAST) {
968 rt->dst.input = ip6_mc_input;
969 } else {
970 rt->dst.input = ip6_forward;
971 }
972
970 if (ort->fib6_nh.fib_nh_lws) {
971 rt->dst.lwtstate = lwtstate_get(ort->fib6_nh.fib_nh_lws);
973 if (res->nh->fib_nh_lws) {
974 rt->dst.lwtstate = lwtstate_get(res->nh->fib_nh_lws);
972 lwtunnel_set_redirect(&rt->dst);
973 }
974
975 rt->dst.lastuse = jiffies;
976}
977
978/* Caller must already hold reference to @from */
979static void rt6_set_from(struct rt6_info *rt, struct fib6_info *from)
980{
981 rt->rt6i_flags &= ~RTF_EXPIRES;
982 rcu_assign_pointer(rt->from, from);
983 ip_dst_init_metrics(&rt->dst, from->fib6_metrics);
984}
985
975 lwtunnel_set_redirect(&rt->dst);
976 }
977
978 rt->dst.lastuse = jiffies;
979}
980
981/* Caller must already hold reference to @from */
982static void rt6_set_from(struct rt6_info *rt, struct fib6_info *from)
983{
984 rt->rt6i_flags &= ~RTF_EXPIRES;
985 rcu_assign_pointer(rt->from, from);
986 ip_dst_init_metrics(&rt->dst, from->fib6_metrics);
987}
988
986/* Caller must already hold reference to @ort */
987static void ip6_rt_copy_init(struct rt6_info *rt, struct fib6_info *ort)
989/* Caller must already hold reference to f6i in result */
990static void ip6_rt_copy_init(struct rt6_info *rt, const struct fib6_result *res)
988{
991{
989 struct net_device *dev = fib6_info_nh_dev(ort);
992 const struct fib6_nh *nh = res->nh;
993 const struct net_device *dev = nh->fib_nh_dev;
994 struct fib6_info *f6i = res->f6i;
990
995
991 ip6_rt_init_dst(rt, ort);
996 ip6_rt_init_dst(rt, res);
992
997
993 rt->rt6i_dst = ort->fib6_dst;
998 rt->rt6i_dst = f6i->fib6_dst;
994 rt->rt6i_idev = dev ? in6_dev_get(dev) : NULL;
999 rt->rt6i_idev = dev ? in6_dev_get(dev) : NULL;
995 rt->rt6i_flags = ort->fib6_flags;
996 if (ort->fib6_nh.fib_nh_gw_family) {
997 rt->rt6i_gateway = ort->fib6_nh.fib_nh_gw6;
1000 rt->rt6i_flags = f6i->fib6_flags;
1001 if (nh->fib_nh_gw_family) {
1002 rt->rt6i_gateway = nh->fib_nh_gw6;
998 rt->rt6i_flags |= RTF_GATEWAY;
999 }
1003 rt->rt6i_flags |= RTF_GATEWAY;
1004 }
1000 rt6_set_from(rt, ort);
1005 rt6_set_from(rt, f6i);
1001#ifdef CONFIG_IPV6_SUBTREES
1006#ifdef CONFIG_IPV6_SUBTREES
1002 rt->rt6i_src = ort->fib6_src;
1007 rt->rt6i_src = f6i->fib6_src;
1003#endif
1004}
1005
1006static struct fib6_node* fib6_backtrack(struct fib6_node *fn,
1007 struct in6_addr *saddr)
1008{
1009 struct fib6_node *pn, *sn;
1010 while (1) {

--- 39 unchanged lines hidden (view full) ---

1050
1051 flags = fib6_info_dst_flags(f6i);
1052 nrt = ip6_dst_alloc(dev_net(dev), dev, flags);
1053 if (!nrt) {
1054 fib6_info_release(f6i);
1055 goto fallback;
1056 }
1057
1008#endif
1009}
1010
1011static struct fib6_node* fib6_backtrack(struct fib6_node *fn,
1012 struct in6_addr *saddr)
1013{
1014 struct fib6_node *pn, *sn;
1015 while (1) {

--- 39 unchanged lines hidden (view full) ---

1055
1056 flags = fib6_info_dst_flags(f6i);
1057 nrt = ip6_dst_alloc(dev_net(dev), dev, flags);
1058 if (!nrt) {
1059 fib6_info_release(f6i);
1060 goto fallback;
1061 }
1062
1058 ip6_rt_copy_init(nrt, f6i);
1063 ip6_rt_copy_init(nrt, res);
1059 return nrt;
1060
1061fallback:
1062 nrt = dev_net(dev)->ipv6.ip6_null_entry;
1063 dst_hold(&nrt->dst);
1064 return nrt;
1065}
1066

--- 120 unchanged lines hidden (view full) ---

1187
1188 /*
1189 * Clone the route.
1190 */
1191
1192 if (!fib6_info_hold_safe(f6i))
1193 return NULL;
1194
1064 return nrt;
1065
1066fallback:
1067 nrt = dev_net(dev)->ipv6.ip6_null_entry;
1068 dst_hold(&nrt->dst);
1069 return nrt;
1070}
1071

--- 120 unchanged lines hidden (view full) ---

1192
1193 /*
1194 * Clone the route.
1195 */
1196
1197 if (!fib6_info_hold_safe(f6i))
1198 return NULL;
1199
1195 dev = ip6_rt_get_dev_rcu(f6i);
1200 dev = ip6_rt_get_dev_rcu(res);
1196 rt = ip6_dst_alloc(dev_net(dev), dev, 0);
1197 if (!rt) {
1198 fib6_info_release(f6i);
1199 return NULL;
1200 }
1201
1201 rt = ip6_dst_alloc(dev_net(dev), dev, 0);
1202 if (!rt) {
1203 fib6_info_release(f6i);
1204 return NULL;
1205 }
1206
1202 ip6_rt_copy_init(rt, res->f6i);
1207 ip6_rt_copy_init(rt, res);
1203 rt->rt6i_flags |= RTF_CACHE;
1204 rt->dst.flags |= DST_HOST;
1205 rt->rt6i_dst.addr = *daddr;
1206 rt->rt6i_dst.plen = 128;
1207
1208 if (!rt6_is_gw_or_nonexthop(res)) {
1209 if (f6i->fib6_dst.plen != 128 &&
1210 ipv6_addr_equal(&f6i->fib6_dst.addr, daddr))

--- 15 unchanged lines hidden (view full) ---

1226 unsigned short flags = fib6_info_dst_flags(f6i);
1227 struct net_device *dev;
1228 struct rt6_info *pcpu_rt;
1229
1230 if (!fib6_info_hold_safe(f6i))
1231 return NULL;
1232
1233 rcu_read_lock();
1208 rt->rt6i_flags |= RTF_CACHE;
1209 rt->dst.flags |= DST_HOST;
1210 rt->rt6i_dst.addr = *daddr;
1211 rt->rt6i_dst.plen = 128;
1212
1213 if (!rt6_is_gw_or_nonexthop(res)) {
1214 if (f6i->fib6_dst.plen != 128 &&
1215 ipv6_addr_equal(&f6i->fib6_dst.addr, daddr))

--- 15 unchanged lines hidden (view full) ---

1231 unsigned short flags = fib6_info_dst_flags(f6i);
1232 struct net_device *dev;
1233 struct rt6_info *pcpu_rt;
1234
1235 if (!fib6_info_hold_safe(f6i))
1236 return NULL;
1237
1238 rcu_read_lock();
1234 dev = ip6_rt_get_dev_rcu(f6i);
1239 dev = ip6_rt_get_dev_rcu(res);
1235 pcpu_rt = ip6_dst_alloc(dev_net(dev), dev, flags);
1236 rcu_read_unlock();
1237 if (!pcpu_rt) {
1238 fib6_info_release(f6i);
1239 return NULL;
1240 }
1240 pcpu_rt = ip6_dst_alloc(dev_net(dev), dev, flags);
1241 rcu_read_unlock();
1242 if (!pcpu_rt) {
1243 fib6_info_release(f6i);
1244 return NULL;
1245 }
1241 ip6_rt_copy_init(pcpu_rt, f6i);
1246 ip6_rt_copy_init(pcpu_rt, res);
1242 pcpu_rt->rt6i_flags |= RTF_PCPU;
1243 return pcpu_rt;
1244}
1245
1246/* It should be called with rcu_read_lock() acquired */
1247static struct rt6_info *rt6_get_pcpu_route(const struct fib6_result *res)
1248{
1249 struct rt6_info *pcpu_rt, **p;

--- 4281 unchanged lines hidden ---
1247 pcpu_rt->rt6i_flags |= RTF_PCPU;
1248 return pcpu_rt;
1249}
1250
1251/* It should be called with rcu_read_lock() acquired */
1252static struct rt6_info *rt6_get_pcpu_route(const struct fib6_result *res)
1253{
1254 struct rt6_info *pcpu_rt, **p;

--- 4281 unchanged lines hidden ---