Files
arnet/arnet.c

247 lines
12 KiB
C
Raw Normal View History

2022-10-24 19:21:04 +02:00
/*
* The ArNet protocol
* https://ciapini.wiki.esiliati.org/view/ArNet
*/
#include <stdint.h>
#include "../../ringbuf.h"
#include "../net.h"
#include "arnet.h"
uint8_t arnet_tx_headers_pending, arnet_tx_headers_done[16], arnet_rx_headers_parsed;
arnet_packet arnet_tx_packet_queue[NET_PACKET_RINGBUF_SIZE], arnet_rx_packet_queue[NET_PACKET_RINGBUF_SIZE];
arnet_node_state node;
arnet_segment_state segment;
arnet_connection_state connection[ARNET_ADDRESS_SIZE];
/* CRC24 table - FCS */
static const uint32_t tbl_crc24[256] = {
0x00000000, 0x00d6a776, 0x00f64557, 0x0020e221, 0x00b78115, 0x00612663, 0x0041c442, 0x00976334,
0x00340991, 0x00e2aee7, 0x00c24cc6, 0x0014ebb0, 0x00838884, 0x00552ff2, 0x0075cdd3, 0x00a36aa5,
0x00681322, 0x00beb454, 0x009e5675, 0x0048f103, 0x00df9237, 0x00093541, 0x0029d760, 0x00ff7016,
0x005c1ab3, 0x008abdc5, 0x00aa5fe4, 0x007cf892, 0x00eb9ba6, 0x003d3cd0, 0x001ddef1, 0x00cb7987,
0x00d02644, 0x00068132, 0x00266313, 0x00f0c465, 0x0067a751, 0x00b10027, 0x0091e206, 0x00474570,
0x00e42fd5, 0x003288a3, 0x00126a82, 0x00c4cdf4, 0x0053aec0, 0x008509b6, 0x00a5eb97, 0x00734ce1,
0x00b83566, 0x006e9210, 0x004e7031, 0x0098d747, 0x000fb473, 0x00d91305, 0x00f9f124, 0x002f5652,
0x008c3cf7, 0x005a9b81, 0x007a79a0, 0x00acded6, 0x003bbde2, 0x00ed1a94, 0x00cdf8b5, 0x001b5fc3,
0x00fb4733, 0x002de045, 0x000d0264, 0x00dba512, 0x004cc626, 0x009a6150, 0x00ba8371, 0x006c2407,
0x00cf4ea2, 0x0019e9d4, 0x00390bf5, 0x00efac83, 0x0078cfb7, 0x00ae68c1, 0x008e8ae0, 0x00582d96,
0x00935411, 0x0045f367, 0x00651146, 0x00b3b630, 0x0024d504, 0x00f27272, 0x00d29053, 0x00043725,
0x00a75d80, 0x0071faf6, 0x005118d7, 0x0087bfa1, 0x0010dc95, 0x00c67be3, 0x00e699c2, 0x00303eb4,
0x002b6177, 0x00fdc601, 0x00dd2420, 0x000b8356, 0x009ce062, 0x004a4714, 0x006aa535, 0x00bc0243,
0x001f68e6, 0x00c9cf90, 0x00e92db1, 0x003f8ac7, 0x00a8e9f3, 0x007e4e85, 0x005eaca4, 0x00880bd2,
0x00437255, 0x0095d523, 0x00b53702, 0x00639074, 0x00f4f340, 0x00225436, 0x0002b617, 0x00d41161,
0x00777bc4, 0x00a1dcb2, 0x00813e93, 0x005799e5, 0x00c0fad1, 0x00165da7, 0x0036bf86, 0x00e018f0,
0x00ad85dd, 0x007b22ab, 0x005bc08a, 0x008d67fc, 0x001a04c8, 0x00cca3be, 0x00ec419f, 0x003ae6e9,
0x00998c4c, 0x004f2b3a, 0x006fc91b, 0x00b96e6d, 0x002e0d59, 0x00f8aa2f, 0x00d8480e, 0x000eef78,
0x00c596ff, 0x00133189, 0x0033d3a8, 0x00e574de, 0x007217ea, 0x00a4b09c, 0x008452bd, 0x0052f5cb,
0x00f19f6e, 0x00273818, 0x0007da39, 0x00d17d4f, 0x00461e7b, 0x0090b90d, 0x00b05b2c, 0x0066fc5a,
0x007da399, 0x00ab04ef, 0x008be6ce, 0x005d41b8, 0x00ca228c, 0x001c85fa, 0x003c67db, 0x00eac0ad,
0x0049aa08, 0x009f0d7e, 0x00bfef5f, 0x00694829, 0x00fe2b1d, 0x00288c6b, 0x00086e4a, 0x00dec93c,
0x0015b0bb, 0x00c317cd, 0x00e3f5ec, 0x0035529a, 0x00a231ae, 0x007496d8, 0x005474f9, 0x0082d38f,
0x0021b92a, 0x00f71e5c, 0x00d7fc7d, 0x00015b0b, 0x0096383f, 0x00409f49, 0x00607d68, 0x00b6da1e,
0x0056c2ee, 0x00806598, 0x00a087b9, 0x007620cf, 0x00e143fb, 0x0037e48d, 0x001706ac, 0x00c1a1da,
0x0062cb7f, 0x00b46c09, 0x00948e28, 0x0042295e, 0x00d54a6a, 0x0003ed1c, 0x00230f3d, 0x00f5a84b,
0x003ed1cc, 0x00e876ba, 0x00c8949b, 0x001e33ed, 0x008950d9, 0x005ff7af, 0x007f158e, 0x00a9b2f8,
0x000ad85d, 0x00dc7f2b, 0x00fc9d0a, 0x002a3a7c, 0x00bd5948, 0x006bfe3e, 0x004b1c1f, 0x009dbb69,
0x0086e4aa, 0x005043dc, 0x0070a1fd, 0x00a6068b, 0x003165bf, 0x00e7c2c9, 0x00c720e8, 0x0011879e,
0x00b2ed3b, 0x00644a4d, 0x0044a86c, 0x00920f1a, 0x00056c2e, 0x00d3cb58, 0x00f32979, 0x00258e0f,
0x00eef788, 0x003850fe, 0x0018b2df, 0x00ce15a9, 0x0059769d, 0x008fd1eb, 0x00af33ca, 0x007994bc,
0x00dafe19, 0x000c596f, 0x002cbb4e, 0x00fa1c38, 0x006d7f0c, 0x00bbd87a, 0x009b3a5b, 0x004d9d2d
};
// da integrare altrove
void arnet_prepare_packet(void) {
arnet_tx_headers_pending = 1; // DH
if (arnet_tx_packet_queue[net_tx_packet_index_out].vc.enabled == 1) arnet_tx_headers_pending++;
if (arnet_tx_packet_queue[net_tx_packet_index_out].ec.enabled == 1) arnet_tx_headers_pending++;
}
void arnet_packet_setup(void) {
arnet_tx_packet_queue[net_tx_packet_index_in].dh.header_size = 0;
arnet_tx_packet_queue[net_tx_packet_index_in].dh.protocol = ARNET_PACKET_PROTOCOL;
arnet_tx_packet_queue[net_tx_packet_index_in].dh.src_addr = node.address;
arnet_tx_packet_queue[net_tx_packet_index_in].dh.dst_addr = node.current_peer;
if (node.enabled.vc == 1) {
// viene popolato in chiusura
arnet_tx_packet_queue[net_tx_packet_index_in].vc.enabled = node.enabled.vc;
arnet_tx_packet_queue[net_tx_packet_index_in].vc.sequence = connection[node.current_peer].sequence;
arnet_tx_packet_queue[net_tx_packet_index_in].dh.header_size++;
}
if (node.enabled.ec == 1) {
// viene popolato in chiusura
arnet_tx_packet_queue[net_tx_packet_index_in].ec.enabled = node.enabled.vc;
arnet_tx_packet_queue[net_tx_packet_index_in].ec.algo = EC_ALGO_CRC24;
arnet_tx_packet_queue[net_tx_packet_index_in].dh.header_size++;
}
}
void arnet_packet_finalize(void) {
if (arnet_tx_packet_queue[net_tx_packet_index_in].vc.enabled == 1) {
// incrementa indice dei pacchetti mandati a questo nodo
connection[arnet_tx_packet_queue[net_tx_packet_index_in].dh.dst_addr].sequence++;
connection[arnet_tx_packet_queue[net_tx_packet_index_in].dh.dst_addr].sequence &= 0xFF; // dovrebbe essere superfluo
}
if (arnet_tx_packet_queue[net_tx_packet_index_in].ec.enabled == 1) {
arnet_tx_packet_queue[net_tx_packet_index_in].ec.value = arnet_generate_ec(net_tx_packet_queue[net_tx_packet_index_in], net_tx_data_ringbuf, arnet_tx_packet_queue[net_tx_packet_index_in].ec.algo);
}
}
// genera header arnet
uint32_t arnet_generate_header(void) {
uint32_t header = 0;
if (arnet_tx_headers_done[HTYPE_DH_VALUE] == 0) {
header |= (uint32_t) ((uint32_t) arnet_tx_packet_queue[net_tx_packet_index_out].dh.protocol << clz(DH_PROTOCOL_MASK));
header |= (uint32_t) ((uint32_t) net_tx_packet_queue[net_tx_packet_index_out].data_size << clz(DH_PAYLOADSIZE_MASK));
header |= (uint32_t) ((uint32_t) arnet_tx_packet_queue[net_tx_packet_index_out].dh.header_size << clz(DH_HEADERSIZE_MASK));
header |= (uint32_t) ((uint32_t) arnet_tx_packet_queue[net_tx_packet_index_out].dh.src_addr << clz(DH_SRC_MASK));
header |= (uint32_t) ((uint32_t) arnet_tx_packet_queue[net_tx_packet_index_out].dh.dst_addr << clz(DH_DST_MASK));
arnet_tx_headers_done[HTYPE_DH_VALUE] = 1;
} else if (arnet_tx_packet_queue[net_tx_packet_index_out].vc.enabled == 1 && arnet_tx_headers_done[HTYPE_VC_VALUE] == 0) {
header |= (uint32_t) ((uint32_t) HTYPE_VC_VALUE << clz(ALLH_HTYPE_MASK));
header |= (uint32_t) ((uint32_t) arnet_tx_packet_queue[net_tx_packet_index_out].vc.sequence << clz(VC_SEQ_MASK));
// questo va stabilito al momento
header |= (uint32_t) ((uint32_t) connection[arnet_tx_packet_queue[net_tx_packet_index_out].dh.dst_addr].acknowledge << clz(VC_ACKSEQ_MASK));
arnet_tx_headers_done[HTYPE_VC_VALUE] = 1;
} else if (arnet_tx_packet_queue[net_tx_packet_index_out].ec.enabled == 1 && arnet_tx_headers_done[HTYPE_EC_VALUE] == 0) {
header |= (uint32_t) ((uint32_t) HTYPE_EC_VALUE << clz(ALLH_HTYPE_MASK));
header |= (uint32_t) ((uint32_t) arnet_tx_packet_queue[net_tx_packet_index_out].ec.value << clz(EC_VALUE_MASK));
arnet_tx_headers_done[HTYPE_EC_VALUE] = 1;
} else {
// boh ?
}
// setta i bytes da mandare, dove va? a cosa serve ?
// arnet_bytes_pending = arnet_tx_packet_queue[net_tx_packet_index_out].dh.payload_size;
return header;
}
// processa blocco header
void arnet_parse_header_block(uint8_t *block, uint8_t block_size, net_packet *net_pck, arnet_packet *arnet_pck) {
uint32_t InputDataBlock = 0;
uint8_t i, InputPacketForMe;
// serializza
for (i = 0; i < block_size; i++) {
InputDataBlock |= (uint32_t) block[i] << (i * 8);
}
if (arnet_rx_headers_parsed == 0) {
// primo header block, e' default
arnet_pck->dh.protocol = get_header_field(InputDataBlock, DH_PROTOCOL_MASK);
if (arnet_pck->dh.protocol != ARNET_PACKET_PROTOCOL) {
// e mo??!?!
// net_rx_state = NET_STATE_IDLE;
}
arnet_pck->dh.src_addr = get_header_field(InputDataBlock, DH_SRC_MASK);
arnet_pck->dh.dst_addr = get_header_field(InputDataBlock, DH_DST_MASK);
if ((arnet_pck->dh.dst_addr == node.address) || (arnet_pck->dh.dst_addr == node.multicast_address) || (arnet_pck->dh.dst_addr == 0)) {
// e' per noi! tenere cmq tutto in coda o fare qualcosa?
InputPacketForMe = 1;
}
arnet_pck->dh.header_size = get_header_field(InputDataBlock, DH_HEADERSIZE_MASK);
net_pck->data_size = get_header_field(InputDataBlock, DH_PAYLOADSIZE_MASK);
} else if (arnet_rx_headers_parsed < (arnet_pck->dh.header_size + 1)) {
// header seguenti
switch (get_header_field(InputDataBlock, ALLH_HTYPE_MASK)) {
case HTYPE_VC_VALUE:
arnet_pck->vc.enabled = 1;
arnet_pck->vc.sequence = get_header_field(InputDataBlock, VC_SEQ_MASK);
arnet_pck->vc.acknowledge = get_header_field(InputDataBlock, VC_ACKSEQ_MASK);
if (arnet_pck->vc.acknowledge == connection[arnet_pck->dh.src_addr].sequence) {
// sequenza corretta, puoi debufferare
} else {
// skip!!!
}
break;
case HTYPE_EC_VALUE:
arnet_pck->ec.enabled = 1;
arnet_pck->ec.algo = get_header_field(InputDataBlock, EC_ALGO_MASK);
arnet_pck->ec.value = get_header_field(InputDataBlock, EC_VALUE_MASK);
break;
}
} else {
}
arnet_rx_headers_parsed++;
// if (arnet_rx_headers_parsed > arnet_pck->dh.header_size) {
// // header completamente parsato
// net_rx_state = NET_STATE_HEADER_DONE;
// arnet_rx_headers_parsed = 0;
//
// // tagga inizio dati - andrebbe fuori
// net_rx_packet_queue[net_rx_packet_index_in].data_start = net_rx_data_ringbuf_input_index; //inizio dati
//
// if (arnet_pck->dh.payload_size > 0) {
// net_rx_data_content = DATA_IS_PAYLOAD;
// net_rx_state = NET_STATE_PAYLOAD_WAIT;
// } else {
// // pacchetto vuoto. qui non sta bene
// net_rx_data_content = DATA_IS_HEADER;
// net_rx_state = NET_STATE_PAYLOAD_DONE;
// StopReceive();
// }
//
// }
}
// estrae campo header
uint32_t get_header_field(uint32_t InputHeaderBlock, uint32_t Mask) {
uint32_t field_value = 0;
field_value = InputHeaderBlock & Mask;
// ndo sta ?
field_value = field_value >> clz(Mask);
return field_value;
}
uint8_t clz(uint32_t in) {
uint8_t i = 0;
while (i < 32) {
if (((in >> i) & 1) == 1) return i;
i++;
}
return i;
}
uint8_t arnet_check_ec(net_packet *net_pck, uint8_t algo) {
uint8_t out;
if (algo == EC_ALGO_CRC24) {
// TODO
} else {
out = ARNET_EC_INVALID_ALGO;
}
return out;
}
uint32_t arnet_generate_ec(net_packet net_pck, uint8_t *data_queue, uint8_t algo) {
uint16_t data_index;
uint32_t crc = 0;
if (algo == EC_ALGO_CRC24) {
data_index = net_pck.data_start;
crc = ARNET_CRC24_INIT;
while (ringbuf_get_distance(net_pck.data_start, data_index, DATA_BUFFER_SIZE, DATA_BUFFER_SIZE_MASK) == net_pck.data_size) {
crc = (crc >> 8) ^ tbl_crc24[(crc ^ data_queue[data_index]) & 0xff];
ringbuf_increment(&data_index, DATA_BUFFER_SIZE_MASK);
}
crc = ~crc;
crc &= 0xffffff;
}
return crc;
}