嵌入式linux中文站在线图书

Previous Page
Next Page

2.2. net_device Structure

The net_device data structure stores all information specifically regarding a network device. There is one such structure for each device, both real ones (such as Ethernet NICs) and virtual ones (such as bonding[] or VLAN[]). In this section, I will use the words interface and device interchangeably, even though the difference between them is important in other contexts.

[] Bonding, also called EtherChannel (Cisco terminology) and trunking (Sun terminology), allows a set of interfaces to be grouped together and be treated as a single interface. This feature is useful when a system needs to support point-to-point connections at a high bandwidth. A nearly linear speedup can be achieved, with the virtual interface having a throughput nearly equal to the sum of the throughputs of the individual interfaces.

[] VLAN stands for Virtual LAN. The use of VLANs is a convenient way to isolate traffic using the same L2 switch in different broadcast domains by means of an additional tag, called the VLAN tag, that is added to the Ethernet frames. You can find an introduction to VLANs and their use with Linux at http://www.linuxjournal.com/article/7268.

The net_device structures for all devices are put into a global list to which the global variable dev_base points. The data structure is defined in include/linux/netdevice.h. The registration of network devices is described in Chapter 8. In that chapter, you can find details on how and when most of the net_device fields are initialized.

Like sk_buff, this structure is quite big and includes many feature-specific parameters, along with parameters from many different layers. For this reason, the overall organization of the structure will probably see some changes soon for optimization reasons.

Network devices can be classified into types such as Ethernet cards and Token Ring cards. While certain fields of the net_device structure are set to the same value for all devices of the same type, some fields must be set differently by each model of device. Thus, for almost every type, Linux provides a general function that initializes the parameters whose values stay the same across all models. Each device driver invokes this function in addition to setting those fields that have unique values for its model. Drivers can also overwrite fields that were already initialized by the kernel (for instance, to improve performance). You can find more details in Chapter 8.

The fields of the net_device structure can be classified into the following categories:

  • Configuration

  • Statistics

  • Device status

  • List management

  • Traffic management

  • Feature specific

  • Generic

  • Function pointers (or VFT)

2.2.1. Identifiers

The net_device structure includes three identifiers , not to be confused:


int ifindex

A unique ID, assigned to each device when it is registered with a call to dev_new_index.


int iflink

This field is mainly used by (virtual) tunnel devices and identifies the real device that will be used to reach the other end of the tunnel.


unsigned short dev_id

Currently used by IPv6 with the zSeries OSA NICs. The field is used to differentiate between virtual instances of the same device that can be shared between different OSes concurrently. See comments in net/ipv6/addrconf.c.

2.2.2. Configuration

Some of the configuration fields are given a default value by the kernel that depends on the class of network device, and some fields are left to the driver to fill. The driver can change defaults, as mentioned earlier, and some fields can even be changed at runtime by commands such as ifconfig and ip. In fact, several parametersbase_addr, if_port, dma, and irqare commonly set by the user when the module for the device is loaded. On the other hand, these parameters are not used by virtual devices.


char name[IFNAMSIZ]

Name of the device (e.g., eth0).


unsigned long mem_start


unsigned long mem_end

These fields describe the shared memory used by the device to communicate with the kernel. They are initialized and accessed only within the device driver; higher layers do not need to care about them.


unsigned long base_addr

The beginning of the I/O memory mapped to the device's own memory.


unsigned int irq

The interrupt number used by the device to talk to the kernel. It can be shared among multiple devices. Drivers use the request_irq function to allocate this variable and free_irq to release it.


unsigned char if_port

The type of port being used for this interface. See the next section, "Interface types and ports."


unsigned char dma

The DMA channel used by the device (if any). To obtain and release a DMA channel from the kernel, the file kernel/dma.c defines the functions request_dma and free_dma. To enable or disable a DMA channel after obtaining it, the functions enable_dma and disable_dma are provided in various include/asm-architecture files (e.g., include/asm-i386). The routines are used by ISA devices; Peripheral Component Interconnect (PCI) devices do not need them because they use others instead.

DMA is not available for all devices because some buses don't use it.


unsigned short flags


unsigned short gflags


unsigned short priv_flags

Some bits in the flags field represent capabilities of the network device (such as IFF_MULTICAST) and others represent changing status (such as IFF_UP or IFF_RUNNING). You can find the complete list of these flags in include/linux/if.h. The device driver usually sets the capabilities at initialization time, and the status flags are managed by the kernel in response to external events. The settings of the flags can be viewed through the familiar ifconfig command:

bash# ifconfig lo
lo          Link encap:Local Loopback
            inet addr:127.0.0.1  Mask:255.0.0.0
            UP LOOPBACK RUNNING  MTU:3924  Metric:1
            RX packets:198 errors:0 dropped:0 overruns:0 frame:0
            TX packets:198 errors:0 dropped:0 overruns:0 carrier:0
            collisions:0 txqueuelen:0

In this example, the words UP LOOPBACK RUNNING correspond to the flags IFF_UP, IFF_LOOPBACK, and IFF_RUNNING.

priv_flags stores flags that are not visible to the user space. Right now this field is used by the VLAN and Bridge virtual devices. gflags is almost never used and is there for compatibility reasons. Flags can be changed through the dev_change_flags function.


int features

Another bitmap of flags used to store some other device capabilities. It is not redundant for this data structure to contain multiple flag variables. The features field reports the card's capabilities for communicating with the CPU, such as whether the card can do DMA to high memory, or checksum all the packets in hardware. The list of the possible features is defined inside the structure net_device itself. This parameter is initialized by the device driver. You can find the list of NETIF_F_XXX features, along with good comments, inside the net_device data structure definition.


unsigned mtu

MTU stands for Maximum Transmission Unit and it represents the maximum size of the frames that the device can handle. Table 2-1 shows the values for the most common network technologies.

Table 2-1. MTU values for different device types

Device type

MTU

PPP

296

SLIP

296

Ethernet

1,500

ISDN

1,500

PLIP

1,500 (ether_setup)

Wavelan

1,500 (ether_setup)

EtherChannel

2,024

FDDI

4,352

Token Ring 4 MB/s (IEEE 802.5)

4,464

Token Bus (IEEE 802.4)

8,182

Token Ring 16 MB/s (IBM)

17,914

Hyperchannel

65,535


The Ethernet MTU deserves a little clarification. The Ethernet frame specification defines the maximum payload size as 1,500 bytes. Sometimes you find the Ethernet MTU defined as 1,518 or 1,514: the first is the maximum size of an Ethernet frame including the header, and the second includes the header but not the frame check sequence (4 bytes of checksum).

In 1998, Alteon Networks (acquired by Nortel Networks in 2000) promoted an initiative to increase the maximum payload of Ethernet frames to 9 KB. This proposal was later formalized with an IETF Internet draft, but the IEEE never accepted it. Frames exceeding the 1,500 bytes of payload in the IEEE specification are commonly called jumbo frames and are used with Gigabit Ethernet to increase throughput. This is because bigger frames mean fewer frames for large data transfers, fewer interrupts, and therefore less CPU usage, less header overhead, etc.). For a discussion of the benefits of increasing the Ethernet MTU and why IEEE does not agree on standardizing this extension, you can read the white paper "Use of Extended Frame Sizes in Ethernet Networks" that can be found with an Internet search, as well as at http://www.ietf.org/proceedings/01aug/I-D/draft-ietf-isis-ext-eth-01.txt.


unsigned short type

The category of devices to which it belongs (Ethernet, Frame Relay, etc.). include/linux/if_arp.h contains the complete list of possible types.


unsigned short hard_header_len

The size of the device header in octets. The Ethernet header, for instance, is 14 octets long. The length of each device header is defined in the header file for that device. For Ethernet, for instance, ETH_HLEN is defined in <include/linux/if_ether.h>.


unsigned char broadcast[MAX_ADDR_LEN]

The link layer broadcast address.


unsigned char dev_addr[MAX_ADDR_LEN]


unsigned char addr_len

dev_addr is the device link layer address; do not confuse it with the L3 or IP address. The address's length in octets is given by addr_len. The value of addr_len depends on the type of device. Ethernet addresses are 8 octets long.


int promiscuity

See the later section "Promiscuous mode."

2.2.2.1. Interface types and ports

Some devices come with more than one connector (the most common combination is BNC + RJ45) and allow the user to select one of them depending on her needs. This parameter is used to set the port type for the device. When the device driver is not forced by configuration commands to select a specific port type, it simply chooses a default one. There are also cases where a single device driver can handle different interface models; in those situations, the interface can discover the port type to use by simply trying all of them in a specific order. This piece of code shows how one device driver sets the interface mode depending on how it has been configured:

        switch (dev->if_port) {
        case IF_PORT_10BASE2:
            writeb((readb(addr) & 0xf8) | 1, addr);
            break;
        case IF_PORT_10BASET:
            writeb((readb(addr) & 0xf8), addr);
            break;
        }

2.2.2.2. Promiscuous mode

Certain network administration tasks require a system to receive all the frames that travel across a shared cable, not just the ones directly addressed to it; a device that receives all packets is said to be in promiscuous mode . This mode is needed, for instance, by applications that check performance or security breaches on their local network segment. Promiscuous mode is also used by bridging code (see Part IV). Finally, it has obvious value to malicious snoopers, unfortunately; for this reason, no data is secure from other users on a local network unless it is encrypted.

The net_device structure contains a counter named promiscuity that indicates a device is in promiscuous mode. The reason it is a counter rather than a simple flag is that several clients may ask for promiscuous mode; therefore, each increments the counter when entering the mode and decrements the counter when leaving the mode. The device does not leave promiscuous mode until the counter reaches zero. Usually the field is manipulated by calling the function dev_set_promiscuity.

Whenever promiscuity is nonzero (such as through a call to dev_set_promiscuity), the IFF_PROMISC bit flag of flags is also set and is checked by the functions that configure the interface.

The following piece of code, taken from the drivers/net/3c59x.c driver, shows how the different receive modes are set based on the flags (bits) in the flags field:

static void set_rx_mode(struct net_device *dev)
{
        int ioaddr = dev->base_addr;
        int new_mode;

        if (dev->flags & IFF_PROMISC) {
             if (corqscreq_debug > 3)
                        printk("%s: Setting promiscuous mode.\n", dev->name);
             new_mode = SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm;
        } else if ((dev->mc_list)  ||  (dev->flags & IFF_ALLMULTI)) {
             new_mode = SetRxFilter | RxStation | RxMulticast | RxBroadcast;
        } else
             new_mode = SetRxFilter | RxStation | RxBroadcast;

        outw(new_mode, ioaddr + EL3_CMD);
}

When the IFF_PROMISC flag is set, the new_mode variable is initialized to accept the traffic addressed to the card (RxStation), multicast traffic (RxMulticast), broadcast traffic (RxBroadcast), and all the other traffic (RxProm). EL3_CMD is the offset to the ioaddr memory address that represents where commands are supposed to be copied when interacting with the device.

2.2.3. Statistics

Instead of providing a collection of fields to keep statistics , the net_device structure includes a pointer named priv that is set by the driver to point to a private data structure storing information about the interface. The private data consists of statistics such as the number of packets transmitted and received and the number of errors encountered.

The format of the structure pointed at by priv depends both on the device type and on the particular model: thus, different Ethernet cards may use different private structures. However, nearly all structures include a field of type net_device_stats (defined in include/linux/netdevice.h) that contains statistics common to all the network devices and that can be retrieved with the method get_stats, described later.

Wireless devices behave so differently from wired devices that wireless ones do not find the net_device_stats data structure appropriate. Instead, they provide a field of type iw_statistics that can be retrieved using a method called get_wireless_stats, described later.

The data structure to which priv points sometimes has a name reflecting the interface (e.g., vortex_private for the Vortex and Boomerang series, also called the 3c59x family), and other times is simply called net_local. Still, the fields in net_local are defined uniquely by each device driver.

The private data structure may be more or less complex depending on the card's capabilities and on how much the device driver writer is willing to employ sophisticated statistics and complex design to enhance performance. Compare, for instance, the generic net_local structure used by the 3c507 Ethernet card in drivers/net/3c507.c with the highly detailed vortex_private structure used by the 3c59x Ethernet card in drivers/net/3c59x.c. Both, however, include a field of type net_device_stats.

As you will see in Chapter 8, the private data structure is sometimes appended to the net_device structure itself (requiring only one malloc for both) and sometimes allocated as a separate block.

2.2.4. Device Status

To control interactions with the NIC, each device driver has to maintain information such as timestamps and flags indicating what kind of behavior the interface requires. In a symmetric multiprocessing (SMP) system, the kernel also has to make sure that concurrent accesses to the same device from different CPUs are handled correctly. Several fields of the net_device structure are dedicated to these types of information:


unsigned long state

A set of flags used by the network queuing subsystem. They are indexed by the constants in the enum netdev_state_t, which is defined in include/linux/netdevice.h and defines constants such as _ _LINK_STATE_XOFF for each bit. Individual bits are set and cleared using the general functions set_bit and clear_bit, usually invoked through a wrapper that hides the details of the bit used. For example, to stop a device queue, the subsystem invokes netif_stop_queue, which looks like this:

static inline void netif_stop_queue(struct net_device *dev)
{
    ...
    set_bit(_ _LINK_STATE_XOFF, &dev->state);
}

The Traffic Control subsystem is briefly introduced in Chapter 11.


enum {...} reg_state

The registration state of the device. See Chapter 8.


unsigned long trans_start

The time (measured in jiffies) when the last frame transmission started. The device driver sets it just before starting transmission. The field is used to detect problems with the card if it does not finish transmission after a given amount of time. An overly long transmission means there is something wrong; in that case, the driver usually resets the card.


unsigned long last_rx

The time (measured in jiffies) when the last packet was received. At the moment, it is not used for any specific purpose, but is available in case of need.


struct net_device *master

Some protocols exist that allow a set of devices to be grouped together and be treated as a single device. These protocols include EQL (Equalizer Load-balancer for serial network interfaces), Bonding (also called EtherChannel and trunking), and the TEQL (true equalizer) queuing discipline of Traffic Control. One of the devices in the group is elected to be the so-called master, which plays a special role. This field is a pointer to the net_device data structure of the master device of the group. If the interface is not a member of such a group, the pointer is simply NULL.


spinlock_t xmit_lock


int xmit_lock_owner

The xmit_lock lock is used to serialize accesses to the driver function hard_start_xmit. This means that each CPU can carry out only one transmission at a time on any given device. xmit_lock_owner is the ID of the CPU that holds the lock. It is always 0 on single-processor systems and -1 when the lock is not taken on SMP systems. It is possible to have lockless transmissions, too, when the device driver supports it. See Chapter 11 for both the lock and the lockless cases.


void *atalk_ptr


void *ip_ptr


void *dn_ptr


void *ip6_ptr


void *ec_ptr


void *ax25_ptr

These six fields are pointers to data structures specific to particular protocols, each data structure containing parameters that are used privately by that protocol. ip_ptr, for instance, points to a data structure of type in_device (even though it is declared as void *) that contains different IPv4-related parameters, among them the list of IP addresses configured on the interface (see Chapter 19). Other sections of this book describe the fields of the data structures used by protocols covered in the book. Most of the time only one of these fields is in use.

2.2.5. List Management

net_device data structures are inserted into a global list and into two hash tables, as described in Chapter 8. The following fields are used to accomplish these tasks:


struct net_device *next

Links each net_device data structure to the next in the global list.


struct hlist_node name_hlist


struct hlist_node index_hlist

Link the net_device structure to the bucket's list of two hash tables.

2.2.6. Link Layer Multicast

Multicast is a mechanism used to deliver data to multiple recipients. Multicasting can be available both at the L3 network layer (i.e., IP) and at the L2 link layer (i.e., Ethernet). In this section, we are concerned with the latter.

Link layer multicast delivery can be achieved by using special addresses or control information in the link layer header. (When it is not supported by the link layer protocol, it may be emulated.) Ethernet natively supports multicasting: we will see in Chapter 13 how an Ethernet address can be classified as unicast, multicast, or broadcast.

Multicast addresses are distinguished from the range of other addresses by a specific bit. This means that 50% of the possible addresses are multicast, and 50% of 248 is a huge number! When an interface is asked to join a lot of multicast groups (each identified by a multicast address), it may be more efficient and faster for it to simply listen to all the multicast addresses instead of maintaining a long list and wasting time filtering ingress L2 multicast frames based on the list. One of the flags in the net_device data structure indicates whether the device should listen to all addresses. The decision about when to set or clear this flag is controlled by the all_multi field shown in this section.

Each device keeps an instance of the dev_mc_list structure for each link layer multicast address it listens to. Link layer multicast addresses can be added and removed with the functions dev_mc_add and dev_mc_delete, respectively. Relevant fields in the net-device structure include:


struct dev_mc_list *mc_list

Pointer to the head of this device's list of dev_mc_list structures.


int mc_count

The number of multicast addresses for this device, which is also the length of the list to which mc_list points.


int allmulti

When nonzero, causes the device to listen to all multicast addresses. Like promiscuity, discussed earlier in this chapter, allmulti is a reference count rather than a simple Boolean. This is because multiple facilities (VLANs and bonding devices, for instance) may independently require listening to all addresses. When the variable goes from 0 to nonzero, the function dev_set_allmulti is called to instruct the interface to listen to all multicast addresses. The opposite happens when allmulti goes to 0.

2.2.7. Traffic Management

The Traffic Control subsystem of Linux has grown quite a lot and represents one of the strengths of the Linux kernel. The associated kernel option is "Device drivers Networking support Networking options QoS and/or fair queueing." Relevant fields in the net-device structure include:


struct net_device *next_sched

Used by one of the software interrupts described in Chapter 11.


struct Qdisc *qdisc


struct Qdisc *qdisc_sleeping


struct Qdisc *qdisc_ingress


struct list_head qdisc_list

These fields are used to manage the ingress and egress packet queues and access to the device from different CPUs.


spinlock_t queue_lock


spinlock_t ingress_lock

The Traffic Control subsystem defines a private egress queue for each network device. queue_lock is used to avoid simultaneous accesses to it (see Chapter 11). ingress_lock does the same for ingress traffic.


unsigned long tx_queue_len

The length of the device's transmission queue. When Traffic Control support is present in the kernel, tx_queue_len may not be used (only a few queuing discipline use it). Table 2-2 shows the values used for the most common device types. Its value can be tuned with the sysfs filesystem (see the /sys/class/net/device_name/ directories).

Table 2-2. tx_queue_len values for different device types

Device type

tx_queue_len

Ethernet

1,000

Token Ring

100

EtherChannel

100

Fibre Channel

100

FDDI

100

TEQL (true link equalizer)a

100

ISDN

30

HIPPI

25

PLIP

10

SLIP

10

AX25

10

EQL (Equalizer load balancer for serial network interfaces)

5

Generic PPP

3

Bonding

0

Loopback

0

Bridge

0

VLAN

0

a TEQL is one of the queuing disciplines you can configure with Traffic Control (the QoS layer).


Depending on the queuing disciplinethe strategy used to queue incoming and outgoing packetsin use, tx_queue_len may or may not be used. It is usually used when the queue type is FIFO (First In, First Out) or something else relatively simple.

Note that all devices with a queue length of 0 are virtual devices: they rely on the associated real devices to do any queuing (with the exception of the loopback device, which does not need it because it is internal to the kernel and delivers all traffic immediately).

2.2.8. Feature Specific

As we saw when describing sk_buff, a few parameters are included in the definition of net_device only if the features they belong to have been included in the kernel:[]

[] The fields are actually included only when the associated feature is part of the kernel. See, for example, br_port.


struct divert_blk *divert

Diverter is a feature that allows you to change the source and destination addresses of the incoming packet. This makes it possible to reroute traffic with specific characteristics specified by the configuration to a different interface or a different host. To work properly and to make sense, diverter needs other features such as bridging. The data structure pointed to by this field stores the parameters needed by the diverter feature. The associated kernel option is "Device drivers Networking support Networking options Frame Diverter."


struct net_bridge_port *br_port

Extra information needed when the device is configured as a bridged port. The bridging code and the Spanning Tree Protocol (STP) are covered in Part IV. The associated kernel option is "Device drivers Networking support Networking options 802.1d Ethernet Bridging."


void (*vlan_rx_register)(...)


void (*vlan_rx_add_vid)(...)


void (*vlan_rx_kill_vid)(...)

These three function pointers are used by the VLAN code to register a device as VLAN tagging capable (see net/8021q/vlan.c), add a VLAN to the device, and delete the VLAN from the device, respectively. The associated kernel option is "Device drivers Networking support Networking options 802.1Q VLAN Support."


int netpoll_rx


void (*poll_controller)(...)

Used by the optional Netpoll feature that is briefly mentioned in Chapter 10.

2.2.9. Generic

In addition to the list management fields of the net_device structure discussed earlier, a few other fields are used to manage structures and make sure they are removed when they are not needed:


atomic_t refcnt

Reference count. The device cannot be unregistered until this counter has gone to zero (see Chapter 8).


int watchdog_timeo


struct timer_list watchdog_timer

Along with the tx_timeout variable discussed earlier, these fields implement the timer discussed in the section "Watchdog timer" in Chapter 11.


int (*poll)(...)


struct list_head poll_list


int quota


int weight

Used by the NAPI feature described in Chapter 10.


const struct iw_handler_def *wireless_handlers


struct iw_public_data *wireless_data

Additional parameters and function pointers used by wireless devices. See also get_wireless_stats.


struct list_head todo_list

The registration and unregistration of a network device is done in two steps. todo_list is used to handle the second one. See Chapter 8.


struct class_device class_dev

Used by the new generic kernel driver infrastructure.

2.2.10. Function Pointers

We saw in Chapter 1 that the networking code makes heavy use of function pointers . The net_device data structure includes quite a few of them. Such functions are used mainly to:

  • Transmit and receive a frame

  • Add or parse the link layer header on a buffer

  • Change a part of the configuration

  • Retrieve statistics

  • Interact with a specific feature

A few function pointers were already introduced in the previous sections when describing the fields used to accomplish a specific task. Here are the generic ones:


struct ethtool_ops *ethtool_ops

Pointer to a set of function pointers used to set or get the configuration of different device parameters. See the section "Ethtool" in Chapter 8.


int (*init)(...)


void (*uninit)(...)


void (*destructor)(...)


int (*open)(...)


int (*stop)(...)

Used to initialize, clean up, destroy, enable, and disable a device. Not all of them are always used. See Chapter 8.


struct net_device_stats* (*get_stats)(...)


struct iw_statistics* (*get_wireless_stats)(...)

Some statistics collected by the device driver can be displayed with user-space applications such as ifconfig and ip, and others are strictly used by the kernel and are discussed in the section "Device Status" earlier in this chapter. These two methods are used to collect statistics. get_stats operates on a normal device and get_wireless_stats on a wireless device. See also the earlier section "Statistics."


int (*hard_start_xmit)(...)

Used to transmit a frame. See Chapter 11.


int (*hard_header)(...)


int (*rebuild_header)(...)


int (*hard_header_cache)(...)


void (*header_cache_update)(...)


int (*hard_header_parse)(...)


int (*neigh_setup)(...)

Used by the neighboring layer. See the sections "Methods Provided by the Device Driver" and "Neighbor Initialization" in Chapter 27.


int (*do_ioctl)(...)

ioctl is the system call used to issue commands to devices (see Chapter 3). This method is called to process some of the ioctl commands (see Chapter 8).


void (*set_multicast_list)(...)

We have already seen in the section "Link Layer Multicast" that mc_list and mc_count are used to manage the list of L2 multicast addresses. This method is used to ask the device driver to configure the device to listen to those addresses. Usually it is not called directly, but through wrappers such as dev_mc_upload or its lockless version, _ _dev_mc_upload. When a device cannot install a list of multicast addresses, it simply enables all of them.


int (*set_mac_address)(...)

Changes the device MAC address. When the device does not provide this capability (as in the case of Bridge virtual devices), it is set to NULL.


int (*set_config)(...)

Configures driver parameters, such as the hardware parameters irq, io_addr, and if_port. Higher-layer parameters (such as protocol addresses) are handled by do_ioctl. Not many devices use this method, especially among the new devices that are better able to implement probe functions. A good example with some documentation can be found in sis900_set_config in drivers/net/sis900.c.


int (*change_mtu)(...)

Changes the device MTU (see the description of mtu in the earlier section, "Configuration"). Changing this field has no effect on the device driver but simply forces the kernel software to respect the new MTU and to handle fragmentation accordingly.


void (*tx_timeout)(...)

The method invoked at the expiration of the watchdog timer, which determines whether a transmission is taking a suspiciously long time to complete. The watchdog timer is not even started unless this method is defined. See the section "Watchdog timer" in Chapter 11 for more information.


int (*accept_fastpath)(...)

Fast switching (also called FASTROUTE) was a kernel feature that allowed device drivers to route incoming traffic during interrupt context using a small cache (bypassing all the software layers). Fast switching is no longer supported, starting with the 2.6.8 kernel. This method was used to test whether the fast-switching feature could be used on the device.


Previous Page
Next Page