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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers eth.c Source File

eth.c

00001 #include <stdint.h>
00002 #include    "log.h"
00003 #include    "net.h"
00004 #include "action.h"
00005 #include    "arp.h"
00006 #include    "ip4.h"
00007 #include    "ip6.h"
00008 #include   "link.h"
00009 #include    "eth.h"
00010 #include    "mac.h"
00011 #include "restart.h"
00012 
00013 #define MTU 1500
00014 
00015 uint16_t EthProtocol; //Set when receiving or sending packets so that higher levels can read the protocol in use
00016 char*    EthMacRemote; //Set when receiving packets so that higher levels can read the protocol in use
00017 
00018 //header variables
00019 static char*    hdrDstPtr(char* pPacket) { return pPacket +  0; }
00020 static char*    hdrSrcPtr(char* pPacket) { return pPacket +  6; }
00021 static char*    hdrTypPtr(char* pPacket) { return pPacket + 12; }
00022 #define HEADER_LENGTH 14
00023 static uint16_t hdrTypGet(char* pPacket) { uint16_t res;     NetInvert16(&res, hdrTypPtr(pPacket)        ); return res; }
00024 static void     hdrTypSet(char* pPacket,   uint16_t value) { NetInvert16(      hdrTypPtr(pPacket), &value); }
00025 
00026 void EthProtocolLog(uint16_t protocol)
00027 {
00028     switch (protocol)
00029     {
00030         case ETH_ARP:  Log("ARP");              break;
00031         case ETH_IPV4: Log("IPV4");             break;
00032         case ETH_IPV6: Log("IPV6");             break;
00033         default:       LogF("%04hX", protocol); break;
00034     }
00035 }
00036 void LogHeader(char* pPacket)
00037 {
00038     if (NetTraceVerbose)
00039     {
00040         Log("ETH header\r\n");
00041         Log("  Destination:  ");         MacLog(hdrDstPtr(pPacket)); Log("\r\n");
00042         Log("  Source:       ");         MacLog(hdrSrcPtr(pPacket)); Log("\r\n");
00043         Log("  EtherType:    "); EthProtocolLog(hdrTypGet(pPacket)); Log("\r\n");        
00044     }
00045     else
00046     {
00047         Log("ETH   header ");
00048         EthProtocolLog(hdrTypGet(pPacket));
00049         Log(" ");
00050         MacLog(hdrSrcPtr(pPacket));
00051         Log(" >>> ");
00052         MacLog(hdrDstPtr(pPacket));
00053         Log("\r\n");
00054     }
00055 }
00056 static char* tracePacket;
00057 static void trace() { LogHeader(tracePacket); }
00058 int EthHandlePacket(char* pPacketRx, int sizeRx, char* pPacketTx, int* pSizeTx)
00059 {
00060     int lastRestartPoint = RestartPoint;
00061     RestartPoint = FAULT_POINT_EthHandlePacket;
00062     
00063     tracePacket = pPacketRx;
00064     
00065     char* pDataRx    = pPacketRx + HEADER_LENGTH;
00066     char* pDataTx    = pPacketTx + HEADER_LENGTH;
00067     int dataLengthRx =    sizeRx - HEADER_LENGTH;
00068     int dataLengthTx =  *pSizeTx - HEADER_LENGTH;
00069     if (dataLengthTx > MTU) dataLengthTx = MTU; //Limit the transmitted length to the maximum ethernet frame payload length
00070         
00071     if (!MacAccept(hdrDstPtr(pPacketRx)))
00072     {
00073         RestartPoint = lastRestartPoint;
00074         return DO_NOTHING;
00075     }
00076     
00077     EthProtocol = hdrTypGet(pPacketRx);
00078     if (EthProtocol < 1500)
00079     {
00080         RestartPoint = lastRestartPoint;
00081         return DO_NOTHING; //drop 802.3 messages
00082     }
00083 
00084     NetTraceHostCheckMac(hdrSrcPtr(pPacketRx));
00085 
00086     int   action = DO_NOTHING;
00087     EthMacRemote = hdrSrcPtr(pPacketRx);
00088     switch (EthProtocol)
00089     {
00090         case ETH_ARP:  action = ArpHandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx);               break;
00091         case ETH_IPV4: action = Ip4HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, EthMacRemote); break;
00092         case ETH_IPV6: action = Ip6HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, EthMacRemote); break;
00093         case 0x6970: break; //Drop Sonos group membership packet
00094         case 0x7374: break; //Drop Sky Q packet
00095         case 0x7475: break; //Drop Sky Q packet
00096         case 0x7380: break; //Drop Sky Q packet
00097         case 0x8100: break; //Drop Sky Q VLAN 802.1Q packet
00098         case 0x887b: break; //Drop Sky Q packet
00099         default:
00100             LogTimeF("ETH protocol %d not handled", EthProtocol);
00101             break;
00102     }
00103     if (!action)
00104     {
00105         RestartPoint = lastRestartPoint;
00106         return DO_NOTHING;
00107     }
00108         
00109     MacMakeFromDest(ActionGetDestPart(action), EthProtocol, EthMacRemote);
00110     MacCopy(hdrSrcPtr(pPacketTx), MacLocal);
00111     MacCopy(hdrDstPtr(pPacketTx), EthMacRemote);
00112     hdrTypSet(pPacketTx, EthProtocol);
00113     
00114     *pSizeTx = HEADER_LENGTH + dataLengthTx;
00115     
00116     if (ActionGetTracePart(action)) LogHeader(pPacketTx);
00117     
00118     RestartPoint = lastRestartPoint;
00119     return action;
00120 }
00121 int EthPollForPacketToSend(char* pPacket, int* pSize)
00122 {
00123     char* pData    = pPacket + HEADER_LENGTH;
00124     int dataLength =  *pSize - HEADER_LENGTH;
00125     if (dataLength > MTU) dataLength = MTU; //Limit the transmitted length to the maximum ethernet frame payload length
00126     
00127     int action = DO_NOTHING;
00128     EthProtocol = 0;
00129     if (!action)
00130     {
00131         EthProtocol = ETH_ARP;
00132         action = ArpPollForPacketToSend(pData, &dataLength);
00133     }
00134 
00135     if (!action)
00136     {
00137         EthProtocol = ETH_IPV6;
00138         action = Ip6PollForPacketToSend(pData, &dataLength, hdrDstPtr(pPacket));
00139     }
00140     
00141     if (!action)
00142     {
00143         EthProtocol = ETH_IPV4;
00144         action = Ip4PollForPacketToSend(pData, &dataLength, hdrDstPtr(pPacket));
00145     }
00146     
00147     if (!action) return DO_NOTHING;
00148     
00149     MacMakeFromDest(ActionGetDestPart(action), EthProtocol, hdrDstPtr(pPacket));
00150     MacCopy(hdrSrcPtr(pPacket), MacLocal);
00151     hdrTypSet(pPacket, EthProtocol);
00152     
00153     *pSize = HEADER_LENGTH + dataLength;
00154     
00155     if (ActionGetTracePart(action)) LogHeader(pPacket);
00156     
00157     return action;
00158 }
00159