aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_policy.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-02 16:38:27 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-02 16:38:27 -0400
commitaecdc33e111b2c447b622e287c6003726daa1426 (patch)
tree3e7657eae4b785e1a1fb5dfb225dbae0b2f0cfc6 /net/xfrm/xfrm_policy.c
parenta20acf99f75e49271381d65db097c9763060a1e8 (diff)
parenta3a6cab5ea10cca64d036851fe0d932448f2fe4f (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking changes from David Miller: 1) GRE now works over ipv6, from Dmitry Kozlov. 2) Make SCTP more network namespace aware, from Eric Biederman. 3) TEAM driver now works with non-ethernet devices, from Jiri Pirko. 4) Make openvswitch network namespace aware, from Pravin B Shelar. 5) IPV6 NAT implementation, from Patrick McHardy. 6) Server side support for TCP Fast Open, from Jerry Chu and others. 7) Packet BPF filter supports MOD and XOR, from Eric Dumazet and Daniel Borkmann. 8) Increate the loopback default MTU to 64K, from Eric Dumazet. 9) Use a per-task rather than per-socket page fragment allocator for outgoing networking traffic. This benefits processes that have very many mostly idle sockets, which is quite common. From Eric Dumazet. 10) Use up to 32K for page fragment allocations, with fallbacks to smaller sizes when higher order page allocations fail. Benefits are a) less segments for driver to process b) less calls to page allocator c) less waste of space. From Eric Dumazet. 11) Allow GRO to be used on GRE tunnels, from Eric Dumazet. 12) VXLAN device driver, one way to handle VLAN issues such as the limitation of 4096 VLAN IDs yet still have some level of isolation. From Stephen Hemminger. 13) As usual there is a large boatload of driver changes, with the scale perhaps tilted towards the wireless side this time around. Fix up various fairly trivial conflicts, mostly caused by the user namespace changes. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1012 commits) hyperv: Add buffer for extended info after the RNDIS response message. hyperv: Report actual status in receive completion packet hyperv: Remove extra allocated space for recv_pkt_list elements hyperv: Fix page buffer handling in rndis_filter_send_request() hyperv: Fix the missing return value in rndis_filter_set_packet_filter() hyperv: Fix the max_xfer_size in RNDIS initialization vxlan: put UDP socket in correct namespace vxlan: Depend on CONFIG_INET sfc: Fix the reported priorities of different filter types sfc: Remove EFX_FILTER_FLAG_RX_OVERRIDE_IP sfc: Fix loopback self-test with separate_tx_channels=1 sfc: Fix MCDI structure field lookup sfc: Add parentheses around use of bitfield macro arguments sfc: Fix null function pointer in efx_sriov_channel_type vxlan: virtual extensible lan igmp: export symbol ip_mc_leave_group netlink: add attributes to fdb interface tg3: unconditionally select HWMON support when tg3 is enabled. Revert "net: ti cpsw ethernet: allow reading phy interface mode from DT" gre: fix sparse warning ...
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
-rw-r--r--net/xfrm/xfrm_policy.c83
1 files changed, 44 insertions, 39 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 46550997548c..41eabc46f110 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -42,13 +42,12 @@ static DEFINE_SPINLOCK(xfrm_policy_sk_bundle_lock);
42static struct dst_entry *xfrm_policy_sk_bundles; 42static struct dst_entry *xfrm_policy_sk_bundles;
43static DEFINE_RWLOCK(xfrm_policy_lock); 43static DEFINE_RWLOCK(xfrm_policy_lock);
44 44
45static DEFINE_RWLOCK(xfrm_policy_afinfo_lock); 45static DEFINE_SPINLOCK(xfrm_policy_afinfo_lock);
46static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO]; 46static struct xfrm_policy_afinfo __rcu *xfrm_policy_afinfo[NPROTO]
47 __read_mostly;
47 48
48static struct kmem_cache *xfrm_dst_cache __read_mostly; 49static struct kmem_cache *xfrm_dst_cache __read_mostly;
49 50
50static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
51static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
52static void xfrm_init_pmtu(struct dst_entry *dst); 51static void xfrm_init_pmtu(struct dst_entry *dst);
53static int stale_bundle(struct dst_entry *dst); 52static int stale_bundle(struct dst_entry *dst);
54static int xfrm_bundle_ok(struct xfrm_dst *xdst); 53static int xfrm_bundle_ok(struct xfrm_dst *xdst);
@@ -95,6 +94,24 @@ bool xfrm_selector_match(const struct xfrm_selector *sel, const struct flowi *fl
95 return false; 94 return false;
96} 95}
97 96
97static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family)
98{
99 struct xfrm_policy_afinfo *afinfo;
100
101 if (unlikely(family >= NPROTO))
102 return NULL;
103 rcu_read_lock();
104 afinfo = rcu_dereference(xfrm_policy_afinfo[family]);
105 if (unlikely(!afinfo))
106 rcu_read_unlock();
107 return afinfo;
108}
109
110static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
111{
112 rcu_read_unlock();
113}
114
98static inline struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, 115static inline struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos,
99 const xfrm_address_t *saddr, 116 const xfrm_address_t *saddr,
100 const xfrm_address_t *daddr, 117 const xfrm_address_t *daddr,
@@ -2421,7 +2438,7 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
2421 return -EINVAL; 2438 return -EINVAL;
2422 if (unlikely(afinfo->family >= NPROTO)) 2439 if (unlikely(afinfo->family >= NPROTO))
2423 return -EAFNOSUPPORT; 2440 return -EAFNOSUPPORT;
2424 write_lock_bh(&xfrm_policy_afinfo_lock); 2441 spin_lock(&xfrm_policy_afinfo_lock);
2425 if (unlikely(xfrm_policy_afinfo[afinfo->family] != NULL)) 2442 if (unlikely(xfrm_policy_afinfo[afinfo->family] != NULL))
2426 err = -ENOBUFS; 2443 err = -ENOBUFS;
2427 else { 2444 else {
@@ -2442,9 +2459,9 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
2442 dst_ops->neigh_lookup = xfrm_neigh_lookup; 2459 dst_ops->neigh_lookup = xfrm_neigh_lookup;
2443 if (likely(afinfo->garbage_collect == NULL)) 2460 if (likely(afinfo->garbage_collect == NULL))
2444 afinfo->garbage_collect = xfrm_garbage_collect_deferred; 2461 afinfo->garbage_collect = xfrm_garbage_collect_deferred;
2445 xfrm_policy_afinfo[afinfo->family] = afinfo; 2462 rcu_assign_pointer(xfrm_policy_afinfo[afinfo->family], afinfo);
2446 } 2463 }
2447 write_unlock_bh(&xfrm_policy_afinfo_lock); 2464 spin_unlock(&xfrm_policy_afinfo_lock);
2448 2465
2449 rtnl_lock(); 2466 rtnl_lock();
2450 for_each_net(net) { 2467 for_each_net(net) {
@@ -2477,21 +2494,26 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo)
2477 return -EINVAL; 2494 return -EINVAL;
2478 if (unlikely(afinfo->family >= NPROTO)) 2495 if (unlikely(afinfo->family >= NPROTO))
2479 return -EAFNOSUPPORT; 2496 return -EAFNOSUPPORT;
2480 write_lock_bh(&xfrm_policy_afinfo_lock); 2497 spin_lock(&xfrm_policy_afinfo_lock);
2481 if (likely(xfrm_policy_afinfo[afinfo->family] != NULL)) { 2498 if (likely(xfrm_policy_afinfo[afinfo->family] != NULL)) {
2482 if (unlikely(xfrm_policy_afinfo[afinfo->family] != afinfo)) 2499 if (unlikely(xfrm_policy_afinfo[afinfo->family] != afinfo))
2483 err = -EINVAL; 2500 err = -EINVAL;
2484 else { 2501 else
2485 struct dst_ops *dst_ops = afinfo->dst_ops; 2502 RCU_INIT_POINTER(xfrm_policy_afinfo[afinfo->family],
2486 xfrm_policy_afinfo[afinfo->family] = NULL; 2503 NULL);
2487 dst_ops->kmem_cachep = NULL; 2504 }
2488 dst_ops->check = NULL; 2505 spin_unlock(&xfrm_policy_afinfo_lock);
2489 dst_ops->negative_advice = NULL; 2506 if (!err) {
2490 dst_ops->link_failure = NULL; 2507 struct dst_ops *dst_ops = afinfo->dst_ops;
2491 afinfo->garbage_collect = NULL; 2508
2492 } 2509 synchronize_rcu();
2510
2511 dst_ops->kmem_cachep = NULL;
2512 dst_ops->check = NULL;
2513 dst_ops->negative_advice = NULL;
2514 dst_ops->link_failure = NULL;
2515 afinfo->garbage_collect = NULL;
2493 } 2516 }
2494 write_unlock_bh(&xfrm_policy_afinfo_lock);
2495 return err; 2517 return err;
2496} 2518}
2497EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); 2519EXPORT_SYMBOL(xfrm_policy_unregister_afinfo);
@@ -2500,33 +2522,16 @@ static void __net_init xfrm_dst_ops_init(struct net *net)
2500{ 2522{
2501 struct xfrm_policy_afinfo *afinfo; 2523 struct xfrm_policy_afinfo *afinfo;
2502 2524
2503 read_lock_bh(&xfrm_policy_afinfo_lock); 2525 rcu_read_lock();
2504 afinfo = xfrm_policy_afinfo[AF_INET]; 2526 afinfo = rcu_dereference(xfrm_policy_afinfo[AF_INET]);
2505 if (afinfo) 2527 if (afinfo)
2506 net->xfrm.xfrm4_dst_ops = *afinfo->dst_ops; 2528 net->xfrm.xfrm4_dst_ops = *afinfo->dst_ops;
2507#if IS_ENABLED(CONFIG_IPV6) 2529#if IS_ENABLED(CONFIG_IPV6)
2508 afinfo = xfrm_policy_afinfo[AF_INET6]; 2530 afinfo = rcu_dereference(xfrm_policy_afinfo[AF_INET6]);
2509 if (afinfo) 2531 if (afinfo)
2510 net->xfrm.xfrm6_dst_ops = *afinfo->dst_ops; 2532 net->xfrm.xfrm6_dst_ops = *afinfo->dst_ops;
2511#endif 2533#endif
2512 read_unlock_bh(&xfrm_policy_afinfo_lock); 2534 rcu_read_unlock();
2513}
2514
2515static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family)
2516{
2517 struct xfrm_policy_afinfo *afinfo;
2518 if (unlikely(family >= NPROTO))
2519 return NULL;
2520 read_lock(&xfrm_policy_afinfo_lock);
2521 afinfo = xfrm_policy_afinfo[family];
2522 if (unlikely(!afinfo))
2523 read_unlock(&xfrm_policy_afinfo_lock);
2524 return afinfo;
2525}
2526
2527static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
2528{
2529 read_unlock(&xfrm_policy_afinfo_lock);
2530} 2535}
2531 2536
2532static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr) 2537static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)