Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

eth.c File Reference

Ethernet driver. More...

#include <const.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <arch/mem.h>
#include <arch/i386.h>
#include <kernel/clock.h>
#include <kernel/console.h>
#include <kernel/kmalloc.h>
#include <kernel/task.h>
#include <net/arp.h>
#include <net/ip.h>
#include <net/network.h>
#include <net/rtl8139.h>
#include <net/tcp.h>
#include <net/eth.h>

Go to the source code of this file.

Defines

#define DEFAULT_IP_ADDR   ( IP_ADDRESS(10, 0, 0, 2) )
 Default IP address for this host.

#define DEFAULT_NETMASK_ADDR   ( IP_ADDRESS(255, 0, 0, 0) )
 Default IP netmask for this host.


Functions

void eth_init_buffer ()
 Initialize the ethernet receive buffer.

int recv_eth_packet (ethernet_t *buf, size_t len, int flags)
 Receive data from the ethernet layer.
Parameters:
buf  A buffer where the ethernet received packet will be copied.
len  The max size of the buffer buf.
flags  Flags.
Returns:
The length in bytes of the packet received.


void eth_recv_daemon ()
 This daemon permanently reads packets from the recv buffer and send them to the opportune layer.

void to_eth_layer (ethernet_t *packet, size_t len)
 Process an ethernet packet received from the physical layer.
Parameters:
packet  The ethernet packet received.
len  The size of the packet.


int send_eth_packet (const uint8_t *to, const void *data, size_t len, uint16_t type)
 Send an ethernet packet to the physiscal layer.
Parameters:
to  The destination ethernet address (MAC).
data  The buffer of data to be sent.
len  The size of the buffer of data to be sent.
type  The packet type.
Returns:
  • The number of bytes sent in case of success.
  • -ENOMEM cannot allocate the packet structure.
  • -ENXIO no ethernet device found.


bool is_eth_promisc ()
 Check if the ethernet device has been configured in promiscuous mode.
Returns:
  • TRUE the ethernet card is in promiscuous mode;
  • FALSE the ethernet card is not in promiscuous mode.


void ifconfig (char *cmd)
 This is the "ifconfig" command for the shell.
Parameters:
cmd  A string of command parameters.



Variables

rtl8139_trtl
 Pointer to the RTL8139 structure.

eth_buf_teth_recv_buf = NULL
 Ethernet receive buffer.

task_teth_recv_thread1 = NULL
 Daemon ethernet tasks 1.

task_teth_recv_thread2 = NULL
 Daemon ethernet tasks 2.


Detailed Description

Ethernet driver.

Author:
Andrea Righi <drizzt@inwind.it>
Date:
Last update: 2003-11-09
Note:
Copyright (©) 2003 Andrea Righi

Definition in file eth.c.


Define Documentation

#define DEFAULT_IP_ADDR   ( IP_ADDRESS(10, 0, 0, 2) )
 

Default IP address for this host.

Definition at line 267 of file eth.c.

#define DEFAULT_NETMASK_ADDR   ( IP_ADDRESS(255, 0, 0, 0) )
 

Default IP netmask for this host.

Definition at line 269 of file eth.c.


Function Documentation

void eth_init_buffer  
 

Initialize the ethernet receive buffer.

Definition at line 42 of file eth.c.

00043 {
00044         // Create the receive buffer                                    //
00045         eth_recv_buf = kmalloc(sizeof(eth_buf_t));
00046 
00047         // Reset the receive buffer                                     //
00048         memset(eth_recv_buf, 0, sizeof(eth_buf_t));
00049 
00050         // Initialize buffer semaphores                                 //
00051         INIT_MUTEX(&eth_recv_buf->mutex);
00052 }

void eth_recv_daemon  
 

This daemon permanently reads packets from the recv buffer and send them to the opportune layer.

Definition at line 109 of file eth.c.

00110 {
00111         unsigned i;
00112         size_t len;
00113         union
00114         {
00115                 uint8_t raw[ETH_FRAME_LEN];
00116                 ethernet_t eth;
00117         } packet;
00118 
00119         while(TRUE)
00120         {
00121                 // Reset the buffer                                     //
00122                 memset(packet.raw, 0, sizeof(packet.raw));
00123                 // Listen the buffer                                    //
00124                 len = recv_eth_packet(&packet.eth, sizeof(packet.raw), 0);
00125 
00126                 // Send the packet to the right layer                   //
00127                 switch( ntohs(packet.eth.type) )
00128                 {
00129                         case ETH_FRAME_ARP:
00130                                 to_arp_layer((arp_t *)(packet.eth.data));
00131                         break;
00132 
00133                         case ETH_FRAME_IP:
00134                                 to_ip_layer((ip_t *)(packet.eth.data));
00135                         break;
00136 
00137                         default:
00138                                 // Unknown magic number                 //
00139                                 kprintf("\n\rPACK TYPE  = UNKNOWN (%04X)", htons(packet.eth.type));
00140                                 // Dump the packet content              //
00141                                 kprintf("\n\rDUMP:\n\r");
00142                                 for (i=0; i<len; i++)
00143                                         kprintf("%02X ", packet.eth.data[i]);
00144                         break;
00145                 }
00146         }
00147 }

void ifconfig char *    cmd
 

This is the "ifconfig" command for the shell.

Parameters:
cmd  A string of command parameters.

Definition at line 273 of file eth.c.

00274 {
00275         uint8_t ip_dot[STR_MAX_LENGTH];
00276         in_addr_t ip, netmask;
00277 
00278         // Skip initial spaces into the parameters string               //
00279         while (*cmd == ' ') cmd++;
00280         if (*cmd == '\0')
00281         {
00282                 // Simply print current ethernet configuration          //
00283                 rtl8139_dump_info(rtl);
00284                 return;
00285         }
00286         if ( strstr(cmd, "up") )
00287         {
00288                 if ( rtl != NULL )
00289                 {
00290                         kprintf("\n\rRTL8139 is already up!");
00291                         if ( strstr(cmd, "promisc") )
00292                                 rtl8139_promisc(get_rtl8139_device(), TRUE);
00293                         else
00294                                 rtl8139_promisc(get_rtl8139_device(), FALSE);
00295                         kprintf("\n\rRTL8139: promiscuous mode %s\n\r",
00296                                 (get_rtl8139_device()->promisc) ? "ENABLED" : "DISABLED");
00297                         return;
00298                 }
00299 
00300                 // Get the host IP and netmask                          //
00301                 kprintf("\n\rIP address: ");
00302                 gets(ip_dot);
00303                 if ( !inet_aton(ip_dot, &ip) )
00304                 {
00305                         // Set the IP to default value                  //
00306                         ip = DEFAULT_IP_ADDR;
00307                 }
00308                 kprintf("\rNetmask   : ");
00309                 gets(ip_dot);
00310                 if ( !inet_aton(ip_dot, &netmask) )
00311                 {
00312                         // Set the netmask to default value             //
00313                         netmask = DEFAULT_NETMASK_ADDR;
00314                 }
00315 
00316                 // Set the host ip and netmask addresses                //
00317                 set_host_ip_net(ip, netmask);
00318                 // Initialize the ethernet buffer                       //
00319                 eth_init_buffer();
00320                 // Reset the ARP cache                                  //
00321                 arp_reset_cache();
00322 
00323                 // Open the TCP module                                  //
00324                 tcp_module_init();
00325 
00326                 // Initialize the RTL8139 device                        //
00327                 switch( rtl8139_init(strstr(cmd, "promisc") ? TRUE : FALSE) )
00328                 {
00329                         case ( 0 ):
00330                         // --- SUCCESS ---                              //
00331                         // Dump the ethernet card informations          //
00332                         rtl8139_dump_info(rtl);
00333                         // Create the ethernet receiver thread          //
00334                         eth_recv_thread1 =
00335                                 create_process(
00336                                         &eth_recv_daemon, &eth_recv_daemon,
00337                                         0, "eth_recvd1", KERNEL_PRIVILEGE);
00338                         eth_recv_thread2 =
00339                                 create_process(
00340                                         &eth_recv_daemon, &eth_recv_daemon,
00341                                         0, "eth_recvd2", KERNEL_PRIVILEGE);
00342                         break;
00343 
00344                         case ( -ENXIO ):
00345                         // --- DEVICE NOT FOUND ---                     //
00346                         // Null the host ip and netmask                 //
00347                         set_host_ip_net(0, 0);
00348                         // Destroy the ethernet buffer                  //
00349                         kfree( eth_recv_buf );
00350                         // Print the error message                      //
00351                         kprintf("\n\rRTL8139: cannot find an ethernet card!\n\r");
00352                         break;
00353 
00354                         case ( -EIO ):
00355                         // --- I/O ERROR ---                            //
00356                         // Null the host ip and netmask                 //
00357                         set_host_ip_net(0, 0);
00358                         // Destroy the ethernet buffer                  //
00359                         kfree( eth_recv_buf );
00360                         // Print the error message                      //
00361                         kprintf("\n\rRTL8139: I/O error!\n\r");
00362                         break;
00363                 }
00364                 return;
00365         }
00366         if ( strstr(cmd, "down") )
00367         {
00368                 kprintf("\n\rRTL8139: shutting down eth0 device...");
00369 
00370                 // Close the TCP module                                 //
00371                 tcp_module_close();
00372 
00373                 // Destroy the ethernet buffer                          //
00374                 kfree( eth_recv_buf );
00375                 // Kill the ethernet receiver thread                    //
00376                 kill(eth_recv_thread1->pid);
00377                 kill(eth_recv_thread2->pid);
00378                 // Reset the ARP cache                                  //
00379                 arp_reset_cache();
00380                 // Close the RTL8139 interface                          //
00381                 rtl8139_close(&rtl);
00382                 kprintf("\n\r");
00383                 return;
00384         }
00385 
00386         // Command unknown!                                             //
00387         kprintf("\n\rerror: %s unknown!\n\r", cmd);
00388 }

bool is_eth_promisc  
 

Check if the ethernet device has been configured in promiscuous mode.

Returns:
  • TRUE the ethernet card is in promiscuous mode;
  • FALSE the ethernet card is not in promiscuous mode.

Definition at line 261 of file eth.c.

00262 {
00263         return( get_rtl8139_device()->promisc );
00264 }

int recv_eth_packet ethernet_t   buf,
size_t    len,
int    flags
 

Receive data from the ethernet layer.

Parameters:
buf  A buffer where the ethernet received packet will be copied.
len  The max size of the buffer buf.
flags  Flags.
Returns:
The length in bytes of the packet received.

Todo:
flags parameter implementation.

Definition at line 67 of file eth.c.

00068 {
00069         dword IF = GET_IF();
00070 
00071         // If the recv buffer is empty, simply do nothing               //
00072         while(TRUE)
00073         {
00074                 DOWN(&eth_recv_buf->mutex);
00075 
00076                 if ( eth_recv_buf->count==0 )
00077                 {
00078                         UP(&eth_recv_buf->mutex);
00079                         sleep_task( get_curr_task() );
00080                         enable();
00081                         idle();
00082                 }
00083                 else
00084                         // The buffer is not empty!                     //
00085                         break;
00086         }
00087 
00088         // Get the packet from the recv buffer and put it into the      //
00089         // requested pointer                                            //
00090         memcpy(
00091                 buf,
00092                 eth_recv_buf->packet[eth_recv_buf->read].data,
00093                 len = MIN(len, eth_recv_buf->packet[eth_recv_buf->read].length)
00094         );
00095         // Update the read pointer and the recv buffer counter          //
00096         eth_recv_buf->read = (eth_recv_buf->read + 1) % ETH_RECV_BUF_DIM;
00097         (eth_recv_buf->count)--;
00098 
00099         UP(&eth_recv_buf->mutex);
00100         SET_IF(IF);
00101 
00102         // Return the length of the received packet                     //
00103         return( len );
00104 }

int send_eth_packet const uint8_t   to,
const void *    data,
size_t    len,
uint16_t    type
 

Send an ethernet packet to the physiscal layer.

Parameters:
to  The destination ethernet address (MAC).
data  The buffer of data to be sent.
len  The size of the buffer of data to be sent.
type  The packet type.
Returns:
  • The number of bytes sent in case of success.
  • -ENOMEM cannot allocate the packet structure.
  • -ENXIO no ethernet device found.

Definition at line 206 of file eth.c.

00207 {
00208         uint8_t *packet;
00209         uint8_t *mac_addr;
00210 
00211         // Analyze the packet length (must be less than ETH_MTU)        //
00212         // TODO: if the packet length if great than ETH_MTU             //
00213         // perform a packet fragmentation.                              //
00214         len = MIN(len, ETH_MTU);
00215 
00216         // Create the ethernet packet                                   //
00217         packet = kmalloc( MAX(len+ETH_HEAD_LEN, ETH_MIN_LEN) );
00218         if (!packet)
00219                 return(-ENOMEM);
00220 
00221         // Get the local mac address                                    //
00222         if ( (mac_addr = get_eth_mac_addr()) == NULL )
00223                 // No such device or address!                           //
00224                 return(-ENXIO);
00225 
00226         // Add the ethernet header to the packet                        //
00227         memcpy(packet, to, ETH_ADDR_LEN);
00228         memcpy(packet + ETH_ADDR_LEN, mac_addr, ETH_ADDR_LEN);
00229         memcpy(packet + 2 * ETH_ADDR_LEN, &type, sizeof(uint16_t));
00230 
00231         // Copy the data into the packet                                //
00232         memcpy(packet + ETH_HEAD_LEN, data, len);
00233 
00234         // Adjust the packet length including the size of the header    //
00235         len += ETH_HEAD_LEN;
00236 
00237         // Auto-pad! Send a minimum payload (another 4 bytes are        //
00238         // sent automatically for the FCS, totalling to 64 bytes)       //
00239         // It is the minimum length of an ethernet packet.              //
00240         while (len < ETH_MIN_LEN)
00241                 packet[len++] = '\0';
00242 
00243         // Go to the physical layer                                     //
00244         len = send_rtl8139_packet(get_rtl8139_device(), packet, len);
00245 
00246         // Free the memory of the packet                                //
00247         kfree(packet);
00248 
00249         // Return the bytes transmitted at this level                   //
00250         return(len);
00251 }

void to_eth_layer ethernet_t   packet,
size_t    len
 

Process an ethernet packet received from the physical layer.

Parameters:
packet  The ethernet packet received.
len  The size of the packet.

Definition at line 153 of file eth.c.

00154 {
00155         DOWN(&eth_recv_buf->mutex);
00156 
00157         #ifdef ETH_DEBUG
00158         // Strip the ethernet header                                    //
00159         kprintf("\n\rMAC DEST   = %02x:%02x:%02x:%02x:%02x:%02x",
00160                 packet->dst[0], packet->dst[1], packet->dst[2],
00161                 packet->dst[3], packet->dst[4], packet->dst[5]);
00162         kprintf("\n\rMAC SOURCE = %02x:%02x:%02x:%02x:%02x:%02x",
00163                 packet->src[0], packet->src[1], packet->src[2],
00164                 packet->src[3], packet->src[4], packet->src[5]);
00165         kprintf("\n\rPACK TYPE  = %04x", ntohs(packet->type));
00166         kprintf("\n\rTOT LENGTH = %u bytes", len);
00167         #endif
00168 
00169         // Store the packet data into the send buffer                   //
00170         memcpy(
00171                 eth_recv_buf->packet[eth_recv_buf->write].data,
00172                 packet,
00173                 len = MIN(len, ETH_FRAME_LEN)
00174         );
00175         // Store the packet length                                      //
00176         eth_recv_buf->packet[eth_recv_buf->write].length = len;
00177         // Update the recv buffer write pointer                         //
00178         eth_recv_buf->write = (eth_recv_buf->write + 1) % ETH_RECV_BUF_DIM;
00179 
00180         if (eth_recv_buf->count <= ETH_RECV_BUF_DIM)
00181                 // Update the packet counter                            //
00182                 (eth_recv_buf->count)++;
00183         else
00184                 // The oldest packet has been overwritten, so update    //
00185                 // also the read pointer                                //
00186                 eth_recv_buf->read = (eth_recv_buf->read + 1) % ETH_RECV_BUF_DIM;
00187 
00188         UP(&eth_recv_buf->mutex);
00189 
00190         // Wakeup the receive daemons                                   //
00191         wakeup_task( eth_recv_thread1 );
00192         wakeup_task( eth_recv_thread2 );
00193 }


Variable Documentation

eth_buf_t* eth_recv_buf = NULL
 

Ethernet receive buffer.

Definition at line 32 of file eth.c.

task_t* eth_recv_thread1 = NULL
 

Daemon ethernet tasks 1.

Definition at line 35 of file eth.c.

task_t * eth_recv_thread2 = NULL
 

Daemon ethernet tasks 2.

Definition at line 37 of file eth.c.

rtl8139_t* rtl
 

Pointer to the RTL8139 structure.

Definition at line 29 of file eth.c.


Generated on Fri Feb 20 15:32:17 2004 for Minirighi by doxygen1.2.18