Harald Welte has submitted this change and it was merged.

Change subject: tests: osmo-pcap: Allow different l2 pkts
......................................................................


tests: osmo-pcap: Allow different l2 pkts

Before this patch, ETH was assumed and other types were not supported.
This patch also adds Linux cooked packet support for L2.

Change-Id: Ie62fa0a8e45e1e141edb64b116dad185ad9c7a5f
---
M tests/osmo-pcap-test/Makefile.am
A tests/osmo-pcap-test/l2_eth.c
A tests/osmo-pcap-test/l2_sll.c
M tests/osmo-pcap-test/l3_ipv4.c
M tests/osmo-pcap-test/l4_tcp.c
M tests/osmo-pcap-test/l4_udp.c
M tests/osmo-pcap-test/pcap.c
M tests/osmo-pcap-test/proto.c
M tests/osmo-pcap-test/proto.h
9 files changed, 189 insertions(+), 50 deletions(-)

Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/tests/osmo-pcap-test/Makefile.am b/tests/osmo-pcap-test/Makefile.am
index a256005..3e5bdf1 100644
--- a/tests/osmo-pcap-test/Makefile.am
+++ b/tests/osmo-pcap-test/Makefile.am
@@ -3,6 +3,8 @@
 check_PROGRAMS = osmo-pcap-test
 
 osmo_pcap_test_SOURCES = proto.c               \
+                        l2_eth.c               \
+                        l2_sll.c               \
                         l3_ipv4.c              \
                         l4_tcp.c               \
                         l4_udp.c               \
diff --git a/tests/osmo-pcap-test/l2_eth.c b/tests/osmo-pcap-test/l2_eth.c
new file mode 100644
index 0000000..3171fd7
--- /dev/null
+++ b/tests/osmo-pcap-test/l2_eth.c
@@ -0,0 +1,48 @@
+/*
+ * (C) 2012 by Pablo Neira Ayuso <pa...@gnumonks.org>
+ * (C) 2012 by On Waves ehf <http://www.on-waves.com>
+ *
+ * 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 vers
+ */
+
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <netinet/ip.h>
+#include <linux/if_ether.h>
+#include <pcap/dlt.h>
+
+#include "proto.h"
+
+#define PRINT_CMP(...)
+
+static int unsigned l2_eth_pkt_l3proto_num(const uint8_t *pkt)
+{
+       const struct ethhdr *eh = (const struct ethhdr *)pkt;
+       switch(ntohs(eh->h_proto)) {
+       case ETH_P_IP:
+               return htons(AF_INET);
+       default:
+               return eh->h_proto;
+       }
+}
+
+static unsigned int l2_eth_pkt_l2hdr_len(const uint8_t *pkt)
+{
+
+       return ETH_HLEN;
+}
+
+static struct osmo_pcap_proto_l2 eth = {
+       //.l2protonum   = ETH_P_IP,
+       .l2protonum     = DLT_EN10MB,
+       .l2pkt_hdr_len  = l2_eth_pkt_l2hdr_len,
+       .l3pkt_proto    = l2_eth_pkt_l3proto_num,
+};
+
+void l2_eth_init(void)
+{
+       osmo_pcap_proto_l2_register(&eth);
+}
diff --git a/tests/osmo-pcap-test/l2_sll.c b/tests/osmo-pcap-test/l2_sll.c
new file mode 100644
index 0000000..5a600ff
--- /dev/null
+++ b/tests/osmo-pcap-test/l2_sll.c
@@ -0,0 +1,47 @@
+/*
+ * (C) 2012 by Pablo Neira Ayuso <pa...@gnumonks.org>
+ * (C) 2012 by On Waves ehf <http://www.on-waves.com>
+ *
+ * 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 vers
+ */
+
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <linux/if_ether.h>
+#include <pcap/sll.h>
+#include <pcap/dlt.h>
+
+#include "proto.h"
+
+#define PRINT_CMP(...)
+
+static unsigned int l2_sll_pkt_l3proto_num(const uint8_t *pkt)
+{
+       const struct sll_header *lh = (const struct sll_header *)pkt;
+       switch(ntohs(lh->sll_protocol)) {
+       case ETH_P_IP:
+               return htons(AF_INET);
+       default:
+               return lh->sll_protocol;
+       }
+}
+
+static unsigned int l2_sll_pkt_l2hdr_len(const uint8_t *pkt)
+{
+
+       return SLL_HDR_LEN;
+}
+
+static struct osmo_pcap_proto_l2 sll = {
+       .l2protonum     = DLT_LINUX_SLL,
+       .l2pkt_hdr_len  = l2_sll_pkt_l2hdr_len,
+       .l3pkt_proto    = l2_sll_pkt_l3proto_num,
+};
+
+void l2_sll_init(void)
+{
+       osmo_pcap_proto_l2_register(&sll);
+}
diff --git a/tests/osmo-pcap-test/l3_ipv4.c b/tests/osmo-pcap-test/l3_ipv4.c
index 83e3479..521a803 100644
--- a/tests/osmo-pcap-test/l3_ipv4.c
+++ b/tests/osmo-pcap-test/l3_ipv4.c
@@ -16,29 +16,27 @@
 
 #define PRINT_CMP(...)
 
-static int l3_ipv4_pkt_l4proto_num(const uint8_t *pkt)
+static unsigned int l3_ipv4_pkt_l4proto_num(const uint8_t *pkt)
 {
        const struct iphdr *iph = (const struct iphdr *)pkt;
 
        return iph->protocol;
 }
 
-static int l3_ipv4_pkt_l3hdr_len(const uint8_t *pkt)
+static unsigned int l3_ipv4_pkt_l3hdr_len(const uint8_t *pkt)
 {
        const struct iphdr *iph = (const struct iphdr *)pkt;
 
        return iph->ihl << 2;
 }
 
-static struct osmo_pcap_proto_l2l3 ipv4 = {
-       .l2protonum     = ETH_P_IP,
+static struct osmo_pcap_proto_l3 ipv4 = {
        .l3protonum     = AF_INET,
-       .l2hdr_len      = ETH_HLEN,
        .l3pkt_hdr_len  = l3_ipv4_pkt_l3hdr_len,
        .l4pkt_proto    = l3_ipv4_pkt_l4proto_num,
 };
 
-void l2l3_ipv4_init(void)
+void l3_ipv4_init(void)
 {
-       osmo_pcap_proto_l2l3_register(&ipv4);
+       osmo_pcap_proto_l3_register(&ipv4);
 }
diff --git a/tests/osmo-pcap-test/l4_tcp.c b/tests/osmo-pcap-test/l4_tcp.c
index 1e024b5..f7aedbd 100644
--- a/tests/osmo-pcap-test/l4_tcp.c
+++ b/tests/osmo-pcap-test/l4_tcp.c
@@ -13,14 +13,14 @@
 
 #include "proto.h"
 
-static int l4_tcp_pkt_hdr_len(const uint8_t *pkt)
+static unsigned int l4_tcp_pkt_hdr_len(const uint8_t *pkt)
 {
        const struct tcphdr *tcph = (const struct tcphdr *)pkt;
 
        return tcph->doff << 2;
 }
 
-static int l4_tcp_pkt_no_data(const uint8_t *pkt)
+static unsigned int l4_tcp_pkt_no_data(const uint8_t *pkt)
 {
        const struct tcphdr *tcph = (const struct tcphdr *)pkt;
        return tcph->syn || tcph->fin || tcph->rst || !tcph->psh;
diff --git a/tests/osmo-pcap-test/l4_udp.c b/tests/osmo-pcap-test/l4_udp.c
index 9ffa77b..1733908 100644
--- a/tests/osmo-pcap-test/l4_udp.c
+++ b/tests/osmo-pcap-test/l4_udp.c
@@ -13,12 +13,12 @@
 
 #include "proto.h"
 
-static int l4_udp_pkt_hdr_len(const uint8_t *pkt)
+static unsigned int l4_udp_pkt_hdr_len(const uint8_t *pkt)
 {
        return sizeof(struct udphdr);
 }
 
-static int l4_udp_pkt_no_data(const uint8_t *pkt)
+static unsigned int l4_udp_pkt_no_data(const uint8_t *pkt)
 {
        /* UDP has no control packets. */
        return 0;
diff --git a/tests/osmo-pcap-test/pcap.c b/tests/osmo-pcap-test/pcap.c
index 61408f8..f9304b9 100644
--- a/tests/osmo-pcap-test/pcap.c
+++ b/tests/osmo-pcap-test/pcap.c
@@ -34,6 +34,7 @@
        uint32_t pkts;
        uint32_t skip;
        uint32_t processed;
+       uint32_t unsupported_l2;
        uint32_t unsupported_l3;
        uint32_t unsupported_l4;
 } osmo_pcap_test_stats;
@@ -41,21 +42,22 @@
 static int
 osmo_pcap_process_packet(struct msgb **msgptr,
                         const uint8_t *pkt, uint32_t pktlen,
-                        struct osmo_pcap_proto_l2l3 *l3h,
+                        struct osmo_pcap_proto_l2 *l2h,
+                        struct osmo_pcap_proto_l3 *l3h,
                         struct osmo_pcap_proto_l4 *l4h,
                         int (*cb)(struct msgb *msgb))
 {
-       unsigned int l3hdr_len, skip_hdr_len;
+       unsigned int l2hdr_len, l3hdr_len, skip_hdr_len;
        struct msgb *msgb;
-       int ret;
 
        /* skip layer 2, 3 and 4 headers */
-       l3hdr_len = l3h->l3pkt_hdr_len(pkt + ETH_HLEN);
-       skip_hdr_len = l3h->l2hdr_len + l3hdr_len +
-                       l4h->l4pkt_hdr_len(pkt + ETH_HLEN + l3hdr_len);
+       l2hdr_len = l2h->l2pkt_hdr_len(pkt);
+       l3hdr_len = l3h->l3pkt_hdr_len(pkt + l2hdr_len);
+       skip_hdr_len = l2hdr_len + l3hdr_len +
+                       l4h->l4pkt_hdr_len(pkt + l2hdr_len + l3hdr_len);
 
        /* This packet contains no data, skip it. */
-       if (l4h->l4pkt_no_data(pkt + l3hdr_len + ETH_HLEN)) {
+       if (l4h->l4pkt_no_data(pkt + l2hdr_len + l3hdr_len)) {
                osmo_pcap_test_stats.skip++;
                return -1;
        }
@@ -101,10 +103,11 @@
 int
 osmo_pcap_test_run(struct osmo_pcap *p, uint8_t pnum, int (*cb)(struct msgb 
*msgb))
 {
-       struct osmo_pcap_proto_l2l3 *l3h;
+       struct osmo_pcap_proto_l2 *l2h;
+       struct osmo_pcap_proto_l3 *l3h;
        struct osmo_pcap_proto_l4 *l4h;
        struct pcap_pkthdr pcaph;
-       const u_char *pkt;
+       const u_char *l2pkt, *l3pkt;
        struct timeval res;
        uint8_t l4protonum;
 
@@ -115,26 +118,34 @@
        }
 
 retry:
-       pkt = pcap_next(p->h, &pcaph);
-       if (pkt == NULL)
+       l2pkt = pcap_next(p->h, &pcaph);
+       if (l2pkt == NULL)
                return -1;
 
        osmo_pcap_test_stats.pkts++;
 
-       l3h = osmo_pcap_proto_l2l3_find(pkt);
+       int linktype = pcap_datalink(p->h);
+       l2h = osmo_pcap_proto_l2_find(linktype);
+       if (l2h == NULL) {
+               osmo_pcap_test_stats.unsupported_l2++;
+               goto retry;
+       }
+
+       l3h = osmo_pcap_proto_l3_find(l2h->l3pkt_proto(l2pkt));
        if (l3h == NULL) {
                osmo_pcap_test_stats.unsupported_l3++;
                goto retry;
        }
-       l4protonum = l3h->l4pkt_proto(pkt + ETH_HLEN);
 
+       l3pkt = l2pkt + l2h->l2pkt_hdr_len(l2pkt);
+       l4protonum = l3h->l4pkt_proto(l3pkt);
        /* filter l4 protocols we are not interested in */
        if (l4protonum != pnum) {
                osmo_pcap_test_stats.skip++;
                goto retry;
        }
 
-       l4h = osmo_pcap_proto_l4_find(pkt, l4protonum);
+       l4h = osmo_pcap_proto_l4_find(l4protonum);
        if (l4h == NULL) {
                osmo_pcap_test_stats.unsupported_l4++;
                goto retry;
@@ -145,7 +156,7 @@
                memcpy(&p->last, &pcaph.ts, sizeof(struct timeval));
 
        /* retry with next packet if this has been skipped. */
-       if (osmo_pcap_process_packet(&p->deliver_msg, pkt, pcaph.caplen, l3h, 
l4h, cb) < 0)
+       if (osmo_pcap_process_packet(&p->deliver_msg, l2pkt, pcaph.caplen, l2h, 
l3h, l4h, cb) < 0)
                goto retry;
 
        /* calculate waiting time */
@@ -161,19 +172,22 @@
 
 void osmo_pcap_stats_printf(void)
 {
-       printf("pkts=%d processed=%d skip=%d "
+       printf("pkts=%d processed=%d skip=%d unsupported_l2=%d "
                "unsupported_l3=%d unsupported_l4=%d\n",
                osmo_pcap_test_stats.pkts,
                osmo_pcap_test_stats.processed,
                osmo_pcap_test_stats.skip,
+               osmo_pcap_test_stats.unsupported_l2,
                osmo_pcap_test_stats.unsupported_l3,
                osmo_pcap_test_stats.unsupported_l4);
 }
 
 void osmo_pcap_init(void)
 {
-       /* Initialization of supported layer 3 and 4 protocols here. */
-       l2l3_ipv4_init();
+       /* Initialization of supported layer 2, 3 and 4 protocols here. */
+       l2_eth_init();
+       l2_sll_init();
+       l3_ipv4_init();
        l4_tcp_init();
        l4_udp_init();
 }
diff --git a/tests/osmo-pcap-test/proto.c b/tests/osmo-pcap-test/proto.c
index f90f07c..085ca25 100644
--- a/tests/osmo-pcap-test/proto.c
+++ b/tests/osmo-pcap-test/proto.c
@@ -15,28 +15,46 @@
 #include <osmocom/core/linuxlist.h>
 #include "proto.h"
 
-static LLIST_HEAD(l2l3_proto_list);
+static LLIST_HEAD(l2_proto_list);
+static LLIST_HEAD(l3_proto_list);
 static LLIST_HEAD(l4_proto_list);
+#include <stdio.h>
 
-struct osmo_pcap_proto_l2l3 *osmo_pcap_proto_l2l3_find(const uint8_t *pkt)
+struct osmo_pcap_proto_l2 *osmo_pcap_proto_l2_find(unsigned int pcap_linktype)
 {
-       const struct ethhdr *eh = (const struct ethhdr *)pkt;
-       struct osmo_pcap_proto_l2l3 *cur;
+       struct osmo_pcap_proto_l2 *cur;
 
-       llist_for_each_entry(cur, &l2l3_proto_list, head) {
-               if (ntohs(cur->l2protonum) == eh->h_proto)
+       llist_for_each_entry(cur, &l2_proto_list, head) {
+               if (cur->l2protonum == pcap_linktype)
                        return cur;
        }
        return NULL;
 }
 
-void osmo_pcap_proto_l2l3_register(struct osmo_pcap_proto_l2l3 *h)
+void osmo_pcap_proto_l2_register(struct osmo_pcap_proto_l2 *h)
 {
-       llist_add(&h->head, &l2l3_proto_list);
+       llist_add(&h->head, &l2_proto_list);
+}
+
+
+struct osmo_pcap_proto_l3 *osmo_pcap_proto_l3_find(unsigned int l3protocol)
+{
+       struct osmo_pcap_proto_l3 *cur;
+
+       llist_for_each_entry(cur, &l3_proto_list, head) {
+               if (ntohs(cur->l3protonum) == l3protocol)
+                       return cur;
+       }
+       return NULL;
+}
+
+void osmo_pcap_proto_l3_register(struct osmo_pcap_proto_l3 *h)
+{
+       llist_add(&h->head, &l3_proto_list);
 }
 
 struct osmo_pcap_proto_l4 *
-osmo_pcap_proto_l4_find(const uint8_t *pkt, unsigned int l4protocol)
+osmo_pcap_proto_l4_find(unsigned int l4protocol)
 {
        struct osmo_pcap_proto_l4 *cur;
 
diff --git a/tests/osmo-pcap-test/proto.h b/tests/osmo-pcap-test/proto.h
index 8cb41ed..2580058 100644
--- a/tests/osmo-pcap-test/proto.h
+++ b/tests/osmo-pcap-test/proto.h
@@ -10,30 +10,42 @@
 
        unsigned int            l4protonum;
 
-       int     (*l4pkt_hdr_len)(const uint8_t *pkt);
-       int     (*l4pkt_no_data)(const uint8_t *pkt);
+       unsigned int    (*l4pkt_hdr_len)(const uint8_t *pkt);
+       unsigned int    (*l4pkt_no_data)(const uint8_t *pkt);
 };
 
-struct osmo_pcap_proto_l2l3 {
+struct osmo_pcap_proto_l3 {
        struct llist_head       head;
-
-       unsigned int            l2protonum;
-       unsigned int            l2hdr_len;
 
        unsigned int            l3protonum;
 
-       int     (*l3pkt_hdr_len)(const uint8_t *pkt);
-       int     (*l4pkt_proto)(const uint8_t *pkt);
+       unsigned int    (*l3pkt_hdr_len)(const uint8_t *pkt);
+       unsigned int    (*l4pkt_proto)(const uint8_t *pkt);
 };
 
-struct osmo_pcap_proto_l2l3 *osmo_pcap_proto_l2l3_find(const uint8_t *pkt);
-void osmo_pcap_proto_l2l3_register(struct osmo_pcap_proto_l2l3 *h);
+struct osmo_pcap_proto_l2 {
+       struct llist_head       head;
 
-struct osmo_pcap_proto_l4 *osmo_pcap_proto_l4_find(const uint8_t *pkt, 
unsigned int l4protonum);
+       unsigned int            l2protonum;
+
+       unsigned int    (*l2pkt_hdr_len)(const uint8_t *pkt);
+       unsigned int    (*l3pkt_proto)(const uint8_t *pkt);
+};
+
+
+struct osmo_pcap_proto_l2 *osmo_pcap_proto_l2_find(unsigned int pcap_linktype);
+void osmo_pcap_proto_l2_register(struct osmo_pcap_proto_l2 *h);
+
+struct osmo_pcap_proto_l3 *osmo_pcap_proto_l3_find(unsigned int l3protonum);
+void osmo_pcap_proto_l3_register(struct osmo_pcap_proto_l3 *h);
+
+struct osmo_pcap_proto_l4 *osmo_pcap_proto_l4_find(unsigned int l4protonum);
 void osmo_pcap_proto_l4_register(struct osmo_pcap_proto_l4 *h);
 
 /* Initialization of supported protocols here. */
-void l2l3_ipv4_init(void);
+void l2_sll_init(void);
+void l2_eth_init(void);
+void l3_ipv4_init(void);
 void l4_tcp_init(void);
 void l4_udp_init(void);
 

-- 
To view, visit https://gerrit.osmocom.org/3064
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ie62fa0a8e45e1e141edb64b116dad185ad9c7a5f
Gerrit-PatchSet: 2
Gerrit-Project: libosmo-netif
Gerrit-Branch: master
Gerrit-Owner: Pau Espin Pedrol <pes...@sysmocom.de>
Gerrit-Reviewer: Harald Welte <lafo...@gnumonks.org>
Gerrit-Reviewer: Jenkins Builder

Reply via email to