Sergey Pastor / 1

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers nic.c Source File

nic.c

Go to the documentation of this file.
00001 /**
00002  * @file nic.c
00003  * @brief Network interface controller abstraction layer
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 NIC_TRACE_LEVEL
00031 
00032 //Dependencies
00033 #include "core/net.h"
00034 #include "core/nic.h"
00035 #include "core/socket.h"
00036 #include "core/raw_socket.h"
00037 #include "core/tcp_misc.h"
00038 #include "core/udp.h"
00039 #include "ipv4/ipv4.h"
00040 #include "ipv6/ipv6.h"
00041 #include "dns/dns_cache.h"
00042 #include "dns/dns_client.h"
00043 #include "mdns/mdns_client.h"
00044 #include "mdns/mdns_responder.h"
00045 #include "dns_sd/dns_sd.h"
00046 #include "mibs/mib2_module.h"
00047 #include "debug.h"
00048 
00049 //Tick counter to handle periodic operations
00050 systime_t nicTickCounter;
00051 
00052 
00053 /**
00054  * @brief Network controller timer handler
00055  *
00056  * This routine is periodically called by the TCP/IP stack to
00057  * handle periodic operations such as polling the link state
00058  *
00059  * @param[in] interface Underlying network interface
00060  **/
00061 
00062 void nicTick(NetInterface *interface)
00063 {
00064    //Disable interrupts
00065    interface->nicDriver->disableIrq(interface);
00066 
00067    //Handle periodic operations
00068    interface->nicDriver->tick(interface);
00069 
00070    //Re-enable interrupts if necessary
00071    if(interface->configured)
00072       interface->nicDriver->enableIrq(interface);
00073 }
00074 
00075 
00076 /**
00077  * @brief Send a packet to the network controller
00078  * @param[in] interface Underlying network interface
00079  * @param[in] buffer Multi-part buffer containing the data to send
00080  * @param[in] offset Offset to the first data byte
00081  * @return Error code
00082  **/
00083 
00084 error_t nicSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
00085 {
00086    error_t error;
00087    bool_t status;
00088 
00089 #if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG)
00090    //Retrieve the length of the packet
00091    size_t length = netBufferGetLength(buffer) - offset;
00092 
00093    //Debug message
00094    TRACE_DEBUG("Sending packet (%" PRIuSIZE " bytes)...\r\n", length);
00095    TRACE_DEBUG_NET_BUFFER("  ", buffer, offset, length);
00096 #endif
00097 
00098    //Wait for the transmitter to be ready to send
00099    status = osWaitForEvent(&interface->nicTxEvent, NIC_MAX_BLOCKING_TIME);
00100 
00101    //Check whether the specified event is in signaled state
00102    if(status)
00103    {
00104       //Disable interrupts
00105       interface->nicDriver->disableIrq(interface);
00106 
00107       //Send Ethernet frame
00108       error = interface->nicDriver->sendPacket(interface, buffer, offset);
00109 
00110       //Re-enable interrupts if necessary
00111       if(interface->configured)
00112          interface->nicDriver->enableIrq(interface);
00113    }
00114    else
00115    {
00116       //The transmitter is busy...
00117       return ERROR_TRANSMITTER_BUSY;
00118    }
00119 
00120    //Return status code
00121    return error;
00122 }
00123 
00124 
00125 /**
00126  * @brief Configure multicast MAC address filtering
00127  * @param[in] interface Underlying network interface
00128  * @return Error code
00129  **/
00130 
00131 error_t nicSetMulticastFilter(NetInterface *interface)
00132 {
00133    error_t error;
00134 
00135    //Disable interrupts
00136    interface->nicDriver->disableIrq(interface);
00137 
00138    //Update MAC filter table
00139    error = interface->nicDriver->setMulticastFilter(interface);
00140 
00141    //Re-enable interrupts if necessary
00142    if(interface->configured)
00143       interface->nicDriver->enableIrq(interface);
00144 
00145    //Return status code
00146    return error;
00147 }
00148 
00149 
00150 /**
00151  * @brief Handle a packet received by the network controller
00152  * @param[in] interface Underlying network interface
00153  * @param[in] packet Incoming packet to process
00154  * @param[in] length Total packet length
00155  **/
00156 
00157 void nicProcessPacket(NetInterface *interface, void *packet, size_t length)
00158 {
00159    NicType type;
00160 
00161    //Re-enable interrupts if necessary
00162    if(interface->configured)
00163       interface->nicDriver->enableIrq(interface);
00164 
00165    //Debug message
00166    TRACE_DEBUG("Packet received (%" PRIuSIZE " bytes)...\r\n", length);
00167    TRACE_DEBUG_ARRAY("  ", packet, length);
00168 
00169    //Retrieve network interface type
00170    type = interface->nicDriver->type;
00171 
00172    //Ethernet interface?
00173    if(type == NIC_TYPE_ETHERNET)
00174    {
00175 #if (ETH_SUPPORT == ENABLED)
00176       //Process incoming Ethernet frame
00177       ethProcessFrame(interface, packet, length);
00178 #endif
00179    }
00180    //PPP interface?
00181    else if(type == NIC_TYPE_PPP)
00182    {
00183 #if (PPP_SUPPORT == ENABLED)
00184       //Process incoming PPP frame
00185       pppProcessFrame(interface, packet, length);
00186 #endif
00187    }
00188    //6LoWPAN interface?
00189    else if(type == NIC_TYPE_6LOWPAN)
00190    {
00191 #if (IPV6_SUPPORT == ENABLED)
00192       NetBuffer1 buffer;
00193 
00194       //The incoming packet fits in a single chunk
00195       buffer.chunkCount = 1;
00196       buffer.maxChunkCount = 1;
00197       buffer.chunk[0].address = packet;
00198       buffer.chunk[0].length = length;
00199       buffer.chunk[0].size = 0;
00200 
00201       //Process incoming IPv6 packet
00202       ipv6ProcessPacket(interface, (NetBuffer *) &buffer, 0);
00203 #endif
00204    }
00205 
00206    //Disable interrupts
00207    interface->nicDriver->disableIrq(interface);
00208 }
00209 
00210 
00211 /**
00212  * @brief Process link state change event
00213  * @param[in] interface Underlying network interface
00214  **/
00215 
00216 void nicNotifyLinkChange(NetInterface *interface)
00217 {
00218    uint_t i;
00219    Socket *socket;
00220 
00221    //Re-enable interrupts if necessary
00222    if(interface->configured)
00223       interface->nicDriver->enableIrq(interface);
00224 
00225    //Check link state
00226    if(interface->linkState)
00227    {
00228       //Display link state
00229       TRACE_INFO("Link is up (%s)...\r\n", interface->name);
00230 
00231       //Display link speed
00232       if(interface->linkSpeed == NIC_LINK_SPEED_1GBPS)
00233       {
00234          //1000BASE-T
00235          TRACE_INFO("  Link speed = 1000 Mbps\r\n");
00236       }
00237       else if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
00238       {
00239          //100BASE-TX
00240          TRACE_INFO("  Link speed = 100 Mbps\r\n");
00241       }
00242       else if(interface->linkSpeed == NIC_LINK_SPEED_10MBPS)
00243       {
00244          //10BASE-T
00245          TRACE_INFO("  Link speed = 10 Mbps\r\n");
00246       }
00247       else if(interface->linkSpeed != NIC_LINK_SPEED_UNKNOWN)
00248       {
00249          //10BASE-T
00250          TRACE_INFO("  Link speed = %" PRIu32 " bps\r\n", interface->linkSpeed);
00251       }
00252 
00253       //Display duplex mode
00254       if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
00255       {
00256          //1000BASE-T
00257          TRACE_INFO("  Duplex mode = Full-Duplex\r\n");
00258       }
00259       else if(interface->duplexMode == NIC_HALF_DUPLEX_MODE)
00260       {
00261          //100BASE-TX
00262          TRACE_INFO("  Duplex mode = Half-Duplex\r\n");
00263       }
00264    }
00265    else
00266    {
00267       //Display link state
00268       TRACE_INFO("Link is down (%s)...\r\n", interface->name);
00269    }
00270 
00271    //Interface's current bandwidth
00272    MIB2_SET_GAUGE32(interface->mibIfEntry->ifSpeed, interface->linkSpeed);
00273 
00274    //The current operational state of the interface
00275    if(interface->linkState)
00276       MIB2_SET_INTEGER(interface->mibIfEntry->ifOperStatus, MIB2_IF_OPER_STATUS_UP);
00277    else
00278       MIB2_SET_INTEGER(interface->mibIfEntry->ifOperStatus, MIB2_IF_OPER_STATUS_DOWN);
00279 
00280    //The time at which the interface entered its current operational state
00281    MIB2_SET_TIME_TICKS(interface->mibIfEntry->ifLastChange, osGetSystemTime() / 10);
00282 
00283 #if (IPV4_SUPPORT == ENABLED)
00284    //Notify IPv4 of link state changes
00285    ipv4LinkChangeEvent(interface);
00286 #endif
00287 
00288 #if (IPV6_SUPPORT == ENABLED)
00289    //Notify IPv6 of link state changes
00290    ipv6LinkChangeEvent(interface);
00291 #endif
00292 
00293 #if (DNS_CLIENT_SUPPORT == ENABLED || MDNS_CLIENT_SUPPORT == ENABLED || \
00294    NBNS_CLIENT_SUPPORT == ENABLED)
00295    //Flush DNS cache
00296    dnsFlushCache(interface);
00297 #endif
00298 
00299 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
00300    //Perform probing and announcing
00301    mdnsResponderLinkChangeEvent(interface->mdnsResponderContext);
00302 #endif
00303 
00304 #if (DNS_SD_SUPPORT == ENABLED)
00305    //Perform probing and announcing
00306    dnsSdLinkChangeEvent(interface->dnsSdContext);
00307 #endif
00308 
00309    //Notify registered users of link state changes
00310    netInvokeLinkChangeCallback(interface, interface->linkState);
00311 
00312    //Loop through opened sockets
00313    for(i = 0; i < SOCKET_MAX_COUNT; i++)
00314    {
00315       //Point to the current socket
00316       socket = socketTable + i;
00317 
00318 #if (TCP_SUPPORT == ENABLED)
00319       //Connection-oriented socket?
00320       if(socket->type == SOCKET_TYPE_STREAM)
00321       {
00322          tcpUpdateEvents(socket);
00323       }
00324 #endif
00325 #if (UDP_SUPPORT == ENABLED)
00326       //Connectionless socket?
00327       if(socket->type == SOCKET_TYPE_DGRAM)
00328       {
00329          udpUpdateEvents(socket);
00330       }
00331 #endif
00332 #if (RAW_SOCKET_SUPPORT == ENABLED)
00333       //Raw socket?
00334       if(socket->type == SOCKET_TYPE_RAW_IP ||
00335          socket->type == SOCKET_TYPE_RAW_ETH)
00336       {
00337          rawSocketUpdateEvents(socket);
00338       }
00339 #endif
00340    }
00341 
00342    //Disable interrupts
00343    interface->nicDriver->disableIrq(interface);
00344 }
00345