Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ See the table below for a list of device types supported by Ixl:
|--------|-------------------------|---------------------------------------|
| e1000 | e1000-compliant NICs | - |
| igb | Intel I350, Intel 82576 | Currently lacks multi-queue support. |
| igc | Intel i225, Intel i226 | Currently lacks multi-queue support. |
| ixgbe | Intel X520/X540 | - |

## Building
Expand Down
1 change: 1 addition & 0 deletions lib/include/driver/igb/igb_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
#define IGB_DEV_ID_82576 0x10C9
#define IGB_DEV_ID_I350 0x1521
#define IGB_DEV_ID_I210 0x1533

/*
* Descriptor structures
Expand Down
225 changes: 225 additions & 0 deletions lib/include/driver/igc/igc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
/**
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you follow the formatting of the other header files? The first comment block should have a one-line description on what the file does, along with your name and the year(s) in that the file was modified. Also dump all of the information of version, date, file. Have a look at e.g. igb.h. The same goes for the layout of comment blocks (where each line should be preceded with an asterisk.

* @file igc.h
* @author Paul Richter (paul.richter@spreewalddreieck.de)
* @brief header of igc driver containing class Igc_device
* @version 0.1
* @date 2025-11-07
*
* @copyright Copyright (c) 2025
*
* The igc device driver was developed as part of the bachelor thesis: "Generic
* aspects of porting a Linux Ethernet driver to the L4Re microkernel" It is
* nearly an identical copy of the ixl igb driver with changed register
* definitions. More information about how it works can be found there. (link
* will be inserted to a later date)
*/

/*
Header file containing the structure of the ixl igc device driver heavly
based on the ixl igb device driver
*/

#pragma once

#include <stdbool.h>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blank line after this include. Also, what is the reason for including stdbool.h here?

#include <l4/ixl/stats.h>

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete that newline. The structure of includes is , , local header files with each category being separated by a newline.

#include <l4/ixl/memory.h>

#include "igc_type.h"
#include "../../pci.h"

namespace Ixl {

/**
* Device driver specialized for the igc NIC family (e.g. I225-IT).
*
* Note: For now, this software is only a slight adaptation of the E1000 driver,
* leaving out many features such as RSS (multi-queue receive) etc. Maybe we
* will add those later, which will make the igc driver much more similar to
* ixgbe than to the original E1000 one (even though many register definitions
* stay the same).
*/
class Igc_device : public Ixl_device {
public:
// set number of queue entries to linux default value
static const int NUM_RX_QUEUE_ENTRIES = 256;
static const int NUM_TX_QUEUE_ENTRIES = 256;

static const int MAX_RX_QUEUE_ENTRIES = 256;
static const int MAX_TX_QUEUE_ENTRIES = 256;

static const int PKT_BUF_ENTRY_SIZE = 2048;

// Reserve at least twice the RX queue depth of packets for mempools. This
// is what the driver needs to remain operational as every received packet
// is immediately replaced with a fresh one in the RX path.
static const int MIN_MEMPOOL_ENTRIES = 2 * NUM_RX_QUEUE_ENTRIES;

static const int TX_CLEAN_BATCH = 32;

static const uint64_t INTERRUPT_INITIAL_INTERVAL = 1000 * 1000 * 1000;

Igc_device(L4vbus::Pci_dev &&dev, struct Dev_cfg &cfg, uint32_t itr_rate);

std::string get_driver_name(void) {
return("ixl-igc");
}

inline uint32_t get_max_frame_size(void) {
return 0;
}

uint32_t rx_batch(uint16_t queue_id, struct pkt_buf* bufs[],
uint32_t num_bufs);

uint32_t tx_batch(uint16_t queue_id, struct pkt_buf* bufs[],
uint32_t num_bufs);

void read_stats(struct device_stats *stats);

void set_promisc(bool enabled);

uint32_t get_link_speed(void);
uint32_t get_link_duplex(void);

struct mac_address get_mac_addr(void);

void set_mac_addr(struct mac_address mac);

bool check_recv_irq(uint16_t qid) override;

void ack_recv_irq(uint16_t qid) override;

// Get the number of descriptors per RX queue
uint32_t get_rx_queue_depth(void) {
return NUM_RX_QUEUE_ENTRIES;
}

// Get the number of descriptors per TX queue
uint32_t get_tx_queue_depth(void) {
return NUM_TX_QUEUE_ENTRIES;
}

// Extend an RX queue's mempool
bool extend_rxq_mempool(uint16_t qid, uint32_t count) {
if (qid >= num_rx_queues)
return false;

struct igc_rx_queue *queue =
((struct igc_rx_queue *) rx_queues) + qid;

return queue->mempool->reserve(count);
}

// Shrink an RX queue's mempool
void shrink_rxq_mempool(uint16_t qid, uint32_t count) {
if (qid >= num_rx_queues)
return;

struct igc_rx_queue *queue =
((struct igc_rx_queue *) rx_queues) + qid;

queue->mempool->cancel_reservation(count);
}

/*
* Initializes and returns the Igc device.
*
* \param pci_dev PCI device handle received from this task's vbus
* \param cfg An Ixl device configuration. See Dev_cfg for details.
*
* \return The initialized Igc device.
*/
static Igc_device* igc_init(L4vbus::Pci_dev&& pci_dev, struct Dev_cfg &cfg);

private:
// allocated for each rx queue, keeps state for the receive function
struct igc_rx_queue {
// DMA'able memory from that the individual descriptors are allocated
struct dma_memory descr_mem;

// Array of descriptors backed by descr_mem
volatile struct igc_rx_desc* descriptors;

// DMA'able memory for storing incoming packets
Mempool* mempool;

// No. of descriptors in the queue
uint16_t num_entries;
// position we are reading from
uint16_t rx_index;
// True if this RX queue contains descriptors not yet processed by the
// driver. We use this flag to skip IRQ receive operations if necessary.
bool rx_pending = false;
// virtual addresses to map descriptors back to their mbuf for freeing
void* virtual_addresses[];
};

// allocated for each tx queue, keeps state for the transmit function
struct igc_tx_queue {
// DMA'able memory from that the individual descriptors are allocated
struct dma_memory descr_mem;

// Array of descriptors backed by descr_mem
volatile struct igc_tx_desc* descriptors;

// No. of descriptors in the queue
uint16_t num_entries;
// position to clean up descriptors that where sent out by the nic
uint16_t clean_index;
// position to insert packets for transmission
uint16_t tx_index;
// virtual addresses to map descriptors back to their mbuf for freeing
void* virtual_addresses[];
};



/*** Functions ***/
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you center these intermediate headings, with the righthand delimiter being aligned to column 80? In this way, the code looks way more fancy :)


/**
* Enables an MSI for receive events. We will configure the NIC in a way
* that an MSI is generated for each packet received, while adhering to the
* ITR limit that the user can specify upon initializing the driver.
*
* \param qid Index of the queue for that the corresponding MSI-X shall be
* enabled.
*/
void enable_rx_interrupt(uint16_t qid);

/**
* Disables an MSI for receive events.
*
* \param qid Index of the RX queue for that the corresponding MSI-X shall
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For these multi-line doxygen statements: Could you align the descriptive text so that all lines of it start in the same column? Or does this break doxygen?

* be disabled.
*/
void disable_rx_interrupt(uint16_t qid);

void disable_interrupts(void);

void init_link(void);

void start_rx_queue(int queue_id);

void start_tx_queue(int queue_id);

void init_rx(void);

void init_tx(void);

void wait_for_link(void);

void reset_and_init(void);

void init_msix(void);

/*** Member variables ***/
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above.


// MAC address of this device
struct mac_address mac_addr;
// Does mac_addr contain a valid value?
bool mac_init = false;
};

} // namespace Ixl
Loading