Skip to content

Commit

Permalink
Modern eth_type_trans adds some functionality for DSA tagging.
Browse files Browse the repository at this point in the history
Mark that we would like to use that functionality.
  • Loading branch information
kohler committed Jan 28, 2010
1 parent ae76f68 commit ee26df2
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 26 deletions.
6 changes: 6 additions & 0 deletions config-linuxmodule.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@
/* Define if you have the netdev_get_tx_queue function. */
#undef HAVE_NETDEV_GET_TX_QUEUE

/* Define if you have the netdev_uses_dsa_tags function. */
#undef HAVE_NETDEV_USES_DSA_TAGS

/* Define if you have the netdev_uses_trailer_tags function. */
#undef HAVE_NETDEV_USES_TRAILER_TAGS

/* Define if netif_receive_skb takes 3 arguments. */
#undef HAVE_NETIF_RECEIVE_SKB_EXTENDED

Expand Down
68 changes: 68 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -10625,6 +10625,74 @@ $as_echo "#define HAVE_NETDEV_GET_TX_QUEUE 1" >>confdefs.h

fi

ac_fn_c_check_decl "$LINENO" "netdev_uses_dsa_tags" "ac_cv_have_decl_netdev_uses_dsa_tags" "#if HAVE_LINUXMODULE_2_6
# define KBUILD_STR(s) #s
# define KBUILD_BASENAME KBUILD_STR(click)
# define KBUILD_MODNAME KBUILD_STR(click)
#endif
#define new linux_new
#define this linux_this
#define delete linux_delete
#define class linux_class
#define virtual linux_virtual
#define typename linux_typename
#define private linux_private
#define protected linux_protected
#define public linux_public
#define namespace linux_namespace
#define false linux_false
#define true linux_true
#include <linux/autoconf.h>
#include <asm/types.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
"
if test "x$ac_cv_have_decl_netdev_uses_dsa_tags" = x""yes; then :
ac_cv_netdev_uses_dsa_tags=yes
else
ac_cv_netdev_uses_dsa_tags=no
fi

if test $ac_cv_netdev_uses_dsa_tags = yes; then

$as_echo "#define HAVE_NETDEV_USES_DSA_TAGS 1" >>confdefs.h

fi

ac_fn_c_check_decl "$LINENO" "netdev_uses_trailer_tags" "ac_cv_have_decl_netdev_uses_trailer_tags" "#if HAVE_LINUXMODULE_2_6
# define KBUILD_STR(s) #s
# define KBUILD_BASENAME KBUILD_STR(click)
# define KBUILD_MODNAME KBUILD_STR(click)
#endif
#define new linux_new
#define this linux_this
#define delete linux_delete
#define class linux_class
#define virtual linux_virtual
#define typename linux_typename
#define private linux_private
#define protected linux_protected
#define public linux_public
#define namespace linux_namespace
#define false linux_false
#define true linux_true
#include <linux/autoconf.h>
#include <asm/types.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
"
if test "x$ac_cv_have_decl_netdev_uses_trailer_tags" = x""yes; then :
ac_cv_netdev_uses_trailer_tags=yes
else
ac_cv_netdev_uses_trailer_tags=no
fi

if test $ac_cv_netdev_uses_trailer_tags = yes; then

$as_echo "#define HAVE_NETDEV_USES_TRAILER_TAGS 1" >>confdefs.h

fi


CC="$save_cc"
CXX="$save_cxx"
Expand Down
14 changes: 14 additions & 0 deletions configure.in
Original file line number Diff line number Diff line change
Expand Up @@ -1297,6 +1297,20 @@ void f1(int64_t) { // will fail if long long and int64_t are the same type
AC_DEFINE([HAVE_NETDEV_GET_TX_QUEUE], [1], [Define if you have the netdev_get_tx_queue function.])
fi

AC_CHECK_DECL(netdev_uses_dsa_tags, [ac_cv_netdev_uses_dsa_tags=yes], [ac_cv_netdev_uses_dsa_tags=no], [CLICK_LINUXMODULE_PROLOGUE()[
#include <linux/skbuff.h>
#include <linux/netdevice.h>]])
if test $ac_cv_netdev_uses_dsa_tags = yes; then
AC_DEFINE([HAVE_NETDEV_USES_DSA_TAGS], [1], [Define if you have the netdev_uses_dsa_tags function.])
fi

AC_CHECK_DECL(netdev_uses_trailer_tags, [ac_cv_netdev_uses_trailer_tags=yes], [ac_cv_netdev_uses_trailer_tags=no], [CLICK_LINUXMODULE_PROLOGUE()[
#include <linux/skbuff.h>
#include <linux/netdevice.h>]])
if test $ac_cv_netdev_uses_trailer_tags = yes; then
AC_DEFINE([HAVE_NETDEV_USES_TRAILER_TAGS], [1], [Define if you have the netdev_uses_trailer_tags function.])
fi


CC="$save_cc"
CXX="$save_cxx"
Expand Down
72 changes: 46 additions & 26 deletions elements/linuxmodule/tohost.cc
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,38 @@ device_notifier_hook(struct notifier_block *nb, unsigned long flags, void *v)
}
}

static inline uint16_t
tohost_eth_type_trans(struct sk_buff *skb, struct net_device *dev)
{
#if 0
/* XXX Newer versions of eth_type_trans have this code, but we can't use
* it in a module since dsa_uses_dsa_tags is not exported. */
# if HAVE_NETDEV_USES_DSA_TAGS
if (netdev_uses_dsa_tags(skb->dev))
return __constant_htons(ETH_P_DSA);
# endif
# if HAVE_NETDEV_USES_TRAILER_TAGS
if (netdev_uses_trailer_tags(skb->dev))
return __constant_htons(ETH_P_TRAILER);
# endif
#endif

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
const ethhdr *eth = eth_hdr(skb);
#else
const ethhdr *eth = skb->mac.ethernet;
#endif
if (ntohs(eth->h_proto) >= 1536)
return eth->h_proto;

const unsigned char *rawp = skb->data;
/* "This is a magic hack to spot IPX packets."
* See net/ethernet/eth.c:eth_type_trans */
if (*(const unsigned short *)rawp == 0xFFFF)
return __constant_htons(ETH_P_802_3);
return __constant_htons(ETH_P_802_2);
}

void
ToHost::push(int port, Packet *p)
{
Expand All @@ -157,9 +189,20 @@ ToHost::push(int port, Packet *p)
skb->pkt_type &= PACKET_TYPE_MASK;
#endif

// skb->dst may be set if the packet came from Linux originally. In this
// case, we must clear skb->dst so Linux finds the correct dst.
#if HAVE_SKB_DST_DROP
skb_dst_drop(skb);
#else
if (skb->dst) {
dst_release(skb->dst);
skb->dst = 0;
}
#endif

// MAC header is the data pointer
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
skb_set_mac_header(skb, 0);
skb_reset_mac_header(skb);
#else
skb->mac.raw = skb->data;
#endif
Expand All @@ -169,33 +212,10 @@ ToHost::push(int port, Packet *p)
skb->protocol = __constant_htons(ETH_P_IP);
else {
// do not call eth_type_trans; it changes pkt_type! Instead, do its
// work directly.
// relevant work directly.
skb_pull(skb, 14);

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
const ethhdr *eth = eth_hdr(skb);
#else
const ethhdr *eth = skb->mac.ethernet;
#endif
if (ntohs(eth->h_proto) >= 1536)
skb->protocol = eth->h_proto;
else {
const unsigned short *crap = (const unsigned short *)skb->data;
// "magic hack to spot IPX packets"
skb->protocol = (*crap == 0xFFFF ? htons(ETH_P_802_3) : htons(ETH_P_802_2));
}
}

// skb->dst may be set if the packet came from Linux originally. In this
// case, we must clear skb->dst so Linux finds the correct dst.
#if HAVE_SKB_DST_DROP
skb_dst_drop(skb);
#else
if (skb->dst) {
dst_release(skb->dst);
skb->dst = 0;
skb->protocol = tohost_eth_type_trans(skb, skb->dev);
}
#endif

// get protocol to pass to Linux
int protocol = (_sniffers ? 0xFFFF : skb->protocol);
Expand Down

0 comments on commit ee26df2

Please sign in to comment.