Improved EoE state machine.
authorFlorian Pose <fp@igh-essen.com>
Tue, 01 Aug 2006 18:37:55 +0000
changeset 322 fceb7b6e0a06
parent 321 64e20e6e9d0b
child 323 d8ac7b1d260e
Improved EoE state machine.
master/ethernet.c
--- a/master/ethernet.c	Tue Aug 01 15:19:11 2006 +0000
+++ b/master/ethernet.c	Tue Aug 01 18:37:55 2006 +0000
@@ -384,114 +384,116 @@
 
     frame_type = EC_READ_U16(data) & 0x000F;
 
-    if (frame_type == 0x00) { // EoE Fragment Request
-        last_fragment = (EC_READ_U16(data) >> 8) & 0x0001;
-        time_appended = (EC_READ_U16(data) >> 9) & 0x0001;
-        fragment_number = EC_READ_U16(data + 2) & 0x003F;
-        fragment_offset = (EC_READ_U16(data + 2) >> 6) & 0x003F;
-        frame_number = (EC_READ_U16(data + 2) >> 12) & 0x000F;
-
-#if EOE_DEBUG_LEVEL > 0
-        EC_DBG("EoE RX fragment %i, offset %i, frame %i%s%s,"
-               " %i octets\n", fragment_number, fragment_offset,
-               frame_number,
-               last_fragment ? ", last fragment" : "",
-               time_appended ? ", + timestamp" : "",
-               time_appended ? rec_size - 8 : rec_size - 4);
-#endif
-
-#if EOE_DEBUG_LEVEL > 1
-        EC_DBG("");
-        for (i = 0; i < rec_size - 4; i++) {
-            printk("%02X ", data[i + 4]);
-            if ((i + 1) % 16 == 0) {
-                printk("\n");
-                EC_DBG("");
-            }
-        }
-        printk("\n");
-#endif
-
-        data_size = time_appended ? rec_size - 8 : rec_size - 4;
-
-        if (!fragment_number) {
-            if (eoe->rx_skb) {
-                EC_WARN("EoE RX freeing old socket buffer...\n");
-                dev_kfree_skb(eoe->rx_skb);
-            }
-
-            // new socket buffer
-            if (!(eoe->rx_skb = dev_alloc_skb(fragment_offset * 32))) {
-                if (printk_ratelimit())
-                    EC_WARN("EoE RX low on mem. frame dropped.\n");
-                eoe->stats.rx_dropped++;
-                eoe->state = ec_eoe_state_tx_start;
-                return;
-            }
-
-            eoe->rx_skb_offset = 0;
-            eoe->rx_skb_size = fragment_offset * 32;
-            eoe->rx_expected_fragment = 0;
-        }
-        else {
-            if (!eoe->rx_skb) {
-                eoe->stats.rx_dropped++;
-                eoe->state = ec_eoe_state_tx_start;
-                return;
-            }
-
-            offset = fragment_offset * 32;
-            if (offset != eoe->rx_skb_offset ||
-                offset + data_size > eoe->rx_skb_size ||
-                fragment_number != eoe->rx_expected_fragment) {
-                eoe->stats.rx_errors++;
-                eoe->state = ec_eoe_state_tx_start;
-                dev_kfree_skb(eoe->rx_skb);
-                eoe->rx_skb = NULL;
-                return;
-            }
-        }
-
-        // copy fragment into socket buffer
-        memcpy(skb_put(eoe->rx_skb, data_size), data + 4, data_size);
-        eoe->rx_skb_offset += data_size;
-
-        if (last_fragment) {
-            // update statistics
-            eoe->stats.rx_packets++;
-            eoe->stats.rx_bytes += eoe->rx_skb->len;
-
-#if EOE_DEBUG_LEVEL > 0
-            EC_DBG("EoE RX frame completed with %u octets.\n",
-                   eoe->rx_skb->len);
-#endif
-
-            // pass socket buffer to network stack
-            eoe->rx_skb->dev = eoe->dev;
-            eoe->rx_skb->protocol = eth_type_trans(eoe->rx_skb, eoe->dev);
-            eoe->rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
-            if (netif_rx(eoe->rx_skb)) {
-                EC_WARN("EoE RX netif_rx failed.\n");
-            }
-            eoe->rx_skb = NULL;
-
-            eoe->state = ec_eoe_state_tx_start;
-        }
-        else {
-            eoe->rx_expected_fragment++;
-#if EOE_DEBUG_LEVEL > 0
-            EC_DBG("EoE RX expecting fragment %i\n",
-                   eoe->rx_expected_fragment);
-#endif
-            eoe->state = ec_eoe_state_rx_start;
-        }
-    }
-    else {
+    if (frame_type != 0x00) {
 #if EOE_DEBUG_LEVEL > 0
         EC_DBG("other frame received.\n");
 #endif
         eoe->stats.rx_dropped++;
         eoe->state = ec_eoe_state_tx_start;
+        return;
+    }
+
+    // EoE Fragment Request received
+
+    last_fragment = (EC_READ_U16(data) >> 8) & 0x0001;
+    time_appended = (EC_READ_U16(data) >> 9) & 0x0001;
+    fragment_number = EC_READ_U16(data + 2) & 0x003F;
+    fragment_offset = (EC_READ_U16(data + 2) >> 6) & 0x003F;
+    frame_number = (EC_READ_U16(data + 2) >> 12) & 0x000F;
+
+#if EOE_DEBUG_LEVEL > 0
+    EC_DBG("EoE RX fragment %i, offset %i, frame %i%s%s,"
+           " %i octets\n", fragment_number, fragment_offset,
+           frame_number,
+           last_fragment ? ", last fragment" : "",
+           time_appended ? ", + timestamp" : "",
+           time_appended ? rec_size - 8 : rec_size - 4);
+#endif
+
+#if EOE_DEBUG_LEVEL > 1
+    EC_DBG("");
+    for (i = 0; i < rec_size - 4; i++) {
+        printk("%02X ", data[i + 4]);
+        if ((i + 1) % 16 == 0) {
+            printk("\n");
+            EC_DBG("");
+        }
+    }
+    printk("\n");
+#endif
+
+    data_size = time_appended ? rec_size - 8 : rec_size - 4;
+
+    if (!fragment_number) {
+        if (eoe->rx_skb) {
+            EC_WARN("EoE RX freeing old socket buffer...\n");
+            dev_kfree_skb(eoe->rx_skb);
+        }
+
+        // new socket buffer
+        if (!(eoe->rx_skb = dev_alloc_skb(fragment_offset * 32))) {
+            if (printk_ratelimit())
+                EC_WARN("EoE RX low on mem. frame dropped.\n");
+            eoe->stats.rx_dropped++;
+            eoe->state = ec_eoe_state_tx_start;
+            return;
+        }
+
+        eoe->rx_skb_offset = 0;
+        eoe->rx_skb_size = fragment_offset * 32;
+        eoe->rx_expected_fragment = 0;
+    }
+    else {
+        if (!eoe->rx_skb) {
+            eoe->stats.rx_dropped++;
+            eoe->state = ec_eoe_state_tx_start;
+            return;
+        }
+
+        offset = fragment_offset * 32;
+        if (offset != eoe->rx_skb_offset ||
+            offset + data_size > eoe->rx_skb_size ||
+            fragment_number != eoe->rx_expected_fragment) {
+            dev_kfree_skb(eoe->rx_skb);
+            eoe->rx_skb = NULL;
+            eoe->stats.rx_errors++;
+            eoe->state = ec_eoe_state_tx_start;
+            return;
+        }
+    }
+
+    // copy fragment into socket buffer
+    memcpy(skb_put(eoe->rx_skb, data_size), data + 4, data_size);
+    eoe->rx_skb_offset += data_size;
+
+    if (last_fragment) {
+        // update statistics
+        eoe->stats.rx_packets++;
+        eoe->stats.rx_bytes += eoe->rx_skb->len;
+
+#if EOE_DEBUG_LEVEL > 0
+        EC_DBG("EoE RX frame completed with %u octets.\n",
+               eoe->rx_skb->len);
+#endif
+
+        // pass socket buffer to network stack
+        eoe->rx_skb->dev = eoe->dev;
+        eoe->rx_skb->protocol = eth_type_trans(eoe->rx_skb, eoe->dev);
+        eoe->rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
+        if (netif_rx(eoe->rx_skb)) {
+            EC_WARN("EoE RX netif_rx failed.\n");
+        }
+        eoe->rx_skb = NULL;
+
+        eoe->state = ec_eoe_state_tx_start;
+    }
+    else {
+        eoe->rx_expected_fragment++;
+#if EOE_DEBUG_LEVEL > 0
+        EC_DBG("EoE RX expecting fragment %i\n",
+               eoe->rx_expected_fragment);
+#endif
+        eoe->state = ec_eoe_state_rx_start;
     }
 }