Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
ethernet.c
Go to the documentation of this file.
00001 /** 00002 * @file ethernet.c 00003 * @brief Ethernet 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This file is part of CycloneTCP Open. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License 00013 * as published by the Free Software Foundation; either version 2 00014 * of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software Foundation, 00023 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 * 00025 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00026 * @version 1.7.6 00027 **/ 00028 00029 //Switch to the appropriate trace level 00030 #define TRACE_LEVEL ETH_TRACE_LEVEL 00031 00032 //Dependencies 00033 #include <stdlib.h> 00034 #include <string.h> 00035 #include <ctype.h> 00036 #include "core/net.h" 00037 #include "core/nic.h" 00038 #include "core/ethernet.h" 00039 #include "core/socket.h" 00040 #include "core/raw_socket.h" 00041 #include "core/tcp_timer.h" 00042 #include "ipv4/arp.h" 00043 #include "ipv4/ipv4.h" 00044 #include "ipv6/ipv6.h" 00045 #include "mibs/mib2_module.h" 00046 #include "debug.h" 00047 00048 //Check TCP/IP stack configuration 00049 #if (ETH_SUPPORT == ENABLED) 00050 00051 //Unspecified MAC address 00052 const MacAddr MAC_UNSPECIFIED_ADDR = {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}; 00053 //Broadcast MAC address 00054 const MacAddr MAC_BROADCAST_ADDR = {{{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}}; 00055 //Unspecified EUI-64 address 00056 const Eui64 EUI64_UNSPECIFIED_ADDR = {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}; 00057 00058 //Padding bytes 00059 const uint8_t ethPadding[64] = 00060 { 00061 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00062 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00063 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00064 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00065 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00066 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00067 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00068 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 00069 }; 00070 00071 //A lookup table can be used to speed up CRC calculation 00072 #if (ETH_FAST_CRC_SUPPORT == ENABLED) 00073 00074 static const uint32_t crc32Table[256] = 00075 { 00076 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 00077 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 00078 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 00079 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 00080 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 00081 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 00082 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 00083 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 00084 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 00085 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 00086 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 00087 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 00088 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 00089 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 00090 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 00091 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 00092 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 00093 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 00094 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 00095 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 00096 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 00097 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 00098 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 00099 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 00100 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 00101 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 00102 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 00103 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 00104 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 00105 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 00106 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 00107 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 00108 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 00109 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 00110 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 00111 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 00112 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 00113 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 00114 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 00115 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 00116 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 00117 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 00118 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 00119 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 00120 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 00121 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 00122 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 00123 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 00124 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 00125 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 00126 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 00127 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 00128 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 00129 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 00130 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 00131 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 00132 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 00133 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 00134 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 00135 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 00136 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 00137 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 00138 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 00139 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D 00140 }; 00141 00142 #endif 00143 00144 00145 /** 00146 * @brief Ethernet related initialization 00147 * @param[in] interface Underlying network interface 00148 * @return Error code 00149 **/ 00150 00151 error_t ethInit(NetInterface *interface) 00152 { 00153 //Clear the MAC filter table contents 00154 memset(interface->macMulticastFilter, 0, 00155 sizeof(interface->macMulticastFilter)); 00156 00157 //Successful initialization 00158 return NO_ERROR; 00159 } 00160 00161 00162 /** 00163 * @brief Process an incoming Ethernet frame 00164 * @param[in] interface Underlying network interface 00165 * @param[in] ethFrame Incoming Ethernet frame to process 00166 * @param[in] length Total frame length 00167 **/ 00168 00169 void ethProcessFrame(NetInterface *interface, EthHeader *ethFrame, size_t length) 00170 { 00171 #if (IPV6_SUPPORT == ENABLED) 00172 NetBuffer1 buffer; 00173 #endif 00174 uint32_t crc; 00175 00176 //Total number of octets received on the interface 00177 MIB2_INC_COUNTER32(interface->mibIfEntry->ifInOctets, length); 00178 00179 //Ensure the length of the incoming frame is valid 00180 if(length < sizeof(EthHeader)) 00181 { 00182 //Number of inbound packets that contained errors 00183 MIB2_INC_COUNTER32(interface->mibIfEntry->ifInErrors, 1); 00184 //Discard the received frame 00185 return; 00186 } 00187 00188 //Debug message 00189 TRACE_DEBUG("Ethernet frame received (%" PRIuSIZE " bytes)...\r\n", length); 00190 //Dump Ethernet header contents for debugging purpose 00191 ethDumpHeader(ethFrame); 00192 00193 //Check whether the CRC is included in the received frame 00194 if(!interface->nicDriver->autoCrcStrip) 00195 { 00196 //Ensure the length of the incoming frame is valid 00197 if(length < (sizeof(EthHeader) + ETH_CRC_SIZE)) 00198 { 00199 //Number of inbound packets that contained errors 00200 MIB2_INC_COUNTER32(interface->mibIfEntry->ifInErrors, 1); 00201 //Discard the received frame 00202 return; 00203 } 00204 00205 //CRC verification not supported by hardware? 00206 if(!interface->nicDriver->autoCrcVerif) 00207 { 00208 //The value of the residue is 0x2144DF1C when no CRC errors are detected 00209 if(ethCalcCrc(ethFrame, length) != 0x2144DF1C) 00210 { 00211 //Debug message 00212 TRACE_WARNING("Wrong CRC detected!\r\n"); 00213 //Number of inbound packets that contained errors 00214 MIB2_INC_COUNTER32(interface->mibIfEntry->ifInErrors, 1); 00215 //Discard the received frame 00216 return; 00217 } 00218 } 00219 00220 //Retrieve CRC value 00221 memcpy(&crc, (uint8_t *) ethFrame + length - ETH_CRC_SIZE, ETH_CRC_SIZE); 00222 //Reseed the pseudo-random number generator 00223 netInitRand(crc); 00224 } 00225 00226 //Frame filtering based on destination MAC address 00227 if(ethCheckDestAddr(interface, ðFrame->destAddr)) 00228 { 00229 //Number of inbound packets which were chosen to be discarded 00230 //even though no errors had been detected 00231 MIB2_INC_COUNTER32(interface->mibIfEntry->ifInDiscards, 1); 00232 //Discard the received frame 00233 return; 00234 } 00235 00236 //Check whether the destination address is a group address 00237 if(macIsMulticastAddr(ðFrame->destAddr)) 00238 { 00239 //Number of non-unicast packets delivered to a higher-layer protocol 00240 MIB2_INC_COUNTER32(interface->mibIfEntry->ifInNUcastPkts, 1); 00241 } 00242 else 00243 { 00244 //Number of unicast packets delivered to a higher-layer protocol 00245 MIB2_INC_COUNTER32(interface->mibIfEntry->ifInUcastPkts, 1); 00246 } 00247 00248 #if (RAW_SOCKET_SUPPORT == ENABLED) 00249 //Allow raw sockets to process Ethernet packets 00250 rawSocketProcessEthPacket(interface, ethFrame, length - ETH_CRC_SIZE); 00251 #endif 00252 00253 //Calculate the length of the data payload 00254 length -= sizeof(EthHeader); 00255 00256 //Check whether the CRC is included in the received frame 00257 if(!interface->nicDriver->autoCrcStrip) 00258 length -= ETH_CRC_SIZE; 00259 00260 //Check Ethernet type field 00261 switch(ntohs(ethFrame->type)) 00262 { 00263 #if (IPV4_SUPPORT == ENABLED) 00264 //ARP packet received? 00265 case ETH_TYPE_ARP: 00266 //Process incoming ARP packet 00267 arpProcessPacket(interface, (ArpPacket *) ethFrame->data, length); 00268 break; 00269 //IPv4 packet received? 00270 case ETH_TYPE_IPV4: 00271 //Process incoming IPv4 packet 00272 ipv4ProcessPacket(interface, (Ipv4Header *) ethFrame->data, length); 00273 break; 00274 #endif 00275 00276 #if (IPV6_SUPPORT == ENABLED) 00277 //IPv6 packet received? 00278 case ETH_TYPE_IPV6: 00279 //The incoming Ethernet frame fits in a single chunk 00280 buffer.chunkCount = 1; 00281 buffer.maxChunkCount = 1; 00282 buffer.chunk[0].address = ethFrame->data; 00283 buffer.chunk[0].length = length; 00284 buffer.chunk[0].size = 0; 00285 00286 //Process incoming IPv6 packet 00287 ipv6ProcessPacket(interface, (NetBuffer *) &buffer, 0); 00288 break; 00289 #endif 00290 00291 //Unknown packet received? 00292 default: 00293 //Debug message 00294 TRACE_WARNING("Unknown Ethernet type!\r\n"); 00295 00296 //Number of packets received via the interface which were 00297 //discarded because of an unknown or unsupported protocol 00298 MIB2_INC_COUNTER32(interface->mibIfEntry->ifInUnknownProtos , 1); 00299 break; 00300 } 00301 } 00302 00303 00304 /** 00305 * @brief Send an Ethernet frame 00306 * @param[in] interface Underlying network interface 00307 * @param[in] destAddr MAC address of the destination host 00308 * @param[in] buffer Multi-part buffer containing the payload 00309 * @param[in] offset Offset to the first payload byte 00310 * @param[in] type Ethernet type 00311 * @return Error code 00312 **/ 00313 00314 error_t ethSendFrame(NetInterface *interface, const MacAddr *destAddr, 00315 NetBuffer *buffer, size_t offset, uint16_t type) 00316 { 00317 error_t error; 00318 size_t length; 00319 EthHeader *header; 00320 00321 //Is there enough space for the Ethernet header? 00322 if(offset < sizeof(EthHeader)) 00323 return ERROR_INVALID_PARAMETER; 00324 00325 //Make room for the Ethernet header 00326 offset -= sizeof(EthHeader); 00327 //Retrieve the length of the frame 00328 length = netBufferGetLength(buffer) - offset; 00329 00330 //Position to the beginning of the frame 00331 header = netBufferAt(buffer, offset); 00332 00333 //Format Ethernet header 00334 header->destAddr = *destAddr; 00335 header->srcAddr = interface->macAddr; 00336 header->type = htons(type); 00337 00338 //Automatic padding not supported by hardware? 00339 if(!interface->nicDriver->autoPadding) 00340 { 00341 //The host controller should manually add padding 00342 //to the packet before transmitting it 00343 if(length < (ETH_MIN_FRAME_SIZE - ETH_CRC_SIZE)) 00344 { 00345 size_t n; 00346 00347 //Add padding as necessary 00348 n = (ETH_MIN_FRAME_SIZE - ETH_CRC_SIZE) - length; 00349 00350 //Append padding bytes 00351 error = netBufferAppend(buffer, ethPadding, n); 00352 //Any error to report? 00353 if(error) 00354 return error; 00355 00356 //Adjust frame length 00357 length += n; 00358 } 00359 } 00360 00361 //CRC calculation not supported by hardware? 00362 if(!interface->nicDriver->autoCrcCalc) 00363 { 00364 uint32_t crc; 00365 00366 //Compute CRC over the header and payload 00367 crc = ethCalcCrcEx(buffer, offset, length); 00368 //Convert from host byte order to little-endian byte order 00369 crc = htole32(crc); 00370 00371 //Append the calculated CRC value 00372 error = netBufferAppend(buffer, &crc, sizeof(crc)); 00373 //Any error to report? 00374 if(error) 00375 return error; 00376 00377 //Adjust frame length 00378 length += sizeof(crc); 00379 } 00380 00381 //Total number of octets transmitted out of the interface 00382 MIB2_INC_COUNTER32(interface->mibIfEntry->ifOutOctets, length); 00383 00384 //Check whether the destination address is a group address 00385 if(macIsMulticastAddr(&header->destAddr)) 00386 { 00387 //Total number of non-unicast packets that higher-level protocols 00388 //requested be transmitted 00389 MIB2_INC_COUNTER32(interface->mibIfEntry->ifOutNUcastPkts, 1); 00390 } 00391 else 00392 { 00393 //Total number of unicast packets that higher-level protocols 00394 //requested be transmitted 00395 MIB2_INC_COUNTER32(interface->mibIfEntry->ifOutUcastPkts, 1); 00396 } 00397 00398 //Debug message 00399 TRACE_DEBUG("Sending Ethernet frame (%" PRIuSIZE " bytes)...\r\n", length); 00400 //Dump Ethernet header contents for debugging purpose 00401 ethDumpHeader(header); 00402 00403 //Send the resulting packet over the specified link 00404 error = nicSendPacket(interface, buffer, offset); 00405 //Return status code 00406 return error; 00407 } 00408 00409 00410 /** 00411 * @brief Destination MAC address filtering 00412 * @param[in] interface Underlying network interface 00413 * @param[in] macAddr Destination MAC address to be checked 00414 * @return Error code 00415 **/ 00416 00417 error_t ethCheckDestAddr(NetInterface *interface, const MacAddr *macAddr) 00418 { 00419 uint_t i; 00420 MacFilterEntry *entry; 00421 00422 //Filter out any invalid addresses 00423 error_t error = ERROR_INVALID_ADDRESS; 00424 00425 //Host address? 00426 if(macCompAddr(macAddr, &interface->macAddr)) 00427 { 00428 error = NO_ERROR; 00429 } 00430 //Broadcast address? 00431 else if(macCompAddr(macAddr, &MAC_BROADCAST_ADDR)) 00432 { 00433 error = NO_ERROR; 00434 } 00435 //Multicast address? 00436 else if(macIsMulticastAddr(macAddr)) 00437 { 00438 //Go through the multicast filter table 00439 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00440 { 00441 //Point to the current entry 00442 entry = &interface->macMulticastFilter[i]; 00443 00444 //Valid entry? 00445 if(entry->refCount > 0) 00446 { 00447 //Check whether the destination MAC address matches 00448 //a relevant multicast address 00449 if(macCompAddr(&entry->addr, macAddr)) 00450 { 00451 //The MAC address is acceptable 00452 error = NO_ERROR; 00453 //Stop immediately 00454 break; 00455 } 00456 } 00457 } 00458 } 00459 00460 //Return status code 00461 return error; 00462 } 00463 00464 00465 /** 00466 * @brief Add a multicast address to the MAC filter table 00467 * @param[in] interface Underlying network interface 00468 * @param[in] macAddr Multicast MAC address to accept 00469 * @return Error code 00470 **/ 00471 00472 error_t ethAcceptMulticastAddr(NetInterface *interface, const MacAddr *macAddr) 00473 { 00474 uint_t i; 00475 MacFilterEntry *entry; 00476 MacFilterEntry *firstFreeEntry; 00477 00478 //Keep track of the first free entry 00479 firstFreeEntry = NULL; 00480 00481 //Go through the multicast filter table 00482 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00483 { 00484 //Point to the current entry 00485 entry = &interface->macMulticastFilter[i]; 00486 00487 //Valid entry? 00488 if(entry->refCount > 0) 00489 { 00490 //Check whether the table already contains the specified MAC address 00491 if(macCompAddr(&entry->addr, macAddr)) 00492 { 00493 //Increment the reference count 00494 entry->refCount++; 00495 //No error to report 00496 return NO_ERROR; 00497 } 00498 } 00499 else 00500 { 00501 //Keep track of the first free entry 00502 if(firstFreeEntry == NULL) 00503 firstFreeEntry = entry; 00504 } 00505 } 00506 00507 //Check whether the multicast filter table is full 00508 if(firstFreeEntry == NULL) 00509 { 00510 //A new entry cannot be added 00511 return ERROR_FAILURE; 00512 } 00513 00514 //Add a new entry to the table 00515 firstFreeEntry->addr = *macAddr; 00516 //Initialize the reference count 00517 firstFreeEntry->refCount = 1; 00518 00519 //Force the network interface controller to add the current 00520 //entry to its MAC filter table 00521 firstFreeEntry->addFlag = TRUE; 00522 firstFreeEntry->deleteFlag = FALSE; 00523 00524 //Update the MAC filter table 00525 nicSetMulticastFilter(interface); 00526 00527 //Clear the flag 00528 firstFreeEntry->addFlag = FALSE; 00529 00530 //No error to report 00531 return NO_ERROR; 00532 } 00533 00534 00535 /** 00536 * @brief Remove a multicast address from the MAC filter table 00537 * @param[in] interface Underlying network interface 00538 * @param[in] macAddr Multicast MAC address to drop 00539 * @return Error code 00540 **/ 00541 00542 error_t ethDropMulticastAddr(NetInterface *interface, const MacAddr *macAddr) 00543 { 00544 uint_t i; 00545 MacFilterEntry *entry; 00546 00547 //Go through the multicast filter table 00548 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00549 { 00550 //Point to the current entry 00551 entry = &interface->macMulticastFilter[i]; 00552 00553 //Valid entry? 00554 if(entry->refCount > 0) 00555 { 00556 //Specified MAC address found? 00557 if(macCompAddr(&entry->addr, macAddr)) 00558 { 00559 //Decrement the reference count 00560 entry->refCount--; 00561 00562 //Remove the entry if the reference count drops to zero 00563 if(entry->refCount == 0) 00564 { 00565 //Force the network interface controller to remove the current 00566 //entry from its MAC filter table 00567 entry->deleteFlag = TRUE; 00568 00569 //Update the MAC filter table 00570 nicSetMulticastFilter(interface); 00571 00572 //Clear the flag 00573 entry->deleteFlag = FALSE; 00574 //Remove the multicast address from the list 00575 entry->addr = MAC_UNSPECIFIED_ADDR; 00576 } 00577 00578 //No error to report 00579 return NO_ERROR; 00580 } 00581 } 00582 } 00583 00584 //The specified MAC address does not exist 00585 return ERROR_ADDRESS_NOT_FOUND; 00586 } 00587 00588 00589 /** 00590 * @brief Ethernet CRC calculation 00591 * @param[in] data Pointer to the data over which to calculate the CRC 00592 * @param[in] length Number of bytes to process 00593 * @return Resulting CRC value 00594 **/ 00595 00596 uint32_t ethCalcCrc(const void *data, size_t length) 00597 { 00598 //A lookup table can be used to speed up CRC calculation 00599 #if (ETH_FAST_CRC_SUPPORT == ENABLED) 00600 uint_t i; 00601 00602 //Point to the data over which to calculate the CRC 00603 const uint8_t *p = (uint8_t *) data; 00604 //CRC preset value 00605 uint32_t crc = 0xFFFFFFFF; 00606 00607 //Loop through data 00608 for(i = 0; i < length; i++) 00609 { 00610 //The message is processed byte by byte 00611 crc = (crc >> 8) ^ crc32Table[(crc & 0xFF) ^ p[i]]; 00612 } 00613 00614 //Return 1's complement value 00615 return ~crc; 00616 00617 //Bit by bit CRC calculation 00618 #else 00619 uint_t i; 00620 uint_t j; 00621 00622 //Point to the data over which to calculate the CRC 00623 const uint8_t *p = (uint8_t *) data; 00624 //CRC preset value 00625 uint32_t crc = 0xFFFFFFFF; 00626 00627 //Loop through data 00628 for(i = 0; i < length; i++) 00629 { 00630 //Update CRC value 00631 crc ^= p[i]; 00632 //The message is processed bit by bit 00633 for(j = 0; j < 8; j++) 00634 { 00635 if(crc & 0x00000001) 00636 crc = (crc >> 1) ^ 0xEDB88320; 00637 else 00638 crc = crc >> 1; 00639 } 00640 } 00641 00642 //Return 1's complement value 00643 return ~crc; 00644 #endif 00645 } 00646 00647 00648 /** 00649 * @brief Calculate CRC over a multi-part buffer 00650 * @param[in] buffer Pointer to the multi-part buffer 00651 * @param[in] offset Offset from the beginning of the buffer 00652 * @param[in] length Number of bytes to process 00653 * @return Resulting CRC value 00654 **/ 00655 00656 uint32_t ethCalcCrcEx(const NetBuffer *buffer, size_t offset, size_t length) 00657 { 00658 uint_t i; 00659 uint_t n; 00660 uint32_t crc; 00661 uint8_t *p; 00662 #if (ETH_FAST_CRC_SUPPORT == DISABLED) 00663 uint_t k; 00664 #endif 00665 00666 //CRC preset value 00667 crc = 0xFFFFFFFF; 00668 00669 //Loop through data chunks 00670 for(i = 0; i < buffer->chunkCount && length > 0; i++) 00671 { 00672 //Is there any data to process in the current chunk? 00673 if(offset < buffer->chunk[i].length) 00674 { 00675 //Point to the first data byte 00676 p = (uint8_t *) buffer->chunk[i].address + offset; 00677 //Compute the number of bytes to process 00678 n = MIN(buffer->chunk[i].length - offset, length); 00679 //Adjust byte counter 00680 length -= n; 00681 00682 //Process current chunk 00683 while(n > 0) 00684 { 00685 #if (ETH_FAST_CRC_SUPPORT == ENABLED) 00686 //The message is processed byte by byte 00687 crc = (crc >> 8) ^ crc32Table[(crc & 0xFF) ^ *p]; 00688 #else 00689 //Update CRC value 00690 crc ^= *p; 00691 00692 //The message is processed bit by bit 00693 for(k = 0; k < 8; k++) 00694 { 00695 if(crc & 0x00000001) 00696 crc = (crc >> 1) ^ 0xEDB88320; 00697 else 00698 crc = crc >> 1; 00699 } 00700 #endif 00701 //Next byte 00702 p++; 00703 n--; 00704 } 00705 00706 //Process the next block from the start 00707 offset = 0; 00708 } 00709 else 00710 { 00711 //Skip the current chunk 00712 offset -= buffer->chunk[i].length; 00713 } 00714 } 00715 00716 //Return 1's complement value 00717 return ~crc; 00718 } 00719 00720 00721 /** 00722 * @brief Allocate a buffer to hold an Ethernet frame 00723 * @param[in] length Desired payload length 00724 * @param[out] offset Offset to the first byte of the payload 00725 * @return The function returns a pointer to the newly allocated 00726 * buffer. If the system is out of resources, NULL is returned 00727 **/ 00728 00729 NetBuffer *ethAllocBuffer(size_t length, size_t *offset) 00730 { 00731 NetBuffer *buffer; 00732 00733 //Allocate a buffer to hold the Ethernet header and the payload 00734 buffer = netBufferAlloc(length + sizeof(EthHeader)); 00735 //Failed to allocate buffer? 00736 if(buffer == NULL) 00737 return NULL; 00738 00739 //Offset to the first byte of the payload 00740 *offset = sizeof(EthHeader); 00741 00742 //Return a pointer to the freshly allocated buffer 00743 return buffer; 00744 } 00745 00746 00747 /** 00748 * @brief Convert a string representation of a MAC address to a binary MAC address 00749 * @param[in] str NULL-terminated string representing the MAC address 00750 * @param[out] macAddr Binary representation of the MAC address 00751 * @return Error code 00752 **/ 00753 00754 error_t macStringToAddr(const char_t *str, MacAddr *macAddr) 00755 { 00756 error_t error; 00757 int_t i = 0; 00758 int_t value = -1; 00759 00760 //Parse input string 00761 while(1) 00762 { 00763 //Hexadecimal digit found? 00764 if(isxdigit((uint8_t) *str)) 00765 { 00766 //First digit to be decoded? 00767 if(value < 0) value = 0; 00768 //Update the value of the current byte 00769 if(isdigit((uint8_t) *str)) 00770 value = (value * 16) + (*str - '0'); 00771 else if(isupper((uint8_t) *str)) 00772 value = (value * 16) + (*str - 'A' + 10); 00773 else 00774 value = (value * 16) + (*str - 'a' + 10); 00775 //Check resulting value 00776 if(value > 0xFF) 00777 { 00778 //The conversion failed 00779 error = ERROR_INVALID_SYNTAX; 00780 break; 00781 } 00782 } 00783 //Dash or colon separator found? 00784 else if((*str == '-' || *str == ':') && i < 6) 00785 { 00786 //Each separator must be preceded by a valid number 00787 if(value < 0) 00788 { 00789 //The conversion failed 00790 error = ERROR_INVALID_SYNTAX; 00791 break; 00792 } 00793 00794 //Save the current byte 00795 macAddr->b[i++] = value; 00796 //Prepare to decode the next byte 00797 value = -1; 00798 } 00799 //End of string detected? 00800 else if(*str == '\0' && i == 5) 00801 { 00802 //The NULL character must be preceded by a valid number 00803 if(value < 0) 00804 { 00805 //The conversion failed 00806 error = ERROR_INVALID_SYNTAX; 00807 } 00808 else 00809 { 00810 //Save the last byte of the MAC address 00811 macAddr->b[i] = value; 00812 //The conversion succeeded 00813 error = NO_ERROR; 00814 } 00815 00816 //We are done 00817 break; 00818 } 00819 //Invalid character... 00820 else 00821 { 00822 //The conversion failed 00823 error = ERROR_INVALID_SYNTAX; 00824 break; 00825 } 00826 00827 //Point to the next character 00828 str++; 00829 } 00830 00831 //Return status code 00832 return error; 00833 } 00834 00835 00836 /** 00837 * @brief Convert a MAC address to a dash delimited string 00838 * @param[in] macAddr Pointer to the MAC address 00839 * @param[out] str NULL-terminated string representing the MAC address 00840 * @return Pointer to the formatted string 00841 **/ 00842 00843 char_t *macAddrToString(const MacAddr *macAddr, char_t *str) 00844 { 00845 static char_t buffer[18]; 00846 00847 //The str parameter is optional 00848 if(str == NULL) 00849 str = buffer; 00850 00851 //Format MAC address 00852 sprintf(str, "%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8, 00853 macAddr->b[0], macAddr->b[1], macAddr->b[2], macAddr->b[3], macAddr->b[4], macAddr->b[5]); 00854 00855 //Return a pointer to the formatted string 00856 return str; 00857 } 00858 00859 00860 /** 00861 * @brief Convert a string representation of an EUI-64 address to a binary EUI-64 address 00862 * @param[in] str NULL-terminated string representing the EUI-64 address 00863 * @param[out] eui64 Binary representation of the EUI-64 address 00864 * @return Error code 00865 **/ 00866 00867 error_t eui64StringToAddr(const char_t *str, Eui64 *eui64) 00868 { 00869 error_t error; 00870 int_t i = 0; 00871 int_t value = -1; 00872 00873 //Parse input string 00874 while(1) 00875 { 00876 //Hexadecimal digit found? 00877 if(isxdigit((uint8_t) *str)) 00878 { 00879 //First digit to be decoded? 00880 if(value < 0) value = 0; 00881 //Update the value of the current byte 00882 if(isdigit((uint8_t) *str)) 00883 value = (value * 16) + (*str - '0'); 00884 else if(isupper((uint8_t) *str)) 00885 value = (value * 16) + (*str - 'A' + 10); 00886 else 00887 value = (value * 16) + (*str - 'a' + 10); 00888 //Check resulting value 00889 if(value > 0xFF) 00890 { 00891 //The conversion failed 00892 error = ERROR_INVALID_SYNTAX; 00893 break; 00894 } 00895 } 00896 //Dash or colon separator found? 00897 else if((*str == '-' || *str == ':') && i < 8) 00898 { 00899 //Each separator must be preceded by a valid number 00900 if(value < 0) 00901 { 00902 //The conversion failed 00903 error = ERROR_INVALID_SYNTAX; 00904 break; 00905 } 00906 00907 //Save the current byte 00908 eui64->b[i++] = value; 00909 //Prepare to decode the next byte 00910 value = -1; 00911 } 00912 //End of string detected? 00913 else if(*str == '\0' && i == 7) 00914 { 00915 //The NULL character must be preceded by a valid number 00916 if(value < 0) 00917 { 00918 //The conversion failed 00919 error = ERROR_INVALID_SYNTAX; 00920 } 00921 else 00922 { 00923 //Save the last byte of the EUI-64 address 00924 eui64->b[i] = value; 00925 //The conversion succeeded 00926 error = NO_ERROR; 00927 } 00928 00929 //We are done 00930 break; 00931 } 00932 //Invalid character... 00933 else 00934 { 00935 //The conversion failed 00936 error = ERROR_INVALID_SYNTAX; 00937 break; 00938 } 00939 00940 //Point to the next character 00941 str++; 00942 } 00943 00944 //Return status code 00945 return error; 00946 } 00947 00948 00949 /** 00950 * @brief Convert an EUI-64 address to a dash delimited string 00951 * @param[in] eui64 Pointer to the EUI-64 address 00952 * @param[out] str NULL-terminated string representing the EUI-64 address 00953 * @return Pointer to the formatted string 00954 **/ 00955 00956 char_t *eui64AddrToString(const Eui64 *eui64, char_t *str) 00957 { 00958 static char_t buffer[24]; 00959 00960 //The str parameter is optional 00961 if(str == NULL) 00962 str = buffer; 00963 00964 //Format EUI-64 identifier 00965 sprintf(str, "%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8 00966 "-%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8, 00967 eui64->b[0], eui64->b[1], eui64->b[2], eui64->b[3], 00968 eui64->b[4], eui64->b[5], eui64->b[6], eui64->b[7]); 00969 00970 //Return a pointer to the formatted string 00971 return str; 00972 } 00973 00974 00975 /** 00976 * @brief Map a MAC address to the IPv6 modified EUI-64 identifier 00977 * @param[in] macAddr Host MAC address 00978 * @param[out] interfaceId IPv6 modified EUI-64 identifier 00979 **/ 00980 00981 void macAddrToEui64(const MacAddr *macAddr, Eui64 *interfaceId) 00982 { 00983 //Copy the Organization Unique Identifier (OUI) 00984 interfaceId->b[0] = macAddr->b[0]; 00985 interfaceId->b[1] = macAddr->b[1]; 00986 interfaceId->b[2] = macAddr->b[2]; 00987 00988 //The middle 16 bits are given the value 0xFFFE 00989 interfaceId->b[3] = 0xFF; 00990 interfaceId->b[4] = 0xFE; 00991 00992 //Copy the right-most 24 bits of the MAC address 00993 interfaceId->b[5] = macAddr->b[3]; 00994 interfaceId->b[6] = macAddr->b[4]; 00995 interfaceId->b[7] = macAddr->b[5]; 00996 00997 //Modified EUI-64 format interface identifiers are 00998 //formed by inverting the Universal/Local bit 00999 interfaceId->b[0] ^= MAC_ADDR_FLAG_LOCAL; 01000 } 01001 01002 01003 /** 01004 * @brief Dump Ethernet header for debugging purpose 01005 * @param[in] ethHeader Pointer to the Ethernet header 01006 **/ 01007 01008 void ethDumpHeader(const EthHeader *ethHeader) 01009 { 01010 //Dump Ethernet header contents 01011 TRACE_DEBUG(" Dest Addr = %s\r\n", macAddrToString(ðHeader->destAddr, NULL)); 01012 TRACE_DEBUG(" Src Addr = %s\r\n", macAddrToString(ðHeader->srcAddr, NULL)); 01013 TRACE_DEBUG(" Type = 0x%04" PRIX16 "\r\n", ntohs(ethHeader->type)); 01014 } 01015 01016 #endif 01017
Generated on Tue Jul 12 2022 17:10:13 by
