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:
2019-07-19
Revision:
151:bde6f7da1755
Parent:
142:a8c0890a58d1
Child:
171:f708d6776752

File content as of revision 151:bde6f7da1755:

#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"
#include "restart.h"

#define MTU 1500

//header variables
static char*    hdrDstPtr(char* pPacket) { return pPacket +  0; }
static char*    hdrSrcPtr(char* pPacket) { return pPacket +  6; }
static char*    hdrTypPtr(char* pPacket) { return pPacket + 12; }
#define HEADER_LENGTH 14
static uint16_t hdrTypGet(char* pPacket) { uint16_t res;     NetInvert16(&res, hdrTypPtr(pPacket)        ); return res; }
static void     hdrTypSet(char* pPacket,   uint16_t value) { NetInvert16(      hdrTypPtr(pPacket), &value); }

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(char* pPacket)
{
    if (NetTraceVerbose)
    {
        Log("ETH header\r\n");
        Log("  Destination:  ");         MacLog(hdrDstPtr(pPacket)); Log("\r\n");
        Log("  Source:       ");         MacLog(hdrSrcPtr(pPacket)); Log("\r\n");
        Log("  EtherType:    "); EthProtocolLog(hdrTypGet(pPacket)); Log("\r\n");        
    }
    else
    {
        Log("ETH   header ");
        EthProtocolLog(hdrTypGet(pPacket));
        Log(" ");
        MacLog(hdrSrcPtr(pPacket));
        Log(" >>> ");
        MacLog(hdrDstPtr(pPacket));
        Log("\r\n");
    }
}
static char* tracePacket;
static void trace() { LogHeader(tracePacket); }
int EthHandlePacket(char* pPacketRx, int sizeRx, char* pPacketTx, int* pSizeTx)
{
    int lastRestartPoint = RestartPoint;
    RestartPoint = FAULT_POINT_EthHandlePacket;
    
    tracePacket = pPacketRx;
    
    char* pDataRx    = pPacketRx + HEADER_LENGTH;
    char* pDataTx    = pPacketTx + HEADER_LENGTH;
    int dataLengthRx =    sizeRx - HEADER_LENGTH;
    int dataLengthTx =  *pSizeTx - HEADER_LENGTH;
    if (dataLengthTx > MTU) dataLengthTx = MTU; //Limit the transmitted length to the maximum ethernet frame payload length
        
    if (!MacAccept(hdrDstPtr(pPacketRx)))
    {
        RestartPoint = lastRestartPoint;
        return DO_NOTHING;
    }
    
    uint16_t protocol = hdrTypGet(pPacketRx);
    if (protocol < 1500)
    {
        RestartPoint = lastRestartPoint;
        return DO_NOTHING; //drop 802.3 messages
    }

    NetTraceHostCheckMac(hdrSrcPtr(pPacketRx));

    int   action = DO_NOTHING;
    char* macRemote = hdrSrcPtr(pPacketRx);
    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)
    {
        RestartPoint = lastRestartPoint;
        return DO_NOTHING;
    }
        
    MacMakeFromDest(ActionGetDestPart(action), protocol, macRemote);
    MacCopy(hdrSrcPtr(pPacketTx), MacLocal);
    MacCopy(hdrDstPtr(pPacketTx), macRemote);
    hdrTypSet(pPacketTx, protocol);
    
    *pSizeTx = HEADER_LENGTH + dataLengthTx;
    
    if (ActionGetTracePart(action)) LogHeader(pPacketTx);
    
    RestartPoint = lastRestartPoint;
    return action;
}
int EthPollForPacketToSend(char* pPacket, int* pSize)
{
    char* pData    = pPacket + HEADER_LENGTH;
    int dataLength =  *pSize - HEADER_LENGTH;
    if (dataLength > MTU) dataLength = MTU; //Limit the transmitted length to the maximum ethernet frame payload length
    
    int action = DO_NOTHING;
    uint16_t protocol = 0;
    if (!action)
    {
        action = ArpPollForPacketToSend(pData, &dataLength);
        protocol = ARP;
    }

    if (!action)
    {
        action = Ip6PollForPacketToSend(pData, &dataLength, hdrDstPtr(pPacket));
        protocol = IPV6;
    }
    
    if (!action)
    {
        action = Ip4PollForPacketToSend(pData, &dataLength, hdrDstPtr(pPacket));
        protocol = IPV4;
    }
    
    if (!action) return DO_NOTHING;
    
    MacMakeFromDest(ActionGetDestPart(action), protocol, hdrDstPtr(pPacket));
    MacCopy(hdrSrcPtr(pPacket), MacLocal);
    hdrTypSet(pPacket, protocol);
    
    *pSize = HEADER_LENGTH + dataLength;
    
    if (ActionGetTracePart(action)) LogHeader(pPacket);
    
    return action;
}