virtio-net: introduce a new macaddr control
In virtio-net guest driver, currently we write MAC address to pci config space byte by byte, this means that we have an intermediate step where mac is wrong. This patch introduced a new control command to set MAC address, it's atomic. VIRTIO_NET_F_CTRL_MAC_ADDR is a new feature bit for compatibility. "mac" field will be set to read-only when VIRTIO_NET_F_CTRL_MAC_ADDR is acked. Signed-off-by: Amos Kong <akong@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
		
							parent
							
								
									921ac5d0f3
								
							
						
					
					
						commit
						c1943a3f37
					
				@ -309,6 +309,10 @@ static QEMUMachine pc_i440fx_machine_v1_4 = {
 | 
			
		||||
            .driver   = "usb-tablet",\
 | 
			
		||||
            .property = "usb_version",\
 | 
			
		||||
            .value    = stringify(1),\
 | 
			
		||||
        },{\
 | 
			
		||||
            .driver   = "virtio-net-pci",\
 | 
			
		||||
            .property = "ctrl_mac_addr",\
 | 
			
		||||
            .value    = "off",      \
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
static QEMUMachine pc_machine_v1_3 = {
 | 
			
		||||
 | 
			
		||||
@ -93,7 +93,8 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config)
 | 
			
		||||
 | 
			
		||||
    memcpy(&netcfg, config, sizeof(netcfg));
 | 
			
		||||
 | 
			
		||||
    if (memcmp(netcfg.mac, n->mac, ETH_ALEN)) {
 | 
			
		||||
    if (!(n->vdev.guest_features >> VIRTIO_NET_F_CTRL_MAC_ADDR & 1) &&
 | 
			
		||||
        memcmp(netcfg.mac, n->mac, ETH_ALEN)) {
 | 
			
		||||
        memcpy(n->mac, netcfg.mac, ETH_ALEN);
 | 
			
		||||
        qemu_format_nic_info_str(&n->nic->nc, n->mac);
 | 
			
		||||
    }
 | 
			
		||||
@ -351,6 +352,16 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
 | 
			
		||||
    struct virtio_net_ctrl_mac mac_data;
 | 
			
		||||
    size_t s;
 | 
			
		||||
 | 
			
		||||
    if (cmd == VIRTIO_NET_CTRL_MAC_ADDR_SET) {
 | 
			
		||||
        if (iov_size(iov, iov_cnt) != sizeof(n->mac)) {
 | 
			
		||||
            return VIRTIO_NET_ERR;
 | 
			
		||||
        }
 | 
			
		||||
        s = iov_to_buf(iov, iov_cnt, 0, &n->mac, sizeof(n->mac));
 | 
			
		||||
        assert(s == sizeof(n->mac));
 | 
			
		||||
        qemu_format_nic_info_str(&n->nic->nc, n->mac);
 | 
			
		||||
        return VIRTIO_NET_OK;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (cmd != VIRTIO_NET_CTRL_MAC_TABLE_SET) {
 | 
			
		||||
        return VIRTIO_NET_ERR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -44,6 +44,8 @@
 | 
			
		||||
#define VIRTIO_NET_F_CTRL_VLAN  19      /* Control channel VLAN filtering */
 | 
			
		||||
#define VIRTIO_NET_F_CTRL_RX_EXTRA 20   /* Extra RX mode control support */
 | 
			
		||||
 | 
			
		||||
#define VIRTIO_NET_F_CTRL_MAC_ADDR   23 /* Set MAC address */
 | 
			
		||||
 | 
			
		||||
#define VIRTIO_NET_S_LINK_UP    1       /* Link is up */
 | 
			
		||||
 | 
			
		||||
#define TX_TIMER_INTERVAL 150000 /* 150 us */
 | 
			
		||||
@ -106,7 +108,7 @@ typedef uint8_t virtio_net_ctrl_ack;
 | 
			
		||||
 #define VIRTIO_NET_CTRL_RX_MODE_NOBCAST      5
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Control the MAC filter table.
 | 
			
		||||
 * Control the MAC
 | 
			
		||||
 *
 | 
			
		||||
 * The MAC filter table is managed by the hypervisor, the guest should
 | 
			
		||||
 * assume the size is infinite.  Filtering should be considered
 | 
			
		||||
@ -119,6 +121,10 @@ typedef uint8_t virtio_net_ctrl_ack;
 | 
			
		||||
 * first sg list contains unicast addresses, the second is for multicast.
 | 
			
		||||
 * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature
 | 
			
		||||
 * is available.
 | 
			
		||||
 *
 | 
			
		||||
 * The ADDR_SET command requests one out scatterlist, it contains a
 | 
			
		||||
 * 6 bytes MAC address. This functionality is present if the
 | 
			
		||||
 * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available.
 | 
			
		||||
 */
 | 
			
		||||
struct virtio_net_ctrl_mac {
 | 
			
		||||
    uint32_t entries;
 | 
			
		||||
@ -126,6 +132,7 @@ struct virtio_net_ctrl_mac {
 | 
			
		||||
};
 | 
			
		||||
#define VIRTIO_NET_CTRL_MAC    1
 | 
			
		||||
 #define VIRTIO_NET_CTRL_MAC_TABLE_SET        0
 | 
			
		||||
 #define VIRTIO_NET_CTRL_MAC_ADDR_SET         1
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Control VLAN filtering
 | 
			
		||||
@ -158,5 +165,6 @@ struct virtio_net_ctrl_mac {
 | 
			
		||||
        DEFINE_PROP_BIT("ctrl_vq", _state, _field, VIRTIO_NET_F_CTRL_VQ, true), \
 | 
			
		||||
        DEFINE_PROP_BIT("ctrl_rx", _state, _field, VIRTIO_NET_F_CTRL_RX, true), \
 | 
			
		||||
        DEFINE_PROP_BIT("ctrl_vlan", _state, _field, VIRTIO_NET_F_CTRL_VLAN, true), \
 | 
			
		||||
        DEFINE_PROP_BIT("ctrl_rx_extra", _state, _field, VIRTIO_NET_F_CTRL_RX_EXTRA, true)
 | 
			
		||||
        DEFINE_PROP_BIT("ctrl_rx_extra", _state, _field, VIRTIO_NET_F_CTRL_RX_EXTRA, true), \
 | 
			
		||||
        DEFINE_PROP_BIT("ctrl_mac_addr", _state, _field, VIRTIO_NET_F_CTRL_MAC_ADDR, true)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user