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 --- |