Improved EoE state machine.
This commit is contained in:
parent
973af4179d
commit
e662e98464
|
|
@ -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 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue