From e644fd10c02b2b94f6fbe4dde23fb0e5c9af84b3 Mon Sep 17 00:00:00 2001
From: phil <me@filou.se>
Date: Wed, 9 Jun 2021 16:00:06 +0200
Subject: [PATCH] eth basics

---
 CMakeLists.txt          |   2 +
 README.md               |   3 +-
 src/core/eth.c          |  37 ++++++++++
 src/include/aes67/def.h |   1 +
 src/include/aes67/eth.h | 157 ++++++++++++++++++++++++++++++++++++++++
 test/CMakeLists.txt     |   1 +
 test/unit/eth.cpp       |  57 +++++++++++++++
 7 files changed, 257 insertions(+), 1 deletion(-)
 create mode 100644 src/core/eth.c
 create mode 100644 src/include/aes67/eth.h
 create mode 100644 test/unit/eth.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index ba8d1d9..011e57c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -54,6 +54,7 @@ set(AES67_INCLUDES
         ${AES67_DIR}/src/include/aes67/rtp-avp.h
         ${AES67_DIR}/src/include/aes67/rtp.h
         ${AES67_DIR}/src/include/aes67/audio.h
+        ${AES67_DIR}/src/include/aes67/eth.h
 
         ${AES67_DIR}/src/include/aes67/host/time.h
         ${AES67_DIR}/src/include/aes67/host/timer.h
@@ -69,6 +70,7 @@ set(AES67_SOURCE_FILES
         ${AES67_DIR}/src/core/sdp.c
         ${AES67_DIR}/src/core/sap.c
         ${AES67_DIR}/src/core/rtp.c
+        ${AES67_DIR}/src/core/eth.c
 
 )
 
diff --git a/README.md b/README.md
index 63b46a4..02f76c8 100644
--- a/README.md
+++ b/README.md
@@ -33,7 +33,8 @@ https://github.com/tschiemer/aes67
 
 
 - Stream
-  - [ ] RTP/RTCP
+  - [ ] RTP
+  - [ ] RTCP
 
   
 - Command line / developer utilities
diff --git a/src/core/eth.c b/src/core/eth.c
new file mode 100644
index 0000000..2a3ac49
--- /dev/null
+++ b/src/core/eth.c
@@ -0,0 +1,37 @@
+/**
+ * AES67 Framework
+ * Copyright (C) 2021  Philip Tschiemer, https://github.com/tschiemer/aes67
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "aes67/eth.h"
+
+u16_t aes67_ipv4_header_checksum(u8_t * header)
+{
+    int len = (header[AES67_IPV4_HEADER_IHL_OFFSET] & AES67_IPV4_HEADER_IHL_MASK) << 1;
+
+    u32_t sum = 0;
+    while(len--){
+        sum += *(header++) << 8;
+        sum += *(header++);
+    }
+
+    sum = (sum & 0xffff) + (sum >> 16);
+    sum = (sum & 0xffff) + (sum >> 16);
+
+    sum = (~sum) & 0xffff;
+
+    return sum;
+}
\ No newline at end of file
diff --git a/src/include/aes67/def.h b/src/include/aes67/def.h
index 21859f1..ab9f0f9 100644
--- a/src/include/aes67/def.h
+++ b/src/include/aes67/def.h
@@ -161,6 +161,7 @@ s32_t aes67_atoi(u8_t * str, size_t len, s32_t base, u16_t * readlen);
 u8_t aes67_xor8(u8_t * buf, size_t count);
 
 #ifndef aes67_crc32
+#define AES67_CRC32_VERIFY_VALUE 0x2144DF1C
 u32_t aes67_crc32(u8_t * buf, size_t count);
 #endif
 
diff --git a/src/include/aes67/eth.h b/src/include/aes67/eth.h
new file mode 100644
index 0000000..8f6fc1c
--- /dev/null
+++ b/src/include/aes67/eth.h
@@ -0,0 +1,157 @@
+/**
+ * @file eth.h
+ * Lower level networking utilities, ethernet, ip, udp.
+ *
+ * References:
+ * AES67-2018 https://www.aes.org/publications/standards/search.cfm?docID=96
+ */
+
+/**
+ * AES67 Framework
+ * Copyright (C) 2021  Philip Tschiemer, https://github.com/tschiemer/aes67
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef AES67_ETH_H
+#define AES67_ETH_H
+
+#include "aes67/arch.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//#define AES67_ETH_HEADER_DST    0
+//#define AES67_ETH_HEADER_SRC    6
+//#define
+
+#define AES67_ETH_ETHERTYPE_IPv4        0x0800
+#define AES67_ETH_ETHERTYPE_ARP         0x0806  // address resolution protocol
+#define AES67_ETH_ETHERTYPE_AVTP        0x22f0  // audio video transport protocol
+#define AES67_ETH_ETHERTYPE_SRP         0x22ea  // stream reservation protocol
+#define AES67_ETH_ETHERTYPE_IPv6        0x86dd
+#define AES67_ETH_ETHERTYPE_VLAN_TAG    0x8100
+#define AES67_ETH_ETHERTYPE_IPv6        0x86dd
+#define AES67_ETH_ETHERTYPE_CobraNet    0x8819
+
+//#define AES67_ETH_CRC32_POLY            0x04c11db7
+//#define AES67_ETH_CRC32_INITIAL         0xffffffff
+
+#define AES67_IPV4_HEADER_MINSIZE                   20
+
+#define AES67_IPV4_HEADER_VERSION_OFFSET            0
+#define AES67_IPV4_HEADER_VERSION_MASK              0xf0
+#define AES67_IPV4_HEADER_IHL_OFFSET                0
+#define AES67_IPV4_HEADER_IHL_MASK                  0x0f
+#define AES67_IPV4_HEADER_DSCP_OFFSET               1  // Differentiated Services Code Point (DiffServ)
+#define AES67_IPV4_HEADER_DSCP_MASK                 0b11111100
+#define AES67_IPV4_HEADER_ECN_OFFSET                1        // Explicit Congestion Notification
+#define AES67_IPV4_HEADER_ECN_MASK                  0b11
+#define AES67_IPV4_HEADER_LENGTH_OFFSET             2
+#define AES67_IPV4_HEADER_IDENTIFICATION_OFFSET     4
+#define AES67_IPV4_HEADER_FRAGMENTATION_OFFSET      6
+#define AES67_IPV4_HEADER_FRAGMENTATION_FLAGS_MASK  0b1110000000000000
+#define AES67_IPV4_HEADER_FRAGMENTATION_FOFFSET_MASK    0b000111111111111
+#define AES67_IPV4_HEADER_TTL_OFFSET                8
+#define AES67_IPV4_HEADER_PROTOCOL_OFFSET           9
+#define AES67_IPV4_HEADER_HEADER_CHECKSUM_OFFSET    10
+#define AES67_IPV4_HEADER_SOURCE_OFFSET             12
+#define AES67_IPV4_HEADER_DESTINATION_OFFSET        16
+#define AES67_IPV4_HEADER_DATA_OFFSET               20  // assuming IHL == 5 (ie no extra headers)
+
+#define AES67_IPV4_HEADER_VERSION_4                 0x40
+#define AES67_IPV4_HEADER_IHL_BASIC                 0x05
+
+#define AES67_IPV4_HEADER_DSCP_DEFAULT              0
+#define AES67_IPV4_HEADER_DSCP_DEFAULT_CLOCK        (46<<2)     // Class EF
+#define AES67_IPV4_HEADER_DSCP_DEFAULT_MEDIA        (34<<2)     // Class AF41
+
+#define AES67_IPV4_HEADER_ECN_NON_ECT               0   // Non ECN capable transport
+#define AES67_IPV4_HEADER_ECN_ECT0                  1   // ECN capable transport 0
+#define AES67_IPV4_HEADER_ECN_ECT1                  2   // ECN capable transport 1
+#define AES67_IPV4_HEADER_ECN_CE                    3   // Congestion encountered
+
+
+#define AES67_IPV4_HEADER_FRAGMENTATION_FLAGS_DF    0b0100000000000000  // don't fragment
+#define AES67_IPV4_HEADER_FRAGMENTATION_FLAGS_MF    0b0010000000000000  // more fragments
+
+#define AES67_IPV4_HEADER_PROTOCOL_ICMP             0x01
+#define AES67_IPV4_HEADER_PROTOCOL_IGMP             0x02
+#define AES67_IPV4_HEADER_PROTOCOL_TCP              0x06
+#define AES67_IPV4_HEADER_PROTOCOL_UDP              0x11
+#define AES67_IPV4_HEADER_PROTOCOL_RSVP             0x2e
+
+// No 802.1Q headers
+struct aes67_eth_frame {
+    u8_t destination[6];
+    u8_t source[6];
+    u8_t tpid[2];
+    u16_t length;
+    u8_t data[];
+} PACK_STRUCT;
+
+
+struct aes67_ipv4_packet {
+    u8_t byte0;             // version + IHL
+    u8_t byte1;             // DSCP + ECN
+    u16_t length;           // total packet size (header + data, >= 20)
+    u16_t identification;   // fragmentation identification
+    u16_t fragmentation;    // flags + offset
+    u8_t ttl;               // time to live
+    u8_t protocol;          //
+    u16_t header_checksum;  // The checksum field is the 16-bit ones' complement of the ones' complement sum of all
+                            // 16-bit words in the header. For purposes of computing the checksum, the value of the
+                            // checksum field is zero.
+    union {
+        u8_t bytes[4];
+        u32_t value;
+    } PACK_STRUCT source;
+    union {
+        u8_t bytes[4];
+        u32_t value;
+    } PACK_STRUCT destination;
+    u8_t data[];
+} PACK_STRUCT;
+
+struct aes67_udp_packet {
+    u16_t source_port;
+    u16_t destination_port;
+    u16_t length;
+    u16_t checksum;
+    u8_t data[];
+} PACK_STRUCT;
+
+struct aes67_udp_ipv4_pseudoheader {
+    union {
+        u8_t bytes[4];
+        u32_t value;
+    } PACK_STRUCT source;
+    union {
+        u8_t bytes[4];
+        u32_t value;
+    } PACK_STRUCT destination;
+    u8_t zeroes;
+    u8_t protocol;
+    u16_t udp_length;
+    struct aes67_udp_packet udp;
+};
+
+u16_t aes67_ipv4_header_checksum(u8_t * header);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //AES67_ETH_H
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index fbf7bf4..8d0ecea 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -30,6 +30,7 @@ set(TEST_UNIT_SOURCE_FILES
         unit/sap.cpp
         unit/sdp.cpp
         unit/rtp.cpp
+        unit/eth.cpp
         )
 
 
diff --git a/test/unit/eth.cpp b/test/unit/eth.cpp
new file mode 100644
index 0000000..bd198c5
--- /dev/null
+++ b/test/unit/eth.cpp
@@ -0,0 +1,57 @@
+/**
+ * AES67 Framework
+ * Copyright (C) 2021  Philip Tschiemer, https://github.com/tschiemer/aes67
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "CppUTest/TestHarness.h"
+
+#include <string>
+
+#include "aes67/eth.h"
+
+TEST_GROUP(Eth_TestGroup){};
+
+TEST(Eth_TestGroup, eth_ipv4_header_checksum) {
+
+    // test value from https://en.wikipedia.org/wiki/IPv4_header_checksum
+
+    // without checksum
+    uint8_t ip1[] = {
+            0x45, 0x00, 0x00, 0x73, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
+            0, 0, // checksum
+            0xc0, 0xa8, 0x00, 0x01,
+            0xc0, 0xa8, 0x00, 0xc7, // end of header
+            0x00, 0x35, 0xe9, 0x7c, 0x00, 0x5f, 0x27, 0x9f, 0x1e, 0x4b, 0x81, 0x80
+    };
+
+    u16_t ck = aes67_ipv4_header_checksum(ip1);
+
+    CHECK_EQUAL(0xb861, ck);
+
+    // same WITH checksum
+    uint8_t ip2[] = {
+            0x45, 0x00, 0x00, 0x73, 0x00, 0x00, 0x40, 0x00, 0x40,
+            0x11, 0xb8, // checksum
+            0x61, 0xc0, 0xa8, 0x00, 0x01,
+            0xc0, 0xa8, 0x00, 0xc7, // end of header
+            0x00, 0x35, 0xe9, 0x7c, 0x00, 0x5f, 0x27, 0x9f, 0x1e, 0x4b, 0x81, 0x80
+    };
+
+    ck = aes67_ipv4_header_checksum(ip2);
+
+    CHECK_EQUAL(0x0000, ck);
+}
\ No newline at end of file
-- 
GitLab