<commit_before>//! Implementation of Xen's network driver

use core::mem;
use alloc_uni::__rust_allocate;

use sync::Arc;
use boxed::Box;

use vec::Vec;
use string::ToString;

use sync::spin::{InterruptSpinLock, SpinLock, RwLock};

use ffi::CString;

use net::{Interface, Packet};
use net::defs::HwAddr;

use hal::mmu::{Vaddr, Mfn};

use hal::xen::store::{XenStore, XenbusState};
use hal::xen::grant::{Table as GrantTable, Ref as GrantRef};
use hal::xen::ring::{SharedRing, FrontRing, Idx as RingIdx};

use hal::xen::defs::EvtchnPort;

use hal::arch::defs::PAGE_SIZE;

use hal::xen::event;

#[repr(i16)]
#[derive(Debug, PartialEq)]
#[allow(dead_code)]
/// XEN_NETIF_RSP_*
enum NetifRsp {
    /// XEN_NETIF_RSP_OKAY
    Okay = 0,
    /// XEN_NETIF_RSP_ERROR
    Error = -1,
    /// XEN_NETIF_RSP_DROPPED
    Dropped = -2,
    /// XEN_NETIF_RSP_NULL
    Null = 1,
}

#[repr(u16)]
#[derive(Debug)]
#[allow(dead_code)]
/// XEN_NETTXF_*
enum NetTxFlags {
    CsumBlank = 1 << 0,
    DataValidated = 1 << 1,
    MoreData = 1 << 2,
    ExtraInfo = 1 << 3,
}

#[repr(u16)]
#[derive(Debug)]
#[allow(dead_code)]
/// XEN_NETRXF_*
enum NetRxFlags {
    DataValidated = 1 << 0,
    CsumBlank = 1 << 1,
    MoreData = 1 << 2,
    ExtraInfo = 1 << 3,
    GsoPrefix = 1 << 4,
}

#[repr(C)]
#[derive(Debug)]
/// struct xen_netif_tx_request
struct NetifTxRequest {
    gref: GrantRef,
    offset: u16,
    flags: NetTxFlags,
    id: u16,
    size: u16,
}

#[repr(C)]
#[derive(Debug)]
/// struct xen_netif_tx_response
struct NetifTxResponse {
    id: u16,
    status: NetifRsp,
}

#[repr(C)]
#[derive(Debug)]
/// struct xen_netif_rx_request
struct NetifRxRequest {
    id: u16,
    gref: GrantRef,
}

#[repr(C)]
#[derive(Debug)]
/// struct xen_netif_rx_response
struct NetifRxResponse {
    id: u16,
    offset: u16,
    flags: NetRxFlags,
    status: i16,
}

type TxSharedRing = SharedRing<NetifTxRequest, NetifTxResponse>;
type RxSharedRing = SharedRing<NetifRxRequest, NetifRxResponse>;

type TxFrontRing = FrontRing<NetifTxRequest, NetifTxResponse>;
type RxFrontRing = FrontRing<NetifRxRequest, NetifRxResponse>;

/// Buffer allocated for packet reception
struct RxBuffer {
    pub id: u16,
    pub page: *mut u8,
    pub grant_ref: GrantRef,
}

/// Buffer allocated for packet transmission
struct TxBuffer {
    pub id: u16,<commit_msg>xen/net: Add discover()<commit_after>//! Implementation of Xen's network driver

use core::mem;
use alloc_uni::__rust_allocate;

use sync::Arc;
use boxed::Box;

use vec::Vec;
use string::ToString;

use sync::spin::{InterruptSpinLock, SpinLock, RwLock};

use ffi::CString;

use net::{Interface, Packet};
use net::defs::HwAddr;

use hal::mmu::{Vaddr, Mfn};

use hal::xen::store::{XenStore, XenbusState};
use hal::xen::grant::{Table as GrantTable, Ref as GrantRef};
use hal::xen::ring::{SharedRing, FrontRing, Idx as RingIdx};

use hal::xen::defs::EvtchnPort;

use hal::arch::defs::PAGE_SIZE;

use hal::xen::event;

#[repr(i16)]
#[derive(Debug, PartialEq)]
#[allow(dead_code)]
/// XEN_NETIF_RSP_*
enum NetifRsp {
    /// XEN_NETIF_RSP_OKAY
    Okay = 0,
    /// XEN_NETIF_RSP_ERROR
    Error = -1,
    /// XEN_NETIF_RSP_DROPPED
    Dropped = -2,
    /// XEN_NETIF_RSP_NULL
    Null = 1,
}

#[repr(u16)]
#[derive(Debug)]
#[allow(dead_code)]
/// XEN_NETTXF_*
enum NetTxFlags {
    CsumBlank = 1 << 0,
    DataValidated = 1 << 1,
    MoreData = 1 << 2,
    ExtraInfo = 1 << 3,
}

#[repr(u16)]
#[derive(Debug)]
#[allow(dead_code)]
/// XEN_NETRXF_*
enum NetRxFlags {
    DataValidated = 1 << 0,
    CsumBlank = 1 << 1,
    MoreData = 1 << 2,
    ExtraInfo = 1 << 3,
    GsoPrefix = 1 << 4,
}

#[repr(C)]
#[derive(Debug)]
/// struct xen_netif_tx_request
struct NetifTxRequest {
    gref: GrantRef,
    offset: u16,
    flags: NetTxFlags,
    id: u16,
    size: u16,
}

#[repr(C)]
#[derive(Debug)]
/// struct xen_netif_tx_response
struct NetifTxResponse {
    id: u16,
    status: NetifRsp,
}

#[repr(C)]
#[derive(Debug)]
/// struct xen_netif_rx_request
struct NetifRxRequest {
    id: u16,
    gref: GrantRef,
}

#[repr(C)]
#[derive(Debug)]
/// struct xen_netif_rx_response
struct NetifRxResponse {
    id: u16,
    offset: u16,
    flags: NetRxFlags,
    status: i16,
}

type TxSharedRing = SharedRing<NetifTxRequest, NetifTxResponse>;
type RxSharedRing = SharedRing<NetifRxRequest, NetifRxResponse>;

type TxFrontRing = FrontRing<NetifTxRequest, NetifTxResponse>;
type RxFrontRing = FrontRing<NetifRxRequest, NetifRxResponse>;

/// Verify if a vif (virtual interface) with id `id` exists
fn vif_id_exists(id: u32) -> bool {
    let mut t = XenStore::start_transaction().unwrap();
    let path = CString::new(format!("device/vif/{}", id)).unwrap();

    let res = match t.read(path) {
        Ok(..) => true,
        Err(..) => false,
    };

    t.end().unwrap();

    res
}

/// Returns a list of interfaces that have a xen backend
pub fn discover() -> Vec<Arc<RwLock<Interface>>> {
    let mut id = 0;
    let mut v = Vec::new();

    // Create interface for every `id` valid
    while vif_id_exists(id) {
        let interface = Arc::new(RwLock::new(Interface::new()));

        v.push(interface);

        // Instantiate the Xen backend
        match XenNetDevice::new(id, v.last().unwrap()) {
            Ok(i) => {
                // Set it as pv_device of the interface
                v.last().unwrap().write().pv_device_set(i);
            }
            Err(..) => {
                v.pop();
                println!("Warning: Impossible to initialize xen network interface {}",
                         id);
            }
        }

        id += 1;
    }

    v
}

/// Buffer allocated for packet reception
struct RxBuffer {
    pub id: u16,
    pub page: *mut u8,
    pub grant_ref: GrantRef,
}

/// Buffer allocated for packet transmission
struct TxBuffer {
    pub id: u16,
{'fraction_non_alphanumeric': 0.15305067218200621, 'fraction_numerical': 0.017580144777662874, 'mean_word_length': 3.3048961424332344, 'pattern_counts': {'":': 0, '<': 50, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4695583', 'n_tokens_mistral': 2289, 'n_tokens_neox': 2195, 'n_words': 506}