1

about netif_rx

 2 years ago
source link: http://ifq.github.io/blog/2015/02/08/2015-02-08-netif_rx-and-softirq/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

由于历史原因,在之前的项目中,用的network stack一直是自研的,和linux原生的stack完全不兼容。渐渐的这种不兼容的痛已经透彻全身,一直想去动但是又动弹不得。马上又要研发新品了,这回觉得是该动一动了。于是开始学习linux原生的做法(之前搞了这么久其实不熟悉linux的实现。。),完全替换不可能,但是融合一下总可以把!

关键字:netif_rx, RPS, backlog, softirq, SMP

netif_rx的过程就不梳理了,只对自己的疑问和找到的答案做个记录。

netif_rx 把skb怎么了?

在RPS宏打开时,首先get_rps_cpu根据skb选择处理的core,然后enqueue_to_backlog把skb放到core对应的skb queue中,并且置位softirq,调度处理之。

backlog的处理是怎么调度的?

关于net_rx_action的softirq是怎么激活的,找了半天最后其实就在眼皮底下的enqueue_to_backlog里。写法不够直观,所以看了几遍才理解了。

static int enqueue_to_backlog(struct sk_buff *skb, int cpu,
			      unsigned int *qtail)
{
	struct softnet_data *sd;
	unsigned long flags;

	sd = &per_cpu(softnet_data, cpu);

	local_irq_save(flags);

	rps_lock(sd);
	if (skb_queue_len(&sd->input_pkt_queue) <= netdev_max_backlog) {
		if (skb_queue_len(&sd->input_pkt_queue)) { // ----- 队列是空的时候才会从这里跳到激活,否则只是做入队操作
enqueue:
			__skb_queue_tail(&sd->input_pkt_queue, skb);
			input_queue_tail_incr_save(sd, qtail);
			rps_unlock(sd);
			local_irq_restore(flags);
			return NET_RX_SUCCESS;
		}

		/* Schedule NAPI for backlog device
		 * We can use non atomic operation since we own the queue lock
		 */
		if (!__test_and_set_bit(NAPI_STATE_SCHED, &sd->backlog.state)) {
			if (!rps_ipi_queued(sd))  // ----- 这里置位,激活softirq
				____napi_schedule(sd, &sd->backlog);
		}
		goto enqueue;
	}

	sd->dropped++;
	rps_unlock(sd);

	local_irq_restore(flags);

	atomic_long_inc(&skb->dev->rx_dropped);
	kfree_skb(skb);
	return NET_RX_DROP;
}

也就是说在第一个skb入队前激活softirq,到softirq实际调度之前的时间里,入队的报文也会一并处理。这是为了提高性能做的处理,把报文聚合了。也就是说上行报文在每个core上会积攒到下一次softirq调度为止(按照以往经验,无线的话最多也就十几个报文把)。

顺便看了下 softirq 是怎么调度的。重点是irq_exit函数。每次IRQ处理函数结束后就会调用它,从而调度softirq。另外,softirq是预先定义好的10种,而tasklet是其中的两种,这个之前没去了解过。原来如此单纯啊,瞬间不高大上了。有个疑问是,如果没有中断上来,softirq的时效性如何保证啊?没有深究。。

CONFIG_RPS 是什么?

Symbol: RPS [=y]
Type : boolean
Prompt: RPS
Defined at net/Kconfig:240
Depends on: NET [=y] && SMP [=y] && SYSFS [=y] && USE_GENERIC_SMP_HELPERS [=y]
Location:
-> Networking support (NET [=y])
-> Networking options

RPS 依赖于 SMP,多核下对报文流进行分配和加速的功能。通过hash将报文流分配到固定的core上,以提高多核的利用率,以及提高cache的命中率。

SMP 下的 IRQ有什么区别?

SMP下使用 APIC,可以配置irq产生到特定core的几率。cat /proc/interrupts 可以看到每个终端在各个core上的次数:

$ cat /proc/interrupts 
           CPU0       CPU1       CPU2       CPU3       
  0:         50          0          0          0   IO-APIC-edge      timer
  1:      30098          0          0          0   IO-APIC-edge      i8042
  8:          0          0          0          0   IO-APIC-edge      rtc0
  9:          0          0          0          0   IO-APIC-fasteoi   acpi
 12:       8113          0          0          0   IO-APIC-edge      i8042
 14:          0          0          0          0   IO-APIC-edge      ata_piix
 15:      50474          0          0          0   IO-APIC-edge      ata_piix
 16:         71          0          0      33906   IO-APIC-fasteoi   eth1
 17:      25732          0          0          0   IO-APIC-fasteoi   eth2
 19:         98          0      63721          0   IO-APIC-fasteoi   eth0

如何控制 IRQ亲和性,IRQ Affinity,网上有很多资料。



About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK