|
| 1 | +From 90df429b3fdfac074351327ca8681f940480229a Mon Sep 17 00:00:00 2001 |
| 2 | +From: Preetham Singh < [email protected]> |
| 3 | +Date: Sun, 8 Sep 2019 09:47:17 +0000 |
| 4 | +Subject: [PATCH] From 0b4074c953a707e8b3103fefeeaa5b439f869b3b Mon Sep 17 |
| 5 | + 00:00:00 2001 Subject: [PATCH]net: IPv6 anycast, mcast routes with nhop |
| 6 | + interface |
| 7 | + |
| 8 | +All auto generated IPv6 LL, anycast and multicast routes are installed |
| 9 | +with nhop as l3mdev instead of interface. |
| 10 | + |
| 11 | +Signed-off-by: Preetham Singh < [email protected]> |
| 12 | +--- |
| 13 | + net/ipv6/addrconf.c | 41 ----------------------------------------- |
| 14 | + net/ipv6/icmp.c | 15 +++++++++++++-- |
| 15 | + net/ipv6/route.c | 45 +++++++++++++++++++++++++++++++++++---------- |
| 16 | + 3 files changed, 48 insertions(+), 53 deletions(-) |
| 17 | + |
| 18 | +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c |
| 19 | +index 4a5d3bbf..a8bd7807 100644 |
| 20 | +--- a/net/ipv6/addrconf.c |
| 21 | ++++ b/net/ipv6/addrconf.c |
| 22 | +@@ -2969,9 +2969,6 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) |
| 23 | + static void init_loopback(struct net_device *dev) |
| 24 | + { |
| 25 | + struct inet6_dev *idev; |
| 26 | +- struct net_device *sp_dev; |
| 27 | +- struct inet6_ifaddr *sp_ifa; |
| 28 | +- struct rt6_info *sp_rt; |
| 29 | + |
| 30 | + /* ::1 */ |
| 31 | + |
| 32 | +@@ -2985,44 +2982,6 @@ static void init_loopback(struct net_device *dev) |
| 33 | + |
| 34 | + add_addr(idev, &in6addr_loopback, 128, IFA_HOST); |
| 35 | + |
| 36 | +- /* Add routes to other interface's IPv6 addresses */ |
| 37 | +- for_each_netdev(dev_net(dev), sp_dev) { |
| 38 | +- if (!strcmp(sp_dev->name, dev->name)) |
| 39 | +- continue; |
| 40 | +- |
| 41 | +- idev = __in6_dev_get(sp_dev); |
| 42 | +- if (!idev) |
| 43 | +- continue; |
| 44 | +- |
| 45 | +- read_lock_bh(&idev->lock); |
| 46 | +- list_for_each_entry(sp_ifa, &idev->addr_list, if_list) { |
| 47 | +- |
| 48 | +- if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE)) |
| 49 | +- continue; |
| 50 | +- |
| 51 | +- if (sp_ifa->rt) { |
| 52 | +- /* This dst has been added to garbage list when |
| 53 | +- * lo device down, release this obsolete dst and |
| 54 | +- * reallocate a new router for ifa. |
| 55 | +- */ |
| 56 | +- if (!atomic_read(&sp_ifa->rt->rt6i_ref)) { |
| 57 | +- ip6_rt_put(sp_ifa->rt); |
| 58 | +- sp_ifa->rt = NULL; |
| 59 | +- } else { |
| 60 | +- continue; |
| 61 | +- } |
| 62 | +- } |
| 63 | +- |
| 64 | +- sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, false); |
| 65 | +- |
| 66 | +- /* Failure cases are ignored */ |
| 67 | +- if (!IS_ERR(sp_rt)) { |
| 68 | +- sp_ifa->rt = sp_rt; |
| 69 | +- ip6_ins_rt(sp_rt); |
| 70 | +- } |
| 71 | +- } |
| 72 | +- read_unlock_bh(&idev->lock); |
| 73 | +- } |
| 74 | + } |
| 75 | + |
| 76 | + void addrconf_add_linklocal(struct inet6_dev *idev, |
| 77 | +diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c |
| 78 | +index 2772004b..f18128fb 100644 |
| 79 | +--- a/net/ipv6/icmp.c |
| 80 | ++++ b/net/ipv6/icmp.c |
| 81 | +@@ -445,9 +445,20 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, |
| 82 | + * Source addr check |
| 83 | + */ |
| 84 | + |
| 85 | +- if (__ipv6_addr_needs_scope_id(addr_type)) |
| 86 | ++ if (__ipv6_addr_needs_scope_id(addr_type)) { |
| 87 | + iif = skb->dev->ifindex; |
| 88 | +- else { |
| 89 | ++ |
| 90 | ++ /* for local packets, get the real device index */ |
| 91 | ++ if (iif == LOOPBACK_IFINDEX) { |
| 92 | ++ dst = skb_dst(skb); |
| 93 | ++ if (dst) { |
| 94 | ++ struct rt6_info *rt; |
| 95 | ++ |
| 96 | ++ rt = container_of(dst, struct rt6_info, dst); |
| 97 | ++ iif = rt->rt6i_idev->dev->ifindex; |
| 98 | ++ } |
| 99 | ++ } |
| 100 | ++ } else { |
| 101 | + dst = skb_dst(skb); |
| 102 | + iif = l3mdev_master_ifindex(dst ? dst->dev : skb->dev); |
| 103 | + } |
| 104 | +diff --git a/net/ipv6/route.c b/net/ipv6/route.c |
| 105 | +index cbc066d2..7dcd34f5 100644 |
| 106 | +--- a/net/ipv6/route.c |
| 107 | ++++ b/net/ipv6/route.c |
| 108 | +@@ -940,10 +940,35 @@ int ip6_ins_rt(struct rt6_info *rt) |
| 109 | + return __ip6_ins_rt(rt, &info, &mxc); |
| 110 | + } |
| 111 | + |
| 112 | ++/* called with rcu_lock held */ |
| 113 | ++static struct net_device *ip6_rt_get_dev_rcu(struct rt6_info *rt) |
| 114 | ++{ |
| 115 | ++ struct net_device *dev = rt->dst.dev; |
| 116 | ++ |
| 117 | ++ if (rt->rt6i_flags & RTF_LOCAL) { |
| 118 | ++ /* for copies of local routes, dst->dev needs to be the |
| 119 | ++ * device if it is a master device, the master device if |
| 120 | ++ * device is enslaved, and the loopback as the default |
| 121 | ++ */ |
| 122 | ++ if (netif_is_l3_slave(dev) && |
| 123 | ++ !rt6_need_strict(&rt->rt6i_dst.addr)) |
| 124 | ++ dev = l3mdev_master_dev_rcu(dev); |
| 125 | ++ else if (!netif_is_l3_master(dev)) |
| 126 | ++ dev = dev_net(dev)->loopback_dev; |
| 127 | ++ /* last case is netif_is_l3_master(dev) is true in which |
| 128 | ++ * case we want dev returned to be dev |
| 129 | ++ */ |
| 130 | ++ } |
| 131 | ++ |
| 132 | ++ return dev; |
| 133 | ++} |
| 134 | ++ |
| 135 | ++ |
| 136 | + static struct rt6_info *ip6_rt_cache_alloc(struct rt6_info *ort, |
| 137 | + const struct in6_addr *daddr, |
| 138 | + const struct in6_addr *saddr) |
| 139 | + { |
| 140 | ++ struct net_device *dev; |
| 141 | + struct rt6_info *rt; |
| 142 | + |
| 143 | + /* |
| 144 | +@@ -953,7 +978,10 @@ static struct rt6_info *ip6_rt_cache_alloc(struct rt6_info *ort, |
| 145 | + if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU)) |
| 146 | + ort = (struct rt6_info *)ort->dst.from; |
| 147 | + |
| 148 | +- rt = __ip6_dst_alloc(dev_net(ort->dst.dev), ort->dst.dev, 0); |
| 149 | ++ rcu_read_lock(); |
| 150 | ++ dev = ip6_rt_get_dev_rcu(ort); |
| 151 | ++ rt = __ip6_dst_alloc(dev_net(dev), dev, 0); |
| 152 | ++ rcu_read_unlock(); |
| 153 | + |
| 154 | + if (!rt) |
| 155 | + return NULL; |
| 156 | +@@ -983,9 +1011,12 @@ static struct rt6_info *ip6_rt_cache_alloc(struct rt6_info *ort, |
| 157 | + static struct rt6_info *ip6_rt_pcpu_alloc(struct rt6_info *rt) |
| 158 | + { |
| 159 | + struct rt6_info *pcpu_rt; |
| 160 | ++ struct net_device *dev; |
| 161 | + |
| 162 | +- pcpu_rt = __ip6_dst_alloc(dev_net(rt->dst.dev), |
| 163 | +- rt->dst.dev, rt->dst.flags); |
| 164 | ++ rcu_read_lock(); |
| 165 | ++ dev = ip6_rt_get_dev_rcu(rt); |
| 166 | ++ pcpu_rt = __ip6_dst_alloc(dev_net(dev), dev, rt->dst.flags); |
| 167 | ++ rcu_read_unlock(); |
| 168 | + |
| 169 | + if (!pcpu_rt) |
| 170 | + return NULL; |
| 171 | +@@ -2623,15 +2654,9 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, |
| 172 | + { |
| 173 | + u32 tb_id; |
| 174 | + struct net *net = dev_net(idev->dev); |
| 175 | +- struct net_device *dev = net->loopback_dev; |
| 176 | ++ struct net_device *dev = idev->dev; |
| 177 | + struct rt6_info *rt; |
| 178 | + |
| 179 | +- /* use L3 Master device as loopback for host routes if device |
| 180 | +- * is enslaved and address is not link local or multicast |
| 181 | +- */ |
| 182 | +- if (!rt6_need_strict(addr)) |
| 183 | +- dev = l3mdev_master_dev_rcu(idev->dev) ? : dev; |
| 184 | +- |
| 185 | + rt = ip6_dst_alloc(net, dev, DST_NOCOUNT); |
| 186 | + if (!rt) |
| 187 | + return ERR_PTR(-ENOMEM); |
| 188 | +-- |
| 189 | +2.18.0 |
| 190 | + |
0 commit comments