このドキュメントで説明するソフトウェアは、Extended SupportまたはSustaining Supportのいずれかにあります。 詳細は、https://www.oracle.com/us/support/library/enterprise-linux-support-policies-069172.pdfを参照してください。
Oracleでは、このドキュメントに記載されているソフトウェアをできるだけ早くアップグレードすることをお薦めします。
ネットワーク・デバイス・ドライバは、外部のシステムに接続するハードウェア・インタフェース上でデータ・パケットを送受信し、ネットワーク・プロトコルでアクセス可能な統一されたインタフェースを提供します。 Oracle Linuxでは、これらのドライバは、基礎となるレイヤー1プロトコルとレイヤー2プロトコルを隠蔽するネットワーク・アダプタ自体のハードウェア実装から抽象化されます。
ブロック・ドライバの
ルーチンと同様に、ネットワーク・ドライバのコールバック・ルーチンのほとんどをカーネルに登録して、ネットワーク・ポートでのデータ着信時またはカーネルがネットワーク・ポート上でデータを送信する必要があるときに、カーネルがこれらのルーチンを実行できるようにする必要があります。 文字ドライバと同様に、ネットワーク・ドライバは物理的にアドレス可能なストレージ・メディアにはアクセスしません(またはファイル・システム・アクセスをサポートしません)。 ブロック・デバイス・ドライバや文字デバイス・ドライバと異なり、ネットワーク・ドライバはdriver_
request()/dev
にデバイス・ファイルを持ちません。 かわりに、ユーザーがnet_device
構造体を使用してネットワーク・インタフェースの機能を定義し、ipなどのコマンドを使用してインタフェースを構成したときに、カーネルがこの構造体のメンバーを更新します。
ネットワーク・デバイス・ドライバの実装は、LinuxとUNIXオペレーティング・システム間において様々な点で異なる場合があり、相違点のほとんどは、ドライバがネットワーク・リクエストの処理に使用する関数、ネットワーク・ドライバのメソッドの表現やネットワーク・インタフェースのプロパティの定義に使用される構造体、およびネットワーク・キューを処理するためのカーネル・インタフェース・ルーチンに関するものです。
UNIXネットワーク・ドライバがデバイスの割込みを処理したり、ネットワーク・デバイスからの着信データをアップストリーム・プロトコル・モジュールに転送する場合に使用する
ルーチンとdriver_
int()
ルーチンは、Linuxシステムでは通常driver_
svr()
およびdriver_
interrupt()
と呼ばれます。 driver_
rx()
メソッドはdriver_
rx()netif_rx()
をコールしてソケット・バッファをアップストリーム・モジュールに渡します。
UNIXネットワーク・デバイス・ドライバがネットワーク・デバイス上でデータの送信に使用する
ルーチンは、Linuxシステムのdriver_
put()ndo_start_xmit()
メソッドに相当します。 このメソッドは、次のユーティリティ関数を使用して送信ソケット・バッファのアップストリーム・キューを制御できます。
-
netif_queue_stopped()
キューが現在停止しているかどうかをカーネルに問い合せます。
-
netif_start_queue()
ドライバがパケット送信を開始できる状態にあることをカーネルに通知します。
-
netif_stop_queue()
送信バッファがフルになったときにパケット送信の停止を、またはデバイスのクローズ時にドライバのクリーンアップをカーネルに要求します。
-
netif_wake_queue()
現在停止中のキューをウェイクアップして、パケット送信を再開するようにカーネルに要求します。
ネットワーク・パケットが正常に送信されると、
がdriver_
interrupt()
ルーチンをコールし、これによりソケット・バッファ・データのドライバのコピーが削除されます。
driver_
tx
<linux/netdevice.h>
に定義されたネットワーク・デバイスのnet_device_ops
構造体には、システムがデバイスとやり取りする方法を指定する一連のメソッド・ポインタが含まれます。
struct net_device_ops { int (*ndo_init)(struct net_device *dev); void (*ndo_uninit)(struct net_device *dev); int (*ndo_open)(struct net_device *dev); int (*ndo_stop)(struct net_device *dev); netdev_tx_t (*ndo_start_xmit) (struct sk_buff *skb, struct net_device *dev); u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb); void (*ndo_change_rx_flags)(struct net_device *dev, int flags); void (*ndo_set_rx_mode)(struct net_device *dev); void (*ndo_set_multicast_list)(struct net_device *dev); int (*ndo_set_mac_address)(struct net_device *dev, void *addr); int (*ndo_validate_addr)(struct net_device *dev); int (*ndo_do_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd); int (*ndo_set_config)(struct net_device *dev, struct ifmap *map); int (*ndo_change_mtu)(struct net_device *dev, int new_mtu); int (*ndo_neigh_setup)(struct net_device *dev, struct neigh_parms *); void (*ndo_tx_timeout) (struct net_device *dev); struct rtnl_link_stats64* (*ndo_get_stats64)(struct net_device *dev, struct rtnl_link_stats64 *storage); struct net_device_stats* (*ndo_get_stats)(struct net_device *dev); void (*ndo_vlan_rx_register)(struct net_device *dev, struct vlan_group *grp); void (*ndo_vlan_rx_add_vid)(struct net_device *dev, unsigned short vid); void (*ndo_vlan_rx_kill_vid)(struct net_device *dev, unsigned short vid); /* Several lines omitted */ };
単純なネットワーク・デバイス・ドライバであれば、次のように、この構造体に定義された関数のサブセットを実装するだけで作成できる場合があります。
struct net_device_opsdriver_netdevops
= { .ndo_init =driver_init
, .ndo_open =driver_open
, .ndo_stop =foo_close
, .ndo_start_xmit =foo_start_xmit
, .ndo_do_ioctl =foo_ioctl
, .ndo_tx_timeout =foo_tx_timeout
, };
カーネルは、ネットワーク・インタフェースを起動してアドレスを割り当てる際にndo_open()
を、インタフェースの停止時にndo_stop()
を、パケットの送信時にndo_start_xmit()
をそれぞれコールします。
<linux/netdevice.h>
に定義された文字デバイスのnet_device
構造体では、ネットワーク・インタフェースのプロパティを定義します。
net_device
構造体の最も重要なメンバーを次に示します。
-
dev_addr
ハードウェアのメディア・アクセス制御(MAC)アドレス。
-
features
デバイスがサポートしている機能を表すビット・マスク。
-
flags
次に示すような、デバイスの現在のプロパティを表します。
-
IFF_BROADCAST
broadcastモードが有効です。
-
IFF_LOOPBACK
インタフェースはループバック・デバイスに対応します。
-
IFF_MULTICAST
multicastモードが有効です。
-
IFF_NOARP
インタフェースではアドレス解決の実行にARPを使用しません。 このフラグは通常、ポイント・ツー・ポイント・インタフェースによって設定されます。
-
IFF_PROMISC
promiscuousモードが有効です。
-
IFF_UP
インタフェースが有効です。 ドライバではこのフラグを設定しません。 ipなどのアプリケーションを使用してインタフェースを起動または停止すると、カーネルは
ndo_open()
メソッドまたはndo_stop()
メソッドを呼び出してフラグを設定/設定解除し、インタフェースの状態を示します。
-
-
irq
割込み要求(IRQ)番号。
-
mtu
最大転送単位(MTU)。デバイスが送信可能な最大フレーム・サイズのことです。
-
name
インタフェースの名前(
eth0
、lo0
など)。-
netdev_ops
インタフェースのメソッドを定義する
net_device_ops
構造体へのポインタ。-
promiscuity
インタフェースをpromiscuousモードに設定しているクライアント・アプリケーションの数を示すカウンタ。
-
stats
インタフェース使用率の統計が含まれる
net_device_stats
構造体。
などのドライバ・メソッドや関連するヘルパー・ルーチンと同様に、ドライバのロード/アンロード時にコールされるドライバ用のdriver_
interrupt()module_init()
初期化ルーチンとmodule_exit()
クリーンアップ・ルーチンを定義するのが一般的です。 これらのルーチンはregister_netdev()
およびunregister_netdev()
をコールして、デバイスを登録/登録解除し、alloc_netdev()
およびfree_netdev()
をコールして、デバイスのカーネル表現を割当て/削除します。 イーサネット・デバイスの場合、alloc_netdev()
のかわりにalloc_etherdev()
をコールするのが一般的です。 ドライバを初期化する場合、request_irq()
を使用して割込みハンドラをインストールしますが、その際、flags
引数のSA_SHIRQ
ビットと、一意のdev_id
(ハンドラはこれを使用して、処理する必要のある割込みを特定できます)を設定して、共有割込みを必ず指定してください。 クリーンアップ・ルーチンではfree_irq()
をコールしてハンドラを登録解除します。