diff options
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r-- | net/ipv4/route.c | 187 |
1 files changed, 106 insertions, 81 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index fd9af60397b5..a8c651216fa6 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -802,7 +802,8 @@ void ip_rt_send_redirect(struct sk_buff *skb) | |||
802 | net = dev_net(rt->dst.dev); | 802 | net = dev_net(rt->dst.dev); |
803 | peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, 1); | 803 | peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, 1); |
804 | if (!peer) { | 804 | if (!peer) { |
805 | icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway); | 805 | icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, |
806 | rt_nexthop(rt, ip_hdr(skb)->daddr)); | ||
806 | return; | 807 | return; |
807 | } | 808 | } |
808 | 809 | ||
@@ -827,7 +828,9 @@ void ip_rt_send_redirect(struct sk_buff *skb) | |||
827 | time_after(jiffies, | 828 | time_after(jiffies, |
828 | (peer->rate_last + | 829 | (peer->rate_last + |
829 | (ip_rt_redirect_load << peer->rate_tokens)))) { | 830 | (ip_rt_redirect_load << peer->rate_tokens)))) { |
830 | icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway); | 831 | __be32 gw = rt_nexthop(rt, ip_hdr(skb)->daddr); |
832 | |||
833 | icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, gw); | ||
831 | peer->rate_last = jiffies; | 834 | peer->rate_last = jiffies; |
832 | ++peer->rate_tokens; | 835 | ++peer->rate_tokens; |
833 | #ifdef CONFIG_IP_ROUTE_VERBOSE | 836 | #ifdef CONFIG_IP_ROUTE_VERBOSE |
@@ -835,7 +838,7 @@ void ip_rt_send_redirect(struct sk_buff *skb) | |||
835 | peer->rate_tokens == ip_rt_redirect_number) | 838 | peer->rate_tokens == ip_rt_redirect_number) |
836 | net_warn_ratelimited("host %pI4/if%d ignores redirects for %pI4 to %pI4\n", | 839 | net_warn_ratelimited("host %pI4/if%d ignores redirects for %pI4 to %pI4\n", |
837 | &ip_hdr(skb)->saddr, inet_iif(skb), | 840 | &ip_hdr(skb)->saddr, inet_iif(skb), |
838 | &ip_hdr(skb)->daddr, &rt->rt_gateway); | 841 | &ip_hdr(skb)->daddr, &gw); |
839 | #endif | 842 | #endif |
840 | } | 843 | } |
841 | out_put_peer: | 844 | out_put_peer: |
@@ -904,22 +907,32 @@ out: kfree_skb(skb); | |||
904 | return 0; | 907 | return 0; |
905 | } | 908 | } |
906 | 909 | ||
907 | static u32 __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) | 910 | static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) |
908 | { | 911 | { |
912 | struct dst_entry *dst = &rt->dst; | ||
909 | struct fib_result res; | 913 | struct fib_result res; |
910 | 914 | ||
915 | if (dst->dev->mtu < mtu) | ||
916 | return; | ||
917 | |||
911 | if (mtu < ip_rt_min_pmtu) | 918 | if (mtu < ip_rt_min_pmtu) |
912 | mtu = ip_rt_min_pmtu; | 919 | mtu = ip_rt_min_pmtu; |
913 | 920 | ||
921 | if (!rt->rt_pmtu) { | ||
922 | dst->obsolete = DST_OBSOLETE_KILL; | ||
923 | } else { | ||
924 | rt->rt_pmtu = mtu; | ||
925 | dst->expires = max(1UL, jiffies + ip_rt_mtu_expires); | ||
926 | } | ||
927 | |||
914 | rcu_read_lock(); | 928 | rcu_read_lock(); |
915 | if (fib_lookup(dev_net(rt->dst.dev), fl4, &res) == 0) { | 929 | if (fib_lookup(dev_net(dst->dev), fl4, &res) == 0) { |
916 | struct fib_nh *nh = &FIB_RES_NH(res); | 930 | struct fib_nh *nh = &FIB_RES_NH(res); |
917 | 931 | ||
918 | update_or_create_fnhe(nh, fl4->daddr, 0, mtu, | 932 | update_or_create_fnhe(nh, fl4->daddr, 0, mtu, |
919 | jiffies + ip_rt_mtu_expires); | 933 | jiffies + ip_rt_mtu_expires); |
920 | } | 934 | } |
921 | rcu_read_unlock(); | 935 | rcu_read_unlock(); |
922 | return mtu; | ||
923 | } | 936 | } |
924 | 937 | ||
925 | static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, | 938 | static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, |
@@ -929,14 +942,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, | |||
929 | struct flowi4 fl4; | 942 | struct flowi4 fl4; |
930 | 943 | ||
931 | ip_rt_build_flow_key(&fl4, sk, skb); | 944 | ip_rt_build_flow_key(&fl4, sk, skb); |
932 | mtu = __ip_rt_update_pmtu(rt, &fl4, mtu); | 945 | __ip_rt_update_pmtu(rt, &fl4, mtu); |
933 | |||
934 | if (!rt->rt_pmtu) { | ||
935 | dst->obsolete = DST_OBSOLETE_KILL; | ||
936 | } else { | ||
937 | rt->rt_pmtu = mtu; | ||
938 | rt->dst.expires = max(1UL, jiffies + ip_rt_mtu_expires); | ||
939 | } | ||
940 | } | 946 | } |
941 | 947 | ||
942 | void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu, | 948 | void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu, |
@@ -1111,10 +1117,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst) | |||
1111 | const struct rtable *rt = (const struct rtable *) dst; | 1117 | const struct rtable *rt = (const struct rtable *) dst; |
1112 | unsigned int mtu = rt->rt_pmtu; | 1118 | unsigned int mtu = rt->rt_pmtu; |
1113 | 1119 | ||
1114 | if (mtu && time_after_eq(jiffies, rt->dst.expires)) | 1120 | if (!mtu || time_after_eq(jiffies, rt->dst.expires)) |
1115 | mtu = 0; | ||
1116 | |||
1117 | if (!mtu) | ||
1118 | mtu = dst_metric_raw(dst, RTAX_MTU); | 1121 | mtu = dst_metric_raw(dst, RTAX_MTU); |
1119 | 1122 | ||
1120 | if (mtu && rt_is_output_route(rt)) | 1123 | if (mtu && rt_is_output_route(rt)) |
@@ -1123,7 +1126,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst) | |||
1123 | mtu = dst->dev->mtu; | 1126 | mtu = dst->dev->mtu; |
1124 | 1127 | ||
1125 | if (unlikely(dst_metric_locked(dst, RTAX_MTU))) { | 1128 | if (unlikely(dst_metric_locked(dst, RTAX_MTU))) { |
1126 | if (rt->rt_gateway && mtu > 576) | 1129 | if (rt->rt_uses_gateway && mtu > 576) |
1127 | mtu = 576; | 1130 | mtu = 576; |
1128 | } | 1131 | } |
1129 | 1132 | ||
@@ -1160,8 +1163,12 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, | |||
1160 | spin_lock_bh(&fnhe_lock); | 1163 | spin_lock_bh(&fnhe_lock); |
1161 | 1164 | ||
1162 | if (daddr == fnhe->fnhe_daddr) { | 1165 | if (daddr == fnhe->fnhe_daddr) { |
1163 | struct rtable *orig; | 1166 | struct rtable *orig = rcu_dereference(fnhe->fnhe_rth); |
1164 | 1167 | if (orig && rt_is_expired(orig)) { | |
1168 | fnhe->fnhe_gw = 0; | ||
1169 | fnhe->fnhe_pmtu = 0; | ||
1170 | fnhe->fnhe_expires = 0; | ||
1171 | } | ||
1165 | if (fnhe->fnhe_pmtu) { | 1172 | if (fnhe->fnhe_pmtu) { |
1166 | unsigned long expires = fnhe->fnhe_expires; | 1173 | unsigned long expires = fnhe->fnhe_expires; |
1167 | unsigned long diff = expires - jiffies; | 1174 | unsigned long diff = expires - jiffies; |
@@ -1174,22 +1181,16 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, | |||
1174 | if (fnhe->fnhe_gw) { | 1181 | if (fnhe->fnhe_gw) { |
1175 | rt->rt_flags |= RTCF_REDIRECTED; | 1182 | rt->rt_flags |= RTCF_REDIRECTED; |
1176 | rt->rt_gateway = fnhe->fnhe_gw; | 1183 | rt->rt_gateway = fnhe->fnhe_gw; |
1177 | } | 1184 | rt->rt_uses_gateway = 1; |
1185 | } else if (!rt->rt_gateway) | ||
1186 | rt->rt_gateway = daddr; | ||
1178 | 1187 | ||
1179 | orig = rcu_dereference(fnhe->fnhe_rth); | ||
1180 | rcu_assign_pointer(fnhe->fnhe_rth, rt); | 1188 | rcu_assign_pointer(fnhe->fnhe_rth, rt); |
1181 | if (orig) | 1189 | if (orig) |
1182 | rt_free(orig); | 1190 | rt_free(orig); |
1183 | 1191 | ||
1184 | fnhe->fnhe_stamp = jiffies; | 1192 | fnhe->fnhe_stamp = jiffies; |
1185 | ret = true; | 1193 | ret = true; |
1186 | } else { | ||
1187 | /* Routes we intend to cache in nexthop exception have | ||
1188 | * the DST_NOCACHE bit clear. However, if we are | ||
1189 | * unsuccessful at storing this route into the cache | ||
1190 | * we really need to set it. | ||
1191 | */ | ||
1192 | rt->dst.flags |= DST_NOCACHE; | ||
1193 | } | 1194 | } |
1194 | spin_unlock_bh(&fnhe_lock); | 1195 | spin_unlock_bh(&fnhe_lock); |
1195 | 1196 | ||
@@ -1204,8 +1205,6 @@ static bool rt_cache_route(struct fib_nh *nh, struct rtable *rt) | |||
1204 | if (rt_is_input_route(rt)) { | 1205 | if (rt_is_input_route(rt)) { |
1205 | p = (struct rtable **)&nh->nh_rth_input; | 1206 | p = (struct rtable **)&nh->nh_rth_input; |
1206 | } else { | 1207 | } else { |
1207 | if (!nh->nh_pcpu_rth_output) | ||
1208 | goto nocache; | ||
1209 | p = (struct rtable **)__this_cpu_ptr(nh->nh_pcpu_rth_output); | 1208 | p = (struct rtable **)__this_cpu_ptr(nh->nh_pcpu_rth_output); |
1210 | } | 1209 | } |
1211 | orig = *p; | 1210 | orig = *p; |
@@ -1214,16 +1213,8 @@ static bool rt_cache_route(struct fib_nh *nh, struct rtable *rt) | |||
1214 | if (prev == orig) { | 1213 | if (prev == orig) { |
1215 | if (orig) | 1214 | if (orig) |
1216 | rt_free(orig); | 1215 | rt_free(orig); |
1217 | } else { | 1216 | } else |
1218 | /* Routes we intend to cache in the FIB nexthop have | ||
1219 | * the DST_NOCACHE bit clear. However, if we are | ||
1220 | * unsuccessful at storing this route into the cache | ||
1221 | * we really need to set it. | ||
1222 | */ | ||
1223 | nocache: | ||
1224 | rt->dst.flags |= DST_NOCACHE; | ||
1225 | ret = false; | 1217 | ret = false; |
1226 | } | ||
1227 | 1218 | ||
1228 | return ret; | 1219 | return ret; |
1229 | } | 1220 | } |
@@ -1284,8 +1275,10 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr, | |||
1284 | if (fi) { | 1275 | if (fi) { |
1285 | struct fib_nh *nh = &FIB_RES_NH(*res); | 1276 | struct fib_nh *nh = &FIB_RES_NH(*res); |
1286 | 1277 | ||
1287 | if (nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK) | 1278 | if (nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK) { |
1288 | rt->rt_gateway = nh->nh_gw; | 1279 | rt->rt_gateway = nh->nh_gw; |
1280 | rt->rt_uses_gateway = 1; | ||
1281 | } | ||
1289 | dst_init_metrics(&rt->dst, fi->fib_metrics, true); | 1282 | dst_init_metrics(&rt->dst, fi->fib_metrics, true); |
1290 | #ifdef CONFIG_IP_ROUTE_CLASSID | 1283 | #ifdef CONFIG_IP_ROUTE_CLASSID |
1291 | rt->dst.tclassid = nh->nh_tclassid; | 1284 | rt->dst.tclassid = nh->nh_tclassid; |
@@ -1294,8 +1287,18 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr, | |||
1294 | cached = rt_bind_exception(rt, fnhe, daddr); | 1287 | cached = rt_bind_exception(rt, fnhe, daddr); |
1295 | else if (!(rt->dst.flags & DST_NOCACHE)) | 1288 | else if (!(rt->dst.flags & DST_NOCACHE)) |
1296 | cached = rt_cache_route(nh, rt); | 1289 | cached = rt_cache_route(nh, rt); |
1297 | } | 1290 | if (unlikely(!cached)) { |
1298 | if (unlikely(!cached)) | 1291 | /* Routes we intend to cache in nexthop exception or |
1292 | * FIB nexthop have the DST_NOCACHE bit clear. | ||
1293 | * However, if we are unsuccessful at storing this | ||
1294 | * route into the cache we really need to set it. | ||
1295 | */ | ||
1296 | rt->dst.flags |= DST_NOCACHE; | ||
1297 | if (!rt->rt_gateway) | ||
1298 | rt->rt_gateway = daddr; | ||
1299 | rt_add_uncached_list(rt); | ||
1300 | } | ||
1301 | } else | ||
1299 | rt_add_uncached_list(rt); | 1302 | rt_add_uncached_list(rt); |
1300 | 1303 | ||
1301 | #ifdef CONFIG_IP_ROUTE_CLASSID | 1304 | #ifdef CONFIG_IP_ROUTE_CLASSID |
@@ -1363,6 +1366,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
1363 | rth->rt_iif = 0; | 1366 | rth->rt_iif = 0; |
1364 | rth->rt_pmtu = 0; | 1367 | rth->rt_pmtu = 0; |
1365 | rth->rt_gateway = 0; | 1368 | rth->rt_gateway = 0; |
1369 | rth->rt_uses_gateway = 0; | ||
1366 | INIT_LIST_HEAD(&rth->rt_uncached); | 1370 | INIT_LIST_HEAD(&rth->rt_uncached); |
1367 | if (our) { | 1371 | if (our) { |
1368 | rth->dst.input= ip_local_deliver; | 1372 | rth->dst.input= ip_local_deliver; |
@@ -1432,7 +1436,6 @@ static int __mkroute_input(struct sk_buff *skb, | |||
1432 | return -EINVAL; | 1436 | return -EINVAL; |
1433 | } | 1437 | } |
1434 | 1438 | ||
1435 | |||
1436 | err = fib_validate_source(skb, saddr, daddr, tos, FIB_RES_OIF(*res), | 1439 | err = fib_validate_source(skb, saddr, daddr, tos, FIB_RES_OIF(*res), |
1437 | in_dev->dev, in_dev, &itag); | 1440 | in_dev->dev, in_dev, &itag); |
1438 | if (err < 0) { | 1441 | if (err < 0) { |
@@ -1442,10 +1445,13 @@ static int __mkroute_input(struct sk_buff *skb, | |||
1442 | goto cleanup; | 1445 | goto cleanup; |
1443 | } | 1446 | } |
1444 | 1447 | ||
1445 | if (out_dev == in_dev && err && | 1448 | do_cache = res->fi && !itag; |
1449 | if (out_dev == in_dev && err && IN_DEV_TX_REDIRECTS(out_dev) && | ||
1446 | (IN_DEV_SHARED_MEDIA(out_dev) || | 1450 | (IN_DEV_SHARED_MEDIA(out_dev) || |
1447 | inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) | 1451 | inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) { |
1448 | flags |= RTCF_DOREDIRECT; | 1452 | flags |= RTCF_DOREDIRECT; |
1453 | do_cache = false; | ||
1454 | } | ||
1449 | 1455 | ||
1450 | if (skb->protocol != htons(ETH_P_IP)) { | 1456 | if (skb->protocol != htons(ETH_P_IP)) { |
1451 | /* Not IP (i.e. ARP). Do not create route, if it is | 1457 | /* Not IP (i.e. ARP). Do not create route, if it is |
@@ -1462,15 +1468,11 @@ static int __mkroute_input(struct sk_buff *skb, | |||
1462 | } | 1468 | } |
1463 | } | 1469 | } |
1464 | 1470 | ||
1465 | do_cache = false; | 1471 | if (do_cache) { |
1466 | if (res->fi) { | 1472 | rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input); |
1467 | if (!itag) { | 1473 | if (rt_cache_valid(rth)) { |
1468 | rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input); | 1474 | skb_dst_set_noref(skb, &rth->dst); |
1469 | if (rt_cache_valid(rth)) { | 1475 | goto out; |
1470 | skb_dst_set_noref(skb, &rth->dst); | ||
1471 | goto out; | ||
1472 | } | ||
1473 | do_cache = true; | ||
1474 | } | 1476 | } |
1475 | } | 1477 | } |
1476 | 1478 | ||
@@ -1489,6 +1491,7 @@ static int __mkroute_input(struct sk_buff *skb, | |||
1489 | rth->rt_iif = 0; | 1491 | rth->rt_iif = 0; |
1490 | rth->rt_pmtu = 0; | 1492 | rth->rt_pmtu = 0; |
1491 | rth->rt_gateway = 0; | 1493 | rth->rt_gateway = 0; |
1494 | rth->rt_uses_gateway = 0; | ||
1492 | INIT_LIST_HEAD(&rth->rt_uncached); | 1495 | INIT_LIST_HEAD(&rth->rt_uncached); |
1493 | 1496 | ||
1494 | rth->dst.input = ip_forward; | 1497 | rth->dst.input = ip_forward; |
@@ -1566,11 +1569,14 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
1566 | if (ipv4_is_zeronet(daddr)) | 1569 | if (ipv4_is_zeronet(daddr)) |
1567 | goto martian_destination; | 1570 | goto martian_destination; |
1568 | 1571 | ||
1569 | if (likely(!IN_DEV_ROUTE_LOCALNET(in_dev))) { | 1572 | /* Following code try to avoid calling IN_DEV_NET_ROUTE_LOCALNET(), |
1570 | if (ipv4_is_loopback(daddr)) | 1573 | * and call it once if daddr or/and saddr are loopback addresses |
1574 | */ | ||
1575 | if (ipv4_is_loopback(daddr)) { | ||
1576 | if (!IN_DEV_NET_ROUTE_LOCALNET(in_dev, net)) | ||
1571 | goto martian_destination; | 1577 | goto martian_destination; |
1572 | 1578 | } else if (ipv4_is_loopback(saddr)) { | |
1573 | if (ipv4_is_loopback(saddr)) | 1579 | if (!IN_DEV_NET_ROUTE_LOCALNET(in_dev, net)) |
1574 | goto martian_source; | 1580 | goto martian_source; |
1575 | } | 1581 | } |
1576 | 1582 | ||
@@ -1595,7 +1601,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
1595 | 1601 | ||
1596 | if (res.type == RTN_LOCAL) { | 1602 | if (res.type == RTN_LOCAL) { |
1597 | err = fib_validate_source(skb, saddr, daddr, tos, | 1603 | err = fib_validate_source(skb, saddr, daddr, tos, |
1598 | net->loopback_dev->ifindex, | 1604 | LOOPBACK_IFINDEX, |
1599 | dev, in_dev, &itag); | 1605 | dev, in_dev, &itag); |
1600 | if (err < 0) | 1606 | if (err < 0) |
1601 | goto martian_source_keep_err; | 1607 | goto martian_source_keep_err; |
@@ -1656,6 +1662,7 @@ local_input: | |||
1656 | rth->rt_iif = 0; | 1662 | rth->rt_iif = 0; |
1657 | rth->rt_pmtu = 0; | 1663 | rth->rt_pmtu = 0; |
1658 | rth->rt_gateway = 0; | 1664 | rth->rt_gateway = 0; |
1665 | rth->rt_uses_gateway = 0; | ||
1659 | INIT_LIST_HEAD(&rth->rt_uncached); | 1666 | INIT_LIST_HEAD(&rth->rt_uncached); |
1660 | if (res.type == RTN_UNREACHABLE) { | 1667 | if (res.type == RTN_UNREACHABLE) { |
1661 | rth->dst.input= ip_error; | 1668 | rth->dst.input= ip_error; |
@@ -1758,6 +1765,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, | |||
1758 | struct in_device *in_dev; | 1765 | struct in_device *in_dev; |
1759 | u16 type = res->type; | 1766 | u16 type = res->type; |
1760 | struct rtable *rth; | 1767 | struct rtable *rth; |
1768 | bool do_cache; | ||
1761 | 1769 | ||
1762 | in_dev = __in_dev_get_rcu(dev_out); | 1770 | in_dev = __in_dev_get_rcu(dev_out); |
1763 | if (!in_dev) | 1771 | if (!in_dev) |
@@ -1794,24 +1802,36 @@ static struct rtable *__mkroute_output(const struct fib_result *res, | |||
1794 | } | 1802 | } |
1795 | 1803 | ||
1796 | fnhe = NULL; | 1804 | fnhe = NULL; |
1805 | do_cache = fi != NULL; | ||
1797 | if (fi) { | 1806 | if (fi) { |
1798 | struct rtable __rcu **prth; | 1807 | struct rtable __rcu **prth; |
1808 | struct fib_nh *nh = &FIB_RES_NH(*res); | ||
1799 | 1809 | ||
1800 | fnhe = find_exception(&FIB_RES_NH(*res), fl4->daddr); | 1810 | fnhe = find_exception(nh, fl4->daddr); |
1801 | if (fnhe) | 1811 | if (fnhe) |
1802 | prth = &fnhe->fnhe_rth; | 1812 | prth = &fnhe->fnhe_rth; |
1803 | else | 1813 | else { |
1804 | prth = __this_cpu_ptr(FIB_RES_NH(*res).nh_pcpu_rth_output); | 1814 | if (unlikely(fl4->flowi4_flags & |
1815 | FLOWI_FLAG_KNOWN_NH && | ||
1816 | !(nh->nh_gw && | ||
1817 | nh->nh_scope == RT_SCOPE_LINK))) { | ||
1818 | do_cache = false; | ||
1819 | goto add; | ||
1820 | } | ||
1821 | prth = __this_cpu_ptr(nh->nh_pcpu_rth_output); | ||
1822 | } | ||
1805 | rth = rcu_dereference(*prth); | 1823 | rth = rcu_dereference(*prth); |
1806 | if (rt_cache_valid(rth)) { | 1824 | if (rt_cache_valid(rth)) { |
1807 | dst_hold(&rth->dst); | 1825 | dst_hold(&rth->dst); |
1808 | return rth; | 1826 | return rth; |
1809 | } | 1827 | } |
1810 | } | 1828 | } |
1829 | |||
1830 | add: | ||
1811 | rth = rt_dst_alloc(dev_out, | 1831 | rth = rt_dst_alloc(dev_out, |
1812 | IN_DEV_CONF_GET(in_dev, NOPOLICY), | 1832 | IN_DEV_CONF_GET(in_dev, NOPOLICY), |
1813 | IN_DEV_CONF_GET(in_dev, NOXFRM), | 1833 | IN_DEV_CONF_GET(in_dev, NOXFRM), |
1814 | fi); | 1834 | do_cache); |
1815 | if (!rth) | 1835 | if (!rth) |
1816 | return ERR_PTR(-ENOBUFS); | 1836 | return ERR_PTR(-ENOBUFS); |
1817 | 1837 | ||
@@ -1824,6 +1844,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, | |||
1824 | rth->rt_iif = orig_oif ? : 0; | 1844 | rth->rt_iif = orig_oif ? : 0; |
1825 | rth->rt_pmtu = 0; | 1845 | rth->rt_pmtu = 0; |
1826 | rth->rt_gateway = 0; | 1846 | rth->rt_gateway = 0; |
1847 | rth->rt_uses_gateway = 0; | ||
1827 | INIT_LIST_HEAD(&rth->rt_uncached); | 1848 | INIT_LIST_HEAD(&rth->rt_uncached); |
1828 | 1849 | ||
1829 | RT_CACHE_STAT_INC(out_slow_tot); | 1850 | RT_CACHE_STAT_INC(out_slow_tot); |
@@ -1871,7 +1892,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4) | |||
1871 | 1892 | ||
1872 | orig_oif = fl4->flowi4_oif; | 1893 | orig_oif = fl4->flowi4_oif; |
1873 | 1894 | ||
1874 | fl4->flowi4_iif = net->loopback_dev->ifindex; | 1895 | fl4->flowi4_iif = LOOPBACK_IFINDEX; |
1875 | fl4->flowi4_tos = tos & IPTOS_RT_MASK; | 1896 | fl4->flowi4_tos = tos & IPTOS_RT_MASK; |
1876 | fl4->flowi4_scope = ((tos & RTO_ONLINK) ? | 1897 | fl4->flowi4_scope = ((tos & RTO_ONLINK) ? |
1877 | RT_SCOPE_LINK : RT_SCOPE_UNIVERSE); | 1898 | RT_SCOPE_LINK : RT_SCOPE_UNIVERSE); |
@@ -1960,7 +1981,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4) | |||
1960 | if (!fl4->daddr) | 1981 | if (!fl4->daddr) |
1961 | fl4->daddr = fl4->saddr = htonl(INADDR_LOOPBACK); | 1982 | fl4->daddr = fl4->saddr = htonl(INADDR_LOOPBACK); |
1962 | dev_out = net->loopback_dev; | 1983 | dev_out = net->loopback_dev; |
1963 | fl4->flowi4_oif = net->loopback_dev->ifindex; | 1984 | fl4->flowi4_oif = LOOPBACK_IFINDEX; |
1964 | res.type = RTN_LOCAL; | 1985 | res.type = RTN_LOCAL; |
1965 | flags |= RTCF_LOCAL; | 1986 | flags |= RTCF_LOCAL; |
1966 | goto make_route; | 1987 | goto make_route; |
@@ -2102,6 +2123,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or | |||
2102 | rt->rt_flags = ort->rt_flags; | 2123 | rt->rt_flags = ort->rt_flags; |
2103 | rt->rt_type = ort->rt_type; | 2124 | rt->rt_type = ort->rt_type; |
2104 | rt->rt_gateway = ort->rt_gateway; | 2125 | rt->rt_gateway = ort->rt_gateway; |
2126 | rt->rt_uses_gateway = ort->rt_uses_gateway; | ||
2105 | 2127 | ||
2106 | INIT_LIST_HEAD(&rt->rt_uncached); | 2128 | INIT_LIST_HEAD(&rt->rt_uncached); |
2107 | 2129 | ||
@@ -2131,7 +2153,7 @@ struct rtable *ip_route_output_flow(struct net *net, struct flowi4 *flp4, | |||
2131 | EXPORT_SYMBOL_GPL(ip_route_output_flow); | 2153 | EXPORT_SYMBOL_GPL(ip_route_output_flow); |
2132 | 2154 | ||
2133 | static int rt_fill_info(struct net *net, __be32 dst, __be32 src, | 2155 | static int rt_fill_info(struct net *net, __be32 dst, __be32 src, |
2134 | struct flowi4 *fl4, struct sk_buff *skb, u32 pid, | 2156 | struct flowi4 *fl4, struct sk_buff *skb, u32 portid, |
2135 | u32 seq, int event, int nowait, unsigned int flags) | 2157 | u32 seq, int event, int nowait, unsigned int flags) |
2136 | { | 2158 | { |
2137 | struct rtable *rt = skb_rtable(skb); | 2159 | struct rtable *rt = skb_rtable(skb); |
@@ -2141,7 +2163,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, | |||
2141 | u32 error; | 2163 | u32 error; |
2142 | u32 metrics[RTAX_MAX]; | 2164 | u32 metrics[RTAX_MAX]; |
2143 | 2165 | ||
2144 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags); | 2166 | nlh = nlmsg_put(skb, portid, seq, event, sizeof(*r), flags); |
2145 | if (nlh == NULL) | 2167 | if (nlh == NULL) |
2146 | return -EMSGSIZE; | 2168 | return -EMSGSIZE; |
2147 | 2169 | ||
@@ -2180,28 +2202,31 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, | |||
2180 | if (nla_put_be32(skb, RTA_PREFSRC, fl4->saddr)) | 2202 | if (nla_put_be32(skb, RTA_PREFSRC, fl4->saddr)) |
2181 | goto nla_put_failure; | 2203 | goto nla_put_failure; |
2182 | } | 2204 | } |
2183 | if (rt->rt_gateway && | 2205 | if (rt->rt_uses_gateway && |
2184 | nla_put_be32(skb, RTA_GATEWAY, rt->rt_gateway)) | 2206 | nla_put_be32(skb, RTA_GATEWAY, rt->rt_gateway)) |
2185 | goto nla_put_failure; | 2207 | goto nla_put_failure; |
2186 | 2208 | ||
2209 | expires = rt->dst.expires; | ||
2210 | if (expires) { | ||
2211 | unsigned long now = jiffies; | ||
2212 | |||
2213 | if (time_before(now, expires)) | ||
2214 | expires -= now; | ||
2215 | else | ||
2216 | expires = 0; | ||
2217 | } | ||
2218 | |||
2187 | memcpy(metrics, dst_metrics_ptr(&rt->dst), sizeof(metrics)); | 2219 | memcpy(metrics, dst_metrics_ptr(&rt->dst), sizeof(metrics)); |
2188 | if (rt->rt_pmtu) | 2220 | if (rt->rt_pmtu && expires) |
2189 | metrics[RTAX_MTU - 1] = rt->rt_pmtu; | 2221 | metrics[RTAX_MTU - 1] = rt->rt_pmtu; |
2190 | if (rtnetlink_put_metrics(skb, metrics) < 0) | 2222 | if (rtnetlink_put_metrics(skb, metrics) < 0) |
2191 | goto nla_put_failure; | 2223 | goto nla_put_failure; |
2192 | 2224 | ||
2193 | if (fl4->flowi4_mark && | 2225 | if (fl4->flowi4_mark && |
2194 | nla_put_be32(skb, RTA_MARK, fl4->flowi4_mark)) | 2226 | nla_put_u32(skb, RTA_MARK, fl4->flowi4_mark)) |
2195 | goto nla_put_failure; | 2227 | goto nla_put_failure; |
2196 | 2228 | ||
2197 | error = rt->dst.error; | 2229 | error = rt->dst.error; |
2198 | expires = rt->dst.expires; | ||
2199 | if (expires) { | ||
2200 | if (time_before(jiffies, expires)) | ||
2201 | expires -= jiffies; | ||
2202 | else | ||
2203 | expires = 0; | ||
2204 | } | ||
2205 | 2230 | ||
2206 | if (rt_is_input_route(rt)) { | 2231 | if (rt_is_input_route(rt)) { |
2207 | if (nla_put_u32(skb, RTA_IIF, rt->rt_iif)) | 2232 | if (nla_put_u32(skb, RTA_IIF, rt->rt_iif)) |
@@ -2301,12 +2326,12 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void | |||
2301 | rt->rt_flags |= RTCF_NOTIFY; | 2326 | rt->rt_flags |= RTCF_NOTIFY; |
2302 | 2327 | ||
2303 | err = rt_fill_info(net, dst, src, &fl4, skb, | 2328 | err = rt_fill_info(net, dst, src, &fl4, skb, |
2304 | NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, | 2329 | NETLINK_CB(in_skb).portid, nlh->nlmsg_seq, |
2305 | RTM_NEWROUTE, 0, 0); | 2330 | RTM_NEWROUTE, 0, 0); |
2306 | if (err <= 0) | 2331 | if (err <= 0) |
2307 | goto errout_free; | 2332 | goto errout_free; |
2308 | 2333 | ||
2309 | err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid); | 2334 | err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid); |
2310 | errout: | 2335 | errout: |
2311 | return err; | 2336 | return err; |
2312 | 2337 | ||