A stack which works with or without an Mbed os library. Provides IPv4 or IPv6 with a full 1500 byte buffer.

Dependents:   oldheating gps motorhome heating

eth/eth.c

Committer:
andrewboyson
Date:
2018-12-05
Revision:
94:e2973a2c488e
Parent:
86:55bc5ddac16c
Child:
97:d91f7db00235

File content as of revision 94:e2973a2c488e:

#include <stdint.h>
#include    "log.h"
#include    "net.h"
#include "action.h"
#include    "arp.h"
#include    "ip4.h"
#include    "ip6.h"
#include   "link.h"
#include    "eth.h"
#include    "mac.h"

#define MTU 1500

//header variables
__packed struct header
{
    char     dst[6];
    char     src[6];
    uint16_t typ;
};
static uint16_t protocol;
void EthProtocolLog(uint16_t prototype)
{
    switch (prototype)
    {
        case ARP:  Log("ARP");               break;
        case IPV4: Log("IPV4");              break;
        case IPV6: Log("IPV6");              break;
        default:   LogF("%04hX", prototype); break;
    }
}
void LogHeader(struct header* pHeader)
{
    if (NetTraceVerbose)
    {
        Log("ETH header\r\n");
        Log("  Destination:  ");         MacLog(pHeader->dst);              Log("\r\n");
        Log("  Source:       ");         MacLog(pHeader->src);              Log("\r\n");
        Log("  EtherType:    "); EthProtocolLog(NetToHost16(pHeader->typ)); Log("\r\n");        
    }
    else
    {
        Log("ETH   header ");
        EthProtocolLog(NetToHost16(pHeader->typ));
        Log(" ");
        MacLog(pHeader->src);
        Log(" >>> ");
        MacLog(pHeader->dst);
        Log("\r\n");
    }
}
static void* tracePacket;
static void trace()
{
    struct header * pHeader = (struct header*)tracePacket;
    LogHeader(pHeader);
}
int EthHandlePacket(void* pPacketRx, int sizeRx, void* pPacketTx, int* pSizeTx)
{
    tracePacket = pPacketRx;
    
    struct header * pHeaderRx = (struct header*)pPacketRx;
    struct header * pHeaderTx = (struct header*)pPacketTx;
    void* pDataRx = (char*)pPacketRx + sizeof(struct header);
    void* pDataTx = (char*)pPacketTx + sizeof(struct header);
    int dataLengthRx =   sizeRx - sizeof(struct header);
    int dataLengthTx = *pSizeTx - sizeof(struct header);
    if (dataLengthTx > MTU) dataLengthTx = MTU; //Limit the transmitted length to the maximum ethernet frame payload length
        
    if (!MacAccept(pHeaderRx->dst))
    {
        return DO_NOTHING;
    }
    
    protocol = NetToHost16(pHeaderRx->typ);
    if (protocol < 1500)
    {
        return DO_NOTHING; //drop 802.3 messages
    }

    NetTraceHostCheckMac(pHeaderRx->src);

    int   action = DO_NOTHING;
    char* macRemote = pHeaderRx->src;
    switch (protocol)
    {
        case ARP:  action = ArpHandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx);            break;
        case IPV4: action = Ip4HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, macRemote); break;
        case IPV6: action = Ip6HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, macRemote); break;
        case 0x6970: break; //Drop Sonos group membership packet
        case 0x7374: break; //Drop Sky Q packet
        case 0x7475: break; //Drop Sky Q packet
        case 0x7380: break; //Drop Sky Q packet
        case 0x8100: break; //Drop Sky Q VLAN 802.1Q packet
        case 0x887b: break; //Drop Sky Q packet
        default:
            LogTimeF("ETH protocol %d not handled", protocol);
            break;
    }
    if (!action)
    {
        return DO_NOTHING;
    }
        
    MacMakeFromDest(ActionGetDestPart(action), protocol, macRemote);
    MacCopy(pHeaderTx->src, MacLocal);
    MacCopy(pHeaderTx->dst, macRemote);
    pHeaderTx->typ = NetToHost16(protocol);
    
    *pSizeTx = sizeof(struct header) + dataLengthTx;
    
    if (ActionGetTracePart(action)) LogHeader(pHeaderTx);
    
    return action;
}
int EthPollForPacketToSend(void* pPacket, int* pSize)
{
    struct header * pHeader = (struct header*)pPacket;
    void* pData = (char*)pPacket + sizeof(struct header);
    
    int dataLength = *pSize - sizeof(struct header);
    if (dataLength > MTU) dataLength = MTU; //Limit the transmitted length to the maximum ethernet frame payload length
    protocol = 0;
    int action = DO_NOTHING;
    if (!action)
    {
        action = ArpPollForPacketToSend(pData, &dataLength);
        protocol = ARP;
    }

    if (!action)
    {
        action = Ip6PollForPacketToSend(pData, &dataLength, pHeader->dst);
        protocol = IPV6;
    }
    
    if (!action)
    {
        action = Ip4PollForPacketToSend(pData, &dataLength, pHeader->dst);
        protocol = IPV4;
    }
    
    if (!action) return DO_NOTHING;
    
    MacMakeFromDest(ActionGetDestPart(action), protocol, pHeader->dst);
    MacCopy(pHeader->src, MacLocal);
    pHeader->typ = NetToHost16(protocol);
    
    *pSize = sizeof(struct header) + dataLength;
    
    if (ActionGetTracePart(action)) LogHeader(pHeader);
    
    return action;
}