Merge branch 'master' of epagris.com:epagris/EtherLib

This commit is contained in:
Wiesner András 2025-01-27 17:27:35 +01:00
commit 1127b3dd1d
11 changed files with 65 additions and 18 deletions

View File

@ -5,6 +5,7 @@
#include "eth_interface.h" #include "eth_interface.h"
#include "dynmem.h" #include "dynmem.h"
#include "etherlib/prefab/conn_blocks/ethernet_connblock.h" #include "etherlib/prefab/conn_blocks/ethernet_connblock.h"
#include "etherlib/prefab/packet_parsers/ipv4_types.h"
#include "etherlib_options.h" #include "etherlib_options.h"
#include "utils.h" #include "utils.h"
@ -74,6 +75,11 @@ EthInterface *ethintf_new(EthIODef *io) {
ethIntf->interceptTxCb = NULL; ethIntf->interceptTxCb = NULL;
ethIntf->interceptRxCb = NULL; ethIntf->interceptRxCb = NULL;
ethIntf->ip = 0;
ethIntf->router = 0;
ethIntf->dns = 0;
ethIntf->netmask = IPv4_ANY_ADDR;
ethIntf->linkState = false; ethIntf->linkState = false;
ethintf_register(ethIntf); ethintf_register(ethIntf);

View File

@ -3,6 +3,8 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
/** /**
* \struct RawPckt * \struct RawPckt
* \brief Raw packet received on wire * \brief Raw packet received on wire
@ -20,6 +22,9 @@
uint32_t arg; ///> User-defined argument uint32_t arg; ///> User-defined argument
} tx; } tx;
} ext; ///> Extensions } ext; ///> Extensions
struct {
bool calculate_ethernet_CRC : 1; ///> Instruct the packet assembler to always computer FCS regardless of device capabilities
} opts;
} RawPckt; } RawPckt;
struct PcktHeaderElement_; struct PcktHeaderElement_;

View File

@ -28,7 +28,7 @@ int pckt_assemble(RawPckt *raw, Pckt *cooked, EthInterface *intf) {
hdrIter = hdrIter->next; hdrIter = hdrIter->next;
} }
frameSize = headerSize + cooked->payloadSize;// + 4; // header + payload frameSize = headerSize + cooked->payloadSize;// + 4; // header + payload
bool computeCRC = !(intf->capabilities & ETHINF_CAP_TX_CRC_OFFLOAD); bool computeCRC = (!(intf->capabilities & ETHINF_CAP_TX_CRC_OFFLOAD)) || raw->opts.calculate_ethernet_CRC;
if (computeCRC) { // + CRC32 checksum area if needed if (computeCRC) { // + CRC32 checksum area if needed
frameSize += 4; frameSize += 4;
} }
@ -73,10 +73,10 @@ int pckt_assemble(RawPckt *raw, Pckt *cooked, EthInterface *intf) {
} }
} }
// insert CRC32 if interface is not capable of inserting CRC // insert CRC32 if interface cannot handle CRC calculation or if explicitly requested
if (computeCRC) { if (computeCRC) {
uint32_t crc = crc32(raw->payload, frameSize - 4); uint32_t crc = crc32(raw->payload, frameSize - 4);
memcpy(raw->payload + frameSize - 4, (const uint8_t *)&crc, 4); memcpy(raw->payload + frameSize - 4, &crc, 4);
} }
// turn off TX timestamping by default // turn off TX timestamping by default

View File

@ -80,6 +80,7 @@ void arp_send(const ConnBlock *connBlock, const ArpProps *props) {
// send packet // send packet
RawPckt rpckt; RawPckt rpckt;
memset(&rpckt, 0, sizeof(RawPckt));
rpckt.size = txBufSize; rpckt.size = txBufSize;
rpckt.payload = txBuf; rpckt.payload = txBuf;
rpckt.ext.tx.txTsCb = NULL; rpckt.ext.tx.txTsCb = NULL;

View File

@ -73,6 +73,7 @@ int cet_send_arg(cbd d, const uint8_t *dest, const uint8_t *data, uint16_t size,
cooked.time_ns = 0; cooked.time_ns = 0;
RawPckt raw; RawPckt raw;
memset(&raw, 0, sizeof(RawPckt));
pckt_assemble(&raw, &cooked, connBlock.sieve->intf); pckt_assemble(&raw, &cooked, connBlock.sieve->intf);
raw.ext.tx.arg = arg; // assign argument raw.ext.tx.arg = arg; // assign argument
raw.ext.tx.txTsCb = connBlock.sieveLayer->txTsCb; // assign with TX timestamp callback raw.ext.tx.txTsCb = connBlock.sieveLayer->txTsCb; // assign with TX timestamp callback

View File

@ -81,6 +81,7 @@ static int icmp_recv_cb(const Pckt * pckt, PcktSieveLayerTag tag) {
// assemble packet // assemble packet
RawPckt raw; RawPckt raw;
memset(&raw, 0, sizeof(RawPckt));
pckt_assemble(&raw, &reply, intf); pckt_assemble(&raw, &reply, intf);
// release headers // release headers

View File

@ -7,6 +7,7 @@
#include "../../dynmem.h" #include "../../dynmem.h"
#include "../../pckt_assembler.h" #include "../../pckt_assembler.h"
#include "../../eth_interface.h" #include "../../eth_interface.h"
#include "etherlib/prefab/packet_parsers/ipv4_packet.h"
#include "ipv4_connblock.h" #include "ipv4_connblock.h"
#include "../packet_parsers/igmp_packet.h" #include "../packet_parsers/igmp_packet.h"
@ -37,6 +38,9 @@ ConnBlock igmp_new_connblock(struct EthInterface_ *intf) {
} }
static void igmp_send(ConnBlock * connBlock, ip4_addr ga, int mt) { static void igmp_send(ConnBlock * connBlock, ip4_addr ga, int mt) {
// fetch interface
EthInterface * intf = connBlock->sieve->intf;
// allocate headers // allocate headers
PcktHeaderElement * igmpHeader = ALLOC_HEADER_ELEMENT(IgmpProps); PcktHeaderElement * igmpHeader = ALLOC_HEADER_ELEMENT(IgmpProps);
PcktHeaderElement * ipHeader = ALLOC_HEADER_ELEMENT(IPv4Props); PcktHeaderElement * ipHeader = ALLOC_HEADER_ELEMENT(IPv4Props);
@ -67,34 +71,49 @@ static void igmp_send(ConnBlock * connBlock, ip4_addr ga, int mt) {
// IP // IP
layer = layer->parent; layer = layer->parent;
ipv4_fill_props(ipProps, ETH_IGMP_HEADER_SIZE, ETH_IGMP_PACKET_CLASS, connBlock->sieve->intf->ip, ga); ipv4_fill_props(ipProps, ETH_IGMP_HEADER_SIZE, ETH_IGMP_PACKET_CLASS, intf->ip, ga);
// Ethernet // Ethernet
ethmc_from_ipmc(ethProps->destAddr, ga); ethmc_from_ipmc(ethProps->destAddr, ga);
memcpy(ethProps->sourceAddr, connBlock->sieve->intf->mac, ETH_HW_ADDR_LEN); memcpy(ethProps->sourceAddr, intf->mac, ETH_HW_ADDR_LEN);
ethProps->length_type = ETH_IPv4_PACKET_CLASS; ethProps->length_type = ETH_IPv4_PACKET_CLASS;
// common fields for packet assembly // common fields for packet assembly
ethProps->hdrInsFn = insert_ethernet_header; ethProps->hdrInsFn = insert_ethernet_header;
ethProps->headerSize = ETH_ETHERNET_HEADER_SIZE; ethProps->headerSize = ETH_ETHERNET_HEADER_SIZE;
Pckt cooked; // allocate transmit buffer
cooked.payload = NULL; uint32_t txHeaderSize = ETH_ETHERNET_HEADER_SIZE + ETH_IPv4_HEADER_SIZE + ETH_IGMP_HEADER_SIZE;
cooked.payloadSize = 0; uint32_t txBufSize = MAX(txHeaderSize + 4, ETH_FRAME_MIN_SIZE);
cooked.header = ethHeader; uint8_t *txBuf = dynmem_alloc(txBufSize);
memset(txBuf, 0, txBufSize);
// NOT FILLED FIELDS // insert Ethernet header
cooked.headerSize = 0; insert_ethernet_header(txBuf, ethHeader, NULL);
cooked.time_s = 0;
cooked.time_ns = 0;
RawPckt raw; // insert IPv4 header
pckt_assemble(&raw, &cooked, connBlock->sieve->intf); insert_ipv4_header(txBuf + ETH_ETHERNET_HEADER_SIZE, ipHeader, intf);
ipv4_fill_in_chksum(txBuf + ETH_ETHERNET_HEADER_SIZE); // fill-in IPv4 checksum
ethinf_transmit(connBlock->sieve->intf, &raw); // insert IGMP header
insert_igmp_header(txBuf + ETH_ETHERNET_HEADER_SIZE + ETH_IPv4_HEADER_SIZE, igmpHeader, intf);
// free headers // release headers
pckthdr_chain_free(ethHeader); dynmem_free(ethHeader);
dynmem_free(ipHeader);
dynmem_free(igmpHeader);
// calculate CRC
uint32_t crc = crc32(txBuf, txBufSize - 4);
memcpy(txBuf + txBufSize - 4, &crc, 4);
// send packet
RawPckt rpckt;
memset(&rpckt, 0, sizeof(RawPckt));
rpckt.size = txBufSize;
rpckt.payload = txBuf;
rpckt.ext.tx.txTsCb = NULL;
ethinf_transmit(intf, &rpckt);
} }
void igmp_report_membership(ConnBlock * connBlock, ip4_addr ga) { void igmp_report_membership(ConnBlock * connBlock, ip4_addr ga) {

View File

@ -694,6 +694,7 @@ int tcp_send_segment(const struct ConnBlock_ *connBlock, TcpFlag flags, TcpOptio
cooked.time_ns = 0; cooked.time_ns = 0;
RawPckt raw; RawPckt raw;
memset(&raw, 0, sizeof(RawPckt));
pckt_assemble(&raw, &cooked, connBlock->sieve->intf); pckt_assemble(&raw, &cooked, connBlock->sieve->intf);
ethinf_transmit(connBlock->sieve->intf, &raw); ethinf_transmit(connBlock->sieve->intf, &raw);

View File

@ -120,6 +120,7 @@ int udp_sendto_arg(cbd d, const uint8_t *data, uint32_t size, ip4_addr addr, uin
cooked.time_ns = 0; cooked.time_ns = 0;
RawPckt raw; RawPckt raw;
memset(&raw, 0, sizeof(RawPckt));
pckt_assemble(&raw, &cooked, connBlock.sieve->intf); pckt_assemble(&raw, &cooked, connBlock.sieve->intf);
raw.ext.tx.arg = arg; // assign argument raw.ext.tx.arg = arg; // assign argument
raw.ext.tx.txTsCb = connBlock.sieveLayer->txTsCb; // assign with TX timestamp callback raw.ext.tx.txTsCb = connBlock.sieveLayer->txTsCb; // assign with TX timestamp callback

View File

@ -145,3 +145,9 @@ void ipv4_fill_props(IPv4Props *ipProps,
ipProps->headerSize = ETH_IPv4_HEADER_SIZE; ipProps->headerSize = ETH_IPv4_HEADER_SIZE;
} }
void ipv4_fill_in_chksum(uint8_t * hdr) {
uint8_t * ChkSumPtr = hdr + 10; // create a pointer to checksum position
uint16_t checksum = chksum(hdr, ETH_IPv4_HEADER_SIZE, false); // compute checksum
memcpy(ChkSumPtr, &checksum, 2); // copy checksum to the proper position
}

View File

@ -76,4 +76,10 @@ void ethmc_from_ipmc(uint8_t * hwa, ip4_addr ipa);
*/ */
void ipv4_fill_props(IPv4Props *ipProps, uint32_t payloadSize, uint16_t protocol, ip4_addr srcIpA, ip4_addr dstIpA); void ipv4_fill_props(IPv4Props *ipProps, uint32_t payloadSize, uint16_t protocol, ip4_addr srcIpA, ip4_addr dstIpA);
/**
* Fill in IPv4 checksum, based on header data.
* @param hdr Pointer to the IPv4 header's beginning. Checksum field's position will be written.
*/
void ipv4_fill_in_chksum(uint8_t * hdr);
#endif //ETHERLIB_IPV4_PACKET_H #endif //ETHERLIB_IPV4_PACKET_H