Пример #1
0
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;
}
Пример #2
0
/*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));
}
Пример #3
0
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;
}