Nefif_rx

2009. 3. 17. 17:06

*Netif_rx*

 

네트워크로부터 디바이스가 패킷을 수신했을 경우 커널에게 이를 알려주어야 한다. 패킷을 수신 하면 인터럽트가 발생하며 이 처리는 디바이스 드라이버가 맡는다. 드라이버는 지정된 커널 영역 메모리에 패킷을 복사한 후 커널로 처리과정을 넘기게 된다.

 

int netif_rx(struct sk_buff *skb)

{

        struct softnet_data *queue; //수신되는 패킷들을 저장해두는 큐로 사용, cpu에 하나씩

        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);

 

local_irq_save(flags);

/*인터럽트가 발생하지 않도록 파라미터로 들어가는 flags변수에 현재 인터럽트 관련 플래그가 저장된 IF 레지스터 정보를 저장한다,*/

        queue = &__get_cpu_var(softnet_data);

           // 받은 패킷들을 저장할 각각의 CPU에 큐를 배정

/ /cpu별 변수(per-CPU variable) get_cpu_var : 커널선점기능을 금지하며 cpu당 배열에서          //지역 cpu의 요소를 선택한다

 


   __get_cpu_var(netdev_rx_stat).total++;  //
cpu에 수신된 총 패킷수 증가

        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);

//queue의 끝에 패킷을 집어 넣는다

                        local_irq_restore(flags);

// local_irq_save 전의 인터럽트 관련 세팅 상태로 원상복귀

                        return NET_RX_SUCCESS; //cpu 상태 반환 : no congestion

                }

 

                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;

}

 

static inline void netif_rx_schedule(struct net_device *dev)

{

        if (netif_rx_schedule_prep(dev))

                __netif_rx_schedule(dev);

}

 

static inline void __netif_rx_schedule(struct net_device *dev)

{

        unsigned long flags;

 

        local_irq_save(flags);

        dev_hold(dev);

        list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);

        if (dev->quota < 0)

                dev->quota += dev->weight;

        else

                dev->quota = dev->weight;

        __raise_softirq_irqoff(NET_RX_SOFTIRQ); //네트워크카드에서 패킷을 수신

/*cpu softirq NET_RX_SOFTIRQ만큼 raise(pending)시킨 후 cpu local irqbottom

half의 카운트가 모두 0일 경우 softirq daemon을 활성화 시킨다 */

        local_irq_restore(flags);

}

'Sabzil' 카테고리의 다른 글

Shellcode site  (0) 2009.09.29
hey JJAAPPPHH ~  (4) 2009.08.17
hey JaPH  (1) 2009.08.12
6회 kisa 해킹방어대회 6번  (0) 2009.07.09
ABI (Application Binary Interface)  (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

badcob Sabzil