#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.
| |||||||||
| 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.
| |||||||||
| 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.
| |||||||||
| bool | is_eth_promisc () | ||||||||
Check if the ethernet device has been configured in promiscuous mode.
| |||||||||
| void | ifconfig (char *cmd) | ||||||||
This is the "ifconfig" command for the shell.
| |||||||||
Variables | |||||||||
| rtl8139_t * | rtl | ||||||||
| Pointer to the RTL8139 structure. | |||||||||
| eth_buf_t * | eth_recv_buf = NULL | ||||||||
| Ethernet receive buffer. | |||||||||
| task_t * | eth_recv_thread1 = NULL | ||||||||
| Daemon ethernet tasks 1. | |||||||||
| task_t * | eth_recv_thread2 = NULL | ||||||||
| Daemon ethernet tasks 2. | |||||||||
Definition in file eth.c.
|
|
Default IP address for this host.
|
|
|
Default IP netmask for this host.
|
|
|
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(ð_recv_buf->mutex);
00052 }
|
|
|
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 }
|
|
|
This is the "ifconfig" command for the shell.
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 ð_recv_daemon, ð_recv_daemon,
00337 0, "eth_recvd1", KERNEL_PRIVILEGE);
00338 eth_recv_thread2 =
00339 create_process(
00340 ð_recv_daemon, ð_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 }
|
|
|
Check if the ethernet device has been configured in promiscuous mode.
Definition at line 261 of file eth.c.
00262 {
00263 return( get_rtl8139_device()->promisc );
00264 }
|
|
||||||||||||||||
|
Receive data from the ethernet layer.
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(ð_recv_buf->mutex);
00075
00076 if ( eth_recv_buf->count==0 )
00077 {
00078 UP(ð_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(ð_recv_buf->mutex);
00100 SET_IF(IF);
00101
00102 // Return the length of the received packet //
00103 return( len );
00104 }
|
|
||||||||||||||||||||
|
Send an ethernet packet to the physiscal layer.
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 }
|
|
||||||||||||
|
Process an ethernet packet received from the physical layer.
Definition at line 153 of file eth.c.
00154 {
00155 DOWN(ð_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(ð_recv_buf->mutex);
00189
00190 // Wakeup the receive daemons //
00191 wakeup_task( eth_recv_thread1 );
00192 wakeup_task( eth_recv_thread2 );
00193 }
|
|
|
Ethernet receive buffer.
|
|
|
Daemon ethernet tasks 1.
|
|
|
Daemon ethernet tasks 2.
|
|
|
Pointer to the RTL8139 structure.
|
1.2.18