bool update_switch_port_status( switch_port *port ) { assert( port != NULL ); assert( port->device != NULL ); bool ret = update_device_status( port->device ); if ( ret == false ) { return false; } bool updated = false; if ( ( ( port->status.state & OFPPS_LINK_DOWN ) != 0 ) && ( port->device->status.up == true ) ) { updated = true; port->status.state &= ~( ( uint32_t ) OFPPS_LINK_DOWN ); } else if ( ( ( port->status.state & OFPPS_LINK_DOWN ) == 0 ) && ( port->device->status.up == false ) ) { updated = true; port->status.state |= OFPPS_LINK_DOWN; } if ( port->status.curr != port->device->status.curr ) { updated = true; port->status.curr = port->device->status.curr; } if ( port->status.advertised != port->device->status.advertised ) { updated = true; port->status.advertised = port->device->status.advertised; } if ( port->status.supported != port->device->status.supported ) { updated = true; port->status.supported = port->device->status.supported; } if ( port->status.peer != port->device->status.peer ) { updated = true; port->status.peer = port->device->status.peer; } return updated; }
/*L:215 * This is the generic routine we call when the Guest uses LHCALL_NOTIFY. In * particular, it's used to notify us of device status changes during boot. */ static void handle_output(unsigned long addr) { struct device *i; /* Check each device. */ for (i = devices.dev; i; i = i->next) { struct virtqueue *vq; /* * Notifications to device descriptors mean they updated the * device status. */ if (from_guest_phys(addr) == i->desc) { update_device_status(i); return; } /* Devices should not be used before features are finalized. */ for (vq = i->vq; vq; vq = vq->next) { if (addr != vq->config.pfn*getpagesize()) continue; errx(1, "Notification on %s before setup!", i->name); } } /* * Early console write is done using notify on a nul-terminated string * in Guest memory. It's also great for hacking debugging messages * into a Guest. */ if (addr >= guest_limit) errx(1, "Bad NOTIFY %#lx", addr); write(STDOUT_FILENO, from_guest_phys(addr), strnlen(from_guest_phys(addr), guest_limit - addr)); }
ether_device * create_ether_device( const char *name, const size_t max_send_queue, const size_t max_recv_queue ) { assert( name != NULL ); assert( strlen( name ) > 0 ); assert( max_send_queue > 0 ); assert( max_recv_queue > 0 ); int nfd = socket( PF_INET, SOCK_DGRAM, 0 ); if ( nfd < 0 ) { char error_string[ ERROR_STRING_SIZE ]; error( "Failed to open a socket ( ret = %d, errno = %s [%d] ).", nfd, safe_strerror_r( errno, error_string, sizeof( error_string ) ), errno ); return NULL; } struct ifreq ifr; memset( &ifr, 0, sizeof( ifr ) ); strncpy( ifr.ifr_name, name, IFNAMSIZ ); ifr.ifr_name[ IFNAMSIZ - 1 ] = '\0'; int ret = ioctl( nfd, SIOCGIFINDEX, &ifr ); if ( ret == -1 ) { char error_string[ ERROR_STRING_SIZE ]; error( "Failed to retrieve an interface index of %s ( ret = %d, errno = %s [%d] ).", name, ret, safe_strerror_r( errno, error_string, sizeof( error_string ) ), errno ); close( nfd ); return NULL; } int ifindex = ifr.ifr_ifindex; ret = ioctl( nfd, SIOCGIFMTU, &ifr ); if ( ret == -1 ) { char error_string[ ERROR_STRING_SIZE ]; error( "Failed to retrieve MTU of %s ( ret = %d, errno = %s [%d] ).", name, ret, safe_strerror_r( errno, error_string, sizeof( error_string ) ), errno ); close( nfd ); return NULL; } int mtu = ifr.ifr_mtu; ret = ioctl( nfd, SIOCGIFHWADDR, &ifr ); if ( ret == -1 ) { char error_string[ ERROR_STRING_SIZE ]; error( "Failed to retrieve hardware address of %s ( ret = %d, error = %s [%d] ).", name, ret, safe_strerror_r( errno, error_string, sizeof( error_string ) ), errno ); close( nfd ); return NULL; } close( nfd ); size_t device_mtu = ( size_t ) mtu + MAX_L2_HEADER_LENGTH; #ifdef WITH_PCAP char errbuf[ PCAP_ERRBUF_SIZE ]; pcap_t *handle = pcap_open_live( name, ( int ) device_mtu, 1, 100, errbuf ); if( handle == NULL ) { error( "Failed to open %s ( %s ).", name, errbuf ); return NULL; } if ( pcap_setnonblock( handle, 1, errbuf ) == -1 ) { warn( "Failed to setnonblock %s ( %s ).", name, errbuf ); } int fd = pcap_get_selectable_fd( handle ); #else // WITH_PCAP int fd = socket( PF_PACKET, SOCK_RAW, htons( ETH_P_ALL ) ); if ( fd < 0 ) { char error_string[ ERROR_STRING_SIZE ]; error( "Failed to open a socket ( ret = %d, errno = %s [%d] ).", fd, safe_strerror_r( errno, error_string, sizeof( error_string ) ), errno ); return NULL; } struct sockaddr_ll sll; memset( &sll, 0, sizeof( sll ) ); sll.sll_family = AF_PACKET; sll.sll_protocol = htons( ETH_P_ALL ); sll.sll_ifindex = ifindex; ret = bind( fd, ( struct sockaddr * ) &sll, sizeof( sll ) ); if ( ret < 0 ) { char error_string[ ERROR_STRING_SIZE ]; error( "Failed to bind ( fd = %d, ret = %d, errno = %s [%d] ).", fd, ret, safe_strerror_r( errno, error_string, sizeof( error_string ) ), errno ); close( fd ); return NULL; } int val = TPACKET_V2; ret = setsockopt( fd, SOL_PACKET, PACKET_VERSION, &val, sizeof( val ) ); if ( ret < 0 ) { char error_string[ ERROR_STRING_SIZE ]; error( "Failed to set PACKET_VERSION to %d ( fd = %d, ret = %d, errno = %s [%d] ).", val, fd, ret, safe_strerror_r( errno, error_string, sizeof( error_string ) ), errno ); close( fd ); return NULL; } val = 1; ret = setsockopt( fd, SOL_PACKET, PACKET_AUXDATA, &val, sizeof( val ) ); if ( ret < 0 ) { char error_string[ ERROR_STRING_SIZE ]; error( "Failed to set PACKET_AUXDATA to %d ( fd = %d, ret = %d, errno = %s [%d] ).", val, fd, ret, safe_strerror_r( errno, error_string, sizeof( error_string ) ), errno ); close( fd ); return NULL; } while ( 1 ) { char buf; ssize_t length = recv( fd, &buf, 1, MSG_DONTWAIT ); if ( length <= 0 ) { break; } } #endif // WITH_PCAP ether_device *device = xmalloc( sizeof( ether_device ) ); memset( device, 0, sizeof( ether_device ) ); strncpy( device->name, name, IFNAMSIZ ); device->name[ IFNAMSIZ - 1 ] = '\0'; #if WITH_PCAP device->pcap = handle; #endif device->fd = fd; device->ifindex = ifindex; memcpy( device->hw_addr, ifr.ifr_hwaddr.sa_data, ETH_ADDRLEN ); device->status.can_retrieve_link_status = true; device->status.can_retrieve_pause = true; device->mtu = device_mtu; device->recv_buffer = alloc_buffer_with_length( device->mtu ); device->send_queue = create_packet_buffers( ( unsigned int ) max_send_queue, device->mtu ); device->recv_queue = create_packet_buffers( ( unsigned int ) max_recv_queue, device->mtu ); short int flags = get_device_flags( device->name ); device->original_flags = flags; set_fd_handler_safe( fd, receive_frame, device, flush_send_queue, device ); set_readable_safe( fd, true ); enable_promiscuous( device ); up_ether_device( device ); update_device_status( device ); time_now( &device->created_at ); return device; }