ethernet.c

Go to the documentation of this file.
00001 /*##############################################################################
00002 
00003 nIP - nano IP stack
00004 
00005 File        : ethernet.c
00006 
00007 Description : Functions to serve ethernet interfaces
00008 
00009 Copyright notice:
00010 
00011 Copyright (C) 2005 -
00012 Andreas Dittrich, dittrich@informatik.hu-berlin.de
00013 Jon Kowal, kowal@informatik.hu-berlin.de
00014 
00015 This program is free software; you can redistribute it and/or
00016 modify it under the terms of the GNU General Public License
00017 as published by the Free Software Foundation; either version 2
00018 of the License, or (at your option) any later version.
00019 
00020 This program is distributed in the hope that it will be useful,
00021 but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00023 GNU General Public License for more details.
00024 
00025 You should have received a copy of the GNU General Public License
00026 along with this program; if not, write to the Free Software
00027 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00028 
00029 ##############################################################################*/
00030 
00031 #include "dispatcher.h"
00032 #include "net/ethernet.h"
00033 #include "net/arp.h"
00034 #include "net/ip.h"
00035 
00036 #if (NIP_ETH_ENABLE == 1)
00037 
00038 // string compare function only needed for mac address check
00039 #if !defined( ETH_NIC_CHECK_MAC )
00040 #       include <string.h>
00041 #endif
00042 
00043 #include "nip_init.h"
00044 #include "net/net_if.h"
00045 
00046 extern nip_net_if_t nip_net_if_list[];
00047 extern nip_disp_state_t nip_disp;
00048 
00049 
00050 /** fill ethernet interface configuration with default values
00051  *
00052  * @param id  id of network interface to configure
00053  **/
00054 void nip_eth_configure_if_defaults( nip_net_if_id_t id )
00055 {
00056         nip_net_if_list[id].phy_conf.flags = NIP_PHY_IFF_BROADCAST;
00057         nip_net_if_list[id].phy_conf.hw_addr_size = 6;
00058         nip_net_if_list[id].phy_conf.open  = NULL; /* driver will fill in */
00059         nip_net_if_list[id].phy_conf.close = NULL; /* driver will fill in */
00060         nip_net_if_list[id].phy_conf.hard_disp_recv = &nip_eth_disp_receive;
00061         nip_net_if_list[id].phy_conf.hard_send_init = NULL; /* driver will fill in */
00062         nip_net_if_list[id].phy_conf.hard_send      = NULL; /* driver will fill in */
00063         nip_net_if_list[id].phy_conf.hard_read_init = NULL; /* driver will fill in */
00064         nip_net_if_list[id].phy_conf.hard_read      = NULL; /* driver will fill in */
00065 }
00066 
00067 
00068 /** Function to be called upon packet reception from Network Interface.
00069  *
00070  * The function will read the first packet from buffer and hand it to the
00071  * appropriate protocol handler. No decision on discarding the packet will be
00072  * made here, unless the ethernet address check fails. Discarding due to lack
00073  * of ressources is up to the protocol handler which may decide to have no
00074  * buffer space for the data. Also it's up to the protocol handler to decide
00075  * which transmission the packet will be assigned to (e.g. only IP can know if
00076  * the received data belongs to a fragmented packet waiting to be completed).
00077  */
00078 void nip_eth_disp_receive( void )
00079 {
00080         uint8_t tmp[6];
00081         uint8_t type[2];
00082         nip_net_if_id_t tmp_if_id = NIP_CURR_IF;
00083 #if !defined( ETH_NIC_CHECK_MAC )
00084         uint8_t tmp1;
00085 #endif
00086         // Packet reception should be completed at this point. There may be packets
00087         // waiting in the interface's buffer, but the previous packet should've been
00088         // received completely. To avoid errors and deadlocks this routine double
00089         // checks on that and empties the receive-buffer if necessary.
00090         if ( nip_net_if_list[ tmp_if_id ].phy_conf.rx_bytes > 0 )
00091         {
00092                 nip_net_if_list[ tmp_if_id ].phy_conf.hard_read(
00093                         NIP_CURR_IF,
00094                         NULL,
00095                         nip_net_if_list[ tmp_if_id ].phy_conf.rx_bytes
00096                 );
00097         }
00098 
00099 
00100         // initialize packet reading
00101         if ( nip_net_if_list[tmp_if_id].phy_conf.hard_read_init( tmp_if_id ) != NIP_E_OK )
00102                 return;
00103 
00104         // make sure we come back and check for another packet (we don't know how
00105         // many packets have been received)
00106         nip_disp_notify_if( tmp_if_id, NIP_DISP_IF_ETH_R );
00107 
00108         // read destination address
00109         nip_net_if_list[tmp_if_id].phy_conf.hard_read( tmp_if_id, tmp, 6 );
00110 
00111 // if the NIC is not doing the physical address check, we'll have to do that
00112 #if !defined( ETH_NIC_CHECK_MAC )
00113         // Check if destination address is broadcast address
00114         tmp1 = 0;
00115         do
00116         {
00117                 if ( tmp[tmp1] != 255 ) break;
00118         }
00119         while ( ++tmp1 < 6 );
00120 
00121         // If all 6 Bytes equalled 255, the given message is a ethernet broadcast
00122         if (  tmp1 == 6 )
00123         {
00124         }
00125         else
00126 #endif
00127         // If the least significant bit of the first address byte equals 1,
00128         // the given ethernet address is a (multicast) group address.
00129         if ( (tmp[0]& 0x01) > 0 )
00130         {
00131                  // TODO check multicast destination. Is this message for us? Treat
00132                  // broadcast as special kind of multicast. Remove above broadcast check
00133                  // when done.
00134                  // if check failed goto terminate_read
00135         }
00136 
00137 // if the NIC is not doing the physical address check, we'll have to do that
00138 #if !defined( ETH_NIC_CHECK_MAC )
00139         else
00140         // check unicast destination
00141         if ( nip_memcmp( tmp, nip_net_if_list[tmp_if_id].phy_conf.hw_addr, 6 ) == 0 )
00142         {
00143         }
00144         else
00145         {
00146                 // Ethernet address check failed
00147                 // TODO discard packet
00148 
00149                 // we use 'goto' here because it's the only way to skip the following
00150                 // lines without having to use additional status variables and conditions.
00151                 // (That saves about 32 Bytes of lovely program memory over the next
00152                 // favorable solution of using tmp1 as status variable indicating wether
00153                 // we're the the correct receiver of the packet)
00154                 goto terminate_read;
00155         }
00156 #endif
00157 
00158         // read source address
00159         nip_net_if_list[tmp_if_id].phy_conf.hard_read( tmp_if_id, nip_disp.next.common.remote_hw_addr, 6 );
00160 
00161         // read type
00162         nip_net_if_list[tmp_if_id].phy_conf.hard_read( tmp_if_id, type, 2 );
00163 
00164         // eval type
00165         #if (NIP_ARP_ENABLE == 1)
00166         if ( type[0] == 0x08 && type[1] == 0x06 )
00167         {
00168                 // received ARP packet
00169                 NIP_CURR_CMD = &nip_disp_arp_receive;;
00170                 return;
00171         }
00172         #endif
00173         #if (NIP_IP_ENABLE == 1)
00174         if ( type[0] == 0x08 && type[1] == 0x00 )
00175         {
00176                 // received IP packet
00177                 NIP_CURR_CMD = &nip_ip_disp_receive;;
00178                 return;
00179         }
00180         #endif
00181 
00182 #if !defined( ETH_NIC_CHECK_MAC )
00183         terminate_read:
00184         // read remaining packet bytes from NIC
00185         nip_net_if_list[tmp_if_id].phy_conf.hard_read(
00186                 tmp_if_id,
00187                 NULL,
00188                 nip_net_if_list[tmp_if_id].phy_conf.rx_bytes
00189         );
00190 #endif
00191 
00192         return;
00193 }
00194 
00195 #endif /* NIP_ETH_ENABLE == 1 */

Generated on Thu Jul 10 01:09:29 2008 for NIP by  doxygen 1.5.5