Webserver+3d print
cyclone_tcp/core/nic.c
- Committer:
- Sergunb
- Date:
- 2017-02-04
- Revision:
- 0:8918a71cdbe9
File content as of revision 0:8918a71cdbe9:
/** * @file nic.c * @brief Network interface controller abstraction layer * * @section License * * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. * * This file is part of CycloneTCP Open. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * @author Oryx Embedded SARL (www.oryx-embedded.com) * @version 1.7.6 **/ //Switch to the appropriate trace level #define TRACE_LEVEL NIC_TRACE_LEVEL //Dependencies #include "core/net.h" #include "core/nic.h" #include "core/socket.h" #include "core/raw_socket.h" #include "core/tcp_misc.h" #include "core/udp.h" #include "ipv4/ipv4.h" #include "ipv6/ipv6.h" #include "dns/dns_cache.h" #include "dns/dns_client.h" #include "mdns/mdns_client.h" #include "mdns/mdns_responder.h" #include "dns_sd/dns_sd.h" #include "mibs/mib2_module.h" #include "debug.h" //Tick counter to handle periodic operations systime_t nicTickCounter; /** * @brief Network controller timer handler * * This routine is periodically called by the TCP/IP stack to * handle periodic operations such as polling the link state * * @param[in] interface Underlying network interface **/ void nicTick(NetInterface *interface) { //Disable interrupts interface->nicDriver->disableIrq(interface); //Handle periodic operations interface->nicDriver->tick(interface); //Re-enable interrupts if necessary if(interface->configured) interface->nicDriver->enableIrq(interface); } /** * @brief Send a packet to the network controller * @param[in] interface Underlying network interface * @param[in] buffer Multi-part buffer containing the data to send * @param[in] offset Offset to the first data byte * @return Error code **/ error_t nicSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset) { error_t error; bool_t status; #if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG) //Retrieve the length of the packet size_t length = netBufferGetLength(buffer) - offset; //Debug message TRACE_DEBUG("Sending packet (%" PRIuSIZE " bytes)...\r\n", length); TRACE_DEBUG_NET_BUFFER(" ", buffer, offset, length); #endif //Wait for the transmitter to be ready to send status = osWaitForEvent(&interface->nicTxEvent, NIC_MAX_BLOCKING_TIME); //Check whether the specified event is in signaled state if(status) { //Disable interrupts interface->nicDriver->disableIrq(interface); //Send Ethernet frame error = interface->nicDriver->sendPacket(interface, buffer, offset); //Re-enable interrupts if necessary if(interface->configured) interface->nicDriver->enableIrq(interface); } else { //The transmitter is busy... return ERROR_TRANSMITTER_BUSY; } //Return status code return error; } /** * @brief Configure multicast MAC address filtering * @param[in] interface Underlying network interface * @return Error code **/ error_t nicSetMulticastFilter(NetInterface *interface) { error_t error; //Disable interrupts interface->nicDriver->disableIrq(interface); //Update MAC filter table error = interface->nicDriver->setMulticastFilter(interface); //Re-enable interrupts if necessary if(interface->configured) interface->nicDriver->enableIrq(interface); //Return status code return error; } /** * @brief Handle a packet received by the network controller * @param[in] interface Underlying network interface * @param[in] packet Incoming packet to process * @param[in] length Total packet length **/ void nicProcessPacket(NetInterface *interface, void *packet, size_t length) { NicType type; //Re-enable interrupts if necessary if(interface->configured) interface->nicDriver->enableIrq(interface); //Debug message TRACE_DEBUG("Packet received (%" PRIuSIZE " bytes)...\r\n", length); TRACE_DEBUG_ARRAY(" ", packet, length); //Retrieve network interface type type = interface->nicDriver->type; //Ethernet interface? if(type == NIC_TYPE_ETHERNET) { #if (ETH_SUPPORT == ENABLED) //Process incoming Ethernet frame ethProcessFrame(interface, packet, length); #endif } //PPP interface? else if(type == NIC_TYPE_PPP) { #if (PPP_SUPPORT == ENABLED) //Process incoming PPP frame pppProcessFrame(interface, packet, length); #endif } //6LoWPAN interface? else if(type == NIC_TYPE_6LOWPAN) { #if (IPV6_SUPPORT == ENABLED) NetBuffer1 buffer; //The incoming packet fits in a single chunk buffer.chunkCount = 1; buffer.maxChunkCount = 1; buffer.chunk[0].address = packet; buffer.chunk[0].length = length; buffer.chunk[0].size = 0; //Process incoming IPv6 packet ipv6ProcessPacket(interface, (NetBuffer *) &buffer, 0); #endif } //Disable interrupts interface->nicDriver->disableIrq(interface); } /** * @brief Process link state change event * @param[in] interface Underlying network interface **/ void nicNotifyLinkChange(NetInterface *interface) { uint_t i; Socket *socket; //Re-enable interrupts if necessary if(interface->configured) interface->nicDriver->enableIrq(interface); //Check link state if(interface->linkState) { //Display link state TRACE_INFO("Link is up (%s)...\r\n", interface->name); //Display link speed if(interface->linkSpeed == NIC_LINK_SPEED_1GBPS) { //1000BASE-T TRACE_INFO(" Link speed = 1000 Mbps\r\n"); } else if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS) { //100BASE-TX TRACE_INFO(" Link speed = 100 Mbps\r\n"); } else if(interface->linkSpeed == NIC_LINK_SPEED_10MBPS) { //10BASE-T TRACE_INFO(" Link speed = 10 Mbps\r\n"); } else if(interface->linkSpeed != NIC_LINK_SPEED_UNKNOWN) { //10BASE-T TRACE_INFO(" Link speed = %" PRIu32 " bps\r\n", interface->linkSpeed); } //Display duplex mode if(interface->duplexMode == NIC_FULL_DUPLEX_MODE) { //1000BASE-T TRACE_INFO(" Duplex mode = Full-Duplex\r\n"); } else if(interface->duplexMode == NIC_HALF_DUPLEX_MODE) { //100BASE-TX TRACE_INFO(" Duplex mode = Half-Duplex\r\n"); } } else { //Display link state TRACE_INFO("Link is down (%s)...\r\n", interface->name); } //Interface's current bandwidth MIB2_SET_GAUGE32(interface->mibIfEntry->ifSpeed, interface->linkSpeed); //The current operational state of the interface if(interface->linkState) MIB2_SET_INTEGER(interface->mibIfEntry->ifOperStatus, MIB2_IF_OPER_STATUS_UP); else MIB2_SET_INTEGER(interface->mibIfEntry->ifOperStatus, MIB2_IF_OPER_STATUS_DOWN); //The time at which the interface entered its current operational state MIB2_SET_TIME_TICKS(interface->mibIfEntry->ifLastChange, osGetSystemTime() / 10); #if (IPV4_SUPPORT == ENABLED) //Notify IPv4 of link state changes ipv4LinkChangeEvent(interface); #endif #if (IPV6_SUPPORT == ENABLED) //Notify IPv6 of link state changes ipv6LinkChangeEvent(interface); #endif #if (DNS_CLIENT_SUPPORT == ENABLED || MDNS_CLIENT_SUPPORT == ENABLED || \ NBNS_CLIENT_SUPPORT == ENABLED) //Flush DNS cache dnsFlushCache(interface); #endif #if (MDNS_RESPONDER_SUPPORT == ENABLED) //Perform probing and announcing mdnsResponderLinkChangeEvent(interface->mdnsResponderContext); #endif #if (DNS_SD_SUPPORT == ENABLED) //Perform probing and announcing dnsSdLinkChangeEvent(interface->dnsSdContext); #endif //Notify registered users of link state changes netInvokeLinkChangeCallback(interface, interface->linkState); //Loop through opened sockets for(i = 0; i < SOCKET_MAX_COUNT; i++) { //Point to the current socket socket = socketTable + i; #if (TCP_SUPPORT == ENABLED) //Connection-oriented socket? if(socket->type == SOCKET_TYPE_STREAM) { tcpUpdateEvents(socket); } #endif #if (UDP_SUPPORT == ENABLED) //Connectionless socket? if(socket->type == SOCKET_TYPE_DGRAM) { udpUpdateEvents(socket); } #endif #if (RAW_SOCKET_SUPPORT == ENABLED) //Raw socket? if(socket->type == SOCKET_TYPE_RAW_IP || socket->type == SOCKET_TYPE_RAW_ETH) { rawSocketUpdateEvents(socket); } #endif } //Disable interrupts interface->nicDriver->disableIrq(interface); }