sk_buff 구조체

2008. 6. 17. 10:16



네트워크 디바이스 드라이버가 패킷을 받게되면 인터럽트가 발생한다. 인터럽트 함수가 패킷의 도착시에 호출되며 디바이스의 레지스터 상태를 확인해서 이것이 RX(receive)인 경우에 netif_rx()함수를 호출 해서 네트워크의 패킷이 도착했음을 상위에 알려준다.

sk_buff구조체는 소켓연결에서 사용하는 구조체로 사용자의 데이터와 각종 프로토콜의 정보를 담는데 쓰인다. 커널내에서 메모리간의 복사(copy) 횟수를 줄여주며, 각각의 프로토콜에서 자신만의 정보를 나타내기에
용이한 점이 있다. -> 네트워크로 전송되는 패킷을 나타내는 구조체

http://www.zdnet.co.kr/builder/platform/nix/0,39031679,39136665,00.htm

Field Description
struct sk_buff *next, *prev sk_buff list의 다음과 이전을 가리키는 포인터
struct sk_buff_head *list 현재 sk_buff가 속한 sk_buff_head에 대한 포인터
struct sock *sk 현재 sk_buff를 사용하는 INET sock에 대한 포인터
struct timeval stamp sk_buff가 도착한 시간
struct net_device *dev 받거나 보내는 Network device의 구조체에 대한 포인터(Network device driver를 참고)
union{} h Transport layer(INET아래에 있는 layer) 들의header정보
union{} nh Network layer(Transport layer아래에 있는 layer)들의 header정보
union{} mac Mac layer(Medium Access Control: Link layer –Network layer아래에 있는 layer) 의 header정보
struct dst_entry 목적지 주소의 entry에 대한 포인터
char cb[48] Control buffer( 모든 layer에서 사용가능하다.)
unsigned int len 실제 데이터의 길이
unsigned int csum Checksum
volatile char used 데이터가 사용자에게 넘어갔음을 나타냄
unsigned char cloned sk_buff_head가 clone(복제)되었음을 나타냄
unsigned char pkt_type 패킷의 타입
unsigned char ip_summed IP checksum으로 driver가 제공함
__u32 priority 패킷의 queueing 우선순위
atomic_t users 패킷의 사용자 카운트
unsigned short protocol 드라이버로부터 받은 패킷의 프로토콜
unsigned short security 패킷의 보안 레벨
unsigned int truesize 버퍼의 실제 크기
unsigned char *head 데이터 버퍼의 head를 가리키는 포인터
unsigned char *data 데이터 버퍼의 데이터 부분을 가리키는 포인터
unsigned char *tail 데이터 버퍼의 데이터 마지막 부분을 가리키는 포인터
unsigned char *end 데이터 버퍼의 마지막을 가리키는 포인터
void (*destructor)(struct sk_buff) sk_buff 구조체를 없애는 함수에 대한 포인터
... 나머지 커널의 구성(configuration)에 따른 변수들

struct sk_buff_head {
/* These two members must be first. */
struct sk_buff * next;
struct sk_buff * prev;
__u32 qlen;
spinlock_t lock;
};

Rx Controller
현재 IP Protocol이 receive 구조를 살펴보면 Device Driver에서 Interrupt를 받고 status를 확인해 Data를 받은 status면 Data를 Device 에서 가져오고 socket buffer에 넣어netif_rx() 함수를 호출하여 socket buffer를 현재 CPU의 softnet_data 구조체의 input_pkt_queue에 넣고, dev structure의 poll_list 정보를 softnet_data structure의 poll_list에 추가한 후 NET_RX_SOFTIRQ를 발생시킨다. 나머지 부분은 softirq로 처리하며 이에 대한 처리는 <net/core/dev.c>에 정의된 net_rx_action() 함수가 맡고 있다

이와 같이 softirq를 발생시켜 후 처리를 IP Stack 에서 하도록 설계 되어 있다.

int netif_rx(struct sk_buff *skb)
{
        struct softnet_data *queue;
        unsigned long flags;

        /* if netpoll wants it, pretend we never saw it */
        if (netpoll_rx(skb))
                return NET_RX_DROP;

        if (!skb->tstamp.off_sec)
                net_timestamp(skb);

        /*
         * The code is rearranged so that the path is the most
         * short when CPU is congested, but is still operating.
         */
        local_irq_save(flags);
        queue = &__get_cpu_var(softnet_data); //받은패킷들을 저장할 CPU에 배정된 큐

        __get_cpu_var(netdev_rx_stat).total++;
        if (queue->input_pkt_queue.qlen <= netdev_max_backlog) {
                if (queue->input_pkt_queue.qlen) {
enqueue:
                        dev_hold(skb->dev);
                        __skb_queue_tail(&queue->input_pkt_queue, skb);
                        local_irq_restore(flags);
                        return NET_RX_SUCCESS;
                }

                netif_rx_schedule(&queue->backlog_dev);
                goto enqueue;
        }

        __get_cpu_var(netdev_rx_stat).dropped++;
        local_irq_restore(flags);

        kfree_skb(skb);
        return NET_RX_DROP;
}

local_irq_save() 함수를 알기전에 cli()라는 함수를 알아야 합니다.

cli 는 clear Interrupt 의 약자로서 CPU 가 interrupt signal을 받더라도
이를 무시하도록 하는 것입니다. 하드웨어 인터럽트와 소프트웨어 모두다
입니다.

이를 통해 synchronization 문제를 해결합니다.
data corruption 을 막는 거죠.

cli 로 critical region 을 보호한 후 sti 로 interrupt signal 받아들이도록
세팅해주어야 합니다.

문제는 sti 로 인터럽트를 받아들이기로 세팅하면 cli 호출
전에 인터럽트를 받아
들이기로 한것인지 아닌지를 깡그리 무시한채 sti 세팅합니다.
cli 호출 전에 인터럽트를 받아들이는 상태였다면 다행이지만
인터럽트 무시 상태였다면 sti 호출후 상태가 틀려지게 되죠.
즉 cli 함수 사용전의 인터럽트 관련 세팅 상태가 원상복귀
되지 않는거죠.

그래서 사용하는 것이 local_irq_save() 함수 입니다.

패러미터로 들어가는
flag 변수(스택에 존재)에
현재 인터럽트 관련 플래그를 저장하는 IF 라는 레지스터
정보를 저장합니다.

cli 가 sti 와 짝을 이루듯 local_irq_save 는 local_irq_restore 와
짝을 이룹니다. local_irq_restore 함수가 호출되면서
flag 변수에 저장되었던 것을
다시 IF 레지스터에 넣는거죠.

그러면 local_irq_save 전의 인터럽트 관련 세팅 상태로 원상복귀됩니다.


printk

http://wiki.kldp.org/wiki.php/UnreliableGuideToHackingTheLinuxKernel#s-6.1


아래의 리스트는 netdev_max_backlog - 네트워크 패킷의 전체 갯수 (보통 300) - 와 같은 일반적인 네트워크 설정을 보여준다. 이 값은 패킷을 받을 때 네트워크의 BandWidth 를 제한할 수 있다. 리눅스는 버퍼를 비우기 위해 스케줄링이 일어날 때 까지 기다려야 한다 (bottom half 메카니즘에 의해 처리). 1000/HZ ms 일 때

  300    *        100             =     30 000
packets     HZ(Timeslice freq)         packets/s
 
30 000   *       1000             =      30 M
packets     average (Bytes/packet)   throughput Bytes/s
	  

만약 더 높은 throughput 을 원한다면 netdev_max_backlog 을 다음과 같이 증가시킬 수 있다:

echo 4000 > /proc/sys/net/core/netdev_max_backlog

참고: HZ 값에 주의하기 바란다: (alpha 나 arm-tbox 같은) 특정 환경에서는 이 값이 1000 으로 설정되어 있기 때문에 평균 300 MBytes/sec 의 throughput 이 나온다.

http://mindeater.tistory.com/282 netif_rx

http://www.ibm.com/developerworks/kr/library/l-linux-networking-stack/  리눅스 네트워킹 스택분석

http://www.wegra.org/products/network/contents/UDP%20Analysis.pdf udp 분석

http://kernelstudy.net/3  cpu별 변수 사용

http://www.zdnet.co.kr/builder/platform/nix/0,39031679,39136665,00.htm 네트워크 서브시스템

http://vger.kernel.org/~davem/skb.html 리눅스커널




'Sabzil' 카테고리의 다른 글

ABI (Application Binary Interface)  (0) 2009.03.17
Nefif_rx  (0) 2009.03.17
usleep에 대해서  (0) 2009.01.08
strtok_r  (0) 2008.09.29
this is RAM  (0) 2008.08.21
nit_if.h  (0) 2008.07.17
about ftp  (0) 2008.07.15
amd64 and x86 endian order  (0) 2008.06.23
glibc-2.5/elf/dl-runtime.c 코드 분석을 통한 lazy binding 재배치 방식 분석  (0) 2008.06.23
xss in 엠파스 게시판  (0) 2008.06.22

badcob Sabzil

Programming - 2. Are you fast enough?

2008. 6. 13. 02:19
Question:

This challenge is a simple calculation.
When you click on the link below you will get a number.
The calculation is: answer = (number * 3 + 2) - 250

Example with number 1500:
4252 = (1500 * 3 + 2) - 250

In this example 4252 is the answer...answer like this: prog2.php?solution=4252
You must do this within 2 seconds. If the answer is correct, you will get the password.


answer: 
             처음엔 걍 c로 만들어서 2초안에 넣어볼라고 쇼를 했다.
             내타수가 그렇게 느린줄 몰랐다. 세상에 만만한거 하나 없더라.
             뭘로 해볼까 하다가 만만한 자바 스크립트로 했는데 막상 해볼려니
             이것 또한 시간을 꽤나 잡아먹었다.

<html>
<head>
<script>
function calc(){
str1 = myform.solution.value;
answer = (str1 * 3 + 2) - 250;
myform.solution.value = answer;
return;
}
</script>
</head>
<body>
<form name="myform" method="get" action="http://net-force.nl/challenge/level602/prog2.php" onsubmit="calc()">
Number: <input type=text name=solution><br>
<input type=submit value=전송>
</form>
</body>
</html>

       
The password is: damnfast

'War game > net-force.nl' 카테고리의 다른 글

Programming - 1. keep walking...  (0) 2008.06.12

badcob War game/net-force.nl

Programming - 1. keep walking...

2008. 6. 12. 16:52

Question :

This is a challenge to test your basic programming skills.

Pseudo code:
Set X = 1
Set Y = 1
Set previous answer = 1

answer = X * Y + previous answer + 3

After that => X + 1 and Y + 1 ('answer' becomes 'previous answer') and repeat this till you have X = 525.

The final answer is the value of 'answer' when X = 525. Fill it in below to check if it's the correct answer. If it is, you will get the password for the challenge page.


answer :

#include <stdio.h>

void main(void)
{
 int x=1, y=1;
 int answer = 1;
 
 for(;x<526;)
 {
 answer = (x++) * (y++) + answer + 3;
  if(x==524)
  printf("\nprevious answer = %d", answer);
 }
 printf("\nx=%d, y=%d\nanswer = %d",x,y,answer);
 return;
 }

enter : 48373851

Nice one, the password is: pr0ggen

'War game > net-force.nl' 카테고리의 다른 글

Programming - 2. Are you fast enough?  (0) 2008.06.13

badcob War game/net-force.nl