데이터 송수신 및 통계정보와 관련된 함수에 대하여 알아 보도록 하겠습니다.

 // 고 수준의 재진입을 하지 못하도록 하는 것을 다룹니다. ( 이것은 바텀할프가 비활성화 되는동안에 호출 됩니다.)

static netdev_tx_t loopback_xmit(struct sk_buff *skb, struct net_device *dev)

{

        struct pcpu_lstats __percpu *pcpu_lstats;

        struct pcpu_lstats *lb_stats;

        int len;


        // 소켓 버퍼의 owner가 가진 destructor함수가 존재할 경우 이를 호출해주며, 

        // 소켓 버퍼의 owner를 없애주는 역할을 하는 함수이다.

        skb_orphan(skb); 


        // eth_type_trans()함수는 패킷의 타입을 결정 하고, 프로토콜의 ID를 넘긴다. 

        // 리턴값을 이용 하여 소켓 버퍼의 protocol 값을 설정 하고, dev 에는 

        // 현재의 네트워크 디바이스 구조체 표시

        skb->protocol = eth_type_trans(skb, dev); 


        // per_cup_ptr 함수를 사용하여 바텀할프로 하지 않는다.

        pcpu_lstats = (void __percpu __force *)dev->ml_priv;

        lb_stats = this_cpu_ptr(pcpu_lstats);


        len = skb->len;


        // 패킷 수신 처리 부분

        if (likely(netif_rx(skb) == NET_RX_SUCCESS)) {

                 // 통계정보를 업데이트 하는 부분이다. 

                lb_stats->bytes += len;

                lb_stats->packets++;

        } else

                lb_stats->drops++;


        return NETDEV_TX_OK;

}


// loopback 디바이스 드라이버가 관리하는 통계정보를 알려주는 역할을 한다. 

// net_device구조체의 stats에 할당한 net_device_stats구조체에 통계 정보를 갱신하고 그값을 리턴.

static struct net_device_stats *loopback_get_stats(struct net_device *dev)

{

        const struct pcpu_lstats __percpu *pcpu_lstats;

        struct net_device_stats *stats = &dev->stats;

        unsigned long bytes = 0;

        unsigned long packets = 0;

        unsigned long drops = 0;

        int i;


        pcpu_lstats = (void __percpu __force *)dev->ml_priv;

        for_each_possible_cpu(i) {

                const struct pcpu_lstats *lb_stats;


                lb_stats = per_cpu_ptr(pcpu_lstats, i);

                bytes   += lb_stats->bytes;

                packets += lb_stats->packets;

                drops   += lb_stats->drops;

        }

        // 상태 정보 구조체에 값을 갱신 한다.

        stats->rx_packets = packets;

        stats->tx_packets = packets;

        stats->rx_dropped = drops;

        stats->rx_errors  = drops;

        stats->rx_bytes   = bytes;

        stats->tx_bytes   = bytes;

        return stats;

}