aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-01-14 09:14:34 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-01-18 15:55:38 -0500
commita65240c1013222dbf41166c8b2c5ed2720c807c3 (patch)
tree782ebe013571cbf1b83c306964372faffe348b42 /net
parent0a214d3f7e5041685ebff054628a4354bedd78c3 (diff)
mac80211: allow drivers to access IPv6 information
To be able to implement NS response offloading (in regular operation or while in WoWLAN) drivers need to know the IPv6 addresses assigned to interfaces. Implement an IPv6 notifier in mac80211 to call the driver when addresses change. Unlike for IPv4, implement it as a callback rather than as a list in the BSS configuration, that is more flexible. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/driver-ops.h12
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/main.c48
-rw-r--r--net/mac80211/trace.h8
4 files changed, 69 insertions, 0 deletions
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index e6033b06caba..d51afbd614d3 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1036,4 +1036,16 @@ drv_set_default_unicast_key(struct ieee80211_local *local,
1036 trace_drv_return_void(local); 1036 trace_drv_return_void(local);
1037} 1037}
1038 1038
1039#if IS_ENABLED(CONFIG_IPV6)
1040static inline void drv_ipv6_addr_change(struct ieee80211_local *local,
1041 struct ieee80211_sub_if_data *sdata,
1042 struct inet6_dev *idev)
1043{
1044 trace_drv_ipv6_addr_change(local, sdata);
1045 if (local->ops->ipv6_addr_change)
1046 local->ops->ipv6_addr_change(&local->hw, &sdata->vif, idev);
1047 trace_drv_return_void(local);
1048}
1049#endif
1050
1039#endif /* __MAC80211_DRIVER_OPS */ 1051#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index b1fed5491ed6..aec1b332aeb7 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1127,6 +1127,7 @@ struct ieee80211_local {
1127 struct timer_list dynamic_ps_timer; 1127 struct timer_list dynamic_ps_timer;
1128 struct notifier_block network_latency_notifier; 1128 struct notifier_block network_latency_notifier;
1129 struct notifier_block ifa_notifier; 1129 struct notifier_block ifa_notifier;
1130 struct notifier_block ifa6_notifier;
1130 1131
1131 /* 1132 /*
1132 * The dynamic ps timeout configured from user space via WEXT - 1133 * The dynamic ps timeout configured from user space via WEXT -
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index baf9720c1876..2bdd454e8bcf 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -23,6 +23,7 @@
23#include <linux/inetdevice.h> 23#include <linux/inetdevice.h>
24#include <net/net_namespace.h> 24#include <net/net_namespace.h>
25#include <net/cfg80211.h> 25#include <net/cfg80211.h>
26#include <net/addrconf.h>
26 27
27#include "ieee80211_i.h" 28#include "ieee80211_i.h"
28#include "driver-ops.h" 29#include "driver-ops.h"
@@ -369,6 +370,37 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
369} 370}
370#endif 371#endif
371 372
373#if IS_ENABLED(CONFIG_IPV6)
374static int ieee80211_ifa6_changed(struct notifier_block *nb,
375 unsigned long data, void *arg)
376{
377 struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)arg;
378 struct inet6_dev *idev = ifa->idev;
379 struct net_device *ndev = ifa->idev->dev;
380 struct ieee80211_local *local =
381 container_of(nb, struct ieee80211_local, ifa6_notifier);
382 struct wireless_dev *wdev = ndev->ieee80211_ptr;
383 struct ieee80211_sub_if_data *sdata;
384
385 /* Make sure it's our interface that got changed */
386 if (!wdev || wdev->wiphy != local->hw.wiphy)
387 return NOTIFY_DONE;
388
389 sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
390
391 /*
392 * For now only support station mode. This is mostly because
393 * doing AP would have to handle AP_VLAN in some way ...
394 */
395 if (sdata->vif.type != NL80211_IFTYPE_STATION)
396 return NOTIFY_DONE;
397
398 drv_ipv6_addr_change(local, sdata, idev);
399
400 return NOTIFY_DONE;
401}
402#endif
403
372static int ieee80211_napi_poll(struct napi_struct *napi, int budget) 404static int ieee80211_napi_poll(struct napi_struct *napi, int budget)
373{ 405{
374 struct ieee80211_local *local = 406 struct ieee80211_local *local =
@@ -977,12 +1009,25 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
977 goto fail_ifa; 1009 goto fail_ifa;
978#endif 1010#endif
979 1011
1012#if IS_ENABLED(CONFIG_IPV6)
1013 local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed;
1014 result = register_inet6addr_notifier(&local->ifa6_notifier);
1015 if (result)
1016 goto fail_ifa6;
1017#endif
1018
980 netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll, 1019 netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll,
981 local->hw.napi_weight); 1020 local->hw.napi_weight);
982 1021
983 return 0; 1022 return 0;
984 1023
1024#if IS_ENABLED(CONFIG_IPV6)
1025 fail_ifa6:
985#ifdef CONFIG_INET 1026#ifdef CONFIG_INET
1027 unregister_inetaddr_notifier(&local->ifa_notifier);
1028#endif
1029#endif
1030#if defined(CONFIG_INET) || defined(CONFIG_IPV6)
986 fail_ifa: 1031 fail_ifa:
987 pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, 1032 pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
988 &local->network_latency_notifier); 1033 &local->network_latency_notifier);
@@ -1018,6 +1063,9 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
1018#ifdef CONFIG_INET 1063#ifdef CONFIG_INET
1019 unregister_inetaddr_notifier(&local->ifa_notifier); 1064 unregister_inetaddr_notifier(&local->ifa_notifier);
1020#endif 1065#endif
1066#if IS_ENABLED(CONFIG_IPV6)
1067 unregister_inet6addr_notifier(&local->ifa6_notifier);
1068#endif
1021 1069
1022 rtnl_lock(); 1070 rtnl_lock();
1023 1071
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index e9f95913c6f0..2a2c2e20307d 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -1437,6 +1437,14 @@ DEFINE_EVENT(local_only_evt, drv_restart_complete,
1437 TP_ARGS(local) 1437 TP_ARGS(local)
1438); 1438);
1439 1439
1440#if IS_ENABLED(CONFIG_IPV6)
1441DEFINE_EVENT(local_sdata_evt, drv_ipv6_addr_change,
1442 TP_PROTO(struct ieee80211_local *local,
1443 struct ieee80211_sub_if_data *sdata),
1444 TP_ARGS(local, sdata)
1445);
1446#endif
1447
1440/* 1448/*
1441 * Tracing for API calls that drivers call. 1449 * Tracing for API calls that drivers call.
1442 */ 1450 */