#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.
|