Webserver+3d print

Dependents:   Nucleo

Committer:
Sergunb
Date:
Sat Feb 04 18:15:49 2017 +0000
Revision:
0:8918a71cdbe9
nothing else

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sergunb 0:8918a71cdbe9 1 /**
Sergunb 0:8918a71cdbe9 2 * @file ethernet.c
Sergunb 0:8918a71cdbe9 3 * @brief Ethernet
Sergunb 0:8918a71cdbe9 4 *
Sergunb 0:8918a71cdbe9 5 * @section License
Sergunb 0:8918a71cdbe9 6 *
Sergunb 0:8918a71cdbe9 7 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
Sergunb 0:8918a71cdbe9 8 *
Sergunb 0:8918a71cdbe9 9 * This file is part of CycloneTCP Open.
Sergunb 0:8918a71cdbe9 10 *
Sergunb 0:8918a71cdbe9 11 * This program is free software; you can redistribute it and/or
Sergunb 0:8918a71cdbe9 12 * modify it under the terms of the GNU General Public License
Sergunb 0:8918a71cdbe9 13 * as published by the Free Software Foundation; either version 2
Sergunb 0:8918a71cdbe9 14 * of the License, or (at your option) any later version.
Sergunb 0:8918a71cdbe9 15 *
Sergunb 0:8918a71cdbe9 16 * This program is distributed in the hope that it will be useful,
Sergunb 0:8918a71cdbe9 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Sergunb 0:8918a71cdbe9 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Sergunb 0:8918a71cdbe9 19 * GNU General Public License for more details.
Sergunb 0:8918a71cdbe9 20 *
Sergunb 0:8918a71cdbe9 21 * You should have received a copy of the GNU General Public License
Sergunb 0:8918a71cdbe9 22 * along with this program; if not, write to the Free Software Foundation,
Sergunb 0:8918a71cdbe9 23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Sergunb 0:8918a71cdbe9 24 *
Sergunb 0:8918a71cdbe9 25 * @author Oryx Embedded SARL (www.oryx-embedded.com)
Sergunb 0:8918a71cdbe9 26 * @version 1.7.6
Sergunb 0:8918a71cdbe9 27 **/
Sergunb 0:8918a71cdbe9 28
Sergunb 0:8918a71cdbe9 29 //Switch to the appropriate trace level
Sergunb 0:8918a71cdbe9 30 #define TRACE_LEVEL ETH_TRACE_LEVEL
Sergunb 0:8918a71cdbe9 31
Sergunb 0:8918a71cdbe9 32 //Dependencies
Sergunb 0:8918a71cdbe9 33 #include <stdlib.h>
Sergunb 0:8918a71cdbe9 34 #include <string.h>
Sergunb 0:8918a71cdbe9 35 #include <ctype.h>
Sergunb 0:8918a71cdbe9 36 #include "core/net.h"
Sergunb 0:8918a71cdbe9 37 #include "core/nic.h"
Sergunb 0:8918a71cdbe9 38 #include "core/ethernet.h"
Sergunb 0:8918a71cdbe9 39 #include "core/socket.h"
Sergunb 0:8918a71cdbe9 40 #include "core/raw_socket.h"
Sergunb 0:8918a71cdbe9 41 #include "core/tcp_timer.h"
Sergunb 0:8918a71cdbe9 42 #include "ipv4/arp.h"
Sergunb 0:8918a71cdbe9 43 #include "ipv4/ipv4.h"
Sergunb 0:8918a71cdbe9 44 #include "ipv6/ipv6.h"
Sergunb 0:8918a71cdbe9 45 #include "mibs/mib2_module.h"
Sergunb 0:8918a71cdbe9 46 #include "debug.h"
Sergunb 0:8918a71cdbe9 47
Sergunb 0:8918a71cdbe9 48 //Check TCP/IP stack configuration
Sergunb 0:8918a71cdbe9 49 #if (ETH_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 50
Sergunb 0:8918a71cdbe9 51 //Unspecified MAC address
Sergunb 0:8918a71cdbe9 52 const MacAddr MAC_UNSPECIFIED_ADDR = {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}};
Sergunb 0:8918a71cdbe9 53 //Broadcast MAC address
Sergunb 0:8918a71cdbe9 54 const MacAddr MAC_BROADCAST_ADDR = {{{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}};
Sergunb 0:8918a71cdbe9 55 //Unspecified EUI-64 address
Sergunb 0:8918a71cdbe9 56 const Eui64 EUI64_UNSPECIFIED_ADDR = {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}};
Sergunb 0:8918a71cdbe9 57
Sergunb 0:8918a71cdbe9 58 //Padding bytes
Sergunb 0:8918a71cdbe9 59 const uint8_t ethPadding[64] =
Sergunb 0:8918a71cdbe9 60 {
Sergunb 0:8918a71cdbe9 61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Sergunb 0:8918a71cdbe9 62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Sergunb 0:8918a71cdbe9 63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Sergunb 0:8918a71cdbe9 64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Sergunb 0:8918a71cdbe9 65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Sergunb 0:8918a71cdbe9 66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Sergunb 0:8918a71cdbe9 67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Sergunb 0:8918a71cdbe9 68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Sergunb 0:8918a71cdbe9 69 };
Sergunb 0:8918a71cdbe9 70
Sergunb 0:8918a71cdbe9 71 //A lookup table can be used to speed up CRC calculation
Sergunb 0:8918a71cdbe9 72 #if (ETH_FAST_CRC_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 73
Sergunb 0:8918a71cdbe9 74 static const uint32_t crc32Table[256] =
Sergunb 0:8918a71cdbe9 75 {
Sergunb 0:8918a71cdbe9 76 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
Sergunb 0:8918a71cdbe9 77 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
Sergunb 0:8918a71cdbe9 78 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
Sergunb 0:8918a71cdbe9 79 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
Sergunb 0:8918a71cdbe9 80 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
Sergunb 0:8918a71cdbe9 81 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
Sergunb 0:8918a71cdbe9 82 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
Sergunb 0:8918a71cdbe9 83 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
Sergunb 0:8918a71cdbe9 84 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
Sergunb 0:8918a71cdbe9 85 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
Sergunb 0:8918a71cdbe9 86 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
Sergunb 0:8918a71cdbe9 87 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
Sergunb 0:8918a71cdbe9 88 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
Sergunb 0:8918a71cdbe9 89 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
Sergunb 0:8918a71cdbe9 90 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
Sergunb 0:8918a71cdbe9 91 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
Sergunb 0:8918a71cdbe9 92 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
Sergunb 0:8918a71cdbe9 93 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
Sergunb 0:8918a71cdbe9 94 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
Sergunb 0:8918a71cdbe9 95 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
Sergunb 0:8918a71cdbe9 96 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
Sergunb 0:8918a71cdbe9 97 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
Sergunb 0:8918a71cdbe9 98 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
Sergunb 0:8918a71cdbe9 99 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
Sergunb 0:8918a71cdbe9 100 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
Sergunb 0:8918a71cdbe9 101 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
Sergunb 0:8918a71cdbe9 102 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
Sergunb 0:8918a71cdbe9 103 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
Sergunb 0:8918a71cdbe9 104 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
Sergunb 0:8918a71cdbe9 105 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
Sergunb 0:8918a71cdbe9 106 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
Sergunb 0:8918a71cdbe9 107 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
Sergunb 0:8918a71cdbe9 108 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
Sergunb 0:8918a71cdbe9 109 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
Sergunb 0:8918a71cdbe9 110 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
Sergunb 0:8918a71cdbe9 111 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
Sergunb 0:8918a71cdbe9 112 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
Sergunb 0:8918a71cdbe9 113 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
Sergunb 0:8918a71cdbe9 114 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
Sergunb 0:8918a71cdbe9 115 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
Sergunb 0:8918a71cdbe9 116 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
Sergunb 0:8918a71cdbe9 117 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
Sergunb 0:8918a71cdbe9 118 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
Sergunb 0:8918a71cdbe9 119 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
Sergunb 0:8918a71cdbe9 120 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
Sergunb 0:8918a71cdbe9 121 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
Sergunb 0:8918a71cdbe9 122 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
Sergunb 0:8918a71cdbe9 123 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
Sergunb 0:8918a71cdbe9 124 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
Sergunb 0:8918a71cdbe9 125 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
Sergunb 0:8918a71cdbe9 126 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
Sergunb 0:8918a71cdbe9 127 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
Sergunb 0:8918a71cdbe9 128 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
Sergunb 0:8918a71cdbe9 129 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
Sergunb 0:8918a71cdbe9 130 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
Sergunb 0:8918a71cdbe9 131 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
Sergunb 0:8918a71cdbe9 132 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
Sergunb 0:8918a71cdbe9 133 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
Sergunb 0:8918a71cdbe9 134 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
Sergunb 0:8918a71cdbe9 135 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
Sergunb 0:8918a71cdbe9 136 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
Sergunb 0:8918a71cdbe9 137 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
Sergunb 0:8918a71cdbe9 138 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
Sergunb 0:8918a71cdbe9 139 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
Sergunb 0:8918a71cdbe9 140 };
Sergunb 0:8918a71cdbe9 141
Sergunb 0:8918a71cdbe9 142 #endif
Sergunb 0:8918a71cdbe9 143
Sergunb 0:8918a71cdbe9 144
Sergunb 0:8918a71cdbe9 145 /**
Sergunb 0:8918a71cdbe9 146 * @brief Ethernet related initialization
Sergunb 0:8918a71cdbe9 147 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 148 * @return Error code
Sergunb 0:8918a71cdbe9 149 **/
Sergunb 0:8918a71cdbe9 150
Sergunb 0:8918a71cdbe9 151 error_t ethInit(NetInterface *interface)
Sergunb 0:8918a71cdbe9 152 {
Sergunb 0:8918a71cdbe9 153 //Clear the MAC filter table contents
Sergunb 0:8918a71cdbe9 154 memset(interface->macMulticastFilter, 0,
Sergunb 0:8918a71cdbe9 155 sizeof(interface->macMulticastFilter));
Sergunb 0:8918a71cdbe9 156
Sergunb 0:8918a71cdbe9 157 //Successful initialization
Sergunb 0:8918a71cdbe9 158 return NO_ERROR;
Sergunb 0:8918a71cdbe9 159 }
Sergunb 0:8918a71cdbe9 160
Sergunb 0:8918a71cdbe9 161
Sergunb 0:8918a71cdbe9 162 /**
Sergunb 0:8918a71cdbe9 163 * @brief Process an incoming Ethernet frame
Sergunb 0:8918a71cdbe9 164 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 165 * @param[in] ethFrame Incoming Ethernet frame to process
Sergunb 0:8918a71cdbe9 166 * @param[in] length Total frame length
Sergunb 0:8918a71cdbe9 167 **/
Sergunb 0:8918a71cdbe9 168
Sergunb 0:8918a71cdbe9 169 void ethProcessFrame(NetInterface *interface, EthHeader *ethFrame, size_t length)
Sergunb 0:8918a71cdbe9 170 {
Sergunb 0:8918a71cdbe9 171 #if (IPV6_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 172 NetBuffer1 buffer;
Sergunb 0:8918a71cdbe9 173 #endif
Sergunb 0:8918a71cdbe9 174 uint32_t crc;
Sergunb 0:8918a71cdbe9 175
Sergunb 0:8918a71cdbe9 176 //Total number of octets received on the interface
Sergunb 0:8918a71cdbe9 177 MIB2_INC_COUNTER32(interface->mibIfEntry->ifInOctets, length);
Sergunb 0:8918a71cdbe9 178
Sergunb 0:8918a71cdbe9 179 //Ensure the length of the incoming frame is valid
Sergunb 0:8918a71cdbe9 180 if(length < sizeof(EthHeader))
Sergunb 0:8918a71cdbe9 181 {
Sergunb 0:8918a71cdbe9 182 //Number of inbound packets that contained errors
Sergunb 0:8918a71cdbe9 183 MIB2_INC_COUNTER32(interface->mibIfEntry->ifInErrors, 1);
Sergunb 0:8918a71cdbe9 184 //Discard the received frame
Sergunb 0:8918a71cdbe9 185 return;
Sergunb 0:8918a71cdbe9 186 }
Sergunb 0:8918a71cdbe9 187
Sergunb 0:8918a71cdbe9 188 //Debug message
Sergunb 0:8918a71cdbe9 189 TRACE_DEBUG("Ethernet frame received (%" PRIuSIZE " bytes)...\r\n", length);
Sergunb 0:8918a71cdbe9 190 //Dump Ethernet header contents for debugging purpose
Sergunb 0:8918a71cdbe9 191 ethDumpHeader(ethFrame);
Sergunb 0:8918a71cdbe9 192
Sergunb 0:8918a71cdbe9 193 //Check whether the CRC is included in the received frame
Sergunb 0:8918a71cdbe9 194 if(!interface->nicDriver->autoCrcStrip)
Sergunb 0:8918a71cdbe9 195 {
Sergunb 0:8918a71cdbe9 196 //Ensure the length of the incoming frame is valid
Sergunb 0:8918a71cdbe9 197 if(length < (sizeof(EthHeader) + ETH_CRC_SIZE))
Sergunb 0:8918a71cdbe9 198 {
Sergunb 0:8918a71cdbe9 199 //Number of inbound packets that contained errors
Sergunb 0:8918a71cdbe9 200 MIB2_INC_COUNTER32(interface->mibIfEntry->ifInErrors, 1);
Sergunb 0:8918a71cdbe9 201 //Discard the received frame
Sergunb 0:8918a71cdbe9 202 return;
Sergunb 0:8918a71cdbe9 203 }
Sergunb 0:8918a71cdbe9 204
Sergunb 0:8918a71cdbe9 205 //CRC verification not supported by hardware?
Sergunb 0:8918a71cdbe9 206 if(!interface->nicDriver->autoCrcVerif)
Sergunb 0:8918a71cdbe9 207 {
Sergunb 0:8918a71cdbe9 208 //The value of the residue is 0x2144DF1C when no CRC errors are detected
Sergunb 0:8918a71cdbe9 209 if(ethCalcCrc(ethFrame, length) != 0x2144DF1C)
Sergunb 0:8918a71cdbe9 210 {
Sergunb 0:8918a71cdbe9 211 //Debug message
Sergunb 0:8918a71cdbe9 212 TRACE_WARNING("Wrong CRC detected!\r\n");
Sergunb 0:8918a71cdbe9 213 //Number of inbound packets that contained errors
Sergunb 0:8918a71cdbe9 214 MIB2_INC_COUNTER32(interface->mibIfEntry->ifInErrors, 1);
Sergunb 0:8918a71cdbe9 215 //Discard the received frame
Sergunb 0:8918a71cdbe9 216 return;
Sergunb 0:8918a71cdbe9 217 }
Sergunb 0:8918a71cdbe9 218 }
Sergunb 0:8918a71cdbe9 219
Sergunb 0:8918a71cdbe9 220 //Retrieve CRC value
Sergunb 0:8918a71cdbe9 221 memcpy(&crc, (uint8_t *) ethFrame + length - ETH_CRC_SIZE, ETH_CRC_SIZE);
Sergunb 0:8918a71cdbe9 222 //Reseed the pseudo-random number generator
Sergunb 0:8918a71cdbe9 223 netInitRand(crc);
Sergunb 0:8918a71cdbe9 224 }
Sergunb 0:8918a71cdbe9 225
Sergunb 0:8918a71cdbe9 226 //Frame filtering based on destination MAC address
Sergunb 0:8918a71cdbe9 227 if(ethCheckDestAddr(interface, &ethFrame->destAddr))
Sergunb 0:8918a71cdbe9 228 {
Sergunb 0:8918a71cdbe9 229 //Number of inbound packets which were chosen to be discarded
Sergunb 0:8918a71cdbe9 230 //even though no errors had been detected
Sergunb 0:8918a71cdbe9 231 MIB2_INC_COUNTER32(interface->mibIfEntry->ifInDiscards, 1);
Sergunb 0:8918a71cdbe9 232 //Discard the received frame
Sergunb 0:8918a71cdbe9 233 return;
Sergunb 0:8918a71cdbe9 234 }
Sergunb 0:8918a71cdbe9 235
Sergunb 0:8918a71cdbe9 236 //Check whether the destination address is a group address
Sergunb 0:8918a71cdbe9 237 if(macIsMulticastAddr(&ethFrame->destAddr))
Sergunb 0:8918a71cdbe9 238 {
Sergunb 0:8918a71cdbe9 239 //Number of non-unicast packets delivered to a higher-layer protocol
Sergunb 0:8918a71cdbe9 240 MIB2_INC_COUNTER32(interface->mibIfEntry->ifInNUcastPkts, 1);
Sergunb 0:8918a71cdbe9 241 }
Sergunb 0:8918a71cdbe9 242 else
Sergunb 0:8918a71cdbe9 243 {
Sergunb 0:8918a71cdbe9 244 //Number of unicast packets delivered to a higher-layer protocol
Sergunb 0:8918a71cdbe9 245 MIB2_INC_COUNTER32(interface->mibIfEntry->ifInUcastPkts, 1);
Sergunb 0:8918a71cdbe9 246 }
Sergunb 0:8918a71cdbe9 247
Sergunb 0:8918a71cdbe9 248 #if (RAW_SOCKET_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 249 //Allow raw sockets to process Ethernet packets
Sergunb 0:8918a71cdbe9 250 rawSocketProcessEthPacket(interface, ethFrame, length - ETH_CRC_SIZE);
Sergunb 0:8918a71cdbe9 251 #endif
Sergunb 0:8918a71cdbe9 252
Sergunb 0:8918a71cdbe9 253 //Calculate the length of the data payload
Sergunb 0:8918a71cdbe9 254 length -= sizeof(EthHeader);
Sergunb 0:8918a71cdbe9 255
Sergunb 0:8918a71cdbe9 256 //Check whether the CRC is included in the received frame
Sergunb 0:8918a71cdbe9 257 if(!interface->nicDriver->autoCrcStrip)
Sergunb 0:8918a71cdbe9 258 length -= ETH_CRC_SIZE;
Sergunb 0:8918a71cdbe9 259
Sergunb 0:8918a71cdbe9 260 //Check Ethernet type field
Sergunb 0:8918a71cdbe9 261 switch(ntohs(ethFrame->type))
Sergunb 0:8918a71cdbe9 262 {
Sergunb 0:8918a71cdbe9 263 #if (IPV4_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 264 //ARP packet received?
Sergunb 0:8918a71cdbe9 265 case ETH_TYPE_ARP:
Sergunb 0:8918a71cdbe9 266 //Process incoming ARP packet
Sergunb 0:8918a71cdbe9 267 arpProcessPacket(interface, (ArpPacket *) ethFrame->data, length);
Sergunb 0:8918a71cdbe9 268 break;
Sergunb 0:8918a71cdbe9 269 //IPv4 packet received?
Sergunb 0:8918a71cdbe9 270 case ETH_TYPE_IPV4:
Sergunb 0:8918a71cdbe9 271 //Process incoming IPv4 packet
Sergunb 0:8918a71cdbe9 272 ipv4ProcessPacket(interface, (Ipv4Header *) ethFrame->data, length);
Sergunb 0:8918a71cdbe9 273 break;
Sergunb 0:8918a71cdbe9 274 #endif
Sergunb 0:8918a71cdbe9 275
Sergunb 0:8918a71cdbe9 276 #if (IPV6_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 277 //IPv6 packet received?
Sergunb 0:8918a71cdbe9 278 case ETH_TYPE_IPV6:
Sergunb 0:8918a71cdbe9 279 //The incoming Ethernet frame fits in a single chunk
Sergunb 0:8918a71cdbe9 280 buffer.chunkCount = 1;
Sergunb 0:8918a71cdbe9 281 buffer.maxChunkCount = 1;
Sergunb 0:8918a71cdbe9 282 buffer.chunk[0].address = ethFrame->data;
Sergunb 0:8918a71cdbe9 283 buffer.chunk[0].length = length;
Sergunb 0:8918a71cdbe9 284 buffer.chunk[0].size = 0;
Sergunb 0:8918a71cdbe9 285
Sergunb 0:8918a71cdbe9 286 //Process incoming IPv6 packet
Sergunb 0:8918a71cdbe9 287 ipv6ProcessPacket(interface, (NetBuffer *) &buffer, 0);
Sergunb 0:8918a71cdbe9 288 break;
Sergunb 0:8918a71cdbe9 289 #endif
Sergunb 0:8918a71cdbe9 290
Sergunb 0:8918a71cdbe9 291 //Unknown packet received?
Sergunb 0:8918a71cdbe9 292 default:
Sergunb 0:8918a71cdbe9 293 //Debug message
Sergunb 0:8918a71cdbe9 294 TRACE_WARNING("Unknown Ethernet type!\r\n");
Sergunb 0:8918a71cdbe9 295
Sergunb 0:8918a71cdbe9 296 //Number of packets received via the interface which were
Sergunb 0:8918a71cdbe9 297 //discarded because of an unknown or unsupported protocol
Sergunb 0:8918a71cdbe9 298 MIB2_INC_COUNTER32(interface->mibIfEntry->ifInUnknownProtos , 1);
Sergunb 0:8918a71cdbe9 299 break;
Sergunb 0:8918a71cdbe9 300 }
Sergunb 0:8918a71cdbe9 301 }
Sergunb 0:8918a71cdbe9 302
Sergunb 0:8918a71cdbe9 303
Sergunb 0:8918a71cdbe9 304 /**
Sergunb 0:8918a71cdbe9 305 * @brief Send an Ethernet frame
Sergunb 0:8918a71cdbe9 306 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 307 * @param[in] destAddr MAC address of the destination host
Sergunb 0:8918a71cdbe9 308 * @param[in] buffer Multi-part buffer containing the payload
Sergunb 0:8918a71cdbe9 309 * @param[in] offset Offset to the first payload byte
Sergunb 0:8918a71cdbe9 310 * @param[in] type Ethernet type
Sergunb 0:8918a71cdbe9 311 * @return Error code
Sergunb 0:8918a71cdbe9 312 **/
Sergunb 0:8918a71cdbe9 313
Sergunb 0:8918a71cdbe9 314 error_t ethSendFrame(NetInterface *interface, const MacAddr *destAddr,
Sergunb 0:8918a71cdbe9 315 NetBuffer *buffer, size_t offset, uint16_t type)
Sergunb 0:8918a71cdbe9 316 {
Sergunb 0:8918a71cdbe9 317 error_t error;
Sergunb 0:8918a71cdbe9 318 size_t length;
Sergunb 0:8918a71cdbe9 319 EthHeader *header;
Sergunb 0:8918a71cdbe9 320
Sergunb 0:8918a71cdbe9 321 //Is there enough space for the Ethernet header?
Sergunb 0:8918a71cdbe9 322 if(offset < sizeof(EthHeader))
Sergunb 0:8918a71cdbe9 323 return ERROR_INVALID_PARAMETER;
Sergunb 0:8918a71cdbe9 324
Sergunb 0:8918a71cdbe9 325 //Make room for the Ethernet header
Sergunb 0:8918a71cdbe9 326 offset -= sizeof(EthHeader);
Sergunb 0:8918a71cdbe9 327 //Retrieve the length of the frame
Sergunb 0:8918a71cdbe9 328 length = netBufferGetLength(buffer) - offset;
Sergunb 0:8918a71cdbe9 329
Sergunb 0:8918a71cdbe9 330 //Position to the beginning of the frame
Sergunb 0:8918a71cdbe9 331 header = netBufferAt(buffer, offset);
Sergunb 0:8918a71cdbe9 332
Sergunb 0:8918a71cdbe9 333 //Format Ethernet header
Sergunb 0:8918a71cdbe9 334 header->destAddr = *destAddr;
Sergunb 0:8918a71cdbe9 335 header->srcAddr = interface->macAddr;
Sergunb 0:8918a71cdbe9 336 header->type = htons(type);
Sergunb 0:8918a71cdbe9 337
Sergunb 0:8918a71cdbe9 338 //Automatic padding not supported by hardware?
Sergunb 0:8918a71cdbe9 339 if(!interface->nicDriver->autoPadding)
Sergunb 0:8918a71cdbe9 340 {
Sergunb 0:8918a71cdbe9 341 //The host controller should manually add padding
Sergunb 0:8918a71cdbe9 342 //to the packet before transmitting it
Sergunb 0:8918a71cdbe9 343 if(length < (ETH_MIN_FRAME_SIZE - ETH_CRC_SIZE))
Sergunb 0:8918a71cdbe9 344 {
Sergunb 0:8918a71cdbe9 345 size_t n;
Sergunb 0:8918a71cdbe9 346
Sergunb 0:8918a71cdbe9 347 //Add padding as necessary
Sergunb 0:8918a71cdbe9 348 n = (ETH_MIN_FRAME_SIZE - ETH_CRC_SIZE) - length;
Sergunb 0:8918a71cdbe9 349
Sergunb 0:8918a71cdbe9 350 //Append padding bytes
Sergunb 0:8918a71cdbe9 351 error = netBufferAppend(buffer, ethPadding, n);
Sergunb 0:8918a71cdbe9 352 //Any error to report?
Sergunb 0:8918a71cdbe9 353 if(error)
Sergunb 0:8918a71cdbe9 354 return error;
Sergunb 0:8918a71cdbe9 355
Sergunb 0:8918a71cdbe9 356 //Adjust frame length
Sergunb 0:8918a71cdbe9 357 length += n;
Sergunb 0:8918a71cdbe9 358 }
Sergunb 0:8918a71cdbe9 359 }
Sergunb 0:8918a71cdbe9 360
Sergunb 0:8918a71cdbe9 361 //CRC calculation not supported by hardware?
Sergunb 0:8918a71cdbe9 362 if(!interface->nicDriver->autoCrcCalc)
Sergunb 0:8918a71cdbe9 363 {
Sergunb 0:8918a71cdbe9 364 uint32_t crc;
Sergunb 0:8918a71cdbe9 365
Sergunb 0:8918a71cdbe9 366 //Compute CRC over the header and payload
Sergunb 0:8918a71cdbe9 367 crc = ethCalcCrcEx(buffer, offset, length);
Sergunb 0:8918a71cdbe9 368 //Convert from host byte order to little-endian byte order
Sergunb 0:8918a71cdbe9 369 crc = htole32(crc);
Sergunb 0:8918a71cdbe9 370
Sergunb 0:8918a71cdbe9 371 //Append the calculated CRC value
Sergunb 0:8918a71cdbe9 372 error = netBufferAppend(buffer, &crc, sizeof(crc));
Sergunb 0:8918a71cdbe9 373 //Any error to report?
Sergunb 0:8918a71cdbe9 374 if(error)
Sergunb 0:8918a71cdbe9 375 return error;
Sergunb 0:8918a71cdbe9 376
Sergunb 0:8918a71cdbe9 377 //Adjust frame length
Sergunb 0:8918a71cdbe9 378 length += sizeof(crc);
Sergunb 0:8918a71cdbe9 379 }
Sergunb 0:8918a71cdbe9 380
Sergunb 0:8918a71cdbe9 381 //Total number of octets transmitted out of the interface
Sergunb 0:8918a71cdbe9 382 MIB2_INC_COUNTER32(interface->mibIfEntry->ifOutOctets, length);
Sergunb 0:8918a71cdbe9 383
Sergunb 0:8918a71cdbe9 384 //Check whether the destination address is a group address
Sergunb 0:8918a71cdbe9 385 if(macIsMulticastAddr(&header->destAddr))
Sergunb 0:8918a71cdbe9 386 {
Sergunb 0:8918a71cdbe9 387 //Total number of non-unicast packets that higher-level protocols
Sergunb 0:8918a71cdbe9 388 //requested be transmitted
Sergunb 0:8918a71cdbe9 389 MIB2_INC_COUNTER32(interface->mibIfEntry->ifOutNUcastPkts, 1);
Sergunb 0:8918a71cdbe9 390 }
Sergunb 0:8918a71cdbe9 391 else
Sergunb 0:8918a71cdbe9 392 {
Sergunb 0:8918a71cdbe9 393 //Total number of unicast packets that higher-level protocols
Sergunb 0:8918a71cdbe9 394 //requested be transmitted
Sergunb 0:8918a71cdbe9 395 MIB2_INC_COUNTER32(interface->mibIfEntry->ifOutUcastPkts, 1);
Sergunb 0:8918a71cdbe9 396 }
Sergunb 0:8918a71cdbe9 397
Sergunb 0:8918a71cdbe9 398 //Debug message
Sergunb 0:8918a71cdbe9 399 TRACE_DEBUG("Sending Ethernet frame (%" PRIuSIZE " bytes)...\r\n", length);
Sergunb 0:8918a71cdbe9 400 //Dump Ethernet header contents for debugging purpose
Sergunb 0:8918a71cdbe9 401 ethDumpHeader(header);
Sergunb 0:8918a71cdbe9 402
Sergunb 0:8918a71cdbe9 403 //Send the resulting packet over the specified link
Sergunb 0:8918a71cdbe9 404 error = nicSendPacket(interface, buffer, offset);
Sergunb 0:8918a71cdbe9 405 //Return status code
Sergunb 0:8918a71cdbe9 406 return error;
Sergunb 0:8918a71cdbe9 407 }
Sergunb 0:8918a71cdbe9 408
Sergunb 0:8918a71cdbe9 409
Sergunb 0:8918a71cdbe9 410 /**
Sergunb 0:8918a71cdbe9 411 * @brief Destination MAC address filtering
Sergunb 0:8918a71cdbe9 412 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 413 * @param[in] macAddr Destination MAC address to be checked
Sergunb 0:8918a71cdbe9 414 * @return Error code
Sergunb 0:8918a71cdbe9 415 **/
Sergunb 0:8918a71cdbe9 416
Sergunb 0:8918a71cdbe9 417 error_t ethCheckDestAddr(NetInterface *interface, const MacAddr *macAddr)
Sergunb 0:8918a71cdbe9 418 {
Sergunb 0:8918a71cdbe9 419 uint_t i;
Sergunb 0:8918a71cdbe9 420 MacFilterEntry *entry;
Sergunb 0:8918a71cdbe9 421
Sergunb 0:8918a71cdbe9 422 //Filter out any invalid addresses
Sergunb 0:8918a71cdbe9 423 error_t error = ERROR_INVALID_ADDRESS;
Sergunb 0:8918a71cdbe9 424
Sergunb 0:8918a71cdbe9 425 //Host address?
Sergunb 0:8918a71cdbe9 426 if(macCompAddr(macAddr, &interface->macAddr))
Sergunb 0:8918a71cdbe9 427 {
Sergunb 0:8918a71cdbe9 428 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 429 }
Sergunb 0:8918a71cdbe9 430 //Broadcast address?
Sergunb 0:8918a71cdbe9 431 else if(macCompAddr(macAddr, &MAC_BROADCAST_ADDR))
Sergunb 0:8918a71cdbe9 432 {
Sergunb 0:8918a71cdbe9 433 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 434 }
Sergunb 0:8918a71cdbe9 435 //Multicast address?
Sergunb 0:8918a71cdbe9 436 else if(macIsMulticastAddr(macAddr))
Sergunb 0:8918a71cdbe9 437 {
Sergunb 0:8918a71cdbe9 438 //Go through the multicast filter table
Sergunb 0:8918a71cdbe9 439 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++)
Sergunb 0:8918a71cdbe9 440 {
Sergunb 0:8918a71cdbe9 441 //Point to the current entry
Sergunb 0:8918a71cdbe9 442 entry = &interface->macMulticastFilter[i];
Sergunb 0:8918a71cdbe9 443
Sergunb 0:8918a71cdbe9 444 //Valid entry?
Sergunb 0:8918a71cdbe9 445 if(entry->refCount > 0)
Sergunb 0:8918a71cdbe9 446 {
Sergunb 0:8918a71cdbe9 447 //Check whether the destination MAC address matches
Sergunb 0:8918a71cdbe9 448 //a relevant multicast address
Sergunb 0:8918a71cdbe9 449 if(macCompAddr(&entry->addr, macAddr))
Sergunb 0:8918a71cdbe9 450 {
Sergunb 0:8918a71cdbe9 451 //The MAC address is acceptable
Sergunb 0:8918a71cdbe9 452 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 453 //Stop immediately
Sergunb 0:8918a71cdbe9 454 break;
Sergunb 0:8918a71cdbe9 455 }
Sergunb 0:8918a71cdbe9 456 }
Sergunb 0:8918a71cdbe9 457 }
Sergunb 0:8918a71cdbe9 458 }
Sergunb 0:8918a71cdbe9 459
Sergunb 0:8918a71cdbe9 460 //Return status code
Sergunb 0:8918a71cdbe9 461 return error;
Sergunb 0:8918a71cdbe9 462 }
Sergunb 0:8918a71cdbe9 463
Sergunb 0:8918a71cdbe9 464
Sergunb 0:8918a71cdbe9 465 /**
Sergunb 0:8918a71cdbe9 466 * @brief Add a multicast address to the MAC filter table
Sergunb 0:8918a71cdbe9 467 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 468 * @param[in] macAddr Multicast MAC address to accept
Sergunb 0:8918a71cdbe9 469 * @return Error code
Sergunb 0:8918a71cdbe9 470 **/
Sergunb 0:8918a71cdbe9 471
Sergunb 0:8918a71cdbe9 472 error_t ethAcceptMulticastAddr(NetInterface *interface, const MacAddr *macAddr)
Sergunb 0:8918a71cdbe9 473 {
Sergunb 0:8918a71cdbe9 474 uint_t i;
Sergunb 0:8918a71cdbe9 475 MacFilterEntry *entry;
Sergunb 0:8918a71cdbe9 476 MacFilterEntry *firstFreeEntry;
Sergunb 0:8918a71cdbe9 477
Sergunb 0:8918a71cdbe9 478 //Keep track of the first free entry
Sergunb 0:8918a71cdbe9 479 firstFreeEntry = NULL;
Sergunb 0:8918a71cdbe9 480
Sergunb 0:8918a71cdbe9 481 //Go through the multicast filter table
Sergunb 0:8918a71cdbe9 482 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++)
Sergunb 0:8918a71cdbe9 483 {
Sergunb 0:8918a71cdbe9 484 //Point to the current entry
Sergunb 0:8918a71cdbe9 485 entry = &interface->macMulticastFilter[i];
Sergunb 0:8918a71cdbe9 486
Sergunb 0:8918a71cdbe9 487 //Valid entry?
Sergunb 0:8918a71cdbe9 488 if(entry->refCount > 0)
Sergunb 0:8918a71cdbe9 489 {
Sergunb 0:8918a71cdbe9 490 //Check whether the table already contains the specified MAC address
Sergunb 0:8918a71cdbe9 491 if(macCompAddr(&entry->addr, macAddr))
Sergunb 0:8918a71cdbe9 492 {
Sergunb 0:8918a71cdbe9 493 //Increment the reference count
Sergunb 0:8918a71cdbe9 494 entry->refCount++;
Sergunb 0:8918a71cdbe9 495 //No error to report
Sergunb 0:8918a71cdbe9 496 return NO_ERROR;
Sergunb 0:8918a71cdbe9 497 }
Sergunb 0:8918a71cdbe9 498 }
Sergunb 0:8918a71cdbe9 499 else
Sergunb 0:8918a71cdbe9 500 {
Sergunb 0:8918a71cdbe9 501 //Keep track of the first free entry
Sergunb 0:8918a71cdbe9 502 if(firstFreeEntry == NULL)
Sergunb 0:8918a71cdbe9 503 firstFreeEntry = entry;
Sergunb 0:8918a71cdbe9 504 }
Sergunb 0:8918a71cdbe9 505 }
Sergunb 0:8918a71cdbe9 506
Sergunb 0:8918a71cdbe9 507 //Check whether the multicast filter table is full
Sergunb 0:8918a71cdbe9 508 if(firstFreeEntry == NULL)
Sergunb 0:8918a71cdbe9 509 {
Sergunb 0:8918a71cdbe9 510 //A new entry cannot be added
Sergunb 0:8918a71cdbe9 511 return ERROR_FAILURE;
Sergunb 0:8918a71cdbe9 512 }
Sergunb 0:8918a71cdbe9 513
Sergunb 0:8918a71cdbe9 514 //Add a new entry to the table
Sergunb 0:8918a71cdbe9 515 firstFreeEntry->addr = *macAddr;
Sergunb 0:8918a71cdbe9 516 //Initialize the reference count
Sergunb 0:8918a71cdbe9 517 firstFreeEntry->refCount = 1;
Sergunb 0:8918a71cdbe9 518
Sergunb 0:8918a71cdbe9 519 //Force the network interface controller to add the current
Sergunb 0:8918a71cdbe9 520 //entry to its MAC filter table
Sergunb 0:8918a71cdbe9 521 firstFreeEntry->addFlag = TRUE;
Sergunb 0:8918a71cdbe9 522 firstFreeEntry->deleteFlag = FALSE;
Sergunb 0:8918a71cdbe9 523
Sergunb 0:8918a71cdbe9 524 //Update the MAC filter table
Sergunb 0:8918a71cdbe9 525 nicSetMulticastFilter(interface);
Sergunb 0:8918a71cdbe9 526
Sergunb 0:8918a71cdbe9 527 //Clear the flag
Sergunb 0:8918a71cdbe9 528 firstFreeEntry->addFlag = FALSE;
Sergunb 0:8918a71cdbe9 529
Sergunb 0:8918a71cdbe9 530 //No error to report
Sergunb 0:8918a71cdbe9 531 return NO_ERROR;
Sergunb 0:8918a71cdbe9 532 }
Sergunb 0:8918a71cdbe9 533
Sergunb 0:8918a71cdbe9 534
Sergunb 0:8918a71cdbe9 535 /**
Sergunb 0:8918a71cdbe9 536 * @brief Remove a multicast address from the MAC filter table
Sergunb 0:8918a71cdbe9 537 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 538 * @param[in] macAddr Multicast MAC address to drop
Sergunb 0:8918a71cdbe9 539 * @return Error code
Sergunb 0:8918a71cdbe9 540 **/
Sergunb 0:8918a71cdbe9 541
Sergunb 0:8918a71cdbe9 542 error_t ethDropMulticastAddr(NetInterface *interface, const MacAddr *macAddr)
Sergunb 0:8918a71cdbe9 543 {
Sergunb 0:8918a71cdbe9 544 uint_t i;
Sergunb 0:8918a71cdbe9 545 MacFilterEntry *entry;
Sergunb 0:8918a71cdbe9 546
Sergunb 0:8918a71cdbe9 547 //Go through the multicast filter table
Sergunb 0:8918a71cdbe9 548 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++)
Sergunb 0:8918a71cdbe9 549 {
Sergunb 0:8918a71cdbe9 550 //Point to the current entry
Sergunb 0:8918a71cdbe9 551 entry = &interface->macMulticastFilter[i];
Sergunb 0:8918a71cdbe9 552
Sergunb 0:8918a71cdbe9 553 //Valid entry?
Sergunb 0:8918a71cdbe9 554 if(entry->refCount > 0)
Sergunb 0:8918a71cdbe9 555 {
Sergunb 0:8918a71cdbe9 556 //Specified MAC address found?
Sergunb 0:8918a71cdbe9 557 if(macCompAddr(&entry->addr, macAddr))
Sergunb 0:8918a71cdbe9 558 {
Sergunb 0:8918a71cdbe9 559 //Decrement the reference count
Sergunb 0:8918a71cdbe9 560 entry->refCount--;
Sergunb 0:8918a71cdbe9 561
Sergunb 0:8918a71cdbe9 562 //Remove the entry if the reference count drops to zero
Sergunb 0:8918a71cdbe9 563 if(entry->refCount == 0)
Sergunb 0:8918a71cdbe9 564 {
Sergunb 0:8918a71cdbe9 565 //Force the network interface controller to remove the current
Sergunb 0:8918a71cdbe9 566 //entry from its MAC filter table
Sergunb 0:8918a71cdbe9 567 entry->deleteFlag = TRUE;
Sergunb 0:8918a71cdbe9 568
Sergunb 0:8918a71cdbe9 569 //Update the MAC filter table
Sergunb 0:8918a71cdbe9 570 nicSetMulticastFilter(interface);
Sergunb 0:8918a71cdbe9 571
Sergunb 0:8918a71cdbe9 572 //Clear the flag
Sergunb 0:8918a71cdbe9 573 entry->deleteFlag = FALSE;
Sergunb 0:8918a71cdbe9 574 //Remove the multicast address from the list
Sergunb 0:8918a71cdbe9 575 entry->addr = MAC_UNSPECIFIED_ADDR;
Sergunb 0:8918a71cdbe9 576 }
Sergunb 0:8918a71cdbe9 577
Sergunb 0:8918a71cdbe9 578 //No error to report
Sergunb 0:8918a71cdbe9 579 return NO_ERROR;
Sergunb 0:8918a71cdbe9 580 }
Sergunb 0:8918a71cdbe9 581 }
Sergunb 0:8918a71cdbe9 582 }
Sergunb 0:8918a71cdbe9 583
Sergunb 0:8918a71cdbe9 584 //The specified MAC address does not exist
Sergunb 0:8918a71cdbe9 585 return ERROR_ADDRESS_NOT_FOUND;
Sergunb 0:8918a71cdbe9 586 }
Sergunb 0:8918a71cdbe9 587
Sergunb 0:8918a71cdbe9 588
Sergunb 0:8918a71cdbe9 589 /**
Sergunb 0:8918a71cdbe9 590 * @brief Ethernet CRC calculation
Sergunb 0:8918a71cdbe9 591 * @param[in] data Pointer to the data over which to calculate the CRC
Sergunb 0:8918a71cdbe9 592 * @param[in] length Number of bytes to process
Sergunb 0:8918a71cdbe9 593 * @return Resulting CRC value
Sergunb 0:8918a71cdbe9 594 **/
Sergunb 0:8918a71cdbe9 595
Sergunb 0:8918a71cdbe9 596 uint32_t ethCalcCrc(const void *data, size_t length)
Sergunb 0:8918a71cdbe9 597 {
Sergunb 0:8918a71cdbe9 598 //A lookup table can be used to speed up CRC calculation
Sergunb 0:8918a71cdbe9 599 #if (ETH_FAST_CRC_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 600 uint_t i;
Sergunb 0:8918a71cdbe9 601
Sergunb 0:8918a71cdbe9 602 //Point to the data over which to calculate the CRC
Sergunb 0:8918a71cdbe9 603 const uint8_t *p = (uint8_t *) data;
Sergunb 0:8918a71cdbe9 604 //CRC preset value
Sergunb 0:8918a71cdbe9 605 uint32_t crc = 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 606
Sergunb 0:8918a71cdbe9 607 //Loop through data
Sergunb 0:8918a71cdbe9 608 for(i = 0; i < length; i++)
Sergunb 0:8918a71cdbe9 609 {
Sergunb 0:8918a71cdbe9 610 //The message is processed byte by byte
Sergunb 0:8918a71cdbe9 611 crc = (crc >> 8) ^ crc32Table[(crc & 0xFF) ^ p[i]];
Sergunb 0:8918a71cdbe9 612 }
Sergunb 0:8918a71cdbe9 613
Sergunb 0:8918a71cdbe9 614 //Return 1's complement value
Sergunb 0:8918a71cdbe9 615 return ~crc;
Sergunb 0:8918a71cdbe9 616
Sergunb 0:8918a71cdbe9 617 //Bit by bit CRC calculation
Sergunb 0:8918a71cdbe9 618 #else
Sergunb 0:8918a71cdbe9 619 uint_t i;
Sergunb 0:8918a71cdbe9 620 uint_t j;
Sergunb 0:8918a71cdbe9 621
Sergunb 0:8918a71cdbe9 622 //Point to the data over which to calculate the CRC
Sergunb 0:8918a71cdbe9 623 const uint8_t *p = (uint8_t *) data;
Sergunb 0:8918a71cdbe9 624 //CRC preset value
Sergunb 0:8918a71cdbe9 625 uint32_t crc = 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 626
Sergunb 0:8918a71cdbe9 627 //Loop through data
Sergunb 0:8918a71cdbe9 628 for(i = 0; i < length; i++)
Sergunb 0:8918a71cdbe9 629 {
Sergunb 0:8918a71cdbe9 630 //Update CRC value
Sergunb 0:8918a71cdbe9 631 crc ^= p[i];
Sergunb 0:8918a71cdbe9 632 //The message is processed bit by bit
Sergunb 0:8918a71cdbe9 633 for(j = 0; j < 8; j++)
Sergunb 0:8918a71cdbe9 634 {
Sergunb 0:8918a71cdbe9 635 if(crc & 0x00000001)
Sergunb 0:8918a71cdbe9 636 crc = (crc >> 1) ^ 0xEDB88320;
Sergunb 0:8918a71cdbe9 637 else
Sergunb 0:8918a71cdbe9 638 crc = crc >> 1;
Sergunb 0:8918a71cdbe9 639 }
Sergunb 0:8918a71cdbe9 640 }
Sergunb 0:8918a71cdbe9 641
Sergunb 0:8918a71cdbe9 642 //Return 1's complement value
Sergunb 0:8918a71cdbe9 643 return ~crc;
Sergunb 0:8918a71cdbe9 644 #endif
Sergunb 0:8918a71cdbe9 645 }
Sergunb 0:8918a71cdbe9 646
Sergunb 0:8918a71cdbe9 647
Sergunb 0:8918a71cdbe9 648 /**
Sergunb 0:8918a71cdbe9 649 * @brief Calculate CRC over a multi-part buffer
Sergunb 0:8918a71cdbe9 650 * @param[in] buffer Pointer to the multi-part buffer
Sergunb 0:8918a71cdbe9 651 * @param[in] offset Offset from the beginning of the buffer
Sergunb 0:8918a71cdbe9 652 * @param[in] length Number of bytes to process
Sergunb 0:8918a71cdbe9 653 * @return Resulting CRC value
Sergunb 0:8918a71cdbe9 654 **/
Sergunb 0:8918a71cdbe9 655
Sergunb 0:8918a71cdbe9 656 uint32_t ethCalcCrcEx(const NetBuffer *buffer, size_t offset, size_t length)
Sergunb 0:8918a71cdbe9 657 {
Sergunb 0:8918a71cdbe9 658 uint_t i;
Sergunb 0:8918a71cdbe9 659 uint_t n;
Sergunb 0:8918a71cdbe9 660 uint32_t crc;
Sergunb 0:8918a71cdbe9 661 uint8_t *p;
Sergunb 0:8918a71cdbe9 662 #if (ETH_FAST_CRC_SUPPORT == DISABLED)
Sergunb 0:8918a71cdbe9 663 uint_t k;
Sergunb 0:8918a71cdbe9 664 #endif
Sergunb 0:8918a71cdbe9 665
Sergunb 0:8918a71cdbe9 666 //CRC preset value
Sergunb 0:8918a71cdbe9 667 crc = 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 668
Sergunb 0:8918a71cdbe9 669 //Loop through data chunks
Sergunb 0:8918a71cdbe9 670 for(i = 0; i < buffer->chunkCount && length > 0; i++)
Sergunb 0:8918a71cdbe9 671 {
Sergunb 0:8918a71cdbe9 672 //Is there any data to process in the current chunk?
Sergunb 0:8918a71cdbe9 673 if(offset < buffer->chunk[i].length)
Sergunb 0:8918a71cdbe9 674 {
Sergunb 0:8918a71cdbe9 675 //Point to the first data byte
Sergunb 0:8918a71cdbe9 676 p = (uint8_t *) buffer->chunk[i].address + offset;
Sergunb 0:8918a71cdbe9 677 //Compute the number of bytes to process
Sergunb 0:8918a71cdbe9 678 n = MIN(buffer->chunk[i].length - offset, length);
Sergunb 0:8918a71cdbe9 679 //Adjust byte counter
Sergunb 0:8918a71cdbe9 680 length -= n;
Sergunb 0:8918a71cdbe9 681
Sergunb 0:8918a71cdbe9 682 //Process current chunk
Sergunb 0:8918a71cdbe9 683 while(n > 0)
Sergunb 0:8918a71cdbe9 684 {
Sergunb 0:8918a71cdbe9 685 #if (ETH_FAST_CRC_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 686 //The message is processed byte by byte
Sergunb 0:8918a71cdbe9 687 crc = (crc >> 8) ^ crc32Table[(crc & 0xFF) ^ *p];
Sergunb 0:8918a71cdbe9 688 #else
Sergunb 0:8918a71cdbe9 689 //Update CRC value
Sergunb 0:8918a71cdbe9 690 crc ^= *p;
Sergunb 0:8918a71cdbe9 691
Sergunb 0:8918a71cdbe9 692 //The message is processed bit by bit
Sergunb 0:8918a71cdbe9 693 for(k = 0; k < 8; k++)
Sergunb 0:8918a71cdbe9 694 {
Sergunb 0:8918a71cdbe9 695 if(crc & 0x00000001)
Sergunb 0:8918a71cdbe9 696 crc = (crc >> 1) ^ 0xEDB88320;
Sergunb 0:8918a71cdbe9 697 else
Sergunb 0:8918a71cdbe9 698 crc = crc >> 1;
Sergunb 0:8918a71cdbe9 699 }
Sergunb 0:8918a71cdbe9 700 #endif
Sergunb 0:8918a71cdbe9 701 //Next byte
Sergunb 0:8918a71cdbe9 702 p++;
Sergunb 0:8918a71cdbe9 703 n--;
Sergunb 0:8918a71cdbe9 704 }
Sergunb 0:8918a71cdbe9 705
Sergunb 0:8918a71cdbe9 706 //Process the next block from the start
Sergunb 0:8918a71cdbe9 707 offset = 0;
Sergunb 0:8918a71cdbe9 708 }
Sergunb 0:8918a71cdbe9 709 else
Sergunb 0:8918a71cdbe9 710 {
Sergunb 0:8918a71cdbe9 711 //Skip the current chunk
Sergunb 0:8918a71cdbe9 712 offset -= buffer->chunk[i].length;
Sergunb 0:8918a71cdbe9 713 }
Sergunb 0:8918a71cdbe9 714 }
Sergunb 0:8918a71cdbe9 715
Sergunb 0:8918a71cdbe9 716 //Return 1's complement value
Sergunb 0:8918a71cdbe9 717 return ~crc;
Sergunb 0:8918a71cdbe9 718 }
Sergunb 0:8918a71cdbe9 719
Sergunb 0:8918a71cdbe9 720
Sergunb 0:8918a71cdbe9 721 /**
Sergunb 0:8918a71cdbe9 722 * @brief Allocate a buffer to hold an Ethernet frame
Sergunb 0:8918a71cdbe9 723 * @param[in] length Desired payload length
Sergunb 0:8918a71cdbe9 724 * @param[out] offset Offset to the first byte of the payload
Sergunb 0:8918a71cdbe9 725 * @return The function returns a pointer to the newly allocated
Sergunb 0:8918a71cdbe9 726 * buffer. If the system is out of resources, NULL is returned
Sergunb 0:8918a71cdbe9 727 **/
Sergunb 0:8918a71cdbe9 728
Sergunb 0:8918a71cdbe9 729 NetBuffer *ethAllocBuffer(size_t length, size_t *offset)
Sergunb 0:8918a71cdbe9 730 {
Sergunb 0:8918a71cdbe9 731 NetBuffer *buffer;
Sergunb 0:8918a71cdbe9 732
Sergunb 0:8918a71cdbe9 733 //Allocate a buffer to hold the Ethernet header and the payload
Sergunb 0:8918a71cdbe9 734 buffer = netBufferAlloc(length + sizeof(EthHeader));
Sergunb 0:8918a71cdbe9 735 //Failed to allocate buffer?
Sergunb 0:8918a71cdbe9 736 if(buffer == NULL)
Sergunb 0:8918a71cdbe9 737 return NULL;
Sergunb 0:8918a71cdbe9 738
Sergunb 0:8918a71cdbe9 739 //Offset to the first byte of the payload
Sergunb 0:8918a71cdbe9 740 *offset = sizeof(EthHeader);
Sergunb 0:8918a71cdbe9 741
Sergunb 0:8918a71cdbe9 742 //Return a pointer to the freshly allocated buffer
Sergunb 0:8918a71cdbe9 743 return buffer;
Sergunb 0:8918a71cdbe9 744 }
Sergunb 0:8918a71cdbe9 745
Sergunb 0:8918a71cdbe9 746
Sergunb 0:8918a71cdbe9 747 /**
Sergunb 0:8918a71cdbe9 748 * @brief Convert a string representation of a MAC address to a binary MAC address
Sergunb 0:8918a71cdbe9 749 * @param[in] str NULL-terminated string representing the MAC address
Sergunb 0:8918a71cdbe9 750 * @param[out] macAddr Binary representation of the MAC address
Sergunb 0:8918a71cdbe9 751 * @return Error code
Sergunb 0:8918a71cdbe9 752 **/
Sergunb 0:8918a71cdbe9 753
Sergunb 0:8918a71cdbe9 754 error_t macStringToAddr(const char_t *str, MacAddr *macAddr)
Sergunb 0:8918a71cdbe9 755 {
Sergunb 0:8918a71cdbe9 756 error_t error;
Sergunb 0:8918a71cdbe9 757 int_t i = 0;
Sergunb 0:8918a71cdbe9 758 int_t value = -1;
Sergunb 0:8918a71cdbe9 759
Sergunb 0:8918a71cdbe9 760 //Parse input string
Sergunb 0:8918a71cdbe9 761 while(1)
Sergunb 0:8918a71cdbe9 762 {
Sergunb 0:8918a71cdbe9 763 //Hexadecimal digit found?
Sergunb 0:8918a71cdbe9 764 if(isxdigit((uint8_t) *str))
Sergunb 0:8918a71cdbe9 765 {
Sergunb 0:8918a71cdbe9 766 //First digit to be decoded?
Sergunb 0:8918a71cdbe9 767 if(value < 0) value = 0;
Sergunb 0:8918a71cdbe9 768 //Update the value of the current byte
Sergunb 0:8918a71cdbe9 769 if(isdigit((uint8_t) *str))
Sergunb 0:8918a71cdbe9 770 value = (value * 16) + (*str - '0');
Sergunb 0:8918a71cdbe9 771 else if(isupper((uint8_t) *str))
Sergunb 0:8918a71cdbe9 772 value = (value * 16) + (*str - 'A' + 10);
Sergunb 0:8918a71cdbe9 773 else
Sergunb 0:8918a71cdbe9 774 value = (value * 16) + (*str - 'a' + 10);
Sergunb 0:8918a71cdbe9 775 //Check resulting value
Sergunb 0:8918a71cdbe9 776 if(value > 0xFF)
Sergunb 0:8918a71cdbe9 777 {
Sergunb 0:8918a71cdbe9 778 //The conversion failed
Sergunb 0:8918a71cdbe9 779 error = ERROR_INVALID_SYNTAX;
Sergunb 0:8918a71cdbe9 780 break;
Sergunb 0:8918a71cdbe9 781 }
Sergunb 0:8918a71cdbe9 782 }
Sergunb 0:8918a71cdbe9 783 //Dash or colon separator found?
Sergunb 0:8918a71cdbe9 784 else if((*str == '-' || *str == ':') && i < 6)
Sergunb 0:8918a71cdbe9 785 {
Sergunb 0:8918a71cdbe9 786 //Each separator must be preceded by a valid number
Sergunb 0:8918a71cdbe9 787 if(value < 0)
Sergunb 0:8918a71cdbe9 788 {
Sergunb 0:8918a71cdbe9 789 //The conversion failed
Sergunb 0:8918a71cdbe9 790 error = ERROR_INVALID_SYNTAX;
Sergunb 0:8918a71cdbe9 791 break;
Sergunb 0:8918a71cdbe9 792 }
Sergunb 0:8918a71cdbe9 793
Sergunb 0:8918a71cdbe9 794 //Save the current byte
Sergunb 0:8918a71cdbe9 795 macAddr->b[i++] = value;
Sergunb 0:8918a71cdbe9 796 //Prepare to decode the next byte
Sergunb 0:8918a71cdbe9 797 value = -1;
Sergunb 0:8918a71cdbe9 798 }
Sergunb 0:8918a71cdbe9 799 //End of string detected?
Sergunb 0:8918a71cdbe9 800 else if(*str == '\0' && i == 5)
Sergunb 0:8918a71cdbe9 801 {
Sergunb 0:8918a71cdbe9 802 //The NULL character must be preceded by a valid number
Sergunb 0:8918a71cdbe9 803 if(value < 0)
Sergunb 0:8918a71cdbe9 804 {
Sergunb 0:8918a71cdbe9 805 //The conversion failed
Sergunb 0:8918a71cdbe9 806 error = ERROR_INVALID_SYNTAX;
Sergunb 0:8918a71cdbe9 807 }
Sergunb 0:8918a71cdbe9 808 else
Sergunb 0:8918a71cdbe9 809 {
Sergunb 0:8918a71cdbe9 810 //Save the last byte of the MAC address
Sergunb 0:8918a71cdbe9 811 macAddr->b[i] = value;
Sergunb 0:8918a71cdbe9 812 //The conversion succeeded
Sergunb 0:8918a71cdbe9 813 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 814 }
Sergunb 0:8918a71cdbe9 815
Sergunb 0:8918a71cdbe9 816 //We are done
Sergunb 0:8918a71cdbe9 817 break;
Sergunb 0:8918a71cdbe9 818 }
Sergunb 0:8918a71cdbe9 819 //Invalid character...
Sergunb 0:8918a71cdbe9 820 else
Sergunb 0:8918a71cdbe9 821 {
Sergunb 0:8918a71cdbe9 822 //The conversion failed
Sergunb 0:8918a71cdbe9 823 error = ERROR_INVALID_SYNTAX;
Sergunb 0:8918a71cdbe9 824 break;
Sergunb 0:8918a71cdbe9 825 }
Sergunb 0:8918a71cdbe9 826
Sergunb 0:8918a71cdbe9 827 //Point to the next character
Sergunb 0:8918a71cdbe9 828 str++;
Sergunb 0:8918a71cdbe9 829 }
Sergunb 0:8918a71cdbe9 830
Sergunb 0:8918a71cdbe9 831 //Return status code
Sergunb 0:8918a71cdbe9 832 return error;
Sergunb 0:8918a71cdbe9 833 }
Sergunb 0:8918a71cdbe9 834
Sergunb 0:8918a71cdbe9 835
Sergunb 0:8918a71cdbe9 836 /**
Sergunb 0:8918a71cdbe9 837 * @brief Convert a MAC address to a dash delimited string
Sergunb 0:8918a71cdbe9 838 * @param[in] macAddr Pointer to the MAC address
Sergunb 0:8918a71cdbe9 839 * @param[out] str NULL-terminated string representing the MAC address
Sergunb 0:8918a71cdbe9 840 * @return Pointer to the formatted string
Sergunb 0:8918a71cdbe9 841 **/
Sergunb 0:8918a71cdbe9 842
Sergunb 0:8918a71cdbe9 843 char_t *macAddrToString(const MacAddr *macAddr, char_t *str)
Sergunb 0:8918a71cdbe9 844 {
Sergunb 0:8918a71cdbe9 845 static char_t buffer[18];
Sergunb 0:8918a71cdbe9 846
Sergunb 0:8918a71cdbe9 847 //The str parameter is optional
Sergunb 0:8918a71cdbe9 848 if(str == NULL)
Sergunb 0:8918a71cdbe9 849 str = buffer;
Sergunb 0:8918a71cdbe9 850
Sergunb 0:8918a71cdbe9 851 //Format MAC address
Sergunb 0:8918a71cdbe9 852 sprintf(str, "%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8,
Sergunb 0:8918a71cdbe9 853 macAddr->b[0], macAddr->b[1], macAddr->b[2], macAddr->b[3], macAddr->b[4], macAddr->b[5]);
Sergunb 0:8918a71cdbe9 854
Sergunb 0:8918a71cdbe9 855 //Return a pointer to the formatted string
Sergunb 0:8918a71cdbe9 856 return str;
Sergunb 0:8918a71cdbe9 857 }
Sergunb 0:8918a71cdbe9 858
Sergunb 0:8918a71cdbe9 859
Sergunb 0:8918a71cdbe9 860 /**
Sergunb 0:8918a71cdbe9 861 * @brief Convert a string representation of an EUI-64 address to a binary EUI-64 address
Sergunb 0:8918a71cdbe9 862 * @param[in] str NULL-terminated string representing the EUI-64 address
Sergunb 0:8918a71cdbe9 863 * @param[out] eui64 Binary representation of the EUI-64 address
Sergunb 0:8918a71cdbe9 864 * @return Error code
Sergunb 0:8918a71cdbe9 865 **/
Sergunb 0:8918a71cdbe9 866
Sergunb 0:8918a71cdbe9 867 error_t eui64StringToAddr(const char_t *str, Eui64 *eui64)
Sergunb 0:8918a71cdbe9 868 {
Sergunb 0:8918a71cdbe9 869 error_t error;
Sergunb 0:8918a71cdbe9 870 int_t i = 0;
Sergunb 0:8918a71cdbe9 871 int_t value = -1;
Sergunb 0:8918a71cdbe9 872
Sergunb 0:8918a71cdbe9 873 //Parse input string
Sergunb 0:8918a71cdbe9 874 while(1)
Sergunb 0:8918a71cdbe9 875 {
Sergunb 0:8918a71cdbe9 876 //Hexadecimal digit found?
Sergunb 0:8918a71cdbe9 877 if(isxdigit((uint8_t) *str))
Sergunb 0:8918a71cdbe9 878 {
Sergunb 0:8918a71cdbe9 879 //First digit to be decoded?
Sergunb 0:8918a71cdbe9 880 if(value < 0) value = 0;
Sergunb 0:8918a71cdbe9 881 //Update the value of the current byte
Sergunb 0:8918a71cdbe9 882 if(isdigit((uint8_t) *str))
Sergunb 0:8918a71cdbe9 883 value = (value * 16) + (*str - '0');
Sergunb 0:8918a71cdbe9 884 else if(isupper((uint8_t) *str))
Sergunb 0:8918a71cdbe9 885 value = (value * 16) + (*str - 'A' + 10);
Sergunb 0:8918a71cdbe9 886 else
Sergunb 0:8918a71cdbe9 887 value = (value * 16) + (*str - 'a' + 10);
Sergunb 0:8918a71cdbe9 888 //Check resulting value
Sergunb 0:8918a71cdbe9 889 if(value > 0xFF)
Sergunb 0:8918a71cdbe9 890 {
Sergunb 0:8918a71cdbe9 891 //The conversion failed
Sergunb 0:8918a71cdbe9 892 error = ERROR_INVALID_SYNTAX;
Sergunb 0:8918a71cdbe9 893 break;
Sergunb 0:8918a71cdbe9 894 }
Sergunb 0:8918a71cdbe9 895 }
Sergunb 0:8918a71cdbe9 896 //Dash or colon separator found?
Sergunb 0:8918a71cdbe9 897 else if((*str == '-' || *str == ':') && i < 8)
Sergunb 0:8918a71cdbe9 898 {
Sergunb 0:8918a71cdbe9 899 //Each separator must be preceded by a valid number
Sergunb 0:8918a71cdbe9 900 if(value < 0)
Sergunb 0:8918a71cdbe9 901 {
Sergunb 0:8918a71cdbe9 902 //The conversion failed
Sergunb 0:8918a71cdbe9 903 error = ERROR_INVALID_SYNTAX;
Sergunb 0:8918a71cdbe9 904 break;
Sergunb 0:8918a71cdbe9 905 }
Sergunb 0:8918a71cdbe9 906
Sergunb 0:8918a71cdbe9 907 //Save the current byte
Sergunb 0:8918a71cdbe9 908 eui64->b[i++] = value;
Sergunb 0:8918a71cdbe9 909 //Prepare to decode the next byte
Sergunb 0:8918a71cdbe9 910 value = -1;
Sergunb 0:8918a71cdbe9 911 }
Sergunb 0:8918a71cdbe9 912 //End of string detected?
Sergunb 0:8918a71cdbe9 913 else if(*str == '\0' && i == 7)
Sergunb 0:8918a71cdbe9 914 {
Sergunb 0:8918a71cdbe9 915 //The NULL character must be preceded by a valid number
Sergunb 0:8918a71cdbe9 916 if(value < 0)
Sergunb 0:8918a71cdbe9 917 {
Sergunb 0:8918a71cdbe9 918 //The conversion failed
Sergunb 0:8918a71cdbe9 919 error = ERROR_INVALID_SYNTAX;
Sergunb 0:8918a71cdbe9 920 }
Sergunb 0:8918a71cdbe9 921 else
Sergunb 0:8918a71cdbe9 922 {
Sergunb 0:8918a71cdbe9 923 //Save the last byte of the EUI-64 address
Sergunb 0:8918a71cdbe9 924 eui64->b[i] = value;
Sergunb 0:8918a71cdbe9 925 //The conversion succeeded
Sergunb 0:8918a71cdbe9 926 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 927 }
Sergunb 0:8918a71cdbe9 928
Sergunb 0:8918a71cdbe9 929 //We are done
Sergunb 0:8918a71cdbe9 930 break;
Sergunb 0:8918a71cdbe9 931 }
Sergunb 0:8918a71cdbe9 932 //Invalid character...
Sergunb 0:8918a71cdbe9 933 else
Sergunb 0:8918a71cdbe9 934 {
Sergunb 0:8918a71cdbe9 935 //The conversion failed
Sergunb 0:8918a71cdbe9 936 error = ERROR_INVALID_SYNTAX;
Sergunb 0:8918a71cdbe9 937 break;
Sergunb 0:8918a71cdbe9 938 }
Sergunb 0:8918a71cdbe9 939
Sergunb 0:8918a71cdbe9 940 //Point to the next character
Sergunb 0:8918a71cdbe9 941 str++;
Sergunb 0:8918a71cdbe9 942 }
Sergunb 0:8918a71cdbe9 943
Sergunb 0:8918a71cdbe9 944 //Return status code
Sergunb 0:8918a71cdbe9 945 return error;
Sergunb 0:8918a71cdbe9 946 }
Sergunb 0:8918a71cdbe9 947
Sergunb 0:8918a71cdbe9 948
Sergunb 0:8918a71cdbe9 949 /**
Sergunb 0:8918a71cdbe9 950 * @brief Convert an EUI-64 address to a dash delimited string
Sergunb 0:8918a71cdbe9 951 * @param[in] eui64 Pointer to the EUI-64 address
Sergunb 0:8918a71cdbe9 952 * @param[out] str NULL-terminated string representing the EUI-64 address
Sergunb 0:8918a71cdbe9 953 * @return Pointer to the formatted string
Sergunb 0:8918a71cdbe9 954 **/
Sergunb 0:8918a71cdbe9 955
Sergunb 0:8918a71cdbe9 956 char_t *eui64AddrToString(const Eui64 *eui64, char_t *str)
Sergunb 0:8918a71cdbe9 957 {
Sergunb 0:8918a71cdbe9 958 static char_t buffer[24];
Sergunb 0:8918a71cdbe9 959
Sergunb 0:8918a71cdbe9 960 //The str parameter is optional
Sergunb 0:8918a71cdbe9 961 if(str == NULL)
Sergunb 0:8918a71cdbe9 962 str = buffer;
Sergunb 0:8918a71cdbe9 963
Sergunb 0:8918a71cdbe9 964 //Format EUI-64 identifier
Sergunb 0:8918a71cdbe9 965 sprintf(str, "%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8
Sergunb 0:8918a71cdbe9 966 "-%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8,
Sergunb 0:8918a71cdbe9 967 eui64->b[0], eui64->b[1], eui64->b[2], eui64->b[3],
Sergunb 0:8918a71cdbe9 968 eui64->b[4], eui64->b[5], eui64->b[6], eui64->b[7]);
Sergunb 0:8918a71cdbe9 969
Sergunb 0:8918a71cdbe9 970 //Return a pointer to the formatted string
Sergunb 0:8918a71cdbe9 971 return str;
Sergunb 0:8918a71cdbe9 972 }
Sergunb 0:8918a71cdbe9 973
Sergunb 0:8918a71cdbe9 974
Sergunb 0:8918a71cdbe9 975 /**
Sergunb 0:8918a71cdbe9 976 * @brief Map a MAC address to the IPv6 modified EUI-64 identifier
Sergunb 0:8918a71cdbe9 977 * @param[in] macAddr Host MAC address
Sergunb 0:8918a71cdbe9 978 * @param[out] interfaceId IPv6 modified EUI-64 identifier
Sergunb 0:8918a71cdbe9 979 **/
Sergunb 0:8918a71cdbe9 980
Sergunb 0:8918a71cdbe9 981 void macAddrToEui64(const MacAddr *macAddr, Eui64 *interfaceId)
Sergunb 0:8918a71cdbe9 982 {
Sergunb 0:8918a71cdbe9 983 //Copy the Organization Unique Identifier (OUI)
Sergunb 0:8918a71cdbe9 984 interfaceId->b[0] = macAddr->b[0];
Sergunb 0:8918a71cdbe9 985 interfaceId->b[1] = macAddr->b[1];
Sergunb 0:8918a71cdbe9 986 interfaceId->b[2] = macAddr->b[2];
Sergunb 0:8918a71cdbe9 987
Sergunb 0:8918a71cdbe9 988 //The middle 16 bits are given the value 0xFFFE
Sergunb 0:8918a71cdbe9 989 interfaceId->b[3] = 0xFF;
Sergunb 0:8918a71cdbe9 990 interfaceId->b[4] = 0xFE;
Sergunb 0:8918a71cdbe9 991
Sergunb 0:8918a71cdbe9 992 //Copy the right-most 24 bits of the MAC address
Sergunb 0:8918a71cdbe9 993 interfaceId->b[5] = macAddr->b[3];
Sergunb 0:8918a71cdbe9 994 interfaceId->b[6] = macAddr->b[4];
Sergunb 0:8918a71cdbe9 995 interfaceId->b[7] = macAddr->b[5];
Sergunb 0:8918a71cdbe9 996
Sergunb 0:8918a71cdbe9 997 //Modified EUI-64 format interface identifiers are
Sergunb 0:8918a71cdbe9 998 //formed by inverting the Universal/Local bit
Sergunb 0:8918a71cdbe9 999 interfaceId->b[0] ^= MAC_ADDR_FLAG_LOCAL;
Sergunb 0:8918a71cdbe9 1000 }
Sergunb 0:8918a71cdbe9 1001
Sergunb 0:8918a71cdbe9 1002
Sergunb 0:8918a71cdbe9 1003 /**
Sergunb 0:8918a71cdbe9 1004 * @brief Dump Ethernet header for debugging purpose
Sergunb 0:8918a71cdbe9 1005 * @param[in] ethHeader Pointer to the Ethernet header
Sergunb 0:8918a71cdbe9 1006 **/
Sergunb 0:8918a71cdbe9 1007
Sergunb 0:8918a71cdbe9 1008 void ethDumpHeader(const EthHeader *ethHeader)
Sergunb 0:8918a71cdbe9 1009 {
Sergunb 0:8918a71cdbe9 1010 //Dump Ethernet header contents
Sergunb 0:8918a71cdbe9 1011 TRACE_DEBUG(" Dest Addr = %s\r\n", macAddrToString(&ethHeader->destAddr, NULL));
Sergunb 0:8918a71cdbe9 1012 TRACE_DEBUG(" Src Addr = %s\r\n", macAddrToString(&ethHeader->srcAddr, NULL));
Sergunb 0:8918a71cdbe9 1013 TRACE_DEBUG(" Type = 0x%04" PRIX16 "\r\n", ntohs(ethHeader->type));
Sergunb 0:8918a71cdbe9 1014 }
Sergunb 0:8918a71cdbe9 1015
Sergunb 0:8918a71cdbe9 1016 #endif
Sergunb 0:8918a71cdbe9 1017