- RawPckt: force FCS computation feature added
- IGMP transmission reworked - IPv4: method for filling in checksum in rendered binary data added
This commit is contained in:
parent
c3f8e53006
commit
8044d8a8b6
5
packet.h
5
packet.h
@ -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_;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
}
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user