노무현 대통령 배너


2006. 3. 28. 10:23

[본문스크랩] net_device구조체

이 구조체는 크게 두 가지로 나뉘는데, 첫 번째는 보이는(visible)필드와 숨겨진(hidden)필드이다.
보이는 필드는 그냥 static구조체에 명시적으로 값을 할당할 수 있는 필드들로 구성된다.
(the visible part of the structure is made up of the fields that can be explicitly assigned in static net_device structure )

보이는 필드는 우리가 신경 써야 되는 부분이며, 숨겨진 필드는 커널에서 내부적으로 사용되는 것이다.

========================================================================================
먼저 보이는 필드를 살펴보자.
 

char name[IFNAMSIZ];

이것은 장치의 이름을 지칭한다.

>>>> net_device dev_get_by_name(const char *name)...참고..^^;;


예를 들어 인터넷장치로 sn0, sn12등을 보았을 것이다. 여기에 %d를 넣으면 0부터 장치이름이 지어진다. 즉 "sn%d"로 한다면 맨 첫 번째 장치는 sn0가 되고 그 다음이 sn1이 된다.


/*
* I/O specific fields
* FIXME: Merge these and struct ifmap into one
*/
unsigned long rmem_end; /* shmem "recv" end */
unsigned long rmem_start; /* shmem "recv" start */
unsigned long mem_end; /* shared mem end */
unsigned long mem_start; /* shared mem start */

장치가 사용하는 메모리 정보이다. 만약 패킷을 받을 때 사용되는 rx와 패킷을 보낼 때 사용하는 tx에서 다른 영역이 할당되었다면 rmem_ 은 rx를 의미하고 mem_은 tx를 의미한다.
mem_start, mem_end는 부팅할 때 명령어 라인에서 지정할 수 있으며, 그값은 ifconfig로서 확인할 수 있다. end - start함으로서 사용되는 메모리를 확인할 수 있다.

-------------------------------------------------------------------

ifconfig의 맨 페이지에 다음과 같은 설명이 나온다.
mem_start addr
Set the start address for shared memory used by this device.
Only a few devices need this.
즉, mem_start를 이용해 ifconfig에서 값을 변경할 수 있다는 것이다.

-------------------------------------------------------------------

unsigned long base_addr; /* device I/O address */
랜카드가 사용하는 I/O 주소이다. 이것도 ifconfig로 확인 가능하다.

unsigned int irq; /* device IRQ number */
할당된 인터럽트 번호이다. ifconfig로 확인 가능하다.

unsigned char if_port ;
이것은 두 개 이상의 포트가 있는 랜카드의 경우 어느 것이 사용되는가를 나타낸다.

unsigned char dma ;
장치에 할당된 dma채널이다. 이것은 isa의 경우에 쓰이며 pci는 안 쓰인다.

unsigned long state ; 장치의 상태이다.
이 값은 보통 직접 접근하여 수정하지 않고, 이 값을 관리하는 함수가 따로 존재한다.

struct net_device *next ;
네트워크장치는 전역 리스트로 관리된다. 이것은 그 전역리스트에서 다음 장치를 지칭한다. 이것은 수정되어서는 안 된다.

int (*init)(struct net_device *dev)
초기화 함수이다.

 

======================================================

이제 숨겨진 필드들을 살펴보도록 하자.

일반적으로 이 필드들은 드라이버를 초기화할 때 할당된다.

unsigned mtu ;
maximum transfer unit(MTU)이다.
이것은 network layer에서 사용되는 것이다.

즉, IP layer 에서의 패킷의 크기를 제한하는데 인터넷의 경우 1500이다.
그렇다면 실제적으로 네트워크라인상에 보내지는 패킷의 최대크기는 몇일까?
mtu(1500) + ethernet header(14) + pad(4) = 1536이다.

 
unsigned long tx_queue_len ;
장치의 전송 큐에 넣을 수 있는 최대한의 프레임 수이다. 이 값은 인터넷의 경우 100으로 할당되어있으나, 변경할 수도 있다.

---------------------------------------------------------------------------------
ifconfig로 확인 가능하다.

eth0 Link encap:Ethernet HWaddr 00:50:FC:0C:ff:ff
...
collisions:0 txqueuelen:100
Interrupt:5 Base address:0xac00

---------------------------------------------------------------------------------

unsigned char addr_len ;
unsigned char broadcast[MAX_ADDR_LEN];
unsigned char dev_addr[MAX_ADDR_LEN


addr_len은 주소의 길이로 인터넷의 경우 6 옥텟(octets)이다. broadcast는 6개의 옥텟이 0xff로 채워짐으로써 이뤄진다. dev_addr 하드웨어 주소를 나타내는 것으로 이 값은 랜카드 마다 고유하게 갖고 있게 되며, 모듈초기화시 랜카드의 EEPROM에서 읽어오게 된다.

unsigned short flags ;
이 플래그는 각각의 장치의 독특한 속성을 지정하게 된다. 앞에 IFF_라는 prefix가 있으며, 에 모두 선언되어있다.몇몇은 커널에 의해 내부적으로 사용되고,몇몇은 초기화 시 사용된다.
다음과 같은 값들이 가능하다.

 
/* Standard interface flags. */
#define IFF_UP 0x1 /* interface is up */
#define IFF_BROADCAST 0x2 /* broadcast address valid */
#define IFF_DEBUG 0x4 /* turn on debugging */
#define IFF_LOOPBACK 0x8 /* is a loopback net */
#define IFF_POINTOPOINT 0x10/* interface is has p-p link */
#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */
#define IFF_RUNNING 0x40 /* resources allocated */
#define IFF_NOARP 0x80 /* no ARP protocol */
#define IFF_PROMISC 0x100 /* receive all packets */
#define IFF_ALLMULTI 0x200/* receive all multicast packets*/

#define IFF_MASTER 0x400 /* master of a load balancer */
#define IFF_SLAVE 0x800 /* slave of a load balancer */

#define IFF_MULTICAST 0x1000 /* Supports multicast */
#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT
|IFF_BROADCAST|IFF_MASTER

|IFF_SLAVE|IFF_RUNNING)

#define IFF_PORTSEL 0x2000 /* can set media type */
#define IFF_AUTOMEDIA 0x4000 /* auto media select active */
#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/

 

IFF_PROMISC:
이것은 자기의 하드웨어 주소에 해당하는 패킷 뿐 아니라 랜에 돌아다니는 모든 패킷을 잡는 것이다. tcpdump는 이 플래그를 이용하여 패킷을 모두 잡는다.

IFF_MULTICAST:
멀티캐스트 패킷을 보내는 것을 가능하게 한다. 이것은 디폴트로 "허용"이므로 만일 멀티캐스트 패킷을 보내지 못하도록 하려면, 초기화 시 이 플래그를 꺼주어야 한다.

IFF_ALLMULTI:
모든 멀티캐스트 패킷을 받도록 한다. 커널은 해당 호스트가 멀티캐스트 라우팅을 할 때, IFF_MULTICAST가 켜져 있는 때에 한하여 이 플래그를 세팅 한다. 이 값은 read-only이다.

 

이러한 플래그들이 수정되면 제일먼저 net_device의 set_multicase_list가 실행된다.그러므로 플래그가 변경되었을 때 실행돼야 할 작업이 있다면 set_multicast_list에 넣도록 한다.

========================================================================================

이제 net_device필드들 중에서 함수들을 살펴보도록 하자.

블록이나 문자장치와 같이 네트워크장치도 장치를 다루는 여러 가지 함수들이 존재한다. 문자나 블록장치는 file_operations구조체에 이 값들을 세팅 하나, 네트워크장치는 net_device구조체에 세팅한다. 이 값들 중 어떤 값은 NULL로 세팅 할 수도 있다.

int (*open)(struct net_device *dev);
ifconfig eth0 up 과 같은 명령을 했을 때 실행되는 함수이다.
여기서는 I/O ports , IRQ, DMA등의 리소스를 등록, usage count증가 등의 작업을 한다.

 
int (*stop)(struct net_device *dev);
ifconfig eth0 down과 같은 명령을 했을 때 실행되며, open에서 할당 받은 리소스들을 반납하는 작업등을 한다.

int (*hard_start_xmit)(struct sk_buff *skb, struct net_device *dev);
패킷을 외부로 전송하기 위한 초기화 작업을 실행한다. 외부로 보내질 모든 데이터는 sk_buff구조체에서 관리한다.

void (*tx_timeout)(struct net_device *dev);
패킷을 전송하는 것에 대한 timeout이다. 즉, 설정된 시간만큼 기다렸는데, 패킷이 전송되지 못했다면, 재전송 등, 어떠한 작업을 해주어야 한다.

struct net_device_stats *(*get_stats)(struct net_device *dev );
장치에 대한 정보를 요청할 때 이 함수가 실행된다.

예를 들어...ifconfig, netstat -i 등이 되겠다.

int (*do_ioctl)(struct net_device *dev, struct ifreg *ifr, int cmd);
ioctl명령어 사용하지 않으려면 NULL로 지정해도 상관없다.

void (*set_multicast_list)(struct net_device *dev);
네트워크장치에 대한 멀티캐스트 리스트(multicast list)가 변경되었거나 플래그가 변경되었을 때 실행된다.

========================================================================================

TIME)


unsigned long trans_start ;
unsigned long last_rx ;
trans_start는 전송을 전송한 시간을 jiffies값으로 갖고 있고, last_rx는 가장 최근에 패킷을 받은 시간을 jiffies값으로 갖고 있다.

int watchdog_timeo ;
이 값도 jiffies값으로 지정되며, 이 시간 동안 전송되지 못했다면, tx_timeout 함수가 실행된다.

void *priv ;
장치의 private 데이터를 저장하는 곳이다.


struct dev_mc_list *mc_list ;
int mc_count ;

이 두개의 필드는 멀티캐스트 전송을 관리하는데 사용된다.

여기서 설명하지 않은 net_device 필드들이 많이 있지만, 그것들은 네트워크 드라이버에 사용되지 않는다.