aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/dst.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/dst.c')
-rw-r--r--net/core/dst.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/net/core/dst.c b/net/core/dst.c
index b99c7c7ffce2..578893505702 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -164,6 +164,8 @@ int dst_discard(struct sk_buff *skb)
164} 164}
165EXPORT_SYMBOL(dst_discard); 165EXPORT_SYMBOL(dst_discard);
166 166
167static const u32 dst_default_metrics[RTAX_MAX];
168
167void *dst_alloc(struct dst_ops *ops) 169void *dst_alloc(struct dst_ops *ops)
168{ 170{
169 struct dst_entry *dst; 171 struct dst_entry *dst;
@@ -180,6 +182,7 @@ void *dst_alloc(struct dst_ops *ops)
180 dst->lastuse = jiffies; 182 dst->lastuse = jiffies;
181 dst->path = dst; 183 dst->path = dst;
182 dst->input = dst->output = dst_discard; 184 dst->input = dst->output = dst_discard;
185 dst_init_metrics(dst, dst_default_metrics, true);
183#if RT_CACHE_DEBUG >= 2 186#if RT_CACHE_DEBUG >= 2
184 atomic_inc(&dst_total); 187 atomic_inc(&dst_total);
185#endif 188#endif
@@ -282,6 +285,42 @@ void dst_release(struct dst_entry *dst)
282} 285}
283EXPORT_SYMBOL(dst_release); 286EXPORT_SYMBOL(dst_release);
284 287
288u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old)
289{
290 u32 *p = kmalloc(sizeof(u32) * RTAX_MAX, GFP_ATOMIC);
291
292 if (p) {
293 u32 *old_p = __DST_METRICS_PTR(old);
294 unsigned long prev, new;
295
296 memcpy(p, old_p, sizeof(u32) * RTAX_MAX);
297
298 new = (unsigned long) p;
299 prev = cmpxchg(&dst->_metrics, old, new);
300
301 if (prev != old) {
302 kfree(p);
303 p = __DST_METRICS_PTR(prev);
304 if (prev & DST_METRICS_READ_ONLY)
305 p = NULL;
306 }
307 }
308 return p;
309}
310EXPORT_SYMBOL(dst_cow_metrics_generic);
311
312/* Caller asserts that dst_metrics_read_only(dst) is false. */
313void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old)
314{
315 unsigned long prev, new;
316
317 new = (unsigned long) dst_default_metrics;
318 prev = cmpxchg(&dst->_metrics, old, new);
319 if (prev == old)
320 kfree(__DST_METRICS_PTR(old));
321}
322EXPORT_SYMBOL(__dst_destroy_metrics_generic);
323
285/** 324/**
286 * skb_dst_set_noref - sets skb dst, without a reference 325 * skb_dst_set_noref - sets skb dst, without a reference
287 * @skb: buffer 326 * @skb: buffer