summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cleopatre/buildroot/target/device/Spidcom/arizona/linux26.config1
-rw-r--r--cleopatre/buildroot/target/device/Spidcom/scr310/linux26.config1
-rw-r--r--cleopatre/buildroot/target/device/Spidcom/spk300/linux26.config1
-rw-r--r--cleopatre/buildroot/target/device/Spidcom/spk300g/linux26.config1
-rw-r--r--cleopatre/buildroot/target/device/Spidcom/spk310/linux26.config1
-rw-r--r--cleopatre/buildroot/target/device/Spidcom/spr300/linux26.config1
-rw-r--r--cleopatre/buildroot/target/device/Spidcom/spr310/linux26.config1
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/include/net/seq_check.h89
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/net/Kconfig9
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/net/Makefile2
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/net/seq_check.c298
11 files changed, 405 insertions, 0 deletions
diff --git a/cleopatre/buildroot/target/device/Spidcom/arizona/linux26.config b/cleopatre/buildroot/target/device/Spidcom/arizona/linux26.config
index 2d870a327d..e30ee6b776 100644
--- a/cleopatre/buildroot/target/device/Spidcom/arizona/linux26.config
+++ b/cleopatre/buildroot/target/device/Spidcom/arizona/linux26.config
@@ -398,6 +398,7 @@ CONFIG_LLC=y
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_SEQ_CHECK is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
diff --git a/cleopatre/buildroot/target/device/Spidcom/scr310/linux26.config b/cleopatre/buildroot/target/device/Spidcom/scr310/linux26.config
index dd3c85bacb..6935ee89e6 100644
--- a/cleopatre/buildroot/target/device/Spidcom/scr310/linux26.config
+++ b/cleopatre/buildroot/target/device/Spidcom/scr310/linux26.config
@@ -353,6 +353,7 @@ CONFIG_LLC=y
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_SEQ_CHECK is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
diff --git a/cleopatre/buildroot/target/device/Spidcom/spk300/linux26.config b/cleopatre/buildroot/target/device/Spidcom/spk300/linux26.config
index c7d4f25fb9..e11229713c 100644
--- a/cleopatre/buildroot/target/device/Spidcom/spk300/linux26.config
+++ b/cleopatre/buildroot/target/device/Spidcom/spk300/linux26.config
@@ -353,6 +353,7 @@ CONFIG_LLC=y
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_SEQ_CHECK is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
diff --git a/cleopatre/buildroot/target/device/Spidcom/spk300g/linux26.config b/cleopatre/buildroot/target/device/Spidcom/spk300g/linux26.config
index 6a821b3159..c530286606 100644
--- a/cleopatre/buildroot/target/device/Spidcom/spk300g/linux26.config
+++ b/cleopatre/buildroot/target/device/Spidcom/spk300g/linux26.config
@@ -354,6 +354,7 @@ CONFIG_LLC=y
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_SEQ_CHECK is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
diff --git a/cleopatre/buildroot/target/device/Spidcom/spk310/linux26.config b/cleopatre/buildroot/target/device/Spidcom/spk310/linux26.config
index 7afb18be32..5ac61e6e62 100644
--- a/cleopatre/buildroot/target/device/Spidcom/spk310/linux26.config
+++ b/cleopatre/buildroot/target/device/Spidcom/spk310/linux26.config
@@ -353,6 +353,7 @@ CONFIG_LLC=y
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_SEQ_CHECK is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
diff --git a/cleopatre/buildroot/target/device/Spidcom/spr300/linux26.config b/cleopatre/buildroot/target/device/Spidcom/spr300/linux26.config
index 58cd6c621d..6e803e9d35 100644
--- a/cleopatre/buildroot/target/device/Spidcom/spr300/linux26.config
+++ b/cleopatre/buildroot/target/device/Spidcom/spr300/linux26.config
@@ -353,6 +353,7 @@ CONFIG_LLC=y
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_SEQ_CHECK is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
diff --git a/cleopatre/buildroot/target/device/Spidcom/spr310/linux26.config b/cleopatre/buildroot/target/device/Spidcom/spr310/linux26.config
index 130d1c205d..ef7caf83b7 100644
--- a/cleopatre/buildroot/target/device/Spidcom/spr310/linux26.config
+++ b/cleopatre/buildroot/target/device/Spidcom/spr310/linux26.config
@@ -353,6 +353,7 @@ CONFIG_LLC=y
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_SEQ_CHECK is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
diff --git a/cleopatre/linux-2.6.25.10-spc300/include/net/seq_check.h b/cleopatre/linux-2.6.25.10-spc300/include/net/seq_check.h
new file mode 100644
index 0000000000..633ae4eeb4
--- /dev/null
+++ b/cleopatre/linux-2.6.25.10-spc300/include/net/seq_check.h
@@ -0,0 +1,89 @@
+#ifndef SEQ_CHECK_H
+#define SEQ_CHECK_H
+
+/*
+ * seq_check
+ * Copyright (C) 2011 SPiDCOM Technologies
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * Checks the sequence numbers in specially crafted packets (like those sent by
+ * iperf), and reports the gaps.
+ * The purpose is to help investigate packet loss in a network chain.
+ * Concerned network drivers participate by calling the appropriate functions
+ * provided by seq_check.
+ * seq_check can be configured (via sysctl) to only check packets with a
+ * specific ethertype. The position of the sequence number in the packet can
+ * also be configured.
+ */
+
+#define SEQ_CHECK_VLAN_MAX 64
+#define SEQ_CHECK_DRV_NAME_SZ 10
+
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/sysctl.h>
+#include <linux/types.h>
+
+/* seq_check context. */
+struct seq_check_ctx
+{
+ /* Expected sequence number for the next received packet. For each VLAN. */
+ uint16_t seq_num_expected_rx[SEQ_CHECK_VLAN_MAX];
+
+ /* Expected sequence number for the next sent packet. For each VLAN. */
+ uint16_t seq_num_expected_tx[SEQ_CHECK_VLAN_MAX];
+
+ /* Name of the network driver. */
+ char drv_name[SEQ_CHECK_DRV_NAME_SZ];
+};
+
+#ifdef CONFIG_SEQ_CHECK
+
+/**
+ * Initialize the seq_check context for a particular network driver.
+ *
+ * \param ctx the seq_check context for the network driver.
+ * \param drv_name the name of the network driver.
+ */
+void seq_check_init(struct seq_check_ctx *ctx, const char *drv_name);
+
+/**
+ * Check the sequence number of a received packet.
+ *
+ * \param ctx the seq_check context for the network driver.
+ * \param skb the skb containing the packet to check.
+ */
+void seq_check_rx(struct seq_check_ctx *ctx, const struct sk_buff *skb);
+
+/**
+ * Check the sequence number of a to be sent packet.
+ *
+ * \param ctx the seq_check context for the network driver.
+ * \param skb the skb containing the packet to check.
+ */
+void seq_check_tx(struct seq_check_ctx *ctx, const struct sk_buff *skb);
+
+#else
+
+#define seq_check_init(ctx, drv_name) do {} while(0)
+#define seq_check_rx(ctx, skb) do {} while(0)
+#define seq_check_tx(ctx, skb) do {} while(0)
+
+#endif /* CONFIG_SEQ_CHECK */
+
+#endif /* SEQ_CHECK_H */
diff --git a/cleopatre/linux-2.6.25.10-spc300/net/Kconfig b/cleopatre/linux-2.6.25.10-spc300/net/Kconfig
index 6627c6ae5d..29d688f59e 100644
--- a/cleopatre/linux-2.6.25.10-spc300/net/Kconfig
+++ b/cleopatre/linux-2.6.25.10-spc300/net/Kconfig
@@ -225,6 +225,14 @@ config NET_TCPPROBE
To compile this code as a module, choose M here: the
module will be called tcp_probe.
+config SEQ_CHECK
+ bool "seq_check"
+ default n
+ help
+ This feature provides a check of the sequence numbers in specially crafted
+ packets(like those sent by the iperf tool), and reports the gaps.
+ The purpose is to help investigate packet loss in a network chain.
+
endmenu
endmenu
@@ -250,6 +258,7 @@ endmenu
source "net/rfkill/Kconfig"
source "net/9p/Kconfig"
+
endif # if NET
endmenu # Networking
diff --git a/cleopatre/linux-2.6.25.10-spc300/net/Makefile b/cleopatre/linux-2.6.25.10-spc300/net/Makefile
index b7a13643b5..c2868bb9a4 100644
--- a/cleopatre/linux-2.6.25.10-spc300/net/Makefile
+++ b/cleopatre/linux-2.6.25.10-spc300/net/Makefile
@@ -57,3 +57,5 @@ obj-$(CONFIG_NET_9P) += 9p/
ifeq ($(CONFIG_NET),y)
obj-$(CONFIG_SYSCTL) += sysctl_net.o
endif
+
+obj-$(CONFIG_SEQ_CHECK) += seq_check.o
diff --git a/cleopatre/linux-2.6.25.10-spc300/net/seq_check.c b/cleopatre/linux-2.6.25.10-spc300/net/seq_check.c
new file mode 100644
index 0000000000..56dc8f49e0
--- /dev/null
+++ b/cleopatre/linux-2.6.25.10-spc300/net/seq_check.c
@@ -0,0 +1,298 @@
+/*
+ * seq_check
+ * Copyright (C) 2011 SPiDCOM Technologies
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <net/seq_check.h>
+
+#include <asm/string.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/sysctl.h>
+#include <linux/types.h>
+
+#define SEQ_CHECK_LOG(ctx, dir, vlan_id, fmt, ...) \
+ printk (KERN_WARNING "seq_check %s %s: [%02u] " \
+ fmt, ctx->drv_name, dir, vlan_id, ##__VA_ARGS__)
+
+#define SEQ_CHECK_SYSCTL_ETHERTYPE_SZ 7 /* = 6 + 1
+ = strlen("0x0800") + '\0' */
+
+#define SEQ_CHECK_DEFAULT_ETHERTYPE "0x0800" /* ETH_P_IP */
+#define SEQ_CHECK_DEFAULT_SEQ_POS 44 /* The position of the sequence number
+ in an iperf packet. */
+
+/* Strings representing the direction (Rx or Tx). */
+static const char *seq_check_dir_rx_str = "Rx";
+static const char *seq_check_dir_tx_str = "Tx";
+
+/* Ethertype of the packets to check. */
+static uint16_t seq_check_ethertype;
+
+/* Position/offset (in bytes) of the sequence number in the packets, relative
+ * to the start of the MAC header. */
+static unsigned int seq_check_seq_num_pos;
+
+/* Sysctl: Ethertype in string format. */
+char seq_check_sysctl_ethertype_str[SEQ_CHECK_SYSCTL_ETHERTYPE_SZ];
+
+/*
+ * Set the ethertype numeric value from the specified string ethertype value.
+ */
+static int
+seq_check_set_ethertype_from_str(void)
+{
+ unsigned long temp;
+ int ret;
+
+ ret = strict_strtoul(seq_check_sysctl_ethertype_str, 16, &temp);
+
+ if (ret == 0)
+ {
+ /* temp is kept in uint16_t range by the size of
+ * sysctl_ethertype_str. */
+ seq_check_ethertype = htons((uint16_t)temp);
+ }
+
+ return ret;
+}
+
+/*
+ * Handler for setting the ethertype from sysctl.
+ */
+static int
+seq_check_sysctl_do_ethertype(ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ int ret;
+
+ ret = proc_dostring(table, write, filp, buffer, lenp, ppos);
+
+ if ((ret == 0) && write)
+ {
+ ret = seq_check_set_ethertype_from_str();
+ }
+
+ return ret;
+}
+
+/* sysctl table: level 1. */
+static ctl_table seq_check_sysctl_table_lvl1[]=
+{
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "ethertype",
+ .data = &seq_check_sysctl_ethertype_str,
+ .maxlen = SEQ_CHECK_SYSCTL_ETHERTYPE_SZ,
+ .mode = 0644,
+ .proc_handler = seq_check_sysctl_do_ethertype,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "seq_num_pos",
+ .data = &seq_check_seq_num_pos,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec
+ },
+ { }
+};
+
+/* sysctl table: level 0. */
+static ctl_table seq_check_sysctl_table_lvl0[]=
+{
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "seq_check",
+ .mode = 0555,
+ .child = seq_check_sysctl_table_lvl1
+ },
+ { }
+};
+
+static struct ctl_table_header *seq_check_sysctl_table_header;
+
+static struct ctl_path seq_check_sysctl_path[] =
+{
+ { .procname = "net", .ctl_name = CTL_NET },
+ { }
+};
+
+void
+seq_check_init(struct seq_check_ctx *ctx, const char *drv_name)
+{
+ BUG_ON(ctx == NULL);
+ BUG_ON(drv_name == NULL);
+
+ memset(ctx->seq_num_expected_rx, 0, sizeof(ctx->seq_num_expected_rx));
+ memset(ctx->seq_num_expected_tx, 0, sizeof(ctx->seq_num_expected_tx));
+ strlcpy(ctx->drv_name, drv_name, sizeof(ctx->drv_name));
+}
+EXPORT_SYMBOL(seq_check_init);
+
+/**
+ * Check the sequence number.
+ *
+ * \param ctx the seq_check context.
+ * \param skb the skb containing the packet to check.
+ * \param seq_num_expected the relevant seq_num_expected (Rx or Tx).
+ * \param dir the relevant string describing the direction (Rx or Tx).
+ */
+static void
+__seq_check(struct seq_check_ctx *ctx, const struct sk_buff *skb,
+ uint16_t seq_num_expected[SEQ_CHECK_VLAN_MAX], const char *dir)
+{
+ unsigned char *mac_hdr; /* Start of the MAC header. */
+ struct ethhdr *ethhdr;
+ uint16_t pkt_ethertype; /* Ethertype of the packet. */
+ unsigned int vlan_id;
+ uint16_t seq_num_actual; /* actual sequence number,
+ ie: the one in the packet. */
+
+ BUG_ON(ctx == NULL);
+ BUG_ON(skb == NULL);
+ BUG_ON(seq_num_expected == NULL);
+ BUG_ON(dir == NULL);
+
+ /* Determine the start of the MAC header.
+ * Note that in Tx packets created via AF_PACKET/SOCK_RAW, skb_mac_header
+ * is not set, so skb->data is used. */
+ if (skb_mac_header_was_set(skb))
+ {
+ mac_hdr = skb_mac_header(skb);
+ }
+ else
+ {
+ mac_hdr = skb->data;
+ }
+
+ BUG_ON(mac_hdr == NULL);
+
+ ethhdr = (struct ethhdr *)mac_hdr;
+
+ /* Determine the Ethernet Type */
+
+ /* VLAN tagged packet ? */
+ if (ethhdr->h_proto == htons(ETH_P_8021Q))
+ {
+ struct vlan_ethhdr *vlan_ethhdr;
+
+ vlan_ethhdr = (struct vlan_ethhdr *)mac_hdr;
+ pkt_ethertype = vlan_ethhdr->h_vlan_encapsulated_proto;
+ vlan_id = (ntohs(vlan_ethhdr->h_vlan_TCI) & VLAN_VID_MASK);
+
+ if (vlan_id >= SEQ_CHECK_VLAN_MAX)
+ {
+ SEQ_CHECK_LOG(ctx, dir, vlan_id,
+ "VLAN_ID (= %u) >= SEQ_CHECK_VLAN_MAX\n", vlan_id);
+ return;
+ }
+ }
+ else
+ {
+ pkt_ethertype = ethhdr->h_proto;
+ vlan_id = 0;
+ }
+
+ if (pkt_ethertype != seq_check_ethertype)
+ {
+ return;
+ }
+
+ if (skb_is_nonlinear(skb))
+ {
+ /* Handling a nonlinear skb (ie where the data may be in additional
+ * pages) is not supported. */
+ SEQ_CHECK_LOG(ctx, dir, vlan_id,
+ "skb is non linear. Not supported.\n");
+ }
+
+ /* Extract the sequence number in the packet. */
+
+ if (seq_check_seq_num_pos >= skb->len)
+ {
+ SEQ_CHECK_LOG(ctx, dir, vlan_id, "packet too small\n");
+ return;
+ }
+
+ seq_num_actual = ntohs(*((uint16_t *)(mac_hdr + seq_check_seq_num_pos)));
+
+ if (seq_num_actual != seq_num_expected[vlan_id])
+ {
+ SEQ_CHECK_LOG(ctx, dir, vlan_id, "expected=%04X, actual=%04X\n",
+ (seq_num_expected[vlan_id]),
+ seq_num_actual);
+ }
+
+ seq_num_expected[vlan_id] = seq_num_actual + 1; /* the overflow will make it
+ loop back to 0. */
+}
+
+/*
+ * Check sequence number in Rx.
+ */
+void
+seq_check_rx(struct seq_check_ctx *ctx, const struct sk_buff *skb)
+{
+ __seq_check(ctx, skb, ctx->seq_num_expected_rx, seq_check_dir_rx_str);
+}
+EXPORT_SYMBOL(seq_check_rx);
+
+/*
+ * Check sequence number in Tx.
+ */
+void
+seq_check_tx(struct seq_check_ctx *ctx, const struct sk_buff *skb)
+{
+ __seq_check(ctx, skb, ctx->seq_num_expected_tx, seq_check_dir_tx_str);
+}
+EXPORT_SYMBOL(seq_check_tx);
+
+
+static int __init
+seq_check_module_init(void)
+{
+ strcpy(seq_check_sysctl_ethertype_str, SEQ_CHECK_DEFAULT_ETHERTYPE);
+ seq_check_set_ethertype_from_str();
+
+ seq_check_seq_num_pos = SEQ_CHECK_DEFAULT_SEQ_POS;
+
+ seq_check_sysctl_table_header
+ = register_sysctl_paths(seq_check_sysctl_path,
+ seq_check_sysctl_table_lvl0);
+
+ return 0;
+}
+
+static void __exit
+seq_check_module_exit(void)
+{
+ if (seq_check_sysctl_table_header != NULL)
+ {
+ unregister_sysctl_table(seq_check_sysctl_table_header);
+ }
+}
+
+module_init(seq_check_module_init);
+module_exit(seq_check_module_exit);
+
+MODULE_AUTHOR("SPiDCOM Technologies");
+MODULE_DESCRIPTION("Detects gaps in sequence numbers of specially crafted packets.");
+MODULE_LICENSE("GPL");