Webserver+3d print
cyclone_tcp/core/ethernet.c@0:8918a71cdbe9, 2017-02-04 (annotated)
- Committer:
- Sergunb
- Date:
- Sat Feb 04 18:15:49 2017 +0000
- Revision:
- 0:8918a71cdbe9
nothing else
Who changed what in which revision?
User | Revision | Line number | New 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, ðFrame->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(ðFrame->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(ðHeader->destAddr, NULL)); |
Sergunb | 0:8918a71cdbe9 | 1012 | TRACE_DEBUG(" Src Addr = %s\r\n", macAddrToString(ðHeader->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 |