int sr_integ_low_level_output(struct sr_instance* sr /* borrowed */, uint8_t* buf /* borrowed */ , unsigned int len, const char* iface /* borrowed */) { #ifdef _CPUMODE_ return sr_cpu_output(sr, buf /*lent*/, len, iface); #else return sr_vns_send_packet(sr, buf /*lent*/, len, iface); #endif /* _CPUMODE_ */ } /* -- sr_vns_integ_output -- */
int sr_cpu_input( struct sr_instance* sr ) { byte buf[ETH_MAX_LEN]; ssize_t len; router_t* router; interface_t* intf; fd_set rdset, errset; int ret, max_fd; unsigned i; struct timeval timeout; /* loop until something interesting happens */ do { /* clear the sets */ FD_ZERO( &rdset ); FD_ZERO( &errset ); /* set the bits on interfaces' fd's that we care about */ max_fd = -1; router = sr->interface_subsystem; for( i=0; i<router->num_interfaces; i++ ) { if( router->interface[i].enabled ) { FD_SET( router->interface[i].hw_fd, &rdset ); FD_SET( router->interface[i].hw_fd, &errset ); if( router->interface[i].hw_fd > max_fd ) max_fd = router->interface[i].hw_fd; #ifdef _DEBUG_ if( router->interface[i].hw_fd > FD_SETSIZE ) die( "Error: fd too big for select (%d > %d)", router->interface[i].hw_fd, FD_SETSIZE ); #endif } } /* wait for something to happen */ timeout.tv_sec = 1; timeout.tv_usec = 0; ret = select( max_fd + 1, &rdset, NULL, &errset, &timeout ); /* check each intf to see if something interesting happened on it */ for( i=0; i<router->num_interfaces; i++ ) { intf = &router->interface[i]; if( intf->enabled ) { /* check for available bytes in the input buffer */ if( FD_ISSET( intf->hw_fd, &rdset ) ) { len = real_read_once( intf->hw_fd, buf, ETH_MAX_LEN ); if( len == 0 ) debug_println( "Warning: HW socket closed to %s", intf->name ); else if( len < 0 ) debug_println( "Warning: error when reading on HW socket to %s", intf->name ); else { #if 0 /* check packet for decap first */ if( len >= 34 ) { if( buf[23] == 0x04 || buf[23] == 0xF4 ) { debug_println( "*** DECAPSULATING PACKET ***" ); /* write a new Ethernet header */ byte* new_buf = buf + 20; memset( new_buf, 0xFF, ETH_ADDR_LEN ); memcpy( new_buf+6, &router->interface[DECAP_NEXT_INTF].mac, ETH_ADDR_LEN ); *((uint16_t*)(new_buf+12)) = IPV4_ETHERTYPE; /* send it back out nf2c{DECAP_NEXT_INTF} */ sr_cpu_output( new_buf, len-20, &router->interface[DECAP_NEXT_INTF] ); count+=len; fprintf(stderr,"%llu\n",count-20); continue; } } #endif /* send the packet to our processing pipeline */ sr_integ_input( sr, buf, len, intf ); /* log the received packet */ sr_log_packet( sr, buf, len ); return 1; } } /* check for an error on the socket */ if( FD_ISSET( intf->hw_fd, &errset ) ) { debug_println( "Warning: error on HW socket to %s", intf->name ); } } } } while( 1 ); }