hc
2024-10-12 a5969cabbb4660eab42b6ef0412cbbd1200cf14d
kernel/net/core/dst.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * net/core/dst.c Protocol independent destination cache.
34 *
....@@ -26,23 +27,6 @@
2627 #include <net/dst.h>
2728 #include <net/dst_metadata.h>
2829
29
-/*
30
- * Theory of operations:
31
- * 1) We use a list, protected by a spinlock, to add
32
- * new entries from both BH and non-BH context.
33
- * 2) In order to keep spinlock held for a small delay,
34
- * we use a second list where are stored long lived
35
- * entries, that are handled by the garbage collect thread
36
- * fired by a workqueue.
37
- * 3) This list is guarded by a mutex,
38
- * so that the gc_task and dst_dev_event() can be synchronized.
39
- */
40
-
41
-/*
42
- * We want to keep lock & list close together
43
- * to dirty as few cache lines as possible in __dst_free().
44
- * As this is not a very strong hint, we dont force an alignment on SMP.
45
- */
4630 int dst_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb)
4731 {
4832 kfree_skb(skb);
....@@ -97,9 +81,13 @@
9781 {
9882 struct dst_entry *dst;
9983
100
- if (ops->gc && dst_entries_get_fast(ops) > ops->gc_thresh) {
101
- if (ops->gc(ops))
84
+ if (ops->gc &&
85
+ !(flags & DST_NOCOUNT) &&
86
+ dst_entries_get_fast(ops) > ops->gc_thresh) {
87
+ if (ops->gc(ops)) {
88
+ pr_notice_ratelimited("Route cache is full: consider increasing sysctl net.ipv6.route.max_size.\n");
10289 return NULL;
90
+ }
10391 }
10492
10593 dst = kmem_cache_alloc(ops->kmem_cachep, GFP_ATOMIC);
....@@ -156,7 +144,7 @@
156144
157145 /* Operations to mark dst as DEAD and clean up the net device referenced
158146 * by dst:
159
- * 1. put the dst under loopback interface and discard all tx/rx packets
147
+ * 1. put the dst under blackhole interface and discard all tx/rx packets
160148 * on this route.
161149 * 2. release the net_device
162150 * This function should be called when removing routes from the fib tree
....@@ -172,7 +160,7 @@
172160 dst->ops->ifdown(dst, dev, true);
173161 dst->input = dst_discard;
174162 dst->output = dst_discard_out;
175
- dst->dev = dev_net(dst->dev)->loopback_dev;
163
+ dst->dev = blackhole_netdev;
176164 dev_hold(dst->dev);
177165 dev_put(dev);
178166 }
....@@ -184,7 +172,7 @@
184172 int newrefcnt;
185173
186174 newrefcnt = atomic_dec_return(&dst->__refcnt);
187
- if (unlikely(newrefcnt < 0))
175
+ if (WARN_ONCE(newrefcnt < 0, "dst_release underflow"))
188176 net_warn_ratelimited("%s: dst:%p refcnt:%d\n",
189177 __func__, dst, newrefcnt);
190178 if (!newrefcnt)
....@@ -199,7 +187,7 @@
199187 int newrefcnt;
200188
201189 newrefcnt = atomic_dec_return(&dst->__refcnt);
202
- if (unlikely(newrefcnt < 0))
190
+ if (WARN_ONCE(newrefcnt < 0, "dst_release_immediate underflow"))
203191 net_warn_ratelimited("%s: dst:%p refcnt:%d\n",
204192 __func__, dst, newrefcnt);
205193 if (!newrefcnt)
....@@ -249,37 +237,62 @@
249237 }
250238 EXPORT_SYMBOL(__dst_destroy_metrics_generic);
251239
252
-static struct dst_ops md_dst_ops = {
253
- .family = AF_UNSPEC,
240
+struct dst_entry *dst_blackhole_check(struct dst_entry *dst, u32 cookie)
241
+{
242
+ return NULL;
243
+}
244
+
245
+u32 *dst_blackhole_cow_metrics(struct dst_entry *dst, unsigned long old)
246
+{
247
+ return NULL;
248
+}
249
+
250
+struct neighbour *dst_blackhole_neigh_lookup(const struct dst_entry *dst,
251
+ struct sk_buff *skb,
252
+ const void *daddr)
253
+{
254
+ return NULL;
255
+}
256
+
257
+void dst_blackhole_update_pmtu(struct dst_entry *dst, struct sock *sk,
258
+ struct sk_buff *skb, u32 mtu,
259
+ bool confirm_neigh)
260
+{
261
+}
262
+EXPORT_SYMBOL_GPL(dst_blackhole_update_pmtu);
263
+
264
+void dst_blackhole_redirect(struct dst_entry *dst, struct sock *sk,
265
+ struct sk_buff *skb)
266
+{
267
+}
268
+EXPORT_SYMBOL_GPL(dst_blackhole_redirect);
269
+
270
+unsigned int dst_blackhole_mtu(const struct dst_entry *dst)
271
+{
272
+ unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
273
+
274
+ return mtu ? : dst->dev->mtu;
275
+}
276
+EXPORT_SYMBOL_GPL(dst_blackhole_mtu);
277
+
278
+static struct dst_ops dst_blackhole_ops = {
279
+ .family = AF_UNSPEC,
280
+ .neigh_lookup = dst_blackhole_neigh_lookup,
281
+ .check = dst_blackhole_check,
282
+ .cow_metrics = dst_blackhole_cow_metrics,
283
+ .update_pmtu = dst_blackhole_update_pmtu,
284
+ .redirect = dst_blackhole_redirect,
285
+ .mtu = dst_blackhole_mtu,
254286 };
255
-
256
-static int dst_md_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb)
257
-{
258
- WARN_ONCE(1, "Attempting to call output on metadata dst\n");
259
- kfree_skb(skb);
260
- return 0;
261
-}
262
-
263
-static int dst_md_discard(struct sk_buff *skb)
264
-{
265
- WARN_ONCE(1, "Attempting to call input on metadata dst\n");
266
- kfree_skb(skb);
267
- return 0;
268
-}
269287
270288 static void __metadata_dst_init(struct metadata_dst *md_dst,
271289 enum metadata_type type, u8 optslen)
272
-
273290 {
274291 struct dst_entry *dst;
275292
276293 dst = &md_dst->dst;
277
- dst_init(dst, &md_dst_ops, NULL, 1, DST_OBSOLETE_NONE,
294
+ dst_init(dst, &dst_blackhole_ops, NULL, 1, DST_OBSOLETE_NONE,
278295 DST_METADATA | DST_NOCOUNT);
279
-
280
- dst->input = dst_md_discard;
281
- dst->output = dst_md_discard_out;
282
-
283296 memset(dst + 1, 0, sizeof(*md_dst) + optslen - sizeof(*dst));
284297 md_dst->type = type;
285298 }