[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