* Re: [PATCH] NetCP: Deletion of unnecessary checks before two function calls
From: David Miller @ 2015-02-05 4:30 UTC (permalink / raw)
To: elfring
Cc: m-karicheri2, w-kwok2, netdev, linux-kernel, kernel-janitors,
julia.lawall
In-Reply-To: <54D11FEF.10804@users.sourceforge.net>
From: SF Markus Elfring <elfring@users.sourceforge.net>
Date: Tue, 03 Feb 2015 20:22:23 +0100
> From: Markus Elfring <elfring@users.sourceforge.net>
> Date: Tue, 3 Feb 2015 20:12:25 +0100
>
> The functions cpsw_ale_destroy() and of_dev_put() test whether their argument
> is NULL and then return immediately. Thus the test around the call
> is not needed.
>
> This issue was detected by using the Coccinelle software.
>
> Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
Applied.
^ permalink raw reply
* Re: [PATCH] IBM-EMAC: Delete an unnecessary check before the function call "of_dev_put"
From: David Miller @ 2015-02-05 4:29 UTC (permalink / raw)
To: elfring; +Cc: netdev, linux-kernel, kernel-janitors, julia.lawall
In-Reply-To: <54D118BA.3080001@users.sourceforge.net>
From: SF Markus Elfring <elfring@users.sourceforge.net>
Date: Tue, 03 Feb 2015 19:51:38 +0100
> From: Markus Elfring <elfring@users.sourceforge.net>
> Date: Tue, 3 Feb 2015 19:47:33 +0100
>
> The of_dev_put() function tests whether its argument is NULL and then
> returns immediately. Thus the test around the call is not needed.
>
> This issue was detected by using the Coccinelle software.
>
> Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
Applied.
^ permalink raw reply
* Re: [PATCH net] amd-xgbe: Adjust for zero-based traffic class count
From: David Miller @ 2015-02-05 4:28 UTC (permalink / raw)
To: thomas.lendacky; +Cc: netdev
In-Reply-To: <20150203184955.14713.98160.stgit@tlendack-t1.amdoffice.net>
From: Tom Lendacky <thomas.lendacky@amd.com>
Date: Tue, 3 Feb 2015 12:49:55 -0600
> The number of traffic classes reported by the hardware is zero-based
> so increment the value returned to get an actual count.
>
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Applied, thanks Tom.
^ permalink raw reply
* Re: [PATCH net 1/1] cls_api.c: Fix dumping of non-existing actions' stats.
From: David Miller @ 2015-02-05 4:26 UTC (permalink / raw)
To: ignacy.gawedzki; +Cc: netdev
In-Reply-To: <20150203173251.GB6246@zenon.in.qult.net>
From: Ignacy Gawędzki <ignacy.gawedzki@green-communications.fr>
Date: Tue, 3 Feb 2015 18:32:51 +0100
> In tcf_exts_dump_stats(), ensure that exts->actions is not empty before
> accessing the first element of that list and calling tcf_action_copy_stats()
> on it. This fixes some random segvs when adding filters of type "basic" with
> no particular action.
>
> This also fixes the dumping of those "no-action" filters, which more often
> than not made calls to tcf_action_copy_stats() fail and consequently netlink
> attributes added by the caller to be removed by a call to nla_nest_cancel().
>
> Signed-off-by: Ignacy Gawędzki <ignacy.gawedzki@green-communications.fr>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH v2 net-next] pkt_sched: fq: better control of DDOS traffic
From: David Miller @ 2015-02-05 4:22 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev
In-Reply-To: <1422984739.907.25.camel@edumazet-glaptop2.roam.corp.google.com>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Tue, 03 Feb 2015 09:32:19 -0800
> + if (tb[TCA_FQ_ORPHAN_MASK])
> + q->orphan_mask = nla_get_u32(tb[TCA_FQ_ORPHAN_MASK]);
This doesn't build, the header file changes that add TCA_FQ_ORPHAN_MASK
are missing from your patch.
^ permalink raw reply
* Re: [PATCH net] pkt_sched: fq: avoid hang when quantum 0
From: David Miller @ 2015-02-05 4:08 UTC (permalink / raw)
To: eric.dumazet; +Cc: kennetkl, netdev
In-Reply-To: <1422985569.907.27.camel@edumazet-glaptop2.roam.corp.google.com>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Tue, 03 Feb 2015 09:46:09 -0800
> On Tue, 2015-02-03 at 17:49 +0100, Kenneth Klette Jonassen wrote:
>> Configuring fq with quantum 0 hangs the system, presumably because of a
>> non-interruptible infinite loop. Either way quantum 0 does not make sense.
>>
>> Reproduce with:
>> sudo tc qdisc add dev lo root fq quantum 0 initial_quantum 0
>> ping 127.0.0.1
>>
>> Signed-off-by: Kenneth Klette Jonassen <kennetkl@ifi.uio.no>
>> ---
>
> Acked-by: Eric Dumazet <edumazet@google.com>
Applied, thanks.
^ permalink raw reply
* Re: [ovs-dev] [PATCH v2] net: openvswitch: Support masked set actions.
From: Jesse Gross @ 2015-02-05 4:01 UTC (permalink / raw)
To: Jarno Rajahalme; +Cc: netdev, dev@openvswitch.org
In-Reply-To: <1423095381-12243-1-git-send-email-jrajahalme@nicira.com>
On Wed, Feb 4, 2015 at 4:16 PM, Jarno Rajahalme <jrajahalme@nicira.com> wrote:
> OVS userspace already probes the openvswitch kernel module for
> OVS_ACTION_ATTR_SET_MASKED support. This patch adds the kernel module
> implementation of masked set actions.
>
> The existing set action sets many fields at once. When only a subset
> of the IP header fields, for example, should be modified, all the IP
> fields need to be exact matched so that the other field values can be
> copied to the set action. A masked set action allows modification of
> an arbitrary subset of the supported header bits without requiring the
> rest to be matched.
>
> Masked set action is now supported for all writeable key types, except
> for the tunnel key. The set tunnel action is an exception as any
> input tunnel info is cleared before action processing starts, so there
> is no tunnel info to mask.
>
> The kernel module converts all (non-tunnel) set actions to masked set
> actions. This makes action processing more uniform, and results in
> less branching and duplicating the action processing code. When
> returning actions to userspace, the set actions that were converted to
> masked set actions are converted back to normal set actions. We use a
> kernel internal action code to be able to tell the userspace provided
> and converted masked set actions apart.
>
> Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com>
> ---
> v2: Fixed checkpatch warnigns and errors, rebase.
I had a few minor comments in my review from December 10th, can you take a look?
^ permalink raw reply
* Re: [ovs-dev] [PATCH v2] net: openvswitch: Support masked set actions.
From: Pravin Shelar @ 2015-02-05 3:57 UTC (permalink / raw)
To: Jarno Rajahalme; +Cc: netdev, dev@openvswitch.org
In-Reply-To: <1423095381-12243-1-git-send-email-jrajahalme@nicira.com>
On Wed, Feb 4, 2015 at 4:16 PM, Jarno Rajahalme <jrajahalme@nicira.com> wrote:
> OVS userspace already probes the openvswitch kernel module for
> OVS_ACTION_ATTR_SET_MASKED support. This patch adds the kernel module
> implementation of masked set actions.
>
> The existing set action sets many fields at once. When only a subset
> of the IP header fields, for example, should be modified, all the IP
> fields need to be exact matched so that the other field values can be
> copied to the set action. A masked set action allows modification of
> an arbitrary subset of the supported header bits without requiring the
> rest to be matched.
>
> Masked set action is now supported for all writeable key types, except
> for the tunnel key. The set tunnel action is an exception as any
> input tunnel info is cleared before action processing starts, so there
> is no tunnel info to mask.
>
> The kernel module converts all (non-tunnel) set actions to masked set
> actions. This makes action processing more uniform, and results in
> less branching and duplicating the action processing code. When
> returning actions to userspace, the set actions that were converted to
> masked set actions are converted back to normal set actions. We use a
> kernel internal action code to be able to tell the userspace provided
> and converted masked set actions apart.
>
> Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com>
> ---
> v2: Fixed checkpatch warnigns and errors, rebase.
>
Looks good.
Acked-by: Pravin B Shelar <pshelar@nicira.com>
^ permalink raw reply
* Re: [PATCH 0/6 v2 net-next] rhashtable fixes
From: Ying Xue @ 2015-02-05 2:32 UTC (permalink / raw)
To: Thomas Graf, davem; +Cc: netdev, herbert
In-Reply-To: <cover.1423097592.git.tgraf@suug.ch>
Hi Thomas,
After I applied the sires, it sounds like panic doesn't occur any more. But soft
lockup still happens although the frequency of its reproduction is much lower
than before. Please take a look at its relevant log:
root@localhost:/mnt# ./bind2 10000
Create 10000 ports
^[[A[ 83.760030] ------------[ cut here ]------------
[ 83.760428] WARNING: CPU: 6 PID: 0 at net/sched/sch_generic.c:303
dev_watchdog+0x247/0x250()
[ 83.760944] NETDEV WATCHDOG: eth0 (e1000): transmit queue 0 timed out
[ 83.761357] Modules linked in: tipc
[ 83.761607] CPU: 6 PID: 0 Comm: swapper/6 Not tainted 3.19.0-rc6+ #185
[ 83.762025] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007
[ 83.762385] 000000000000012f ffff880017d83d08 ffffffff8175d285 000000000000104b
[ 83.762884] ffff880017d83d58 ffff880017d83d48 ffffffff81059717 ffffffff00000000
[ 83.763384] ffff880015e92000 ffff880015e923e0 ffff88000008ae00 0000000000000001
[ 83.763883] Call Trace:
[ 83.764018] <IRQ> [<ffffffff8175d285>] dump_stack+0x4c/0x65
[ 83.764018] [<ffffffff81059717>] warn_slowpath_common+0x97/0xe0
[ 83.764018] [<ffffffff81059816>] warn_slowpath_fmt+0x46/0x50
[ 83.764018] [<ffffffff81654617>] dev_watchdog+0x247/0x250
[ 83.764018] [<ffffffff816543d0>] ? pfifo_fast_dequeue+0xe0/0xe0
[ 83.764018] [<ffffffff816543d0>] ? pfifo_fast_dequeue+0xe0/0xe0
[ 83.764018] [<ffffffff810c5ebc>] call_timer_fn+0x8c/0x1e0
[ 83.764018] [<ffffffff810c5e35>] ? call_timer_fn+0x5/0x1e0
[ 83.764018] [<ffffffff817669d0>] ? _raw_spin_unlock_irq+0x30/0x40
[ 83.764018] [<ffffffff816543d0>] ? pfifo_fast_dequeue+0xe0/0xe0
[ 83.764018] [<ffffffff810c7994>] run_timer_softirq+0x2d4/0x320
[ 83.764018] [<ffffffff810d6214>] ? clockevents_program_event+0x74/0x100
[ 83.764018] [<ffffffff8105d653>] __do_softirq+0x123/0x360
[ 83.764018] [<ffffffff8105db2e>] irq_exit+0x8e/0xb0
[ 83.764018] [<ffffffff81769b2a>] smp_apic_timer_interrupt+0x4a/0x60
[ 83.764018] [<ffffffff81767eaf>] apic_timer_interrupt+0x6f/0x80
[ 83.764018] <EOI> [<ffffffff8100d174>] ? default_idle+0x24/0x100
[ 83.764018] [<ffffffff8100d172>] ? default_idle+0x22/0x100
[ 83.764018] [<ffffffff8100daaf>] arch_cpu_idle+0xf/0x20
[ 83.764018] [<ffffffff8109a509>] cpu_startup_entry+0x2c9/0x3c0
[ 83.764018] [<ffffffff810d5ea2>] ? clockevents_register_device+0xe2/0x140
[ 83.764018] [<ffffffff810333c1>] start_secondary+0x141/0x150
[ 83.764018] ---[ end trace 57f25794303fa7e9 ]---
[ 83.776059] e1000 0000:00:03.0 eth0: Reset adapter
[ 88.088005] NMI watchdog: BUG: soft lockup - CPU#0 stuck for 23s! [bind2:667]
[ 88.088005] Modules linked in: tipc
[ 88.088005] irq event stamp: 25367
[ 88.088005] hardirqs last enabled at (25366): [<ffffffff81767be0>]
restore_args+0x0/0x30
[ 88.088005] hardirqs last disabled at (25367): [<ffffffff81767eaa>]
apic_timer_interrupt+0x6a/0x80
[ 88.088005] softirqs last enabled at (11842): [<ffffffff8139d66a>]
unlock_buckets+0x5a/0x70
[ 88.088005] softirqs last disabled at (11880): [<ffffffff8139d51a>]
lock_buckets+0x3a/0x80
[ 88.088005] CPU: 0 PID: 667 Comm: bind2 Tainted: G W 3.19.0-rc6+ #185
[ 88.088005] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007
[ 88.088005] task: ffff880015038000 ti: ffff880000198000 task.ti: ffff880000198000
[ 88.088005] RIP: 0010:[<ffffffff81390b6a>] [<ffffffff81390b6a>] memcmp+0x3a/0x50
[ 88.088005] RSP: 0018:ffff88000019bcf8 EFLAGS: 00000212
[ 88.088005] RAX: 00000000000000a8 RBX: ffff880000198000 RCX: 000000000000002b
[ 88.088005] RDX: 0000000000000004 RSI: ffff8800153dd87c RDI: ffff88000019747c
[ 88.088005] RBP: ffff88000019bcf8 R08: 000000002d196482 R09: ffff8800153dd87c
[ 88.088005] R10: 0000000000000002 R11: 0000000000000001 R12: 0000000000000000
[ 88.088005] R13: 0000000000000001 R14: 0000000000000000 R15: 0000000000000000
[ 88.088005] FS: 0000000000000000(0000) GS:ffff880017c00000(0063)
knlGS:00000000f75b3900
[ 88.088005] CS: 0010 DS: 002b ES: 002b CR0: 000000008005003b
[ 88.088005] CR2: 0000000008acec4c CR3: 000000001479e000 CR4: 00000000000006f0
[ 88.088005] Stack:
[ 88.088005] ffff88000019bd08 ffffffff8139d698 ffff88000019bd68 ffffffff8139e5ce
[ 88.088005] ffffffff8139e540 00000002810a6a25 069b23b200000000 ffff88001328e000
[ 88.088005] ffff88000019bd68 ffff880000149090 ffff88001328e000 00000000000001b2
[ 88.088005] Call Trace:
[ 88.088005] [<ffffffff8139d698>] rhashtable_compare+0x18/0x20
[ 88.088005] [<ffffffff8139e5ce>] rhashtable_lookup_compare+0x8e/0x120
[ 88.088005] [<ffffffff8139e540>] ? rht_deferred_worker+0xa0/0xa0
[ 88.088005] [<ffffffff8139e72f>] rhashtable_lookup_compare_insert+0x9f/0x110
[ 88.088005] [<ffffffff8139e6c5>] ? rhashtable_lookup_compare_insert+0x35/0x110
[ 88.088005] [<ffffffff8139d680>] ? unlock_buckets+0x70/0x70
[ 88.088005] [<ffffffff8139e7d2>] rhashtable_lookup_insert+0x32/0x40
[ 88.088005] [<ffffffffa00164ec>] tipc_sk_create+0x1ec/0x340 [tipc]
[ 88.088005] [<ffffffffa00163a2>] ? tipc_sk_create+0xa2/0x340 [tipc]
[ 88.088005] [<ffffffff81615e60>] __sock_create+0x170/0x270
[ 88.088005] [<ffffffff81615daf>] ? __sock_create+0xbf/0x270
[ 88.088005] [<ffffffff81615fc0>] sock_create+0x30/0x40
[ 88.088005] [<ffffffff81616d36>] SyS_socket+0x36/0xb0
[ 88.088005] [<ffffffff8118500f>] ? might_fault+0xaf/0xc0
[ 88.088005] [<ffffffff81184fc6>] ? might_fault+0x66/0xc0
[ 88.088005] [<ffffffff816523bb>] compat_SyS_socketcall+0x6b/0x200
[ 88.088005] [<ffffffff817693f3>] sysenter_dispatch+0x7/0x1f
[ 88.088005] [<ffffffff8139660e>] ? trace_hardirqs_on_thunk+0x3a/0x3f
[ 88.088005] Code: b6 0e 29 c8 75 25 48 83 ea 01 31 c9 eb 18 0f 1f 00 44 0f b6
4c 0f 01 44 0f b6 44 0e 01 48 83 c1 01 45 29 c1 75 0b 48 39 d1 75 e6 <5d> c3 0f
1f 40 00 44 89 c8 5d c3 66 66 2e 0f 1f 84 00 00 00 00
[ 116.088006] NMI watchdog: BUG: soft lockup - CPU#0 stuck for 23s! [bind2:667]
[ 116.088006] Modules linked in: tipc
[ 116.088006] irq event stamp: 39357
[ 116.088006] hardirqs last enabled at (39356): [<ffffffff81767be0>]
restore_args+0x0/0x30
[ 116.088006] hardirqs last disabled at (39357): [<ffffffff81767eaa>]
apic_timer_interrupt+0x6a/0x80
[ 116.088006] softirqs last enabled at (11842): [<ffffffff8139d66a>]
unlock_buckets+0x5a/0x70
[ 116.088006] softirqs last disabled at (11880): [<ffffffff8139d51a>]
lock_buckets+0x3a/0x80
[ 116.088006] CPU: 0 PID: 667 Comm: bind2 Tainted: G W L 3.19.0-rc6+ #185
[ 116.088006] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007
[ 116.088006] task: ffff880015038000 ti: ffff880000198000 task.ti: ffff880000198000
[ 116.088006] RIP: 0010:[<ffffffff81390b3e>] [<ffffffff81390b3e>] memcmp+0xe/0x50
[ 116.088006] RSP: 0018:ffff88000019bcf8 EFLAGS: 00000202
[ 116.088006] RAX: 00000000000000d3 RBX: ffffffff81767be0 RCX: 000000000000002b
[ 116.088006] RDX: 0000000000000004 RSI: ffff8800153dd87c RDI: ffff88000019747c
[ 116.088006] RBP: ffff88000019bcf8 R08: 000000002d196482 R09: ffff8800153dd87c
[ 116.088006] R10: 0000000000000002 R11: 0000000000000001 R12: ffff88000019bc68
[ 116.088006] R13: 0000000000000046 R14: ffff880000198000 R15: ffff880015038000
[ 116.088006] FS: 0000000000000000(0000) GS:ffff880017c00000(0063)
knlGS:00000000f75b3900
[ 116.088006] CS: 0010 DS: 002b ES: 002b CR0: 000000008005003b
[ 116.088006] CR2: 0000000008acec4c CR3: 000000001479e000 CR4: 00000000000006f0
[ 116.088006] Stack:
[ 116.088006] ffff88000019bd08 ffffffff8139d698 ffff88000019bd68 ffffffff8139e5ce
[ 116.088006] ffffffff8139e540 00000002810a6a25 069b23b200000000 ffff88001328e000
[ 116.088006] ffff88000019bd68 ffff880000149090 ffff88001328e000 00000000000001b2
[ 116.088006] Call Trace:
[ 116.088006] [<ffffffff8139d698>] rhashtable_compare+0x18/0x20
[ 116.088006] [<ffffffff8139e5ce>] rhashtable_lookup_compare+0x8e/0x120
[ 116.088006] [<ffffffff8139e540>] ? rht_deferred_worker+0xa0/0xa0
[ 116.088006] [<ffffffff8139e72f>] rhashtable_lookup_compare_insert+0x9f/0x110
[ 116.088006] [<ffffffff8139e6c5>] ? rhashtable_lookup_compare_insert+0x35/0x110
[ 116.088006] [<ffffffff8139d680>] ? unlock_buckets+0x70/0x70
[ 116.088006] [<ffffffff8139e7d2>] rhashtable_lookup_insert+0x32/0x40
[ 116.088006] [<ffffffffa00164ec>] tipc_sk_create+0x1ec/0x340 [tipc]
[ 116.088006] [<ffffffffa00163a2>] ? tipc_sk_create+0xa2/0x340 [tipc]
[ 116.088006] [<ffffffff81615e60>] __sock_create+0x170/0x270
[ 116.088006] [<ffffffff81615daf>] ? __sock_create+0xbf/0x270
[ 116.088006] [<ffffffff81615fc0>] sock_create+0x30/0x40
[ 116.088006] [<ffffffff81616d36>] SyS_socket+0x36/0xb0
[ 116.088006] [<ffffffff8118500f>] ? might_fault+0xaf/0xc0
[ 116.088006] [<ffffffff81184fc6>] ? might_fault+0x66/0xc0
[ 116.088006] [<ffffffff816523bb>] compat_SyS_socketcall+0x6b/0x200
[ 116.088006] [<ffffffff817693f3>] sysenter_dispatch+0x7/0x1f
[ 116.088006] [<ffffffff8139660e>] ? trace_hardirqs_on_thunk+0x3a/0x3f
[ 116.088006] Code: 06 01 5d c3 66 0f 1f 84 00 00 00 00 00 31 c0 c6 06 00 5d c3
66 0f 1f 84 00 00 00 00 00 55 31 c0 48 85 d2 48 89 e5 74 2f 0f b6 07 <0f> b6 0e
29 c8 75 25 48 83 ea 01 31 c9 eb 18 0f 1f 00 44 0f b6
[ 121.200005] INFO: rcu_sched self-detected stall on CPU { 0} (t=15000 jiffies
g=915 c=914 q=1273)
[ 121.200005] Task dump for CPU 0:
[ 121.200005] bind2 R running task 0 667 614 0x20020008
[ 121.200005] 0000000000000266 ffff880017c03d68 ffffffff81086c26 ffffffff81086b88
[ 121.200005] 00000000bd07bd06 0000000000000000 ffffffff81c53940 ffff880017c03d88
[ 121.200005] ffffffff8108a57f ffffffff81c53940 ffffffff81c53940 ffff880017c03db8
[ 121.200005] Call Trace:
[ 121.200005] <IRQ> [<ffffffff81086c26>] sched_show_task+0x106/0x170
[ 121.200005] [<ffffffff81086b88>] ? sched_show_task+0x68/0x170
[ 121.200005] [<ffffffff8108a57f>] dump_cpu_task+0x3f/0x50
[ 121.200005] [<ffffffff810bfa7b>] rcu_dump_cpu_stacks+0x8b/0xc0
[ 121.200005] [<ffffffff810c33d0>] rcu_check_callbacks+0x480/0x6d0
[ 121.200005] [<ffffffff810a133d>] ? trace_hardirqs_off+0xd/0x10
[ 121.200005] [<ffffffff810c8408>] update_process_times+0x38/0x70
[ 121.200005] [<ffffffff810d8623>] tick_sched_handle.isra.15+0x33/0x70
[ 121.200005] [<ffffffff810d88cb>] tick_sched_timer+0x4b/0x80
[ 121.200005] [<ffffffff810c8d8b>] __run_hrtimer+0x9b/0x290
[ 121.200005] [<ffffffff810d8880>] ? tick_sched_do_timer+0x40/0x40
[ 121.200005] [<ffffffff810c95e4>] ? hrtimer_interrupt+0x74/0x260
[ 121.200005] [<ffffffff810c9677>] hrtimer_interrupt+0x107/0x260
[ 121.200005] [<ffffffff8139d680>] ? unlock_buckets+0x70/0x70
[ 121.200005] [<ffffffff81034cb9>] local_apic_timer_interrupt+0x39/0x60
[ 121.200005] [<ffffffff81769b25>] smp_apic_timer_interrupt+0x45/0x60
[ 121.200005] [<ffffffff81767eaf>] apic_timer_interrupt+0x6f/0x80
[ 121.200005] <EOI> [<ffffffff8139e5c8>] ? rhashtable_lookup_compare+0x88/0x120
[ 121.200005] [<ffffffff8139e5ce>] ? rhashtable_lookup_compare+0x8e/0x120
[ 121.200005] [<ffffffff8139e540>] ? rht_deferred_worker+0xa0/0xa0
[ 121.200005] [<ffffffff8139e72f>] rhashtable_lookup_compare_insert+0x9f/0x110
[ 121.200005] [<ffffffff8139e6c5>] ? rhashtable_lookup_compare_insert+0x35/0x110
[ 121.200005] [<ffffffff8139d680>] ? unlock_buckets+0x70/0x70
[ 121.200005] [<ffffffff8139e7d2>] rhashtable_lookup_insert+0x32/0x40
[ 121.200005] [<ffffffffa00164ec>] tipc_sk_create+0x1ec/0x340 [tipc]
[ 121.200005] [<ffffffffa00163a2>] ? tipc_sk_create+0xa2/0x340 [tipc]
[ 121.200005] [<ffffffff81615e60>] __sock_create+0x170/0x270
[ 121.200005] [<ffffffff81615daf>] ? __sock_create+0xbf/0x270
[ 121.200005] [<ffffffff81615fc0>] sock_create+0x30/0x40
[ 121.200005] [<ffffffff81616d36>] SyS_socket+0x36/0xb0
[ 121.200005] [<ffffffff8118500f>] ? might_fault+0xaf/0xc0
[ 121.200005] [<ffffffff81184fc6>] ? might_fault+0x66/0xc0
[ 121.200005] [<ffffffff816523bb>] compat_SyS_socketcall+0x6b/0x200
[ 121.200005] [<ffffffff817693f3>] sysenter_dispatch+0x7/0x1f
[ 121.200005] [<ffffffff8139660e>] ? trace_hardirqs_on_thunk+0x3a/0x3f
[ 121.220016] INFO: rcu_sched detected stalls on CPUs/tasks: { 0} (detected by
5, t=15006 jiffies, g=915, c=914, q=1273)
[ 121.223334] Task dump for CPU 0:
[ 121.223334] bind2 R running task 0 667 614 0x20020008
[ 121.223334] 000000000000002b 0000000000000004 ffff8800153dd87c ffff88000019747c
[ 121.223334] ffffffffffffff10 ffffffff81390b6a ffff8800153dd87c ffff880000197000
[ 121.228029] ffffffffffffff10 ffffffff8139e5c8 0000000000000010 ffff88000019bd08
[ 121.228029] Call Trace:
[ 121.228029] [<ffffffff8139e5c8>] ? rhashtable_lookup_compare+0x88/0x120
[ 121.228029] [<ffffffff8139d698>] ? rhashtable_compare+0x18/0x20
[ 121.228029] [<ffffffff8139e5ce>] ? rhashtable_lookup_compare+0x8e/0x120
[ 121.228029] [<ffffffff8139e540>] ? rht_deferred_worker+0xa0/0xa0
[ 121.228029] [<ffffffff8139e72f>] ? rhashtable_lookup_compare_insert+0x9f/0x110
[ 121.228029] [<ffffffff8139e6c5>] ? rhashtable_lookup_compare_insert+0x35/0x110
[ 121.228029] [<ffffffff8139d680>] ? unlock_buckets+0x70/0x70
[ 121.236021] [<ffffffff8139e7d2>] ? rhashtable_lookup_insert+0x32/0x40
[ 121.236021] [<ffffffffa00164ec>] ? tipc_sk_create+0x1ec/0x340 [tipc]
[ 121.236021] [<ffffffffa00163a2>] ? tipc_sk_create+0xa2/0x340 [tipc]
[ 121.236021] [<ffffffff81615e60>] ? __sock_create+0x170/0x270
[ 121.236021] [<ffffffff81615daf>] ? __sock_create+0xbf/0x270
[ 121.236021] [<ffffffff81615fc0>] ? sock_create+0x30/0x40
[ 121.236021] [<ffffffff81616d36>] ? SyS_socket+0x36/0xb0
[ 121.236021] [<ffffffff8118500f>] ? might_fault+0xaf/0xc0
[ 121.236021] [<ffffffff81184fc6>] ? might_fault+0x66/0xc0
[ 121.244025] [<ffffffff816523bb>] ? compat_SyS_socketcall+0x6b/0x200
[ 121.244025] [<ffffffff817693f3>] ? sysenter_dispatch+0x7/0x1f
[ 121.244025] [<ffffffff8139660e>] ? trace_hardirqs_on_thunk+0x3a/0x3f
[ 148.088005] NMI watchdog: BUG: soft lockup - CPU#0 stuck for 22s! [bind2:667]
[ 148.088005] Modules linked in: tipc
[ 148.088005] irq event stamp: 55335
[ 148.088005] hardirqs last enabled at (55334): [<ffffffff81767be0>]
restore_args+0x0/0x30
[ 148.088005] hardirqs last disabled at (55335): [<ffffffff81767eaa>]
apic_timer_interrupt+0x6a/0x80
[ 148.088005] softirqs last enabled at (11842): [<ffffffff8139d66a>]
unlock_buckets+0x5a/0x70
[ 148.088005] softirqs last disabled at (11880): [<ffffffff8139d51a>]
lock_buckets+0x3a/0x80
[ 148.088005] CPU: 0 PID: 667 Comm: bind2 Tainted: G W L 3.19.0-rc6+ #185
[ 148.088005] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007
[ 148.088005] task: ffff880015038000 ti: ffff880000198000 task.ti: ffff880000198000
[ 148.088005] RIP: 0010:[<ffffffff81390b31>] [<ffffffff81390b31>] memcmp+0x1/0x50
[ 148.088005] RSP: 0018:ffff88000019bcf8 EFLAGS: 00000282
[ 148.088005] RAX: ffff880000149090 RBX: ffff88000019bc78 RCX: 000000000000002b
[ 148.088005] RDX: 0000000000000004 RSI: ffff8800153dd87c RDI: ffff88000019747c
[ 148.088005] RBP: ffff88000019bd08 R08: 000000002d196482 R09: ffff8800153dd87c
[ 148.088005] R10: 0000000000000002 R11: 0000000000000001 R12: ffff880000198000
[ 148.088005] R13: ffff880015038000 R14: 0000000000000000 R15: 0000000000000001
[ 148.088005] FS: 0000000000000000(0000) GS:ffff880017c00000(0063)
knlGS:00000000f75b3900
[ 148.088005] CS: 0010 DS: 002b ES: 002b CR0: 000000008005003b
[ 148.088005] CR2: 0000000008acec4c CR3: 000000001479e000 CR4: 00000000000006f0
[ 148.088005] Stack:
[ 148.088005] ffff88000019bd08 ffffffff8139d698 ffff88000019bd68 ffffffff8139e5ce
[ 148.088005] ffffffff8139e540 00000002810a6a25 069b23b200000000 ffff88001328e000
[ 148.088005] ffff88000019bd68 ffff880000149090 ffff88001328e000 00000000000001b2
[ 148.088005] Call Trace:
[ 148.088005] [<ffffffff8139d698>] ? rhashtable_compare+0x18/0x20
[ 148.088005] [<ffffffff8139e5ce>] rhashtable_lookup_compare+0x8e/0x120
[ 148.088005] [<ffffffff8139e540>] ? rht_deferred_worker+0xa0/0xa0
[ 148.088005] [<ffffffff8139e72f>] rhashtable_lookup_compare_insert+0x9f/0x110
[ 148.088005] [<ffffffff8139e6c5>] ? rhashtable_lookup_compare_insert+0x35/0x110
[ 148.088005] [<ffffffff8139d680>] ? unlock_buckets+0x70/0x70
[ 148.088005] [<ffffffff8139e7d2>] rhashtable_lookup_insert+0x32/0x40
[ 148.088005] [<ffffffffa00164ec>] tipc_sk_create+0x1ec/0x340 [tipc]
[ 148.088005] [<ffffffffa00163a2>] ? tipc_sk_create+0xa2/0x340 [tipc]
[ 148.088005] [<ffffffff81615e60>] __sock_create+0x170/0x270
[ 148.088005] [<ffffffff81615daf>] ? __sock_create+0xbf/0x270
[ 148.088005] [<ffffffff81615fc0>] sock_create+0x30/0x40
[ 148.088005] [<ffffffff81616d36>] SyS_socket+0x36/0xb0
[ 148.088005] [<ffffffff8118500f>] ? might_fault+0xaf/0xc0
[ 148.088005] [<ffffffff81184fc6>] ? might_fault+0x66/0xc0
[ 148.088005] [<ffffffff816523bb>] compat_SyS_socketcall+0x6b/0x200
[ 148.088005] [<ffffffff817693f3>] sysenter_dispatch+0x7/0x1f
[ 148.088005] [<ffffffff8139660e>] ? trace_hardirqs_on_thunk+0x3a/0x3f
[ 148.088005] Code: 00 00 3c 30 74 14 3c 31 75 e9 31 c0 c6 06 01 5d c3 66 0f 1f
84 00 00 00 00 00 31 c0 c6 06 00 5d c3 66 0f 1f 84 00 00 00 00 00 55 <31> c0 48
85 d2 48 89 e5 74 2f 0f b6 07 0f b6 0e 29 c8 75 25 48
Regards,
Ying
On 02/05/2015 09:03 AM, Thomas Graf wrote:
> This series fixes all remaining known issues with rhashtable that
> have been reported. In particular the race condition reported by
> Ying Xue.
>
> ---
> Dave/Herbert: I'm posting this now as it fixes real issues. I'm
> fine with taking Herbert's rehash patches instead if they resolve
> all the reported issues as well.
>
> v2:
> - Rebased on top of Herbert Xu's iterator code
> - Fixed last remaining race that remained. Special thanks
> to Daniel Borkmann for assistance while debugging.
>
> Thomas Graf (6):
> rhashtable: key_hashfn() must return full hash value
> rhashtable: Use a single bucket lock for sibling buckets
> rhashtable: Wait for RCU readers after final unzip work
> rhashtable: Dump bucket tables on locking violation under
> PROVE_LOCKING
> rhashtable: Add more lock verification
> rhashtable: Avoid bucket cross reference after removal
>
> lib/rhashtable.c | 305 ++++++++++++++++++++++++++++++-------------------------
> 1 file changed, 167 insertions(+), 138 deletions(-)
>
>
^ permalink raw reply
* [RFC PATCH 29/29] iproute2: Add vrf option to ip link command
From: David Ahern @ 2015-02-05 1:34 UTC (permalink / raw)
To: netdev; +Cc: ebiederm, David Ahern
In-Reply-To: <1423100070-31848-1-git-send-email-dsahern@gmail.com>
Add option to ip link to change the vrf context on a netdevice.
e.g., ip link set dev eth4 vrf 99
Signed-off-by: David Ahern <dsahern@gmail.com>
---
bridge/link.c | 3 +++
include/linux/if_link.h | 2 ++
ip/ipaddress.c | 2 ++
ip/iplink.c | 9 +++++++++
4 files changed, 16 insertions(+)
diff --git a/bridge/link.c b/bridge/link.c
index c8555f82d5b4..520e656f3bf8 100644
--- a/bridge/link.c
+++ b/bridge/link.c
@@ -146,6 +146,9 @@ int print_linkinfo(const struct sockaddr_nl *who,
print_link_flags(fp, ifi->ifi_flags);
+ if (tb[IFLA_VRF])
+ fprintf(fp, "vrf %u ", rta_getattr_u32(tb[IFLA_VRF]));
+
if (tb[IFLA_MTU])
fprintf(fp, "mtu %u ", rta_getattr_u32(tb[IFLA_MTU]));
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 167ec34bab73..c261d3040b88 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -146,6 +146,8 @@ enum {
IFLA_PHYS_PORT_ID,
IFLA_CARRIER_CHANGES,
IFLA_PHYS_SWITCH_ID,
+ IFLA_LINK_NETNSID,
+ IFLA_VRF,
__IFLA_MAX
};
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index d5e863dd1f12..f4001e0ef8cb 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -625,6 +625,8 @@ int print_linkinfo(const struct sockaddr_nl *who,
if (tb[IFLA_MTU])
fprintf(fp, "mtu %u ", *(int*)RTA_DATA(tb[IFLA_MTU]));
+ if (tb[IFLA_VRF])
+ fprintf(fp, "vrf %u ", *(int*)RTA_DATA(tb[IFLA_VRF]));
if (tb[IFLA_QDISC])
fprintf(fp, "qdisc %s ", rta_getattr_str(tb[IFLA_QDISC]));
if (tb[IFLA_MASTER]) {
diff --git a/ip/iplink.c b/ip/iplink.c
index c93d1dc3d5f6..0474293527c5 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -72,6 +72,7 @@ void iplink_usage(void)
fprintf(stderr, " [ mtu MTU ]\n");
fprintf(stderr, " [ netns PID ]\n");
fprintf(stderr, " [ netns NAME ]\n");
+ fprintf(stderr, " [ vrf ID]\n");
fprintf(stderr, " [ alias NAME ]\n");
fprintf(stderr, " [ vf NUM [ mac LLADDR ]\n");
fprintf(stderr, " [ vlan VLANID [ qos VLAN-QOS ] ]\n");
@@ -383,6 +384,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
int mtu = -1;
int netns = -1;
int vf = -1;
+ int vrf = -1;
int numtxqueues = -1;
int numrxqueues = -1;
int dev_index = 0;
@@ -447,6 +449,13 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4);
else
invarg("Invalid \"netns\" value\n", *argv);
+ } else if (strcmp(*argv, "vrf") == 0) {
+ NEXT_ARG();
+ if (vrf != -1)
+ duparg("vrf", *argv);
+ if (get_integer(&vrf, *argv, 0))
+ invarg("Invalid \"vrf\" value\n", *argv);
+ addattr_l(&req->n, sizeof(*req), IFLA_VRF, &vrf, 4);
} else if (strcmp(*argv, "multicast") == 0) {
NEXT_ARG();
req->i.ifi_change |= IFF_MULTICAST;
--
1.9.3 (Apple Git-50)
^ permalink raw reply related
* [RFC PATCH 27/29] net: vrf: Add vrf checks and context to ipv4 proc files
From: David Ahern @ 2015-02-05 1:34 UTC (permalink / raw)
To: netdev; +Cc: ebiederm, David Ahern
In-Reply-To: <1423100070-31848-1-git-send-email-dsahern@gmail.com>
Signed-off-by: David Ahern <dsahern@gmail.com>
---
net/ipv4/fib_trie.c | 24 ++++++++++++++++++------
net/ipv4/proc.c | 10 +++++-----
net/ipv4/raw.c | 7 ++++---
net/ipv4/route.c | 2 +-
net/ipv4/tcp_ipv4.c | 15 ++++++++-------
net/ipv4/udp.c | 6 +++---
6 files changed, 39 insertions(+), 25 deletions(-)
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 3daf0224ff2e..a3ff1100dc2a 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1439,6 +1439,8 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
}
if (fi->fib_flags & RTNH_F_DEAD)
continue;
+ if (!vrf_eq(fi->fib_net_ctx.vrf, flp->flowi4_vrf))
+ continue;
for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) {
const struct fib_nh *nh = &fi->fib_nh[nhsel];
@@ -1738,6 +1740,7 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah,
int i, s_i;
struct fib_alias *fa;
__be32 xkey = htonl(key);
+ __u32 vrf = skb->sk->sk_vrf;
s_i = cb->args[5];
i = 0;
@@ -1750,6 +1753,10 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah,
continue;
}
+ if (!vrf_eq(fa->fa_info->fib_net_ctx.vrf, vrf) &&
+ !vrf_is_any(vrf))
+ continue;
+
if (fib_dump_info(skb, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq,
RTM_NEWROUTE,
@@ -2078,7 +2085,7 @@ static void fib_table_print(struct seq_file *seq, struct fib_table *tb)
static int fib_triestat_seq_show(struct seq_file *seq, void *v)
{
- struct net *net = (struct net *)seq->private;
+ struct net *net = seq_file_net(seq);
unsigned int h;
seq_printf(seq,
@@ -2414,11 +2421,12 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
{
struct tnode *l = v;
struct leaf_info *li;
+ struct net_ctx *ctx = seq_file_net_ctx(seq);
if (v == SEQ_START_TOKEN) {
seq_printf(seq, "%-127s\n", "Iface\tDestination\tGateway "
"\tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU"
- "\tWindow\tIRTT");
+ "\tWindow\tIRTT\tvrf");
return 0;
}
@@ -2439,10 +2447,13 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
seq_setwidth(seq, 127);
+ if (fi && !vrf_eq_or_any(fi->fib_vrf, ctx->vrf))
+ continue;
+
if (fi)
seq_printf(seq,
"%s\t%08X\t%08X\t%04X\t%d\t%u\t"
- "%d\t%08X\t%d\t%u\t%u",
+ "%d\t%08X\t%d\t%u\t%u\t%u",
fi->fib_dev ? fi->fib_dev->name : "*",
prefix,
fi->fib_nh->nh_gw, flags, 0, 0,
@@ -2451,13 +2462,14 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
(fi->fib_advmss ?
fi->fib_advmss + 40 : 0),
fi->fib_window,
- fi->fib_rtt >> 3);
+ fi->fib_rtt >> 3,
+ fi->fib_vrf);
else
seq_printf(seq,
"*\t%08X\t%08X\t%04X\t%d\t%u\t"
- "%d\t%08X\t%d\t%u\t%u",
+ "%d\t%08X\t%d\t%u\t%u\t%u",
prefix, 0, flags, 0, 0, 0,
- mask, 0, 0, 0);
+ mask, 0, 0, 0, 0);
seq_pad(seq, '\n');
}
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 8f9cd200ce20..721dd600d722 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -51,7 +51,7 @@
*/
static int sockstat_seq_show(struct seq_file *seq, void *v)
{
- struct net *net = seq->private;
+ struct net *net = seq_file_net(seq);
unsigned int frag_mem;
int orphans, sockets;
@@ -319,7 +319,7 @@ static void icmpmsg_put(struct seq_file *seq)
int i, count;
unsigned short type[PERLINE];
unsigned long vals[PERLINE], val;
- struct net *net = seq->private;
+ struct net *net = seq_file_net(seq);
count = 0;
for (i = 0; i < ICMPMSG_MIB_MAX; i++) {
@@ -341,7 +341,7 @@ static void icmpmsg_put(struct seq_file *seq)
static void icmp_put(struct seq_file *seq)
{
int i;
- struct net *net = seq->private;
+ struct net *net = seq_file_net(seq);
atomic_long_t *ptr = net->mib.icmpmsg_statistics->mibs;
seq_puts(seq, "\nIcmp: InMsgs InErrors InCsumErrors");
@@ -371,7 +371,7 @@ static void icmp_put(struct seq_file *seq)
static int snmp_seq_show(struct seq_file *seq, void *v)
{
int i;
- struct net *net = seq->private;
+ struct net *net = seq_file_net(seq);
seq_puts(seq, "Ip: Forwarding DefaultTTL");
@@ -455,7 +455,7 @@ static const struct file_operations snmp_seq_fops = {
static int netstat_seq_show(struct seq_file *seq, void *v)
{
int i;
- struct net *net = seq->private;
+ struct net *net = seq_file_net(seq);
seq_puts(seq, "TcpExt:");
for (i = 0; snmp4_net_list[i].name != NULL; i++)
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 6d4be3fd2d01..11e8313b5ea2 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -1027,14 +1027,15 @@ static void raw_sock_seq_show(struct seq_file *seq, struct sock *sp, int i)
srcp = inet->inet_num;
seq_printf(seq, "%4d: %08X:%04X %08X:%04X"
- " %02X %08X:%08X %02X:%08lX %08X %5u %8d %lu %d %pK %d\n",
+ " %02X %08X:%08X %02X:%08lX %08X %5u %8d %lu %d %pK %d %d\n",
i, src, srcp, dest, destp, sp->sk_state,
sk_wmem_alloc_get(sp),
sk_rmem_alloc_get(sp),
0, 0L, 0,
from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
0, sock_i_ino(sp),
- atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops));
+ atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops),
+ sp->sk_vrf);
}
static int raw_seq_show(struct seq_file *seq, void *v)
@@ -1042,7 +1043,7 @@ static int raw_seq_show(struct seq_file *seq, void *v)
if (v == SEQ_START_TOKEN)
seq_printf(seq, " sl local_address rem_address st tx_queue "
"rx_queue tr tm->when retrnsmt uid timeout "
- "inode ref pointer drops\n");
+ "inode ref pointer drops vrf\n");
else
raw_sock_seq_show(seq, v, raw_seq_private(seq)->bucket);
return 0;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index d6c5f0a8ab17..59af5016bf26 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -215,7 +215,7 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, "%-127s\n",
"Iface\tDestination\tGateway \tFlags\t\tRefCnt\tUse\t"
"Metric\tSource\t\tMTU\tWindow\tIRTT\tTOS\tHHRef\t"
- "HHUptod\tSpecDst");
+ "HHUptod\tSpecDst\tvrf");
return 0;
}
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 24089b9534bf..249ce80d12d6 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2215,7 +2215,7 @@ static void get_openreq4(const struct sock *sk, const struct request_sock *req,
long delta = req->expires - jiffies;
seq_printf(f, "%4d: %08X:%04X %08X:%04X"
- " %02X %08X:%08X %02X:%08lX %08X %5u %8d %u %d %pK",
+ " %02X %08X:%08X %02X:%08lX %08X %5u %8d %u %d %pK %d",
i,
ireq->ir_loc_addr,
ntohs(inet_sk(sk)->inet_sport),
@@ -2230,7 +2230,7 @@ static void get_openreq4(const struct sock *sk, const struct request_sock *req,
0, /* non standard timer */
0, /* open_requests have no inode */
atomic_read(&sk->sk_refcnt),
- req);
+ req, sk->sk_vrf);
}
static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i)
@@ -2272,7 +2272,7 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i)
rx_queue = max_t(int, tp->rcv_nxt - tp->copied_seq, 0);
seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
- "%08X %5u %8d %lu %d %pK %lu %lu %u %u %d",
+ "%08X %5u %8d %lu %d %pK %lu %lu %u %u %d %2d",
i, src, srcp, dest, destp, sk->sk_state,
tp->write_seq - tp->snd_una,
rx_queue,
@@ -2289,7 +2289,8 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i)
tp->snd_cwnd,
sk->sk_state == TCP_LISTEN ?
(fastopenq ? fastopenq->max_qlen : 0) :
- (tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh));
+ (tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh),
+ sk->sk_vrf);
}
static void get_timewait4_sock(const struct inet_timewait_sock *tw,
@@ -2305,10 +2306,10 @@ static void get_timewait4_sock(const struct inet_timewait_sock *tw,
srcp = ntohs(tw->tw_sport);
seq_printf(f, "%4d: %08X:%04X %08X:%04X"
- " %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK",
+ " %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK %2d",
i, src, srcp, dest, destp, tw->tw_substate, 0, 0,
3, jiffies_delta_to_clock_t(delta), 0, 0, 0, 0,
- atomic_read(&tw->tw_refcnt), tw);
+ atomic_read(&tw->tw_refcnt), tw, tw->tw_vrf);
}
#define TMPSZ 150
@@ -2322,7 +2323,7 @@ static int tcp4_seq_show(struct seq_file *seq, void *v)
if (v == SEQ_START_TOKEN) {
seq_puts(seq, " sl local_address rem_address st tx_queue "
"rx_queue tr tm->when retrnsmt uid timeout "
- "inode");
+ "inode vrf");
goto out;
}
st = seq->private;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 2d7e2748a138..345d5a5b4489 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -2422,7 +2422,7 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f,
__u16 srcp = ntohs(inet->inet_sport);
seq_printf(f, "%5d: %08X:%04X %08X:%04X"
- " %02X %08X:%08X %02X:%08lX %08X %5u %8d %lu %d %pK %d",
+ " %02X %08X:%08X %02X:%08lX %08X %5u %8d %lu %d %pK %d %d",
bucket, src, srcp, dest, destp, sp->sk_state,
sk_wmem_alloc_get(sp),
sk_rmem_alloc_get(sp),
@@ -2430,7 +2430,7 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f,
from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)),
0, sock_i_ino(sp),
atomic_read(&sp->sk_refcnt), sp,
- atomic_read(&sp->sk_drops));
+ atomic_read(&sp->sk_drops), sp->sk_vrf);
}
int udp4_seq_show(struct seq_file *seq, void *v)
@@ -2439,7 +2439,7 @@ int udp4_seq_show(struct seq_file *seq, void *v)
if (v == SEQ_START_TOKEN)
seq_puts(seq, " sl local_address rem_address st tx_queue "
"rx_queue tr tm->when retrnsmt uid timeout "
- "inode ref pointer drops");
+ "inode ref pointer drops vrf");
else {
struct udp_iter_state *state = seq->private;
--
1.9.3 (Apple Git-50)
^ permalink raw reply related
* [RFC PATCH 28/29] iproute2: vrf: Add vrf subcommand
From: David Ahern @ 2015-02-05 1:34 UTC (permalink / raw)
To: netdev; +Cc: ebiederm, David Ahern
In-Reply-To: <1423100070-31848-1-git-send-email-dsahern@gmail.com>
Add vrf subcommand with exec option to run a process in a specific VRF
context. Similar to ip netns subcommand.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
ip/Makefile | 2 +-
ip/ip.c | 3 +-
ip/ip_common.h | 1 +
ip/ipvrf.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 113 insertions(+), 2 deletions(-)
create mode 100644 ip/ipvrf.c
diff --git a/ip/Makefile b/ip/Makefile
index 2c742f305fef..4d44906802bd 100644
--- a/ip/Makefile
+++ b/ip/Makefile
@@ -1,4 +1,4 @@
-IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
+IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o ipvrf.o \
rtm_map.o iptunnel.o ip6tunnel.o tunnel.o ipneigh.o ipntable.o iplink.o \
ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o iptuntap.o iptoken.o \
ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \
diff --git a/ip/ip.c b/ip/ip.c
index 850a001756af..80d90a409541 100644
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -48,7 +48,7 @@ static void usage(void)
" ip [ -force ] -batch filename\n"
"where OBJECT := { link | addr | addrlabel | route | rule | neigh | ntable |\n"
" tunnel | tuntap | maddr | mroute | mrule | monitor | xfrm |\n"
-" netns | l2tp | fou | tcp_metrics | token | netconf }\n"
+" netns | vrf | l2tp | fou | tcp_metrics | token | netconf }\n"
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
" -h[uman-readable] | -iec |\n"
" -f[amily] { inet | inet6 | ipx | dnet | bridge | link } |\n"
@@ -93,6 +93,7 @@ static const struct cmd {
{ "mroute", do_multiroute },
{ "mrule", do_multirule },
{ "netns", do_netns },
+ { "vrf", do_vrf },
{ "netconf", do_ipnetconf },
{ "help", do_help },
{ 0 }
diff --git a/ip/ip_common.h b/ip/ip_common.h
index 89a495ea1074..499f9f34cd36 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -49,6 +49,7 @@ extern int do_multiaddr(int argc, char **argv);
extern int do_multiroute(int argc, char **argv);
extern int do_multirule(int argc, char **argv);
extern int do_netns(int argc, char **argv);
+extern int do_vrf(int argc, char **argv);
extern int do_xfrm(int argc, char **argv);
extern int do_ipl2tp(int argc, char **argv);
extern int do_ipfou(int argc, char **argv);
diff --git a/ip/ipvrf.c b/ip/ipvrf.c
new file mode 100644
index 000000000000..df9b2e76b309
--- /dev/null
+++ b/ip/ipvrf.c
@@ -0,0 +1,109 @@
+#define _ATFILE_SOURCE
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/inotify.h>
+#include <sys/mount.h>
+#include <sys/param.h>
+#include <sys/syscall.h>
+#include <stdio.h>
+#include <string.h>
+#include <sched.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include "utils.h"
+#include "ip_common.h"
+
+static int usage(void)
+{
+ fprintf(stderr, "Usage: ip vrf exec ID cmd ...\n");
+ exit(-1);
+}
+
+static int vrf_exec(int argc, char **argv)
+{
+ const char *cmd, *id;
+ char vrf_path[MAXPATHLEN];
+ int fd;
+
+ if (argc < 1) {
+ fprintf(stderr, "No vrf id specified\n");
+ return -1;
+ }
+ if (argc < 2) {
+ fprintf(stderr, "No command specified\n");
+ return -1;
+ }
+
+ id = argv[0];
+ cmd = argv[1];
+ snprintf(vrf_path, sizeof(vrf_path), "/proc/%d/vrf", getpid());
+ fd = open(vrf_path, O_WRONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Cannot open vrf file: %s\n",
+ strerror(errno));
+ return -1;
+ }
+ if (write(fd, id, strlen(id)) < 0) {
+ fprintf(stderr, "Failed to set vrf id: %s\n",
+ strerror(errno));
+ close(fd);
+ return -1;
+ }
+ close(fd);
+
+ fflush(stdout);
+
+ if (batch_mode) {
+ int status;
+ pid_t pid;
+
+ pid = fork();
+ if (pid < 0) {
+ perror("fork");
+ exit(1);
+ }
+
+ if (pid != 0) {
+ /* Parent */
+ if (waitpid(pid, &status, 0) < 0) {
+ perror("waitpid");
+ exit(1);
+ }
+
+ if (WIFEXITED(status)) {
+ /* ip must return the status of the child,
+ * but do_cmd() will add a minus to this,
+ * so let's add another one here to cancel it.
+ */
+ return -WEXITSTATUS(status);
+ }
+
+ exit(1);
+ }
+ }
+
+ if (execvp(cmd, argv + 1) < 0)
+ fprintf(stderr, "exec of \"%s\" failed: %s\n",
+ cmd, strerror(errno));
+ _exit(1);
+}
+
+int do_vrf(int argc, char **argv)
+{
+ if (*argv == NULL)
+ return usage();
+
+ if (matches(*argv, "help") == 0)
+ return usage();
+
+ if (matches(*argv, "exec") == 0)
+ return vrf_exec(argc-1, argv+1);
+
+ fprintf(stderr, "Command \"%s\" is unknown, try \"ip vrf help\".\n", *argv);
+ exit(-1);
+}
--
1.9.3 (Apple Git-50)
^ permalink raw reply related
* [RFC PATCH 26/29] net: vrf: Change single_open_net to pass net_ctx
From: David Ahern @ 2015-02-05 1:34 UTC (permalink / raw)
To: netdev; +Cc: ebiederm, David Ahern
In-Reply-To: <1423100070-31848-1-git-send-email-dsahern@gmail.com>
Signed-off-by: David Ahern <dsahern@gmail.com>
---
fs/proc/proc_net.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index 4996f5e91a90..3745661b5370 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -56,6 +56,8 @@ int seq_open_net(struct inode *ino, struct file *f,
#ifdef CONFIG_NET_NS
p->net_ctx.net = net;
#endif
+ p->net_ctx.vrf = current->vrf;
+
return 0;
}
EXPORT_SYMBOL_GPL(seq_open_net);
@@ -65,19 +67,32 @@ int single_open_net(struct inode *inode, struct file *file,
{
int err;
struct net *net;
+ struct seq_net_private *p;
err = -ENXIO;
net = get_proc_net(inode);
if (net == NULL)
goto err_net;
- err = single_open(file, show, net);
+ err = -ENOMEM;
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (p == NULL)
+ goto err_malloc;
+
+#ifdef CONFIG_NET_NS
+ p->net_ctx.net = net;
+#endif
+ p->net_ctx.vrf = current->vrf;
+
+ err = single_open(file, show, p);
if (err < 0)
goto err_open;
return 0;
err_open:
+ kfree(p);
+err_malloc:
put_net(net);
err_net:
return err;
@@ -99,7 +114,8 @@ EXPORT_SYMBOL_GPL(seq_release_net);
int single_release_net(struct inode *ino, struct file *f)
{
struct seq_file *seq = f->private_data;
- put_net(seq->private);
+ put_net(seq_file_net(seq));
+ kfree(seq->private);
return single_release(ino, f);
}
EXPORT_SYMBOL_GPL(single_release_net);
--
1.9.3 (Apple Git-50)
^ permalink raw reply related
* [RFC PATCH 25/29] net: vrf: Handle VRF any context
From: David Ahern @ 2015-02-05 1:34 UTC (permalink / raw)
To: netdev; +Cc: ebiederm, David Ahern
In-Reply-To: <1423100070-31848-1-git-send-email-dsahern@gmail.com>
VRF any context applies only to tasks to and sockets. Devices are
associated with a single VRF, and skb's by extension are connected to
a single VRF.
Listen sockets and unconnected sockets can be opened in a "VRF any"
context allowing a single daemon to provide service across all VRFs
in a namespace. Connected sockets must be in a specific vrf context.
Accepted sockets acquire the VRF context from the device the packet
enters (via the skb).
"VRF any" context is also useful for tasks wanting to view L3/L4
data for all VRFs.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/linux/netdevice.h | 15 +++++++++++++++
include/net/inet_hashtables.h | 4 +++-
include/net/neighbour.h | 29 +++++++++++++++++++++++++++++
include/net/sock.h | 2 +-
net/core/dev.c | 2 +-
net/core/fib_rules.c | 4 ++++
net/core/neighbour.c | 18 +++++++++---------
net/ipv4/af_inet.c | 4 ++++
net/ipv4/arp.c | 6 ++++++
net/ipv4/datagram.c | 3 +++
net/ipv4/devinet.c | 7 +++++--
net/ipv4/fib_frontend.c | 4 ++++
net/ipv4/igmp.c | 4 ++--
net/ipv4/raw.c | 9 +++++++++
net/ipv4/udp.c | 4 ++++
15 files changed, 99 insertions(+), 16 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 7d983f005622..a1de460b1b7c 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1864,6 +1864,21 @@ int dev_net_ctx_eq(const struct net_device *dev, struct net_ctx *ctx)
return 0;
}
+/*
+ * same as above except if ctx has 'any' vrf that it counts as a match
+ * (devices are not assigned to 'any' vrf)
+ */
+static inline
+int dev_net_ctx_eq_any(const struct net_device *dev, struct net_ctx *ctx)
+{
+ if (net_eq(dev_net(dev), ctx->net) &&
+ (vrf_eq(dev->nd_vrf, ctx->vrf) || vrf_is_any(ctx->vrf))) {
+ return 1;
+ }
+
+ return 0;
+}
+
static inline bool netdev_uses_dsa(struct net_device *dev)
{
#if IS_ENABLED(CONFIG_NET_DSA)
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 199809e46133..e4ba898af422 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -101,8 +101,10 @@ void ib_net_ctx_set(struct inet_bind_bucket *ib, struct net_ctx *ctx)
static inline
int ib_net_ctx_eq(struct inet_bind_bucket *ib, struct net_ctx *ctx)
{
+ __u32 vrf = ib->ib_net_ctx.vrf;
+
if (net_eq(ib_net(ib), ctx->net) &&
- vrf_eq(ib->ib_net_ctx.vrf, ctx->vrf))
+ (vrf_eq_or_any(vrf, ctx->vrf)))
return 1;
return 0;
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index f3527b25d612..122a3acda83e 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -303,6 +303,21 @@ int neigh_parms_net_ctx_eq(const struct neigh_parms *parms,
return 1;
#endif
}
+static inline int neigh_parms_net_ctx_eq_any(const struct neigh_parms *parms,
+ const struct net_ctx *net_ctx)
+{
+#ifdef CONFIG_NET_NS
+ if (net_eq(neigh_parms_net(parms), net_ctx->net) &&
+ (vrf_eq(neigh_parms_vrf(parms), net_ctx->vrf) ||
+ vrf_is_any(net_ctx->vrf))) {
+ return 1;
+ }
+
+ return 0;
+#else
+ return 1;
+#endif
+}
unsigned long neigh_rand_reach_time(unsigned long base);
void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
@@ -340,6 +355,20 @@ int pneigh_net_ctx_eq(const struct pneigh_entry *pneigh,
return 1;
#endif
}
+static inline
+int pneigh_net_ctx_eq_any(const struct pneigh_entry *pneigh,
+ const struct net_ctx *net_ctx)
+{
+#ifdef CONFIG_NET_NS
+ if (net_eq(pneigh_net(pneigh), net_ctx->net) &&
+ vrf_eq_or_any(pneigh->net_ctx.vrf, net_ctx->vrf))
+ return 1;
+
+ return 0;
+#else
+ return 1;
+#endif
+}
void neigh_app_ns(struct neighbour *n);
void neigh_for_each(struct neigh_table *tbl,
diff --git a/include/net/sock.h b/include/net/sock.h
index a9b45fca4605..6a880d04361e 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -2205,7 +2205,7 @@ void sock_net_set(struct sock *sk, struct net *net)
static inline
int sock_net_ctx_eq(struct sock *sk, struct net_ctx *ctx)
{
- return net_eq(sock_net(sk), ctx->net) && vrf_eq(sk->sk_vrf, ctx->vrf);
+ return net_eq(sock_net(sk), ctx->net) && vrf_eq_or_any(sk->sk_vrf, ctx->vrf);
}
/*
diff --git a/net/core/dev.c b/net/core/dev.c
index d96d0d46dc6e..0dae3cfd2890 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -688,7 +688,7 @@ struct net_device *__dev_get_by_name_ctx(struct net_ctx *ctx, const char *name)
{
struct net_device *dev = __dev_get_by_name(ctx->net, name);
- if (dev && !vrf_eq(dev_vrf(dev), ctx->vrf))
+ if (dev && !vrf_eq_or_any(dev_vrf(dev), ctx->vrf))
dev = NULL;
return dev;
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index aea74e16360c..637a6738165e 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -301,6 +301,10 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh)
if (err < 0)
goto errout;
+ /* cannot create new rule for any vrf context */
+ if (vrf_is_any(sk_ctx.vrf))
+ goto errout;
+
rule = kzalloc(ops->rule_size, GFP_KERNEL);
if (rule == NULL) {
err = -ENOMEM;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 46b7e8cc7c70..d15f84de860d 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -442,7 +442,7 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl,
n != NULL;
n = rcu_dereference_bh(n->next)) {
if (!memcmp(n->primary_key, pkey, key_len) &&
- dev_net_ctx_eq(n->dev, ctx)) {
+ dev_net_ctx_eq_any(n->dev, ctx)) {
if (!atomic_inc_not_zero(&n->refcnt))
n = NULL;
NEIGH_CACHE_STAT_INC(tbl, hits);
@@ -2138,7 +2138,7 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
nidx = 0;
p = list_next_entry(&tbl->parms, list);
list_for_each_entry_from(p, &tbl->parms_list, list) {
- if (!neigh_parms_net_ctx_eq(p, &ctx))
+ if (!neigh_parms_net_ctx_eq_any(p, &ctx))
continue;
if (nidx < neigh_skip)
@@ -2271,7 +2271,7 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
n != NULL;
n = rcu_dereference_bh(n->next)) {
- if (!dev_net_ctx_eq(n->dev, &ctx))
+ if (!dev_net_ctx_eq_any(n->dev, &ctx))
continue;
if (idx < s_idx)
goto next;
@@ -2308,7 +2308,7 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
if (h > s_h)
s_idx = 0;
for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
- if (!dev_net_ctx_eq(n->dev, &ctx))
+ if (!dev_net_ctx_eq_any(n->dev, &ctx))
continue;
if (idx < s_idx)
goto next;
@@ -2446,7 +2446,7 @@ static struct neighbour *neigh_get_first(struct seq_file *seq)
n = rcu_dereference_bh(nht->hash_buckets[bucket]);
while (n) {
- if (!dev_net_ctx_eq(n->dev, ctx))
+ if (!dev_net_ctx_eq_any(n->dev, ctx))
goto next;
if (state->neigh_sub_iter) {
loff_t fakep = 0;
@@ -2489,7 +2489,7 @@ static struct neighbour *neigh_get_next(struct seq_file *seq,
while (1) {
while (n) {
- if (!dev_net_ctx_eq(n->dev, ctx))
+ if (!dev_net_ctx_eq_any(n->dev, ctx))
goto next;
if (state->neigh_sub_iter) {
void *v = state->neigh_sub_iter(state, n, pos);
@@ -2546,7 +2546,7 @@ static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
state->flags |= NEIGH_SEQ_IS_PNEIGH;
for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
pn = tbl->phash_buckets[bucket];
- while (pn && !pneigh_net_ctx_eq(pn, ctx))
+ while (pn && !pneigh_net_ctx_eq_any(pn, ctx))
pn = pn->next;
if (pn)
break;
@@ -2566,13 +2566,13 @@ static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
do {
pn = pn->next;
- } while (pn && !pneigh_net_ctx_eq(pn, ctx));
+ } while (pn && !pneigh_net_ctx_eq_any(pn, ctx));
while (!pn) {
if (++state->bucket > PNEIGH_HASHMASK)
break;
pn = tbl->phash_buckets[state->bucket];
- while (pn && !pneigh_net_ctx_eq(pn, ctx))
+ while (pn && !pneigh_net_ctx_eq_any(pn, ctx))
pn = pn->next;
if (pn)
break;
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 2627fff2b2d0..a2b9a8ad0f76 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -565,6 +565,10 @@ int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
int err;
long timeo;
+ /* sockets must be set into a vrf context to connect */
+ if (vrf_is_any(sk->sk_vrf))
+ return -EINVAL;
+
if (addr_len < sizeof(uaddr->sa_family))
return -EINVAL;
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index ed1453b9eeab..4f52a5bce975 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -1195,6 +1195,9 @@ int arp_ioctl(struct net_ctx *ctx, unsigned int cmd, void __user *arg)
case SIOCSARP:
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
+ /* must set vrf context to modify arp cache */
+ if (vrf_is_any(ctx->vrf))
+ return -EINVAL;
case SIOCGARP:
err = copy_from_user(&r, arg, sizeof(struct arpreq));
if (err)
@@ -1215,6 +1218,9 @@ int arp_ioctl(struct net_ctx *ctx, unsigned int cmd, void __user *arg)
htonl(0xFFFFFFFFUL);
rtnl_lock();
if (r.arp_dev[0]) {
+ err = -EINVAL;
+ if (vrf_is_any(ctx->vrf))
+ goto out;
err = -ENODEV;
dev = __dev_get_by_name_ctx(ctx, r.arp_dev);
if (dev == NULL)
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c
index 7f93d6b92d0b..40b3602bfc78 100644
--- a/net/ipv4/datagram.c
+++ b/net/ipv4/datagram.c
@@ -30,6 +30,9 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
int oif;
int err;
+ /* connected sockets must have a specific vrf context */
+ if (vrf_is_any(sk->sk_vrf))
+ return -EINVAL;
if (addr_len < sizeof(*usin))
return -EINVAL;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 54afa816ff66..d9e7140df915 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -942,6 +942,9 @@ int devinet_ioctl(struct net_ctx *net_ctx, unsigned int cmd, void __user *arg)
ret = -EINVAL;
if (sin->sin_family != AF_INET)
goto out;
+ /* cannot use vrf any for set */
+ if (vrf_is_any(net_ctx->vrf))
+ goto out;
break;
default:
ret = -EINVAL;
@@ -1566,7 +1569,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
goto cont;
if (h > s_h || idx > s_idx)
s_ip_idx = 0;
- if (!vrf_eq(dev_vrf(dev), vrf))
+ if (!vrf_eq_or_any(dev_vrf(dev), vrf))
goto cont;
in_dev = __in_dev_get_rcu(dev);
if (!in_dev)
@@ -1890,7 +1893,7 @@ static int inet_netconf_dump_devconf(struct sk_buff *skb,
hlist_for_each_entry_rcu(dev, head, index_hlist) {
if (idx < s_idx)
goto cont;
- if (!vrf_eq(dev_vrf(dev), vrf))
+ if (!vrf_eq_or_any(dev_vrf(dev), vrf))
goto cont;
in_dev = __in_dev_get_rcu(dev);
if (!in_dev)
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 8713618e2835..b024afcbf0b9 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -495,6 +495,10 @@ int ip_rt_ioctl(struct net_ctx *ctx, unsigned int cmd, void __user *arg)
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
+ /* route table can only be manipulated in a vrf context */
+ if (vrf_is_any(ctx->vrf))
+ return -EINVAL;
+
if (copy_from_user(&rt, arg, sizeof(rt)))
return -EFAULT;
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index fddc3bbf6b8b..ba66840688c2 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -2451,7 +2451,7 @@ static inline struct ip_mc_list *igmp_mc_get_first(struct seq_file *seq)
for_each_netdev_rcu(net, state->dev) {
struct in_device *in_dev;
- if (!vrf_eq(dev_vrf(state->dev), ctx->vrf))
+ if (!vrf_eq_or_any(dev_vrf(state->dev), ctx->vrf))
continue;
in_dev = __in_dev_get_rcu(state->dev);
@@ -2600,7 +2600,7 @@ static inline struct ip_sf_list *igmp_mcf_get_first(struct seq_file *seq)
for_each_netdev_rcu(net, state->dev) {
struct in_device *idev;
- if (!vrf_eq(dev_vrf(state->dev), ctx->vrf))
+ if (!vrf_eq_or_any(dev_vrf(state->dev), ctx->vrf))
continue;
idev = __in_dev_get_rcu(state->dev);
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index f3a349ea3dd8..6d4be3fd2d01 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -591,6 +591,11 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
} else if (!ipc.oif)
ipc.oif = inet->uc_index;
+ /* out vrf cannot be set to VRF_ANY */
+ err = -EINVAL;
+ if (vrf_is_any(sk_ctx.vrf))
+ goto done;
+
flowi4_init_output(&fl4, sk_ctx.vrf, ipc.oif, sk->sk_mark, tos,
RT_SCOPE_UNIVERSE,
inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
@@ -690,6 +695,10 @@ static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
int chk_addr_ret;
struct net_ctx sk_ctx = SOCK_NET_CTX(sk);
+ /* any vrf socket cannot bind to an address or device */
+ if (vrf_is_any(sk->sk_vrf))
+ goto out;
+
if (sk->sk_state != TCP_CLOSE || addr_len < sizeof(struct sockaddr_in))
goto out;
chk_addr_ret = inet_addr_type(&sk_ctx, addr->sin_addr.s_addr);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 1446c84428d8..2d7e2748a138 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -904,6 +904,10 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
if (len > 0xFFFF)
return -EMSGSIZE;
+ /* out vrf cannot be set to VRF_ANY */
+ if (vrf_is_any(sk_ctx.vrf))
+ return -EINVAL;
+
/*
* Check the flags.
*/
--
1.9.3 (Apple Git-50)
^ permalink raw reply related
* [RFC PATCH 24/29] net: vrf: Add support to get/set vrf context on a device
From: David Ahern @ 2015-02-05 1:34 UTC (permalink / raw)
To: netdev; +Cc: ebiederm, David Ahern
In-Reply-To: <1423100070-31848-1-git-send-email-dsahern@gmail.com>
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/linux/netdevice.h | 1 +
include/uapi/linux/if_link.h | 1 +
net/core/dev.c | 28 ++++++++++++++++++++++++++++
net/core/rtnetlink.c | 12 ++++++++++++
4 files changed, 42 insertions(+)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index f4a707263446..7d983f005622 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2922,6 +2922,7 @@ int dev_change_name(struct net_device *, const char *);
int dev_set_alias(struct net_device *, const char *, size_t);
int dev_change_net_namespace(struct net_device *, struct net *, const char *);
int dev_set_mtu(struct net_device *, int);
+int dev_set_vrf(struct net_device *, __u32);
void dev_set_group(struct net_device *, int);
int dev_set_mac_address(struct net_device *, struct sockaddr *);
int dev_change_carrier(struct net_device *, bool new_carrier);
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 0deee3eeddbf..0afdb50ee75c 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -147,6 +147,7 @@ enum {
IFLA_CARRIER_CHANGES,
IFLA_PHYS_SWITCH_ID,
IFLA_LINK_NETNSID,
+ IFLA_VRF,
__IFLA_MAX
};
diff --git a/net/core/dev.c b/net/core/dev.c
index adf575d6d267..d96d0d46dc6e 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5882,6 +5882,34 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
}
EXPORT_SYMBOL(dev_set_mtu);
+ /**
+ * dev_set_vrf - Change VRF
+ * @dev: device
+ * @new_vrf: new VRF
+ *
+ * Change the VRF association for the network device.
+ */
+int dev_set_vrf(struct net_device *dev, __u32 new_vrf)
+{
+ if (!netif_device_present(dev))
+ return -ENODEV;
+
+ /* device needs to be taken down to drop routes */
+ if (dev->flags & IFF_UP)
+ return -EINVAL;
+
+ if (!vrf_is_valid(new_vrf))
+ return -EINVAL;
+
+ if (new_vrf == dev->nd_vrf)
+ return 0;
+
+ dev->nd_vrf = new_vrf;
+
+ return 0;
+}
+EXPORT_SYMBOL(dev_set_vrf);
+
/**
* dev_set_group - Change group this device belongs to
* @dev: device
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 673cb4c6f391..bf41e63f87ae 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -866,6 +866,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
+ nla_total_size(4) /* IFLA_TXQLEN */
+ nla_total_size(4) /* IFLA_WEIGHT */
+ nla_total_size(4) /* IFLA_MTU */
+ + nla_total_size(4) /* IFLA_VRF */
+ nla_total_size(4) /* IFLA_LINK */
+ nla_total_size(4) /* IFLA_MASTER */
+ nla_total_size(1) /* IFLA_CARRIER */
@@ -1031,6 +1032,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
netif_running(dev) ? dev->operstate : IF_OPER_DOWN) ||
nla_put_u8(skb, IFLA_LINKMODE, dev->link_mode) ||
nla_put_u32(skb, IFLA_MTU, dev->mtu) ||
+ nla_put_u32(skb, IFLA_VRF, dev->nd_vrf) ||
nla_put_u32(skb, IFLA_GROUP, dev->group) ||
nla_put_u32(skb, IFLA_PROMISCUITY, dev->promiscuity) ||
nla_put_u32(skb, IFLA_NUM_TX_QUEUES, dev->num_tx_queues) ||
@@ -1249,6 +1251,7 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
[IFLA_CARRIER_CHANGES] = { .type = NLA_U32 }, /* ignored */
[IFLA_PHYS_SWITCH_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_ITEM_ID_LEN },
[IFLA_LINK_NETNSID] = { .type = NLA_S32 },
+ [IFLA_VRF] = { .type = NLA_U32 },
};
static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
@@ -1616,6 +1619,13 @@ static int do_setlink(const struct sk_buff *skb,
status |= DO_SETLINK_MODIFIED;
}
+ if (tb[IFLA_VRF]) {
+ err = dev_set_vrf(dev, nla_get_u32(tb[IFLA_VRF]));
+ if (err < 0)
+ goto errout;
+ status |= DO_SETLINK_MODIFIED;
+ }
+
if (tb[IFLA_GROUP]) {
dev_set_group(dev, nla_get_u32(tb[IFLA_GROUP]));
status |= DO_SETLINK_NOTIFY;
@@ -1911,6 +1921,8 @@ struct net_device *rtnl_create_link(struct net *net,
if (tb[IFLA_MTU])
dev->mtu = nla_get_u32(tb[IFLA_MTU]);
+ if (tb[IFLA_VRF])
+ dev->nd_vrf = nla_get_u32(tb[IFLA_VRF]);
if (tb[IFLA_ADDRESS]) {
memcpy(dev->dev_addr, nla_data(tb[IFLA_ADDRESS]),
nla_len(tb[IFLA_ADDRESS]));
--
1.9.3 (Apple Git-50)
^ permalink raw reply related
* [RFC PATCH 23/29] net: vrf: Enable vrf checks
From: David Ahern @ 2015-02-05 1:34 UTC (permalink / raw)
To: netdev; +Cc: ebiederm, David Ahern
In-Reply-To: <1423100070-31848-1-git-send-email-dsahern@gmail.com>
Add vrf comparison to all of the net_ctx_eq functions and a few other
places needed to enable vrf awareness.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/linux/netdevice.h | 3 ++-
include/net/inet_hashtables.h | 3 ++-
include/net/ip_fib.h | 3 ++-
include/net/ipv6.h | 2 +-
include/net/neighbour.h | 6 ++++--
include/net/net_namespace.h | 2 +-
include/net/sock.h | 2 +-
net/core/dev.c | 9 +++++++++
net/core/fib_rules.c | 4 ++--
net/core/neighbour.c | 6 ++++--
net/ipv4/arp.c | 4 +++-
net/ipv4/devinet.c | 11 ++++++++++-
net/ipv4/fib_frontend.c | 2 +-
net/ipv4/fib_semantics.c | 5 +++++
net/ipv4/igmp.c | 7 +++++++
net/ipv4/inet_hashtables.c | 2 ++
net/ipv4/ip_sockglue.c | 4 ++++
17 files changed, 60 insertions(+), 15 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index b6de06eda683..f4a707263446 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1857,7 +1857,8 @@ __u32 dev_vrf(const struct net_device *dev)
static inline
int dev_net_ctx_eq(const struct net_device *dev, struct net_ctx *ctx)
{
- if (net_eq(dev_net(dev), ctx->net))
+ if (net_eq(dev_net(dev), ctx->net) &&
+ vrf_eq(dev_vrf(dev), ctx->vrf))
return 1;
return 0;
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index eec177ef0798..199809e46133 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -101,7 +101,8 @@ void ib_net_ctx_set(struct inet_bind_bucket *ib, struct net_ctx *ctx)
static inline
int ib_net_ctx_eq(struct inet_bind_bucket *ib, struct net_ctx *ctx)
{
- if (net_eq(ib_net(ib), ctx->net))
+ if (net_eq(ib_net(ib), ctx->net) &&
+ vrf_eq(ib->ib_net_ctx.vrf, ctx->vrf))
return 1;
return 0;
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index e6b823c0305e..d49358bc342c 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -127,7 +127,8 @@ struct fib_info {
static inline
int fib_net_ctx_eq(const struct fib_info *fi, const struct net_ctx *ctx)
{
- if (net_eq(fi->fib_net_ctx.net, ctx->net))
+ if (net_eq(fi->fib_net_ctx.net, ctx->net) &&
+ vrf_eq(fi->fib_net_ctx.vrf, ctx->vrf))
return 1;
return 0;
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 61f8b6df8bb9..ba1d145d67fd 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -247,7 +247,7 @@ static inline
int fl_net_ctx_eq(struct ip6_flowlabel *fl, struct net_ctx *ctx)
{
#ifdef CONFIG_NET_NS
- return net_eq(fl->fl_net, ctx->net);
+ return net_eq(fl->fl_net, ctx->net) && vrf_eq(fl->fl_vrf, ctx->vrf);
#else
return 1;
#endif
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index d9e2328ad60a..f3527b25d612 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -294,7 +294,8 @@ int neigh_parms_net_ctx_eq(const struct neigh_parms *parms,
const struct net_ctx *net_ctx)
{
#ifdef CONFIG_NET_NS
- if (net_eq(neigh_parms_net(parms), net_ctx->net))
+ if (net_eq(neigh_parms_net(parms), net_ctx->net) &&
+ vrf_eq(neigh_parms_vrf(parms), net_ctx->vrf))
return 1;
return 0;
@@ -330,7 +331,8 @@ int pneigh_net_ctx_eq(const struct pneigh_entry *pneigh,
const struct net_ctx *net_ctx)
{
#ifdef CONFIG_NET_NS
- if (net_eq(pneigh_net(pneigh), net_ctx->net))
+ if (net_eq(pneigh_net(pneigh), net_ctx->net) &&
+ vrf_eq(pneigh->net_ctx.vrf, net_ctx->vrf))
return 1;
return 0;
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index d0a3414758f8..7ae98b85cd21 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -215,7 +215,7 @@ int net_eq(const struct net *net1, const struct net *net2)
static inline
int net_ctx_eq(struct net_ctx *ctx1, struct net_ctx *ctx2)
{
- return net_eq(ctx1->net, ctx2->net);
+ return net_eq(ctx1->net, ctx2->net) && vrf_eq(ctx1->vrf, ctx2->vrf);
}
diff --git a/include/net/sock.h b/include/net/sock.h
index d3668b691f82..a9b45fca4605 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -2205,7 +2205,7 @@ void sock_net_set(struct sock *sk, struct net *net)
static inline
int sock_net_ctx_eq(struct sock *sk, struct net_ctx *ctx)
{
- return net_eq(sock_net(sk), ctx->net);
+ return net_eq(sock_net(sk), ctx->net) && vrf_eq(sk->sk_vrf, ctx->vrf);
}
/*
diff --git a/net/core/dev.c b/net/core/dev.c
index d64f5b107dba..adf575d6d267 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -688,6 +688,9 @@ struct net_device *__dev_get_by_name_ctx(struct net_ctx *ctx, const char *name)
{
struct net_device *dev = __dev_get_by_name(ctx->net, name);
+ if (dev && !vrf_eq(dev_vrf(dev), ctx->vrf))
+ dev = NULL;
+
return dev;
}
EXPORT_SYMBOL(__dev_get_by_name_ctx);
@@ -771,6 +774,9 @@ struct net_device *__dev_get_by_index_ctx(struct net_ctx *ctx, int ifindex)
{
struct net_device *dev = __dev_get_by_index(ctx->net, ifindex);
+ if (dev && !vrf_eq(dev_vrf(dev), ctx->vrf))
+ dev = NULL;
+
return dev;
}
EXPORT_SYMBOL(__dev_get_by_index_ctx);
@@ -814,6 +820,9 @@ struct net_device *dev_get_by_index_rcu_ctx(struct net_ctx *ctx, int ifindex)
{
struct net_device *dev = dev_get_by_index_rcu(ctx->net, ifindex);
+ if (dev && !vrf_eq(dev_vrf(dev), ctx->vrf))
+ dev = NULL;
+
return dev;
}
EXPORT_SYMBOL(dev_get_by_index_rcu_ctx);
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 223a4004bdd0..aea74e16360c 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -317,7 +317,7 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh)
rule->iifindex = -1;
nla_strlcpy(rule->iifname, tb[FRA_IIFNAME], IFNAMSIZ);
- dev = __dev_get_by_name(net, rule->iifname);
+ dev = __dev_get_by_name_ctx(&sk_ctx, rule->iifname);
if (dev)
rule->iifindex = dev->ifindex;
}
@@ -327,7 +327,7 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh)
rule->oifindex = -1;
nla_strlcpy(rule->oifname, tb[FRA_OIFNAME], IFNAMSIZ);
- dev = __dev_get_by_name(net, rule->oifname);
+ dev = __dev_get_by_name_ctx(&sk_ctx, rule->oifname);
if (dev)
rule->oifindex = dev->ifindex;
}
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index e6c03d367f56..46b7e8cc7c70 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2846,9 +2846,11 @@ static void neigh_copy_dflt_parms(struct net_ctx *ctx, struct neigh_parms *p,
rcu_read_lock();
for_each_netdev_rcu(ctx->net, dev) {
- struct neigh_parms *dst_p =
- neigh_get_dev_parms_rcu(dev, family);
+ struct neigh_parms *dst_p;
+ if (!vrf_eq(dev_vrf(dev), ctx->vrf))
+ continue;
+ dst_p = neigh_get_dev_parms_rcu(dev, family);
if (dst_p && !test_bit(index, dst_p->data_state))
dst_p->data[index] = p->data[index];
}
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index b24773b275a9..ed1453b9eeab 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -1021,6 +1021,8 @@ static int arp_req_set_public(struct net_ctx *ctx, struct arpreq *r,
if (!dev && (r->arp_flags & ATF_COM)) {
dev = dev_getbyhwaddr_rcu(net, r->arp_ha.sa_family,
r->arp_ha.sa_data);
+ if (dev && !vrf_eq(dev_vrf(dev), ctx->vrf))
+ dev = NULL;
if (!dev)
return -ENODEV;
}
@@ -1214,7 +1216,7 @@ int arp_ioctl(struct net_ctx *ctx, unsigned int cmd, void __user *arg)
rtnl_lock();
if (r.arp_dev[0]) {
err = -ENODEV;
- dev = __dev_get_by_name(net, r.arp_dev);
+ dev = __dev_get_by_name_ctx(ctx, r.arp_dev);
if (dev == NULL)
goto out;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 7c0c3bc17599..54afa816ff66 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -951,7 +951,7 @@ int devinet_ioctl(struct net_ctx *net_ctx, unsigned int cmd, void __user *arg)
rtnl_lock();
ret = -ENODEV;
- dev = __dev_get_by_name(net, ifr.ifr_name);
+ dev = __dev_get_by_name_ctx(net_ctx, ifr.ifr_name);
if (!dev)
goto done;
@@ -1166,6 +1166,7 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
__be32 addr = 0;
struct in_device *in_dev;
struct net *net = dev_net(dev);
+ __u32 vrf = dev_vrf(dev);
rcu_read_lock();
in_dev = __in_dev_get_rcu(dev);
@@ -1192,6 +1193,8 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
in dev_base list.
*/
for_each_netdev_rcu(net, dev) {
+ if (!vrf_eq(dev_vrf(dev), vrf))
+ continue;
in_dev = __in_dev_get_rcu(dev);
if (!in_dev)
continue;
@@ -1266,6 +1269,8 @@ __be32 inet_confirm_addr(struct net_ctx *ctx, struct in_device *in_dev,
rcu_read_lock();
for_each_netdev_rcu(ctx->net, dev) {
+ if (!vrf_eq(dev_vrf(dev), ctx->vrf))
+ continue;
in_dev = __in_dev_get_rcu(dev);
if (in_dev) {
addr = confirm_addr_indev(in_dev, dst, local, scope);
@@ -1561,6 +1566,8 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
goto cont;
if (h > s_h || idx > s_idx)
s_ip_idx = 0;
+ if (!vrf_eq(dev_vrf(dev), vrf))
+ goto cont;
in_dev = __in_dev_get_rcu(dev);
if (!in_dev)
goto cont;
@@ -1883,6 +1890,8 @@ static int inet_netconf_dump_devconf(struct sk_buff *skb,
hlist_for_each_entry_rcu(dev, head, index_hlist) {
if (idx < s_idx)
goto cont;
+ if (!vrf_eq(dev_vrf(dev), vrf))
+ goto cont;
in_dev = __in_dev_get_rcu(dev);
if (!in_dev)
goto cont;
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 2f06b71bed53..8713618e2835 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -418,7 +418,7 @@ static int rtentry_to_fib_config(struct net_ctx *ctx, int cmd,
colon = strchr(devname, ':');
if (colon)
*colon = 0;
- dev = __dev_get_by_name(net, devname);
+ dev = __dev_get_by_name_ctx(ctx, devname);
if (!dev)
return -ENODEV;
cfg->fc_oif = dev->ifindex;
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 65d01c5b747e..0aa5990b1c02 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -929,6 +929,11 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
err = -ENODEV;
if (nh->nh_dev == NULL)
goto failure;
+ if (!vrf_eq(dev_vrf(nh->nh_dev), net_ctx->vrf)) {
+ dev_put(nh->nh_dev);
+ nh->nh_dev = NULL;
+ goto failure;
+ }
} else {
change_nexthops(fi) {
err = fib_check_nh(cfg, fi, nexthop_nh);
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 86aa303a1cf7..fddc3bbf6b8b 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -2451,6 +2451,9 @@ static inline struct ip_mc_list *igmp_mc_get_first(struct seq_file *seq)
for_each_netdev_rcu(net, state->dev) {
struct in_device *in_dev;
+ if (!vrf_eq(dev_vrf(state->dev), ctx->vrf))
+ continue;
+
in_dev = __in_dev_get_rcu(state->dev);
if (!in_dev)
continue;
@@ -2596,6 +2599,10 @@ static inline struct ip_sf_list *igmp_mcf_get_first(struct seq_file *seq)
state->im = NULL;
for_each_netdev_rcu(net, state->dev) {
struct in_device *idev;
+
+ if (!vrf_eq(dev_vrf(state->dev), ctx->vrf))
+ continue;
+
idev = __in_dev_get_rcu(state->dev);
if (unlikely(idev == NULL))
continue;
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 71c31c81aea1..0dcde9839d66 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -220,6 +220,8 @@ struct sock *__inet_lookup_listener(struct net_ctx *ctx,
result = NULL;
hiscore = 0;
sk_nulls_for_each_rcu(sk, node, &ilb->head) {
+ if (!vrf_eq(sk->sk_vrf, ctx->vrf) && !vrf_is_any(sk->sk_vrf))
+ continue;
score = compute_score(sk, ctx, hnum, daddr, dif);
if (score > hiscore) {
result = sk;
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index eeb51e935379..b5521f7b36b1 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -728,6 +728,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
{
struct net_device *dev = NULL;
int ifindex;
+ __u32 vrf;
if (optlen != sizeof(int))
goto e_inval;
@@ -743,7 +744,10 @@ static int do_ip_setsockopt(struct sock *sk, int level,
err = -EADDRNOTAVAIL;
if (!dev)
break;
+ vrf = dev_vrf(dev);
dev_put(dev);
+ if (!vrf_eq(vrf, sk_ctx.vrf))
+ break;
err = -EINVAL;
if (sk->sk_bound_dev_if)
--
1.9.3 (Apple Git-50)
^ permalink raw reply related
* [RFC PATCH 22/29] net: vrf: Set VRF id in various network structs
From: David Ahern @ 2015-02-05 1:34 UTC (permalink / raw)
To: netdev; +Cc: ebiederm, David Ahern
In-Reply-To: <1423100070-31848-1-git-send-email-dsahern@gmail.com>
VRF id comes from passed in network context similar to namespace.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/net/inet_hashtables.h | 1 +
include/net/neighbour.h | 1 +
net/core/fib_rules.c | 3 +++
net/core/neighbour.c | 1 +
net/ipv4/fib_frontend.c | 3 +++
net/ipv4/fib_semantics.c | 1 +
net/ipv4/icmp.c | 1 +
net/ipv4/ipmr.c | 1 +
net/ipv4/route.c | 1 +
9 files changed, 13 insertions(+)
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 9ddc1b2309ce..eec177ef0798 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -95,6 +95,7 @@ static inline
void ib_net_ctx_set(struct inet_bind_bucket *ib, struct net_ctx *ctx)
{
write_pnet(&ib->ib_net_ctx.net, hold_net(ctx->net));
+ ib->ib_net_ctx.vrf = ctx->vrf;
}
static inline
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 73d0938b085c..d9e2328ad60a 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -323,6 +323,7 @@ void pneigh_net_ctx_set(struct pneigh_entry *pneigh,
const struct net_ctx *net_ctx)
{
write_pnet(&pneigh->net_ctx.net, hold_net(net_ctx->net));
+ pneigh->net_ctx.vrf = net_ctx->vrf;
}
static inline
int pneigh_net_ctx_eq(const struct pneigh_entry *pneigh,
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 9a1a4a23b6f6..223a4004bdd0 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -32,6 +32,7 @@ int fib_default_rule_add(struct fib_rules_ops *ops,
r->table = table;
r->flags = flags;
r->fr_net = hold_net(ops->fro_net);
+ r->fr_vrf = ops->fro_vrf;
r->suppress_prefixlen = -1;
r->suppress_ifgroup = -1;
@@ -137,6 +138,7 @@ fib_rules_register(const struct fib_rules_ops *tmpl, struct net_ctx *ctx)
INIT_LIST_HEAD(&ops->rules_list);
ops->fro_net = ctx->net;
+ ops->fro_vrf = ctx->vrf;
err = __fib_rules_register(ops);
if (err) {
@@ -305,6 +307,7 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh)
goto errout;
}
rule->fr_net = hold_net(net);
+ rule->fr_vrf = sk_ctx.vrf;
if (tb[FRA_PRIORITY])
rule->pref = nla_get_u32(tb[FRA_PRIORITY]);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 0fbbe70be170..e6c03d367f56 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1467,6 +1467,7 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
dev_hold(dev);
p->dev = dev;
write_pnet(&p->net_ctx.net, hold_net(dev_ctx.net));
+ p->net_ctx.vrf = dev_ctx.vrf;
p->sysctl_table = NULL;
if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index cba1e2c9c2ec..2f06b71bed53 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -357,6 +357,7 @@ static int rtentry_to_fib_config(struct net_ctx *ctx, int cmd,
memset(cfg, 0, sizeof(*cfg));
cfg->fc_nlinfo.nl_net = net;
+ cfg->fc_nlinfo.nl_vrf = ctx->vrf;
if (rt->rt_dst.sa_family != AF_INET)
return -EAFNOSUPPORT;
@@ -564,6 +565,7 @@ static int rtm_to_fib_config(struct net_ctx *ctx, struct sk_buff *skb,
cfg->fc_nlinfo.portid = NETLINK_CB(skb).portid;
cfg->fc_nlinfo.nlh = nlh;
cfg->fc_nlinfo.nl_net = ctx->net;
+ cfg->fc_nlinfo.nl_vrf = ctx->vrf;
if (cfg->fc_type > RTN_MAX) {
err = -EINVAL;
@@ -714,6 +716,7 @@ static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifad
.fc_nlflags = NLM_F_CREATE | NLM_F_APPEND,
.fc_nlinfo = {
.nl_net = net,
+ .nl_vrf = dev_vrf(ifa->ifa_dev->dev),
},
};
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index a7d810cafada..65d01c5b747e 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -819,6 +819,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
fi->fib_metrics = (u32 *) dst_default_metrics;
fi->fib_net = hold_net(net);
+ fi->fib_vrf = net_ctx->vrf;
fi->fib_protocol = cfg->fc_protocol;
fi->fib_scope = cfg->fc_scope;
fi->fib_flags = cfg->fc_flags;
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 9d4c38292fee..b7766a73e46d 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -564,6 +564,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
goto out;
net = dev_net(rt->dst.dev);
dev_ctx.net = net;
+ dev_ctx.vrf = dev_vrf(rt->dst.dev);
/*
* Find the original header. It is expected to be valid, of course.
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index a9e438c7aaa4..d00ba199a012 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -2081,6 +2081,7 @@ static int __pim_rcv(struct mr_table *mrt, struct sk_buff *skb,
skb->ip_summed = CHECKSUM_NONE;
dev_ctx.net = dev_net(reg_dev);
+ dev_ctx.vrf = dev_vrf(reg_dev);
skb_tunnel_rx(skb, reg_dev, &dev_ctx);
netif_rx(skb);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index f980a42a995f..d6c5f0a8ab17 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1621,6 +1621,7 @@ static int __mkroute_input(struct sk_buff *skb,
}
dev_ctx.net = dev_net(rth->dst.dev);
+ dev_ctx.vrf = dev_vrf(rth->dst.dev);
rth->rt_genid = rt_genid_ipv4(&dev_ctx);
rth->rt_flags = flags;
rth->rt_type = res->type;
--
1.9.3 (Apple Git-50)
^ permalink raw reply related
* [RFC PATCH 21/29] net: vrf: Add vrf context to genid's
From: David Ahern @ 2015-02-05 1:34 UTC (permalink / raw)
To: netdev; +Cc: ebiederm, David Ahern
In-Reply-To: <1423100070-31848-1-git-send-email-dsahern@gmail.com>
Bottom 12 bits (VRF_BITS) are the VRF id.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/net/ip_fib.h | 2 +-
include/net/net_namespace.h | 12 ++++++++----
net/ipv4/devinet.c | 12 ++++++++----
net/ipv4/fib_frontend.c | 8 +++++---
net/ipv4/fib_semantics.c | 2 +-
net/ipv4/route.c | 13 +++++++++++--
6 files changed, 34 insertions(+), 15 deletions(-)
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 577479d7f268..e6b823c0305e 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -180,7 +180,7 @@ __be32 fib_info_update_nh_saddr(struct net_ctx *ctx, struct fib_nh *nh);
#define FIB_RES_SADDR(ctx, res) \
((FIB_RES_NH(res).nh_saddr_genid == \
- atomic_read(&(ctx)->net->ipv4.dev_addr_genid)) ? \
+ (atomic_read(&(ctx)->net->ipv4.dev_addr_genid) + (ctx)->vrf)) ? \
FIB_RES_NH(res).nh_saddr : \
fib_info_update_nh_saddr((ctx), &FIB_RES_NH(res)))
#define FIB_RES_GW(res) (FIB_RES_NH(res).nh_gw)
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 7cc7b0a1a20b..d0a3414758f8 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -372,12 +372,14 @@ static inline void unregister_net_sysctl_table(struct ctl_table_header *header)
static inline int rt_genid_ipv4(struct net_ctx *ctx)
{
- return atomic_read(&ctx->net->ipv4.rt_genid);
+ return atomic_read(&ctx->net->ipv4.rt_genid) + ctx->vrf;
}
static inline void rt_genid_bump_ipv4(struct net *net)
{
- atomic_inc(&net->ipv4.rt_genid);
+ int inc = 1 << VRF_BITS;
+
+ atomic_add(inc, &net->ipv4.rt_genid);
}
extern void (*__fib6_flush_trees)(struct net *net);
@@ -404,12 +406,14 @@ static inline void rt_genid_bump_all(struct net *net)
static inline int fnhe_genid(struct net_ctx *ctx)
{
- return atomic_read(&ctx->net->fnhe_genid);
+ return atomic_read(&ctx->net->fnhe_genid) + ctx->vrf;
}
static inline void fnhe_genid_bump(struct net *net)
{
- atomic_inc(&net->fnhe_genid);
+ int inc = 1 << VRF_BITS;
+
+ atomic_add(inc, &net->fnhe_genid);
}
#endif /* __NET_NET_NAMESPACE_H */
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 02ffbfb8bfee..7c0c3bc17599 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1536,6 +1536,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
{
struct net_ctx sk_ctx = SOCK_NET_CTX(skb->sk);
struct net *net = sk_ctx.net;
+ __u32 vrf = sk_ctx.vrf;
int h, s_h;
int idx, s_idx;
int ip_idx, s_ip_idx;
@@ -1549,11 +1550,12 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
s_ip_idx = ip_idx = cb->args[2];
for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
+ int genid;
idx = 0;
head = &net->dev_index_head[h];
rcu_read_lock();
- cb->seq = atomic_read(&net->ipv4.dev_addr_genid) ^
- net->dev_base_seq;
+ genid = atomic_read(&net->ipv4.dev_addr_genid) + vrf;
+ cb->seq = genid ^ net->dev_base_seq;
hlist_for_each_entry_rcu(dev, head, index_hlist) {
if (idx < s_idx)
goto cont;
@@ -1861,6 +1863,7 @@ static int inet_netconf_dump_devconf(struct sk_buff *skb,
{
struct net_ctx sk_ctx = SOCK_NET_CTX(skb->sk);
struct net *net = sk_ctx.net;
+ __u32 vrf = sk_ctx.vrf;
int h, s_h;
int idx, s_idx;
struct net_device *dev;
@@ -1871,11 +1874,12 @@ static int inet_netconf_dump_devconf(struct sk_buff *skb,
s_idx = idx = cb->args[1];
for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
+ int genid;
idx = 0;
head = &net->dev_index_head[h];
rcu_read_lock();
- cb->seq = atomic_read(&net->ipv4.dev_addr_genid) ^
- net->dev_base_seq;
+ genid = atomic_read(&net->ipv4.dev_addr_genid) + vrf;
+ cb->seq = genid ^ net->dev_base_seq;
hlist_for_each_entry_rcu(dev, head, index_hlist) {
if (idx < s_idx)
goto cont;
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index f2a8a557a3d8..cba1e2c9c2ec 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -1021,6 +1021,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event,
struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
struct net_device *dev = ifa->ifa_dev->dev;
struct net *net = dev_net(dev);
+ int inc = 1 << VRF_BITS;
switch (event) {
case NETDEV_UP:
@@ -1028,12 +1029,12 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event,
#ifdef CONFIG_IP_ROUTE_MULTIPATH
fib_sync_up(dev);
#endif
- atomic_inc(&net->ipv4.dev_addr_genid);
+ atomic_add(inc, &net->ipv4.dev_addr_genid);
rt_cache_flush(dev_net(dev));
break;
case NETDEV_DOWN:
fib_del_ifaddr(ifa, NULL);
- atomic_inc(&net->ipv4.dev_addr_genid);
+ atomic_add(inc, &net->ipv4.dev_addr_genid);
if (ifa->ifa_dev->ifa_list == NULL) {
/* Last address was deleted from this interface.
* Disable IP.
@@ -1052,6 +1053,7 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
struct in_device *in_dev;
struct net *net = dev_net(dev);
+ int inc = 1 << VRF_BITS;
if (event == NETDEV_UNREGISTER) {
fib_disable_ip(dev, 2);
@@ -1071,7 +1073,7 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo
#ifdef CONFIG_IP_ROUTE_MULTIPATH
fib_sync_up(dev);
#endif
- atomic_inc(&net->ipv4.dev_addr_genid);
+ atomic_add(inc, &net->ipv4.dev_addr_genid);
rt_cache_flush(net);
break;
case NETDEV_DOWN:
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 9fc5487e66fe..a7d810cafada 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -756,7 +756,7 @@ __be32 fib_info_update_nh_saddr(struct net_ctx *net_ctx, struct fib_nh *nh)
nh->nh_saddr = inet_select_addr(nh->nh_dev,
nh->nh_gw,
nh->nh_parent->fib_scope);
- nh->nh_saddr_genid = atomic_read(&net->ipv4.dev_addr_genid);
+ nh->nh_saddr_genid = atomic_read(&net->ipv4.dev_addr_genid) + net_ctx->vrf;
return nh->nh_saddr;
}
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 8271c5b30322..f980a42a995f 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2706,10 +2706,19 @@ static __net_initdata struct pernet_operations sysctl_route_ops = {
static __net_init int rt_genid_init(struct net *net)
{
+ int genid;
+
atomic_set(&net->ipv4.rt_genid, 0);
atomic_set(&net->fnhe_genid, 0);
- get_random_bytes(&net->ipv4.dev_addr_genid,
- sizeof(net->ipv4.dev_addr_genid));
+
+again:
+ get_random_bytes(&genid, sizeof(genid));
+ genid &= ~VRF_MASK;
+ if (genid == 0)
+ goto again;
+
+ atomic_set(&net->ipv4.dev_addr_genid, genid);
+
return 0;
}
--
1.9.3 (Apple Git-50)
^ permalink raw reply related
* [RFC PATCH 20/29] net: vrf: Add vrf context to flow struct
From: David Ahern @ 2015-02-05 1:34 UTC (permalink / raw)
To: netdev; +Cc: ebiederm, David Ahern
In-Reply-To: <1423100070-31848-1-git-send-email-dsahern@gmail.com>
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/net/flow.h | 7 ++++++-
include/net/route.h | 4 ++--
net/ipv4/devinet.c | 2 +-
net/ipv4/fib_frontend.c | 5 ++++-
net/ipv4/fib_rules.c | 2 ++
net/ipv4/fib_semantics.c | 1 +
net/ipv4/icmp.c | 3 +++
net/ipv4/inet_connection_sock.c | 4 ++--
net/ipv4/ip_output.c | 2 +-
net/ipv4/ipmr.c | 2 ++
net/ipv4/netfilter.c | 1 +
net/ipv4/ping.c | 2 +-
net/ipv4/raw.c | 2 +-
net/ipv4/route.c | 23 +++++++++++++----------
net/ipv4/syncookies.c | 2 +-
net/ipv4/udp.c | 3 ++-
net/ipv4/xfrm4_policy.c | 2 ++
net/sctp/protocol.c | 1 +
18 files changed, 46 insertions(+), 22 deletions(-)
diff --git a/include/net/flow.h b/include/net/flow.h
index 07e7a58b9aac..6d35a8bfbe72 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -30,6 +30,7 @@ struct flowi_common {
#define FLOWI_FLAG_ANYSRC 0x01
#define FLOWI_FLAG_KNOWN_NH 0x02
__u32 flowic_secid;
+ __u32 flowic_vrf;
};
union flowi_uli {
@@ -66,6 +67,7 @@ struct flowi4 {
#define flowi4_proto __fl_common.flowic_proto
#define flowi4_flags __fl_common.flowic_flags
#define flowi4_secid __fl_common.flowic_secid
+#define flowi4_vrf __fl_common.flowic_vrf
/* (saddr,daddr) must be grouped, same order as in IP header */
__be32 saddr;
@@ -81,7 +83,7 @@ struct flowi4 {
#define fl4_gre_key uli.gre_key
} __attribute__((__aligned__(BITS_PER_LONG/8)));
-static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
+static inline void flowi4_init_output(struct flowi4 *fl4, __u32 vrf, int oif,
__u32 mark, __u8 tos, __u8 scope,
__u8 proto, __u8 flags,
__be32 daddr, __be32 saddr,
@@ -95,6 +97,7 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
fl4->flowi4_proto = proto;
fl4->flowi4_flags = flags;
fl4->flowi4_secid = 0;
+ fl4->flowi4_vrf = vrf;
fl4->daddr = daddr;
fl4->saddr = saddr;
fl4->fl4_dport = dport;
@@ -122,6 +125,7 @@ struct flowi6 {
#define flowi6_proto __fl_common.flowic_proto
#define flowi6_flags __fl_common.flowic_flags
#define flowi6_secid __fl_common.flowic_secid
+#define flowi6_vrf __fl_common.flowic_vrf
struct in6_addr daddr;
struct in6_addr saddr;
__be32 flowlabel;
@@ -165,6 +169,7 @@ struct flowi {
#define flowi_proto u.__fl_common.flowic_proto
#define flowi_flags u.__fl_common.flowic_flags
#define flowi_secid u.__fl_common.flowic_secid
+#define flowi_vrf u.__fl_common.flowic_vrf
} __attribute__((__aligned__(BITS_PER_LONG/8)));
static inline struct flowi *flowi4_to_flowi(struct flowi4 *fl4)
diff --git a/include/net/route.h b/include/net/route.h
index 5f0b770225d7..a062df826c67 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -139,7 +139,7 @@ static inline struct rtable *ip_route_output_ports(struct net_ctx *ctx, struct f
__be16 dport, __be16 sport,
__u8 proto, __u8 tos, int oif)
{
- flowi4_init_output(fl4, oif, sk ? sk->sk_mark : 0, tos,
+ flowi4_init_output(fl4, ctx->vrf, oif, sk ? sk->sk_mark : 0, tos,
RT_SCOPE_UNIVERSE, proto,
sk ? inet_sk_flowi_flags(sk) : 0,
daddr, saddr, dport, sport);
@@ -250,7 +250,7 @@ static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst, __be32
if (inet_sk(sk)->transparent)
flow_flags |= FLOWI_FLAG_ANYSRC;
- flowi4_init_output(fl4, oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE,
+ flowi4_init_output(fl4, sk->sk_vrf, oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE,
protocol, flow_flags, dst, src, dport, sport);
}
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 59de98a44508..02ffbfb8bfee 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -155,7 +155,7 @@ struct net_device *__ip_dev_find(struct net_ctx *ctx, __be32 addr, bool devref)
}
}
if (!result) {
- struct flowi4 fl4 = { .daddr = addr };
+ struct flowi4 fl4 = { .daddr = addr, .flowi4_vrf = ctx->vrf };
struct fib_result res = { 0 };
struct fib_table *local;
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index b068ab996cc3..f2a8a557a3d8 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -155,7 +155,7 @@ static inline unsigned int __inet_dev_addr_type(struct net_ctx *ctx,
__be32 addr)
{
struct net *net = ctx->net;
- struct flowi4 fl4 = { .daddr = addr };
+ struct flowi4 fl4 = { .daddr = addr, .flowi4_vrf = ctx->vrf };
struct fib_result res;
unsigned int ret = RTN_BROADCAST;
struct fib_table *local_table;
@@ -221,6 +221,7 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb)
fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
fl4.flowi4_scope = scope;
fl4.flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0;
+ fl4.flowi4_vrf = dev_ctx.vrf;
if (!fib_lookup(&dev_ctx, &fl4, &res))
return FIB_RES_PREFSRC(&dev_ctx, res);
} else {
@@ -258,6 +259,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
no_addr = idev->ifa_list == NULL;
fl4.flowi4_mark = IN_DEV_SRC_VMARK(idev) ? skb->mark : 0;
+ fl4.flowi4_vrf = dev_ctx.vrf;
if (fib_lookup(&dev_ctx, &fl4, &res))
goto last_resort;
@@ -292,6 +294,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
if (rpf == 1)
goto e_rpf;
fl4.flowi4_oif = dev->ifindex;
+ fl4.flowi4_vrf = dev_vrf(dev);
ret = 0;
if (fib_lookup(&dev_ctx, &fl4, &res) == 0) {
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index bb9399e2c1cb..0dc8adf7b767 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -55,6 +55,8 @@ int __fib_lookup(struct net_ctx *ctx, struct flowi4 *flp, struct fib_result *res
};
int err;
+ flp->flowi4_vrf = ctx->vrf;
+
err = fib_rules_lookup(ctx->net->ipv4.rules_ops, flowi4_to_flowi(flp),
0, &arg);
#ifdef CONFIG_IP_ROUTE_CLASSID
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 99af28c2fb6d..9fc5487e66fe 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -617,6 +617,7 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
.flowi4_scope = cfg->fc_scope + 1,
.flowi4_oif = nh->nh_oif,
.flowi4_iif = LOOPBACK_IFINDEX,
+ .flowi4_vrf = net_ctx->vrf,
};
/* It is not necessary, but requires a bit of thinking */
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 2d1e98e6ad14..9d4c38292fee 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -426,6 +426,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
fl4.flowi4_mark = mark;
fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
fl4.flowi4_proto = IPPROTO_ICMP;
+ fl4.flowi4_vrf = skb->vrf;
security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
rt = ip_route_output_key(&dev_ctx, &fl4);
if (IS_ERR(rt))
@@ -457,6 +458,7 @@ static struct rtable *icmp_route_lookup(struct net_ctx *ctx,
fl4->flowi4_mark = mark;
fl4->flowi4_tos = RT_TOS(tos);
fl4->flowi4_proto = IPPROTO_ICMP;
+ fl4->flowi4_vrf = skb_in->vrf;
fl4->fl4_icmp_type = type;
fl4->fl4_icmp_code = code;
security_skb_classify_flow(skb_in, flowi4_to_flowi(fl4));
@@ -490,6 +492,7 @@ static struct rtable *icmp_route_lookup(struct net_ctx *ctx,
unsigned long orefdst;
fl4_2.daddr = fl4_dec.saddr;
+ fl4_2.flowi4_vrf = skb_in->vrf;
rt2 = ip_route_output_key(ctx, &fl4_2);
if (IS_ERR(rt2)) {
err = PTR_ERR(rt2);
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 3b8df03c69db..ace32910667e 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -407,7 +407,7 @@ struct dst_entry *inet_csk_route_req(struct sock *sk,
struct net_ctx ctx = { .net = net, .vrf = ireq->ir_vrf };
int flags = inet_sk_flowi_flags(sk);
- flowi4_init_output(fl4, sk->sk_bound_dev_if, ireq->ir_mark,
+ flowi4_init_output(fl4, ctx.vrf, sk->sk_bound_dev_if, ireq->ir_mark,
RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,
sk->sk_protocol,
flags,
@@ -445,7 +445,7 @@ struct dst_entry *inet_csk_route_child_sock(struct sock *sk,
rcu_read_lock();
opt = rcu_dereference(newinet->inet_opt);
- flowi4_init_output(fl4, sk->sk_bound_dev_if, inet_rsk(req)->ir_mark,
+ flowi4_init_output(fl4, ctx.vrf, sk->sk_bound_dev_if, inet_rsk(req)->ir_mark,
RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,
sk->sk_protocol, inet_sk_flowi_flags(sk),
(opt && opt->opt.srr) ? opt->opt.faddr : ireq->ir_rmt_addr,
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 383bac145bf4..9b2d8d7ff6cb 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1556,7 +1556,7 @@ void ip_send_unicast_reply(struct net_ctx *ctx, struct sk_buff *skb,
daddr = replyopts.opt.opt.faddr;
}
- flowi4_init_output(&fl4, arg->bound_dev_if,
+ flowi4_init_output(&fl4, skb->vrf, arg->bound_dev_if,
IP4_REPLY_MARK(ctx->net, skb->mark),
RT_TOS(arg->tos),
RT_SCOPE_UNIVERSE, ip_hdr(skb)->protocol,
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 84d6efeeb072..a9e438c7aaa4 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -458,6 +458,7 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
.flowi4_oif = dev->ifindex,
.flowi4_iif = skb->skb_iif ? : LOOPBACK_IFINDEX,
.flowi4_mark = skb->mark,
+ .flowi4_vrf = skb->vrf,
};
int err;
@@ -1934,6 +1935,7 @@ static struct mr_table *ipmr_rt_fib_lookup(struct net *net, struct sk_buff *skb)
LOOPBACK_IFINDEX :
skb->dev->ifindex),
.flowi4_mark = skb->mark,
+ .flowi4_vrf = skb->vrf,
};
struct mr_table *mrt;
int err;
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index a10ab84b69d8..c00ea581839a 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -43,6 +43,7 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned int addr_type)
fl4.flowi4_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0;
fl4.flowi4_mark = skb->mark;
fl4.flowi4_flags = flags;
+ fl4.flowi4_vrf = skb->vrf;
rt = ip_route_output_key(&ctx, &fl4);
if (IS_ERR(rt))
return PTR_ERR(rt);
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index bca4f27502b0..e08f7ae8d8fe 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -779,7 +779,7 @@ static int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m
} else if (!ipc.oif)
ipc.oif = inet->uc_index;
- flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
+ flowi4_init_output(&fl4, sk_ctx.vrf, ipc.oif, sk->sk_mark, tos,
RT_SCOPE_UNIVERSE, sk->sk_protocol,
inet_sk_flowi_flags(sk), faddr, saddr, 0, 0);
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index c06dd58e538b..f3a349ea3dd8 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -591,7 +591,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
} else if (!ipc.oif)
ipc.oif = inet->uc_index;
- flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
+ flowi4_init_output(&fl4, sk_ctx.vrf, ipc.oif, sk->sk_mark, tos,
RT_SCOPE_UNIVERSE,
inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
inet_sk_flowi_flags(sk) |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 018e292ff145..8271c5b30322 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -503,7 +503,7 @@ EXPORT_SYMBOL(__ip_select_ident);
static void __build_flow_key(struct flowi4 *fl4, const struct sock *sk,
const struct iphdr *iph,
- int oif, u8 tos,
+ __u32 vrf, int oif, u8 tos,
u8 prot, u32 mark, int flow_flags)
{
if (sk) {
@@ -511,10 +511,11 @@ static void __build_flow_key(struct flowi4 *fl4, const struct sock *sk,
oif = sk->sk_bound_dev_if;
mark = sk->sk_mark;
+ vrf = sk->sk_vrf;
tos = RT_CONN_FLAGS(sk);
prot = inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol;
}
- flowi4_init_output(fl4, oif, mark, tos,
+ flowi4_init_output(fl4, vrf, oif, mark, tos,
RT_SCOPE_UNIVERSE, prot,
flow_flags,
iph->daddr, iph->saddr, 0, 0);
@@ -529,7 +530,7 @@ static void build_skb_flow_key(struct flowi4 *fl4, const struct sk_buff *skb,
u8 prot = iph->protocol;
u32 mark = skb->mark;
- __build_flow_key(fl4, sk, iph, oif, tos, prot, mark, 0);
+ __build_flow_key(fl4, sk, iph, skb->vrf, oif, tos, prot, mark, 0);
}
static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk)
@@ -542,7 +543,7 @@ static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk)
inet_opt = rcu_dereference(inet->inet_opt);
if (inet_opt && inet_opt->opt.srr)
daddr = inet_opt->opt.faddr;
- flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark,
+ flowi4_init_output(fl4, sk->sk_vrf, sk->sk_bound_dev_if, sk->sk_mark,
RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,
inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
inet_sk_flowi_flags(sk),
@@ -794,7 +795,7 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buf
rt = (struct rtable *) dst;
- __build_flow_key(&fl4, sk, iph, oif, tos, prot, mark, 0);
+ __build_flow_key(&fl4, sk, iph, skb->vrf, oif, tos, prot, mark, 0);
__ip_do_redirect(rt, skb, &fl4, true);
}
@@ -1006,7 +1007,7 @@ void ipv4_update_pmtu(struct sk_buff *skb, struct net_ctx *ctx, u32 mtu,
if (!mark)
mark = IP4_REPLY_MARK(ctx->net, skb->mark);
- __build_flow_key(&fl4, NULL, iph, oif,
+ __build_flow_key(&fl4, NULL, iph, skb->vrf, oif,
RT_TOS(iph->tos), protocol, mark, flow_flags);
rt = __ip_route_output_key(ctx, &fl4);
if (!IS_ERR(rt)) {
@@ -1023,7 +1024,7 @@ static void __ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
struct rtable *rt;
struct net_ctx sk_ctx = SOCK_NET_CTX(sk);
- __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
+ __build_flow_key(&fl4, sk, iph, skb->vrf, 0, 0, 0, 0, 0);
if (!fl4.flowi4_mark)
fl4.flowi4_mark = IP4_REPLY_MARK(sk_ctx.net, skb->mark);
@@ -1056,7 +1057,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
goto out;
}
- __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
+ __build_flow_key(&fl4, sk, iph, skb->vrf, 0, 0, 0, 0, 0);
rt = (struct rtable *)odst;
if (odst->obsolete && odst->ops->check(odst, 0) == NULL) {
@@ -1096,7 +1097,7 @@ void ipv4_redirect(struct sk_buff *skb, struct net_ctx *ctx,
struct flowi4 fl4;
struct rtable *rt;
- __build_flow_key(&fl4, NULL, iph, oif,
+ __build_flow_key(&fl4, NULL, iph, skb->vrf, oif,
RT_TOS(iph->tos), protocol, mark, flow_flags);
rt = __ip_route_output_key(ctx, &fl4);
if (!IS_ERR(rt)) {
@@ -1113,7 +1114,7 @@ void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk)
struct rtable *rt;
struct net_ctx sk_ctx = SOCK_NET_CTX(sk);
- __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
+ __build_flow_key(&fl4, sk, iph, skb->vrf, 0, 0, 0, 0, 0);
rt = __ip_route_output_key(&sk_ctx, &fl4);
if (!IS_ERR(rt)) {
__ip_do_redirect(rt, skb, &fl4, false);
@@ -1190,6 +1191,7 @@ void ip_rt_get_source(u8 *addr, struct sk_buff *skb, struct rtable *rt)
fl4.flowi4_oif = rt->dst.dev->ifindex;
fl4.flowi4_iif = skb->dev->ifindex;
fl4.flowi4_mark = skb->mark;
+ fl4.flowi4_vrf = skb->vrf;
rcu_read_lock();
if (fib_lookup(&dev_ctx, &fl4, &res) == 0)
@@ -1724,6 +1726,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
fl4.flowi4_iif = dev->ifindex;
fl4.flowi4_mark = skb->mark;
fl4.flowi4_tos = tos;
+ fl4.flowi4_vrf = skb->vrf;
fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
fl4.daddr = daddr;
fl4.saddr = saddr;
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 7702e1f94174..916994d21f17 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -368,7 +368,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
* hasn't changed since we received the original syn, but I see
* no easy way to do this.
*/
- flowi4_init_output(&fl4, sk->sk_bound_dev_if, ireq->ir_mark,
+ flowi4_init_output(&fl4, skb->vrf, sk->sk_bound_dev_if, ireq->ir_mark,
RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, IPPROTO_TCP,
inet_sk_flowi_flags(sk),
opt->srr ? opt->faddr : ireq->ir_rmt_addr,
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 1787dc8e5db3..1446c84428d8 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1023,7 +1023,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
struct net *net = sk_ctx.net;
fl4 = &fl4_stack;
- flowi4_init_output(fl4, ipc.oif, sk->sk_mark, tos,
+ flowi4_init_output(fl4, sk_ctx.vrf, ipc.oif, sk->sk_mark, tos,
RT_SCOPE_UNIVERSE, sk->sk_protocol,
inet_sk_flowi_flags(sk),
faddr, saddr, dport, inet->inet_sport);
@@ -1083,6 +1083,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
fl4->saddr = saddr;
fl4->fl4_dport = dport;
fl4->fl4_sport = inet->inet_sport;
+ fl4->flowi4_vrf = sk_ctx.vrf;
up->pending = AF_INET;
do_append_data:
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index c892b6bb0383..660059d09872 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -28,6 +28,7 @@ static struct dst_entry *__xfrm4_dst_lookup(struct net_ctx *ctx, struct flowi4 *
memset(fl4, 0, sizeof(*fl4));
fl4->daddr = daddr->a4;
fl4->flowi4_tos = tos;
+ fl4->flowi4_vrf = ctx->vrf;
if (saddr)
fl4->saddr = saddr->a4;
@@ -112,6 +113,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
memset(fl4, 0, sizeof(struct flowi4));
fl4->flowi4_mark = skb->mark;
fl4->flowi4_oif = reverse ? skb->skb_iif : oif;
+ fl4->flowi4_vrf = skb->vrf;
if (!ip_is_fragment(iph)) {
switch (iph->protocol) {
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index d59affad3f01..11c1a58296d8 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -435,6 +435,7 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
fl4->daddr = daddr->v4.sin_addr.s_addr;
fl4->fl4_dport = daddr->v4.sin_port;
fl4->flowi4_proto = IPPROTO_SCTP;
+ fl4->flowi4_vrf = sk_ctx.vrf;
if (asoc) {
fl4->flowi4_tos = RT_CONN_FLAGS(asoc->base.sk);
fl4->flowi4_oif = asoc->base.sk->sk_bound_dev_if;
--
1.9.3 (Apple Git-50)
^ permalink raw reply related
* [RFC PATCH 18/29] net: vrf: Plumbing for vrf context on a socket
From: David Ahern @ 2015-02-05 1:34 UTC (permalink / raw)
To: netdev; +Cc: ebiederm, David Ahern
In-Reply-To: <1423100070-31848-1-git-send-email-dsahern@gmail.com>
Sockets inherit the vrf context of the task opening it. The context can
be read/changed via a socket option (IP_VRF_CONTEXT).
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/uapi/linux/in.h | 1 +
net/core/sock.c | 2 ++
net/ipv4/inet_connection_sock.c | 5 +++--
net/ipv4/inet_hashtables.c | 1 +
net/ipv4/inet_timewait_sock.c | 1 +
net/ipv4/ip_output.c | 1 +
net/ipv4/ip_sockglue.c | 14 ++++++++++++++
net/ipv4/tcp_minisocks.c | 1 +
8 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/include/uapi/linux/in.h b/include/uapi/linux/in.h
index 589ced069e8a..77ac6fce6493 100644
--- a/include/uapi/linux/in.h
+++ b/include/uapi/linux/in.h
@@ -145,6 +145,7 @@ struct in_addr {
#define MCAST_MSFILTER 48
#define IP_MULTICAST_ALL 49
#define IP_UNICAST_IF 50
+#define IP_VRF_CONTEXT 51
#define MCAST_EXCLUDE 0
#define MCAST_INCLUDE 1
diff --git a/net/core/sock.c b/net/core/sock.c
index 93c8b20c91e4..8a4ef8540e50 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1392,6 +1392,8 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
sk->sk_prot = sk->sk_prot_creator = prot;
sock_lock_init(sk);
sock_net_set(sk, get_net(net));
+ /* by default socket takes on vrf of task */
+ sk->sk_vrf = current->vrf;
atomic_set(&sk->sk_wmem_alloc, 1);
sock_update_classid(sk);
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index b3580594d08a..3b8df03c69db 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -404,7 +404,7 @@ struct dst_entry *inet_csk_route_req(struct sock *sk,
const struct inet_request_sock *ireq = inet_rsk(req);
struct ip_options_rcu *opt = inet_rsk(req)->opt;
struct net *net = sock_net(sk);
- struct net_ctx ctx = { .net = net };
+ struct net_ctx ctx = { .net = net, .vrf = ireq->ir_vrf };
int flags = inet_sk_flowi_flags(sk);
flowi4_init_output(fl4, sk->sk_bound_dev_if, ireq->ir_mark,
@@ -437,7 +437,7 @@ struct dst_entry *inet_csk_route_child_sock(struct sock *sk,
struct inet_sock *newinet = inet_sk(newsk);
struct ip_options_rcu *opt;
struct net *net = sock_net(sk);
- struct net_ctx ctx = { .net = net };
+ struct net_ctx ctx = { .net = net, .vrf = ireq->ir_vrf };
struct flowi4 *fl4;
struct rtable *rt;
@@ -681,6 +681,7 @@ struct sock *inet_csk_clone_lock(const struct sock *sk,
newsk->sk_write_space = sk_stream_write_space;
newsk->sk_mark = inet_rsk(req)->ir_mark;
+ newsk->sk_vrf = inet_rsk(req)->ir_vrf;
newicsk->icsk_retransmits = 0;
newicsk->icsk_backoff = 0;
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 8b3d94ca634c..71c31c81aea1 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -62,6 +62,7 @@ struct inet_bind_bucket *inet_bind_bucket_create(struct kmem_cache *cachep,
if (tb != NULL) {
write_pnet(&tb->ib_net_ctx.net, hold_net(ctx->net));
+ tb->ib_net_ctx.vrf = ctx->vrf;
tb->port = snum;
tb->fastreuse = 0;
tb->fastreuseport = 0;
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
index 6d592f8555fb..faec08993a46 100644
--- a/net/ipv4/inet_timewait_sock.c
+++ b/net/ipv4/inet_timewait_sock.c
@@ -196,6 +196,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat
tw->tw_transparent = inet->transparent;
tw->tw_prot = sk->sk_prot_creator;
twsk_net_set(tw, hold_net(sock_net(sk)));
+ tw->tw_vrf = sk->sk_vrf;
/*
* Because we use RCU lookups, we should not set tw_refcnt
* to a non null value before everything is setup for this
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 855e003e43d8..126d6edea34e 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1574,6 +1574,7 @@ void ip_send_unicast_reply(struct net_ctx *ctx, struct sk_buff *skb,
sk->sk_protocol = ip_hdr(skb)->protocol;
sk->sk_bound_dev_if = arg->bound_dev_if;
sock_net_set(sk, ctx->net);
+ sk->sk_vrf = ctx->vrf;
__skb_queue_head_init(&sk->sk_write_queue);
sk->sk_sndbuf = sysctl_wmem_default;
err = ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base,
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 8ab03f0431f5..eeb51e935379 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -555,6 +555,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
case IP_MULTICAST_LOOP:
case IP_RECVORIGDSTADDR:
case IP_CHECKSUM:
+ case IP_VRF_CONTEXT:
if (optlen >= sizeof(int)) {
if (get_user(val, (int __user *) optval))
return -EFAULT;
@@ -1104,6 +1105,16 @@ static int do_ip_setsockopt(struct sock *sk, int level,
inet->min_ttl = val;
break;
+ case IP_VRF_CONTEXT:
+ /* VRF context can only be set on unconnected sockets */
+ if (inet->inet_sport || inet->inet_dport) {
+ err = -EINVAL;
+ break;
+ }
+ sk->sk_vrf = val;
+ err = 0;
+ break;
+
default:
err = -ENOPROTOOPT;
break;
@@ -1411,6 +1422,9 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
case IP_MINTTL:
val = inet->min_ttl;
break;
+ case IP_VRF_CONTEXT:
+ val = sk->sk_vrf;
+ break;
default:
release_sock(sk);
return -ENOPROTOOPT;
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index bc9216dc9de1..f5b869799b14 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -283,6 +283,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
tw->tw_transparent = inet->transparent;
tw->tw_rcv_wscale = tp->rx_opt.rcv_wscale;
+ tw->tw_vrf = sk->sk_vrf;
tcptw->tw_rcv_nxt = tp->rcv_nxt;
tcptw->tw_snd_nxt = tp->snd_nxt;
tcptw->tw_rcv_wnd = tcp_receive_window(tp);
--
1.9.3 (Apple Git-50)
^ permalink raw reply related
* [RFC PATCH 19/29] net: vrf: Add vrf context to skb
From: David Ahern @ 2015-02-05 1:34 UTC (permalink / raw)
To: netdev; +Cc: ebiederm, David Ahern
In-Reply-To: <1423100070-31848-1-git-send-email-dsahern@gmail.com>
On ingress skb's inherit vrf context from the net_device. For TX skb's
inherit the vrf context from the socket originating the packet. Update
SKB related net_ctx macros to set vrf.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/linux/skbuff.h | 7 ++++---
include/net/sock.h | 2 ++
include/net/tcp.h | 1 +
net/core/dev.c | 1 +
net/core/fib_rules.c | 2 ++
net/core/neighbour.c | 2 ++
net/core/skbuff.c | 12 ++++++++++++
net/ipv4/devinet.c | 2 ++
net/ipv4/icmp.c | 2 +-
net/ipv4/ip_output.c | 2 ++
net/ipv4/syncookies.c | 1 +
net/ipv4/tcp_ipv4.c | 3 ++-
net/netlink/af_netlink.c | 12 ++++++++++++
13 files changed, 44 insertions(+), 5 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index a5dfef469d07..bdbee41e8032 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -522,6 +522,7 @@ struct sk_buff {
};
struct sock *sk;
struct net_device *dev;
+ __u32 vrf;
/*
* This is the control buffer. It is free to use for every
@@ -665,9 +666,9 @@ struct sk_buff {
atomic_t users;
};
-#define SKB_NET_CTX_DEV(skb) { .net = dev_net((skb)->dev) }
-#define SKB_NET_CTX_DST(skb) { .net = dev_net(skb_dst((skb))->dev) }
-#define SKB_NET_CTX_SOCK(skb) { .net = sock_net((skb)->sk) }
+#define SKB_NET_CTX_DEV(skb) { .net = dev_net((skb)->dev), .vrf = (skb)->vrf }
+#define SKB_NET_CTX_DST(skb) { .net = dev_net(skb_dst((skb))->dev), .vrf = (skb)->vrf }
+#define SKB_NET_CTX_SOCK(skb) { .net = sock_net((skb)->sk), .vrf = (skb)->vrf }
#ifdef __KERNEL__
/*
diff --git a/include/net/sock.h b/include/net/sock.h
index a7cd250e9daf..d3668b691f82 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1976,6 +1976,7 @@ static inline void skb_set_owner_w(struct sk_buff *skb, struct sock *sk)
skb_orphan(skb);
skb->sk = sk;
skb->destructor = sock_wfree;
+ skb->vrf = sk->sk_vrf;
skb_set_hash_from_sk(skb, sk);
/*
* We used to take a refcount on sk, but following operation
@@ -1990,6 +1991,7 @@ static inline void skb_set_owner_r(struct sk_buff *skb, struct sock *sk)
skb_orphan(skb);
skb->sk = sk;
skb->destructor = sock_rfree;
+ skb->vrf = sk->sk_vrf;
atomic_add(skb->truesize, &sk->sk_rmem_alloc);
sk_mem_charge(sk, skb->truesize);
}
diff --git a/include/net/tcp.h b/include/net/tcp.h
index b8fdc6bab3f3..ed46170de42a 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1155,6 +1155,7 @@ static inline void tcp_openreq_init(struct request_sock *req,
ireq->ir_rmt_port = tcp_hdr(skb)->source;
ireq->ir_num = ntohs(tcp_hdr(skb)->dest);
ireq->ir_mark = inet_request_mark(sk, skb);
+ ireq->ir_vrf = skb->vrf;
}
extern void tcp_openreq_init_rwin(struct request_sock *req,
diff --git a/net/core/dev.c b/net/core/dev.c
index 0d50b2c1944e..d64f5b107dba 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3698,6 +3698,7 @@ static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc)
another_round:
skb->skb_iif = skb->dev->ifindex;
+ skb->vrf = skb->dev->nd_vrf;
__this_cpu_inc(softnet_data.processed);
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index b793196f9521..9a1a4a23b6f6 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -690,6 +690,8 @@ static void notify_rule_change(int event, struct fib_rule *rule,
if (skb == NULL)
goto errout;
+ skb->vrf = ops->fro_vrf;
+
err = fib_nl_fill_rule(skb, rule, pid, nlh->nlmsg_seq, event, 0, ops);
if (err < 0) {
/* -EMSGSIZE implies BUG in fib_rule_nlmsg_size() */
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index f64e178738de..0fbbe70be170 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2780,6 +2780,8 @@ static void __neigh_notify(struct neighbour *n, int type, int flags)
if (skb == NULL)
goto errout;
+ skb->vrf = n->dev->nd_vrf;
+
err = neigh_fill_info(skb, n, 0, 0, type, flags);
if (err < 0) {
/* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index a5bff2767f15..61a75e891342 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -251,6 +251,7 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
skb->end = skb->tail + size;
skb->mac_header = (typeof(skb->mac_header))~0U;
skb->transport_header = (typeof(skb->transport_header))~0U;
+ skb->vrf = VRF_DEFAULT;
/* make sure we initialize shinfo sequentially */
shinfo = skb_shinfo(skb);
@@ -514,6 +515,7 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
if (likely(skb)) {
skb_reserve(skb, NET_SKB_PAD);
skb->dev = dev;
+ skb->vrf = dev->nd_vrf;
}
return skb;
@@ -832,6 +834,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
#endif
#endif
+ new->vrf = old->vrf;
}
/*
@@ -864,6 +867,8 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
atomic_inc(&(skb_shinfo(skb)->dataref));
skb->cloned = 1;
+ n->vrf = skb->vrf;
+
return n;
#undef C
}
@@ -1057,6 +1062,9 @@ struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask)
BUG();
copy_skb_header(n, skb);
+
+ n->vrf = skb->vrf;
+
return n;
}
EXPORT_SYMBOL(skb_copy);
@@ -1120,6 +1128,8 @@ struct sk_buff *__pskb_copy_fclone(struct sk_buff *skb, int headroom,
}
copy_skb_header(n, skb);
+
+ n->vrf = skb->vrf;
out:
return n;
}
@@ -1294,6 +1304,8 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
skb_headers_offset_update(n, newheadroom - oldheadroom);
+ n->vrf = skb->vrf;
+
return n;
}
EXPORT_SYMBOL(skb_copy_expand);
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index a0182f79f6bf..59de98a44508 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1603,6 +1603,8 @@ static void rtmsg_ifa(int event, struct in_ifaddr *ifa, struct nlmsghdr *nlh,
if (skb == NULL)
goto errout;
+ skb->vrf = ifa->ifa_dev->dev->nd_vrf;
+
err = inet_fill_ifaddr(skb, ifa, portid, seq, event, 0);
if (err < 0) {
/* -EMSGSIZE implies BUG in inet_nlmsg_size() */
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index f64de76f55ef..2d1e98e6ad14 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -389,7 +389,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
struct ipcm_cookie ipc;
struct rtable *rt = skb_rtable(skb);
struct net *net = dev_net(rt->dst.dev);
- struct net_ctx dev_ctx = { .net = net };
+ struct net_ctx dev_ctx = { .net = net, .vrf = skb->vrf };
struct flowi4 fl4;
struct sock *sk;
struct inet_sock *inet;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 126d6edea34e..383bac145bf4 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -471,6 +471,8 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
to->ipvs_property = from->ipvs_property;
#endif
skb_copy_secmark(to, from);
+
+ to->vrf = from->vrf;
}
/*
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 14b7a772c7a9..7702e1f94174 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -340,6 +340,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
ireq->ir_loc_addr = ip_hdr(skb)->daddr;
ireq->ir_rmt_addr = ip_hdr(skb)->saddr;
ireq->ir_mark = inet_request_mark(sk, skb);
+ ireq->ir_vrf = skb->vrf;
ireq->snd_wscale = tcp_opt.snd_wscale;
ireq->sack_ok = tcp_opt.sack_ok;
ireq->wscale_ok = tcp_opt.wscale_ok;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index ceb5616a4273..24089b9534bf 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1368,6 +1368,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
sk_nocaps_add(newsk, NETIF_F_GSO_MASK);
}
#endif
+ newsk->sk_vrf = skb->vrf;
if (__inet_inherit_port(sk, newsk) < 0)
goto put_and_exit;
@@ -1395,7 +1396,7 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
const struct iphdr *iph = ip_hdr(skb);
struct sock *nsk;
struct request_sock **prev;
- struct net_ctx ctx = { .net = sock_net(sk) };
+ struct net_ctx ctx = { .net = sock_net(sk), .vrf = skb->vrf };
/* Find possible connection requests. */
struct request_sock *req = inet_csk_search_req(sk, &prev, th->source,
iph->saddr, iph->daddr);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index a36777b7cfb6..bd613406e033 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1736,6 +1736,14 @@ static struct sk_buff *netlink_trim(struct sk_buff *skb, gfp_t allocation)
return skb;
}
+/*
+ * kernel sockets are all in vrf 1 (default vrf). Transactions
+ * (e.g., add/delete address/route) are happening in other vrfs.
+ * Packets for transactions from userpsace are funneled through the
+ * kernel sockets. Handle this case by resetting skb vrf after ownership
+ * assignment. rtnetlink based functions need to use skb->vrf for
+ * decisions which is set to the original userspace socket's vrf id.
+ */
static int netlink_unicast_kernel(struct sock *sk, struct sk_buff *skb,
struct sock *ssk)
{
@@ -1744,8 +1752,11 @@ static int netlink_unicast_kernel(struct sock *sk, struct sk_buff *skb,
ret = -ECONNREFUSED;
if (nlk->netlink_rcv != NULL) {
+ __u32 vrf = skb->vrf;
ret = skb->len;
netlink_skb_set_owner_r(skb, sk);
+ /* use vrf from sending socket, not kernel's socket context */
+ skb->vrf = vrf;
NETLINK_CB(skb).sk = ssk;
netlink_deliver_tap_kernel(sk, ssk, skb);
nlk->netlink_rcv(skb);
@@ -2313,6 +2324,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
if (skb == NULL)
goto out;
+ skb->vrf = sk->sk_vrf;
NETLINK_CB(skb).portid = nlk->portid;
NETLINK_CB(skb).dst_group = dst_group;
NETLINK_CB(skb).creds = scm.creds;
--
1.9.3 (Apple Git-50)
^ permalink raw reply related
* [RFC PATCH 17/29] net: vrf: Add vrf context to task struct
From: David Ahern @ 2015-02-05 1:34 UTC (permalink / raw)
To: netdev; +Cc: ebiederm, David Ahern
In-Reply-To: <1423100070-31848-1-git-send-email-dsahern@gmail.com>
vrf context is passed parent to child. Defaults to 1 and can be read
and changed via /proc/<pid>/vrf. In time the /proc write option can be
removed in favor of a prctl; writing to a proc file is a lot simpler
at this point.
A tasks' vrf context is the default used for sockets created by the
task. This is addressed in the next patch.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
fs/proc/base.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++
include/linux/init_task.h | 1 +
include/linux/sched.h | 2 +
kernel/fork.c | 2 +
4 files changed, 99 insertions(+)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 3f3d7aeb0712..9e538075f7e5 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -90,6 +90,7 @@
#ifdef CONFIG_HARDWALL
#include <asm/hardwall.h>
#endif
+#include <net/vrf.h>
#include <trace/events/oom.h>
#include "internal.h"
#include "fd.h"
@@ -456,6 +457,97 @@ static int proc_pid_limits(struct seq_file *m, struct pid_namespace *ns,
return 0;
}
+static ssize_t vrf_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
+ char buffer[16];
+ size_t len;
+ __u32 vrf = 0;
+ unsigned long flags;
+
+ if (!task)
+ return -ESRCH;
+
+ if (lock_task_sighand(task, &flags)) {
+ vrf = task->vrf;
+ unlock_task_sighand(task, &flags);
+ }
+
+ put_task_struct(task);
+
+ if (vrf == VRF_ANY)
+ len = snprintf(buffer, sizeof(buffer), "any\n");
+ else
+ len = snprintf(buffer, sizeof(buffer), "%i\n", vrf);
+
+ return simple_read_from_buffer(buf, count, ppos, buffer, len);
+}
+
+static ssize_t vrf_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct task_struct *task;
+ char buffer[16], *pbuf;
+ __u32 vrf;
+ unsigned long flags;
+ int err;
+
+ memset(buffer, 0, sizeof(buffer));
+ if (count > sizeof(buffer) - 1)
+ count = sizeof(buffer) - 1;
+ if (copy_from_user(buffer, buf, count)) {
+ err = -EFAULT;
+ goto out;
+ }
+
+ pbuf = strstrip(buffer);
+ if (strcmp(pbuf, "any") == 0)
+ vrf = VRF_ANY;
+ else {
+ err = kstrtouint(strstrip(buffer), 0, &vrf);
+ if (err)
+ goto out;
+
+ if (!vrf_is_valid(vrf)) {
+ err = -EINVAL;
+ goto out;
+ }
+ }
+
+ task = get_proc_task(file_inode(file));
+ if (!task) {
+ err = -ESRCH;
+ goto out;
+ }
+
+ task_lock(task);
+ if (!task->mm) {
+ err = -EINVAL;
+ goto err_task_lock;
+ }
+
+ if (!lock_task_sighand(task, &flags)) {
+ err = -ESRCH;
+ goto err_task_lock;
+ }
+
+ task->vrf = vrf;
+
+ unlock_task_sighand(task, &flags);
+err_task_lock:
+ task_unlock(task);
+ put_task_struct(task);
+out:
+ return err < 0 ? err : count;
+}
+
+static const struct file_operations proc_vrf_operations = {
+ .read = vrf_read,
+ .write = vrf_write,
+ .llseek = generic_file_llseek,
+};
+
#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
static int proc_pid_syscall(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task)
@@ -2628,6 +2720,7 @@ static const struct pid_entry tgid_base_stuff[] = {
#ifdef CONFIG_CHECKPOINT_RESTORE
REG("timers", S_IRUGO, proc_timers_operations),
#endif
+ REG("vrf", S_IRUGO|S_IWUSR, proc_vrf_operations),
};
static int proc_tgid_base_readdir(struct file *file, struct dir_context *ctx)
@@ -2970,6 +3063,7 @@ static const struct pid_entry tid_base_stuff[] = {
REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations),
REG("setgroups", S_IRUGO|S_IWUSR, proc_setgroups_operations),
#endif
+ REG("vrf", S_IRUGO|S_IWUSR, proc_vrf_operations),
};
static int proc_tid_base_readdir(struct file *file, struct dir_context *ctx)
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 3037fc085e8e..3ae3a93d42ce 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -247,6 +247,7 @@ extern struct task_group root_task_group;
INIT_RT_MUTEXES(tsk) \
INIT_VTIME(tsk) \
INIT_NUMA_BALANCING(tsk) \
+ .vrf = VRF_DEFAULT, \
}
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 8db31ef98d2f..8b40ba202906 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1459,6 +1459,8 @@ struct task_struct {
struct files_struct *files;
/* namespaces */
struct nsproxy *nsproxy;
+/* vrf context within a namespace */
+ __u32 vrf;
/* signal handlers */
struct signal_struct *signal;
struct sighand_struct *sighand;
diff --git a/kernel/fork.c b/kernel/fork.c
index 4dc2ddade9f1..a6f412da1378 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -352,6 +352,8 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
tsk->splice_pipe = NULL;
tsk->task_frag.page = NULL;
+ tsk->vrf = orig->vrf;
+
account_kernel_stack(ti, 1);
return tsk;
--
1.9.3 (Apple Git-50)
^ permalink raw reply related
* [RFC PATCH 16/29] net: vrf: Set default vrf
From: David Ahern @ 2015-02-05 1:34 UTC (permalink / raw)
To: netdev; +Cc: ebiederm, David Ahern
In-Reply-To: <1423100070-31848-1-git-send-email-dsahern@gmail.com>
Set default vrf to DEFAULT_VRF for devices, neighbor table, and a few
other places.
If a device is moved from one namespace to another reset the vrf id to
DEFAULT_VRF.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
net/core/dev.c | 4 ++++
net/core/neighbour.c | 1 +
net/ipv4/fib_rules.c | 2 +-
net/ipv4/ipconfig.c | 4 ++--
net/ipv4/ipmr.c | 2 +-
5 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index fa92d1046eeb..0d50b2c1944e 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -6817,6 +6817,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
dev_uc_init(dev);
dev_net_set(dev, &init_net);
+ dev->nd_vrf = VRF_DEFAULT;
dev->gso_max_size = GSO_MAX_SIZE;
dev->gso_max_segs = GSO_MAX_SEGS;
@@ -7079,6 +7080,9 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
/* Actually switch the network namespace */
dev_net_set(dev, net);
+ /* reset vrf id since we changed namespaces */
+ dev->nd_vrf = VRF_DEFAULT;
+
/* If there is an ifindex conflict assign a new one */
if (__dev_get_by_index(net, dev->ifindex)) {
int iflink = (dev->iflink == dev->ifindex);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index d872ada6720a..f64e178738de 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1526,6 +1526,7 @@ void neigh_table_init(int index, struct neigh_table *tbl)
INIT_LIST_HEAD(&tbl->parms_list);
list_add(&tbl->parms.list, &tbl->parms_list);
write_pnet(&tbl->parms.net_ctx.net, &init_net);
+ tbl->parms.net_ctx.vrf = VRF_DEFAULT;
atomic_set(&tbl->parms.refcnt, 1);
tbl->parms.reachable_time =
neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 60b14866661b..bb9399e2c1cb 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -331,7 +331,7 @@ int __net_init fib4_rules_init(struct net *net)
{
int err;
struct fib_rules_ops *ops;
- struct net_ctx ctx = { .net = net };
+ struct net_ctx ctx = { .net = net, .vrf = VRF_DEFAULT };
ops = fib_rules_register(&fib4_rules_ops_template, &ctx);
if (IS_ERR(ops))
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index e25e3b67be76..b0a5226faaef 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -329,7 +329,7 @@ set_sockaddr(struct sockaddr_in *sin, __be32 addr, __be16 port)
static int __init ic_devinet_ioctl(unsigned int cmd, struct ifreq *arg)
{
- struct net_ctx ctx = { .net = &init_net };
+ struct net_ctx ctx = INIT_NET_CTX;
int res;
mm_segment_t oldfs = get_fs();
@@ -352,7 +352,7 @@ static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg)
static int __init ic_route_ioctl(unsigned int cmd, struct rtentry *arg)
{
- struct net_ctx ctx = { .net = &init_net };
+ struct net_ctx ctx = INIT_NET_CTX;
int res;
mm_segment_t oldfs = get_fs();
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 935f45f54862..84d6efeeb072 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -244,7 +244,7 @@ static const struct fib_rules_ops __net_initconst ipmr_rules_ops_template = {
static int __net_init ipmr_rules_init(struct net *net)
{
- struct net_ctx ctx = { .net = net };
+ struct net_ctx ctx = { .net = net, .vrf = VRF_DEFAULT };
struct fib_rules_ops *ops;
struct mr_table *mrt;
int err;
--
1.9.3 (Apple Git-50)
^ permalink raw reply related
* [RFC PATCH 15/29] net: vrf: Add vrf to net_ctx struct
From: David Ahern @ 2015-02-05 1:34 UTC (permalink / raw)
To: netdev; +Cc: ebiederm, David Ahern
In-Reply-To: <1423100070-31848-1-git-send-email-dsahern@gmail.com>
Add vrf macros for accessing vrf in net_ctx references similar to what
exists for net, update helper functions and macros to set vrf context,
and handle initialization of vrf context for all existing net_ctx uses.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/linux/netdevice.h | 9 ++++++++-
include/net/fib_rules.h | 2 ++
include/net/inet_sock.h | 1 +
include/net/inet_timewait_sock.h | 1 +
include/net/ip_fib.h | 1 +
include/net/ipv6.h | 1 +
include/net/neighbour.h | 9 +++++++++
include/net/net_namespace.h | 4 +++-
include/net/netlink.h | 1 +
include/net/sock.h | 4 +++-
net/core/neighbour.c | 2 +-
11 files changed, 31 insertions(+), 4 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 43bb40260bfa..b6de06eda683 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1699,6 +1699,7 @@ struct net_device {
struct net_ctx net_ctx;
#define nd_net net_ctx.net
+#define nd_vrf net_ctx.vrf
/* mid-layer private */
union {
@@ -1845,7 +1846,13 @@ void dev_net_set(struct net_device *dev, struct net *net)
}
/* get net_ctx from device */
-#define DEV_NET_CTX(dev) { .net = dev_net((dev)) }
+#define DEV_NET_CTX(dev) { .net = dev_net((dev)), .vrf = (dev)->nd_vrf }
+
+static inline
+__u32 dev_vrf(const struct net_device *dev)
+{
+ return dev->nd_vrf;
+}
static inline
int dev_net_ctx_eq(const struct net_device *dev, struct net_ctx *ctx)
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index 1a545b23494e..0af67c3122f3 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -22,6 +22,7 @@ struct fib_rule {
struct fib_rule __rcu *ctarget;
struct net_ctx fr_net_ctx;
#define fr_net fr_net_ctx.net
+#define fr_vrf fr_net_ctx.vrf
atomic_t refcnt;
u32 pref;
@@ -78,6 +79,7 @@ struct fib_rules_ops {
struct module *owner;
struct net_ctx fro_net_ctx;
#define fro_net fro_net_ctx.net
+#define fro_vrf fro_net_ctx.vrf
struct rcu_head rcu;
};
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index eb16c7beed1e..de59174d3124 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -77,6 +77,7 @@ struct inet_request_sock {
#define ir_v6_rmt_addr req.__req_common.skc_v6_daddr
#define ir_v6_loc_addr req.__req_common.skc_v6_rcv_saddr
#define ir_iif req.__req_common.skc_bound_dev_if
+#define ir_vrf req.__req_common.skc_net_ctx.vrf
kmemcheck_bitfield_begin(flags);
u16 snd_wscale : 4,
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index 6c566034e26d..c9f3bf6f8b24 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -116,6 +116,7 @@ struct inet_timewait_sock {
#define tw_hash __tw_common.skc_hash
#define tw_prot __tw_common.skc_prot
#define tw_net __tw_common.skc_net
+#define tw_vrf __tw_common.skc_vrf
#define tw_daddr __tw_common.skc_daddr
#define tw_v6_daddr __tw_common.skc_v6_daddr
#define tw_rcv_saddr __tw_common.skc_rcv_saddr
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 85f5ddacba8d..577479d7f268 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -100,6 +100,7 @@ struct fib_info {
struct hlist_node fib_lhash;
struct net_ctx fib_net_ctx;
#define fib_net fib_net_ctx.net
+#define fib_vrf fib_net_ctx.vrf
int fib_treeref;
atomic_t fib_clntref;
unsigned int fib_flags;
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 2d025ed7a183..61f8b6df8bb9 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -240,6 +240,7 @@ struct ip6_flowlabel {
unsigned long expires;
struct net_ctx fl_net_ctx;
#define fl_net fl_net_ctx.net
+#define fl_vrf fl_net_ctx.vrf
};
static inline
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 8cf9bc2236da..73d0938b085c 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -281,6 +281,15 @@ struct net *neigh_parms_net(const struct neigh_parms *parms)
}
static inline
+__u32 neigh_parms_vrf(const struct neigh_parms *parms)
+{
+ return parms->net_ctx.vrf;
+}
+
+#define NEIGH_PARMS_NET_CTX(p) \
+ { .net = neigh_parms_net((p)), .vrf = neigh_parms_vrf((p)) }
+
+static inline
int neigh_parms_net_ctx_eq(const struct neigh_parms *parms,
const struct net_ctx *net_ctx)
{
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index e7060b43570d..7cc7b0a1a20b 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -27,6 +27,7 @@
#include <net/netns/nftables.h>
#include <net/netns/xfrm.h>
#include <linux/ns_common.h>
+#include <net/vrf.h>
struct user_namespace;
struct proc_dir_entry;
@@ -138,6 +139,7 @@ struct net_ctx {
#ifdef CONFIG_NET_NS
struct net *net;
#endif
+ __u32 vrf;
};
#include <linux/seq_file_net.h>
@@ -145,7 +147,7 @@ struct net_ctx {
/* Init's network namespace */
extern struct net init_net;
-#define INIT_NET_CTX { .net = &init_net }
+#define INIT_NET_CTX { .net = &init_net, .vrf = VRF_DEFAULT }
#ifdef CONFIG_NET_NS
struct net *copy_net_ns(unsigned long flags, struct user_namespace *user_ns,
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 587a6ef973e5..82c4a2628106 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -224,6 +224,7 @@ struct nl_info {
struct nlmsghdr *nlh;
struct net_ctx nl_net_ctx;
#define nl_net nl_net_ctx.net
+#define nl_vrf nl_net_ctx.vrf
u32 portid;
};
diff --git a/include/net/sock.h b/include/net/sock.h
index e67347ed1555..a7cd250e9daf 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -192,6 +192,7 @@ struct sock_common {
struct proto *skc_prot;
struct net_ctx skc_net_ctx;
#define skc_net skc_net_ctx.net
+#define skc_vrf skc_net_ctx.vrf
#if IS_ENABLED(CONFIG_IPV6)
struct in6_addr skc_v6_daddr;
@@ -326,6 +327,7 @@ struct sock {
#define sk_bind_node __sk_common.skc_bind_node
#define sk_prot __sk_common.skc_prot
#define sk_net __sk_common.skc_net_ctx.net
+#define sk_vrf __sk_common.skc_net_ctx.vrf
#define sk_v6_daddr __sk_common.skc_v6_daddr
#define sk_v6_rcv_saddr __sk_common.skc_v6_rcv_saddr
@@ -2196,7 +2198,7 @@ void sock_net_set(struct sock *sk, struct net *net)
write_pnet(&sk->sk_net, net);
}
-#define SOCK_NET_CTX(sk) { .net = sock_net((sk)) }
+#define SOCK_NET_CTX(sk) { .net = sock_net((sk)), .vrf = (sk)->sk_vrf }
static inline
int sock_net_ctx_eq(struct sock *sk, struct net_ctx *ctx)
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 93a7701a7ae7..d872ada6720a 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2855,7 +2855,7 @@ static void neigh_proc_update(struct ctl_table *ctl, int write)
{
struct net_device *dev = ctl->extra1;
struct neigh_parms *p = ctl->extra2;
- struct net_ctx ctx = { .net = neigh_parms_net(p) };
+ struct net_ctx ctx = NEIGH_PARMS_NET_CTX(p);
int index = (int *) ctl->data - p->data;
if (!write)
--
1.9.3 (Apple Git-50)
^ permalink raw reply related
* [RFC PATCH 14/29] net: vrf: Introduce vrf header file
From: David Ahern @ 2015-02-05 1:34 UTC (permalink / raw)
To: netdev; +Cc: ebiederm, David Ahern
In-Reply-To: <1423100070-31848-1-git-send-email-dsahern@gmail.com>
Defines for min and max vrf id and helpers for examining
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/net/vrf.h | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
create mode 100644 include/net/vrf.h
diff --git a/include/net/vrf.h b/include/net/vrf.h
new file mode 100644
index 000000000000..67bc2e465661
--- /dev/null
+++ b/include/net/vrf.h
@@ -0,0 +1,36 @@
+#ifndef _VRF_H_
+#define _VRF_H_
+
+#define VRF_BITS 12
+#define VRF_MIN 1
+#define VRF_MAX ((1 << VRF_BITS) - 1)
+#define VRF_MASK VRF_MAX
+
+#define VRF_DEFAULT 1
+#define VRF_ANY 0xffff
+
+static inline
+int vrf_eq(__u32 vrf1, __u32 vrf2)
+{
+ return vrf1 == vrf2;
+}
+
+static inline
+int vrf_eq_or_any(__u32 vrf1, __u32 vrf2)
+{
+ return vrf1 == vrf2 || vrf1 == VRF_ANY || vrf2 == VRF_ANY;
+}
+
+static inline int vrf_is_valid(__u32 vrf)
+{
+ if ((vrf < VRF_MIN || vrf > VRF_MAX) && vrf != VRF_ANY)
+ return 0;
+
+ return 1;
+}
+
+static inline int vrf_is_any(__u32 vrf)
+{
+ return vrf == VRF_ANY;
+}
+#endif
--
1.9.3 (Apple Git-50)
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox