Skip to content
Snippets Groups Projects
Commit 27f4c209 authored by Florian Pose's avatar Florian Pose
Browse files

Improved EoE state machine.

parent 52601263
No related branches found
No related tags found
No related merge requests found
......@@ -384,114 +384,116 @@ void ec_eoe_state_rx_fetch(ec_eoe_t *eoe /**< EoE handler */)
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 (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);
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("");
}
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");
}
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;
}
}
data_size = time_appended ? rec_size - 8 : rec_size - 4;
// copy fragment into socket buffer
memcpy(skb_put(eoe->rx_skb, data_size), data + 4, data_size);
eoe->rx_skb_offset += data_size;
if (!fragment_number) {
if (eoe->rx_skb) {
EC_WARN("EoE RX freeing old socket buffer...\n");
dev_kfree_skb(eoe->rx_skb);
}
if (last_fragment) {
// update statistics
eoe->stats.rx_packets++;
eoe->stats.rx_bytes += eoe->rx_skb->len;
// 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;
}
#if EOE_DEBUG_LEVEL > 0
EC_DBG("EoE RX frame completed with %u octets.\n",
eoe->rx_skb->len);
#endif
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;
}
// 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");
}
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;
}
else {
eoe->rx_expected_fragment++;
}
// 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 expecting fragment %i\n",
eoe->rx_expected_fragment);
EC_DBG("EoE RX frame completed with %u octets.\n",
eoe->rx_skb->len);
#endif
eoe->state = ec_eoe_state_rx_start;
// 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("other frame received.\n");
EC_DBG("EoE RX expecting fragment %i\n",
eoe->rx_expected_fragment);
#endif
eoe->stats.rx_dropped++;
eoe->state = ec_eoe_state_tx_start;
eoe->state = ec_eoe_state_rx_start;
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment