Improved EoE state machine.
--- 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;
}
}