dpdk 对网卡 lsc 中断的支持与配置及其隐含的问题

dpdk 版本信息

dpdk-19.11

lsc 中断

lsc 中断全称为链路状态改变中断,当网卡的链路状态发生改变(down -> up、up->down)时会触发此中断调用中断处理函数更新链路状态。

dpdk 支持配置使能网卡的 lsc 中断,rte_eth_conf 结构的 intr_conf 字段用于配置 lsc 及收发包中断,lsc 中断缺省为关闭状态。

intr_conf 字段的定义如下:

	struct rte_eth_intr_conf {
        /** enable/disable lsc interrupt. 0 (default) - disable, 1 enable */
        uint32_t lsc:1;
        /** enable/disable rxq interrupt. 0 (default) - disable, 1 enable */
        uint32_t rxq:1;
        /** enable/disable rmv interrupt. 0 (default) - disable, 1 enable */
        uint32_t rmv:1;
};

当设置 lsc 字段为 1 时,dpdk 会使能网卡 lsc 中断。

lsc 中断的触发过程(以 ixgbe 网卡驱动与 igb_uio 为例)

当网卡状态改变时,硬件中断触发,首先进入到内核的中断处理函数中,根据中断向量表查询到 igb_uio 模块注册的中断回调 igbuio_pci_irqhandler 函数并调用此函数处理中断。

igbuio_pci_irqhandler 主要功能是调用 uio_event_notify 函数唤醒监听 /dev/uioX 事件的进程投递中断到用户态。用户态根据 fd 将中断投递到网卡驱动 probe 阶段注册的中断回调中,此回调在网卡驱动 probe 过程中被注册,ixgbe 的实现代码如下:

 rte_intr_callback_register(intr_handle,
                                   ixgbe_dev_interrupt_handler, eth_dev);

ixgeb_dev_interrupt_handler 回调函数通过读取中断相关寄存器分发中断到不同的处理逻辑中,主要有如下两个步骤:

  1. 读取中断状态寄存器并保存
  2. 判断状态并执行具体的中断处理流程

ixgbe 网卡的 lsc 中断处理过程如下:

        if (intr->flags & IXGBE_FLAG_NEED_LINK_UPDATE) {
                struct rte_eth_link link;

                /* get the link status before link update, for predicting later */
                rte_eth_linkstatus_get(dev, &link);

                ixgbe_dev_link_update(dev, 0);

                /* likely to up */
                if (!link.link_status)
                        /* handle it 1 sec later, wait it being stable */
                        timeout = IXGBE_LINK_UP_CHECK_TIMEOUT;
                /* likely to down */
                else
                        /* handle it 4 sec later, wait it being stable */
                        timeout = IXGBE_LINK_DOWN_CHECK_TIMEOUT;

                ixgbe_dev_link_status_print(dev);
                if (rte_eal_alarm_set(timeout * 1000,
                                      ixgbe_dev_interrupt_delayed_handler, (void *)dev) < 0)
                        PMD_DRV_LOG(ERR, "Error setting alarm");
                else {
                        /* remember original mask */
                        intr->mask_original = intr->mask;
                        /* only disable lsc interrupt */
                        intr->mask &= ~IXGBE_EIMS_LSC;
                }
        }

上述代码在判断到 lsc 中断标志后,调用 ixgbe_dev_link_update 函数访问网卡硬件获取实际的链路状态,同时为了避免抖动,增加了延时检测的逻辑,当延时检测完成后才会重新开启 lsc 中断,避免中断重入问题。

开关 lsc 中断的影响与可能存在的问题

dpdk 内部调用 rte_eth_link_get_nowait 函数来获取接口的 up、down 状态,此接口判断网卡使能 lsc 中断的状态,有如下两种执行逻辑:

1. 使能 lsc 中断的情况

如果使能了 lsc——link status change 中断,则直接原子读取 dev 中的 data->dev_link 成员向上层返回网卡的 down、up 状态。此时网卡 link 状态只在 dpdk 捕获到 lsc 中断并调用相应地中断回调函数时才会更新。

2. 未使能 lsc 中断的情况

如果没有使用 lsc 中断,则调用 pmd 驱动中实现的 dev_ops->link_update 函数来完成。 此时,每次获取网卡的 down、up 状态都会读取网卡硬件寄存器,dpdk 程序定时轮询获取网卡物理状态。

使能 lsc 中断潜在的问题

当接口开启 lsc 中断时,此函数只读取当前接口的软件状态,当关闭 lsc 中断时它才会真正读取寄存器获取硬件真实状态。这里状态的同步由网卡注册的 lsc 中断回调来完成,捕获到 lsc 中断后,网卡中断回调被调用,中断直接调用网卡驱动实现的 link_update 虚函数来获取真实的网卡状态并更新到相应的数据结构中。

当 lsc 中断上报不及时、没有上报时,上层程序获取到的链路状态将一直得不到更新,此时就会造成问题。

是否要开启 lsc 中断?

尽管 lsc 中断有上文提到的潜在问题,该问题也仅在特定的网卡及驱动实现中出现,并不影响正常的使用。一般来说建议开启 lsc,这样仅在中断触发的时候检测硬件状态并更新相关字段,避免了持续周期性轮询网卡硬件状态带来的额外负载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值