dev.c의 netif_rx() 를 분석중입니다.
글쓴이: cjy1126 / 작성시간: 토, 2004/01/17 - 4:54오후
커널이 무언지도 모르면서... tcp/ip 책보면서... 인터넷 검색하면서 소스 분석중입니다.
처음보는 함수는 인터넷에서 찾아가면서 하는데, 왜 사용하는지조차 모르는것들도 있어서 질문올립니다.
혹시 dev.c를 분석해보신적이 있으시다며 도움 부탁드립니다.
int netif_rx(struct sk_buff *skb) { int this_cpu = smp_processor_id(); struct softnet_data *queue; unsigned long flags; if (skb->stamp.tv_sec == 0) do_gettimeofday(&skb->stamp); queue = &softnet_data[this_cpu]; local_irq_save(flags); 질문1: 소프트웨어 인터럽트를 활성화한다. 외부에의한 소프트웨어에의한 인터럽트를 막는것인가요? 아니면 이 함수에서 소프트웨어 인터럽트 발생을 가능하게 하는것인가요? 이 소스에서는 어떤 부분때문에 소프트웨어 인터럽트를 활성화하는것인가요?(왜 사용하는지?) 초기화도안된 flags는 무슨 의미가 있나요? netdev_rx_stat[this_cpu].total++; if (queue->input_pkt_queue.qlen <= netdev_max_backlog) { if (queue->input_pkt_queue.qlen) { if (queue->throttle) goto drop; enqueue: 질문2: dev_hold... 장치를 묶는다? 무슨 역할인가요? dev_hold(skb->dev); __skb_queue_tail(&queue->input_pkt_queue,skb); local_irq_restore(flags); #ifndef OFFLINE_SAMPLE get_sample_stats(this_cpu); #endif return queue->cng_level; } if (queue->throttle) { queue->throttle = 0; #ifdef CONFIG_NET_HW_FLOWCONTROL if (atomic_dec_and_test(&netdev_dropping)) netdev_wakeup(); #endif } netif_rx_schedule(&queue->blog_dev); goto enqueue; } if (queue->throttle == 0) { queue->throttle = 1; netdev_rx_stat[this_cpu].throttled++; #ifdef CONFIG_NET_HW_FLOWCONTROL atomic_inc(&netdev_dropping); #endif } drop: netdev_rx_stat[this_cpu].dropped++; local_irq_restore(flags); kfree_skb(skb); return NET_RX_DROP; }
제가 하려는건 L2 Swtich를 만드는것인데, 이 함수에서 MAC주소만 바꿔서 dev_queue_xmit이나 hard_start_xmit으로 쏘면안되나요?
저한테 온 패킷의 MAC을 비교하고, 버리기전에 무조건 제가 정한 임의의 호스트A 로 보낼려고합니다. (IP는 호스트A의 IP로 도착합니다.)
sk_buff에서 바꾼것은
1. skb->mac.ethernet->h_dest를 호스트A의 MAC으로...(dest IP는 호스트A니까 안바꿨습니다.)
2. skb->dev = dev_get_by_name("eth1");
이것만으로는 랜카드에서 데이터를 안쏘나요?
호스트 A에서 모든패킷을 잡아서 출력하게 만들었는데, 제가 보내는 패킷은 안잡네요.
Forums:
질문 1에 대해서....
:roll:
질문 1의 답변임다. 혹 틀리더라도 비난은 자제 -.-
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 전의 인터럽트 관련 세팅 상태로 원상복귀됩니다.
/***************************************
Being the one is just like being in love.
***************************************/
질문에 대한 답변은 아닌데 혹 도움이....
l2 switch를 만드신다면 netif_rx 다음에서 처리하시는것이 어떨까요?
net_receive_skb 에서 frame 을 후킹하는 지점이 있는데 여기서 적절히 처리후 dev_queue_xmit 으로 보내면 되지 않을까요?
댓글 달기