[Click] [PATCH 4/5] FromDevice: use netdev_rx_handler_register
Joonwoo Park
joonwpark81 at gmail.com
Sun Jan 30 04:21:22 EST 2011
Linux net has removed function pointers which had used for intercepting
packet from protocol handlers/pesudo devices like bridge and introduced
netdev_rx_handler_register() instead.
Subsequently br_handle_frame_hook is not available anymore.
For patchless linux, use netdev_rx_handler_register().
Signed-off-by: Joonwoo Park <joonwpark81 at gmail.com>
---
config-linuxmodule.h.in | 3 ++
configure.in | 7 +++++
elements/linuxmodule/anydevice.cc | 2 +-
elements/linuxmodule/fromdevice.cc | 53 +++++++++++++++++++++++++++++++++++-
elements/linuxmodule/fromdevice.hh | 5 +++
5 files changed, 68 insertions(+), 2 deletions(-)
diff --git a/config-linuxmodule.h.in b/config-linuxmodule.h.in
index dbef4e2..e31ed3a 100644
--- a/config-linuxmodule.h.in
+++ b/config-linuxmodule.h.in
@@ -103,6 +103,9 @@
/* Define if you have the netdev_uses_trailer_tags function. */
#undef HAVE_NETDEV_USES_TRAILER_TAGS
+/* Define if your Linux kernel has netdev_rx_handler_register. */
+#undef HAVE_LINUX_NETDEV_RX_HANDLER_REGISTER
+
/* Define if netif_receive_skb takes 3 arguments. */
#undef HAVE_NETIF_RECEIVE_SKB_EXTENDED
diff --git a/configure.in b/configure.in
index 04fad1f..b3b0c3b 100644
--- a/configure.in
+++ b/configure.in
@@ -1373,6 +1373,13 @@ void f1(int64_t) { // will fail if long long and int64_t are the same type
AC_DEFINE([HAVE_NETDEV_USES_TRAILER_TAGS], [1], [Define if you have the netdev_uses_trailer_tags function.])
fi
+ AC_CACHE_CHECK(for netdev_rx_handler_register kernel symbol, ac_cv_linux_netdev_rx_handler_register,
+ [if grep "__ksymtab_netdev_rx_handler_register" $linux_system_map >/dev/null 2>&1; then
+ ac_cv_linux_netdev_rx_handler_register=yes
+ else ac_cv_linux_netdev_rx_handler_register=no; fi])
+ if test $ac_cv_linux_netdev_rx_handler_register = yes; then
+ AC_DEFINE(HAVE_LINUX_NETDEV_RX_HANDLER_REGISTER)
+ fi
CC="$save_cc"
CXX="$save_cxx"
diff --git a/elements/linuxmodule/anydevice.cc b/elements/linuxmodule/anydevice.cc
index d01d842..6fd09cd 100644
--- a/elements/linuxmodule/anydevice.cc
+++ b/elements/linuxmodule/anydevice.cc
@@ -117,7 +117,7 @@ AnyDevice::alter_promiscuity(int delta)
void
AnyDevice::alter_from_device(int delta)
{
-#if !HAVE_CLICK_KERNEL && (defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+#if !HAVE_CLICK_KERNEL && !HAVE_LINUX_NETDEV_RX_HANDLER_REGISTER && (defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
if (!_dev)
return;
fake_bridge *fb = reinterpret_cast<fake_bridge *>(_dev->br_port);
diff --git a/elements/linuxmodule/fromdevice.cc b/elements/linuxmodule/fromdevice.cc
index 9aff966..fc7ef8b 100644
--- a/elements/linuxmodule/fromdevice.cc
+++ b/elements/linuxmodule/fromdevice.cc
@@ -31,6 +31,14 @@
#include <click/standard/scheduleinfo.hh>
#include <click/straccum.hh>
+#include <click/cxxprotect.h>
+CLICK_CXX_PROTECT
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+# include <linux/rtnetlink.h>
+#endif
+CLICK_CXX_UNPROTECT
+#include <click/cxxunprotect.h>
+
static AnyDeviceMap from_device_map;
static int registered_readers;
#if HAVE_CLICK_KERNEL
@@ -39,7 +47,9 @@ static struct notifier_block packet_notifier;
static struct notifier_block device_notifier_early;
static struct notifier_block device_notifier_late;
-#if !HAVE_CLICK_KERNEL && (defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE))
+#if HAVE_LINUX_NETDEV_RX_HANDLER_REGISTER
+# define CLICK_FROMDEVICE_USE_NETDEV_RX_HANDLER_REGISTER 1
+#elif !HAVE_CLICK_KERNEL && (defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE))
# define CLICK_FROMDEVICE_USE_BRIDGE 1
#endif
@@ -58,6 +68,8 @@ static int packet_notifier_hook(struct notifier_block *nb, unsigned long val, vo
#elif CLICK_FROMDEVICE_USE_BRIDGE
static struct sk_buff *click_br_handle_frame_hook(struct net_bridge_port *p, struct sk_buff *skb);
static struct sk_buff *(*real_br_handle_frame_hook)(struct net_bridge_port *p, struct sk_buff *skb);
+#elif CLICK_FROMDEVICE_USE_NETDEV_RX_HANDLER_REGISTER
+static struct sk_buff *click_rx_handler(struct sk_buff *skb);
#endif
static int device_notifier_hook_early(struct notifier_block *nb, unsigned long val, void *v);
static int device_notifier_hook_late(struct notifier_block *nb, unsigned long val, void *v);
@@ -138,6 +150,18 @@ FromDevice::configure(Vector<String> &conf, ErrorHandler *errh)
int before = errh->nerrors();
net_device *dev = lookup_device(errh);
set_device(dev, &from_device_map, anydev_from_device);
+
+#if CLICK_FROMDEVICE_USE_NETDEV_RX_HANDLER_REGISTER
+ if (dev) {
+ rtnl_lock();
+ _real_rx_handler = dev->rx_handler;
+ _real_rx_handler_data = dev->rx_handler_data;
+ netdev_rx_handler_unregister(dev);
+ netdev_rx_handler_register(dev, click_rx_handler, this);
+ rtnl_unlock();
+ }
+#endif
+
return errh->nerrors() == before ? 0 : -1;
}
@@ -166,6 +190,7 @@ FromDevice::initialize(ErrorHandler *errh)
#elif CLICK_FROMDEVICE_USE_BRIDGE
real_br_handle_frame_hook = br_handle_frame_hook;
br_handle_frame_hook = click_br_handle_frame_hook;
+#elif CLICK_FROMDEVICE_USE_NETDEV_RX_HANDLER_REGISTER
#else
errh->warning("can't get packets: not compiled for a Click kernel");
#endif
@@ -198,6 +223,11 @@ FromDevice::cleanup(CleanupStage stage)
#elif CLICK_FROMDEVICE_USE_BRIDGE
if (registered_readers == 0)
br_handle_frame_hook = real_br_handle_frame_hook;
+#elif CLICK_FROMDEVICE_USE_NETDEV_RX_HANDLER_REGISTER
+ rtnl_lock();
+ netdev_rx_handler_unregister(_dev);
+ netdev_rx_handler_register(_dev, _real_rx_handler, _real_rx_handler_data);
+ rtnl_unlock();
#endif
}
@@ -280,6 +310,27 @@ click_br_handle_frame_hook(struct net_bridge_port *p, struct sk_buff *skb)
else
return skb;
}
+#elif CLICK_FROMDEVICE_USE_NETDEV_RX_HANDLER_REGISTER
+static struct sk_buff *
+click_rx_handler(struct sk_buff *skb)
+{
+ int stolen;
+ sk_buff *ret = skb;
+ FromDevice *fd = rcu_dereference((*(FromDevice **)&skb->dev->rx_handler_data));
+
+ stolen = fd->got_skb(skb);
+ if (stolen)
+ ret = NULL;
+ else if (fd->_real_rx_handler) {
+ rcu_assign_pointer(*(unsigned long **)&skb->dev->rx_handler_data,
+ (unsigned long *)fd->_real_rx_handler_data);
+ ret = (*fd->_real_rx_handler)(skb);
+ rcu_assign_pointer(*(unsigned long **)&skb->dev->rx_handler_data,
+ (unsigned long *)fd);
+ }
+
+ return ret;
+}
#endif
static int
diff --git a/elements/linuxmodule/fromdevice.hh b/elements/linuxmodule/fromdevice.hh
index e31ac1f..1d2749c 100644
--- a/elements/linuxmodule/fromdevice.hh
+++ b/elements/linuxmodule/fromdevice.hh
@@ -159,6 +159,11 @@ class FromDevice : public AnyTaskDevice, public Storage { public:
_runs = _empty_runs = _count = _drops = 0;
}
+#if HAVE_LINUX_NETDEV_RX_HANDLER_REGISTER
+ rx_handler_func_t *_real_rx_handler;
+ void *_real_rx_handler_data;
+#endif
+
private:
bool _active;
--
1.7.1
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0004-FromDevice-use-netdev_rx_handler_register.patch
Type: text/x-diff
Size: 7258 bytes
Desc: not available
Url : http://amsterdam.lcs.mit.edu/pipermail/click/attachments/20110130/fd1f252b/attachment-0001.patch
More information about the click
mailing list