cpus_equal()

检测该进程当前所在处理器是否可以执行该进程,如果可以则返回1,否则返回0
#define cpus_equal(src1, src2) __cpus_equal(&(src1), &(src2), NR_CPUS)
static inline int __cpus_equal(const cpumask_t *src1p,
                    const cpumask_t *src2p, int nbits)
{
    return bitmap_equal(src1p->bits, src2p->bits, nbits);
}

static inline int bitmap_equal(const unsigned long *src1,
            const unsigned long *src2, int nbits)
{
    if (nbits <= BITS_PER_LONG)
        return ! ((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits));
    else
        return __bitmap_equal(src1, src2, nbits);
}

#define BITMAP_LAST_WORD_MASK(nbits)                /
(                                                   /
    ((nbits) % BITS_PER_LONG) ?                     /
        (1UL<<((nbits) % BITS_PER_LONG))-1 : ~0UL   /
)
假设nbits = 5; 则
1UL<<((nbits) % BITS_PER_LONG)            100000
(1UL<<((nbits) % BITS_PER_LONG))-1         11111


注:
(1)
-----------------------------------
^     位异或    对应的两位相异为1,相同为0

(2)
-----------------------------------
src1中有多位为1    --  可以执行该进程的CPU掩码集
src2中只有1位为1   --  该进程当前所在处理器的位图

*src1 ^ *src2 运算结果,如果src2中的1所在位为0,表明该进程可以在该当前处理器上运行
(*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits) 运算结果为0








 
补充:目前确认是只要skb经过skb_vlan_untag处理,就会发不出去,不经过skb_vlan_untag处理的skb能正常发出,并且补充skb_vlan_untag处理后的xmit函数实现,请分析问题: static netdev_tx_t edma_dp_xmit(struct nss_dp_data_plane_ctx *dpc, struct sk_buff *skb) { struct net_device *netdev = dpc->dev; struct edma_txdesc_ring *txdesc_ring; struct edma_pcpu_stats *pcpu_stats; struct edma_tx_stats *stats; struct nss_dp_dev *dp_dev; struct sk_buff *segs; uint32_t skbq; uint8_t cpu_id; int ret; enum edma_tx_gso result; #ifdef NSS_DP_MHT_SW_PORT_MAP uint32_t skb_mark = 0; #endif /* * Select a TX ring */ skbq = (skb_get_queue_mapping(skb) & (NR_CPUS - 1)); dp_dev = (struct nss_dp_dev *)netdev_priv(netdev); #ifdef NSS_DP_MHT_SW_PORT_MAP if (dp_dev->nss_dp_mht_dev) { if (EDMA_TX_MHT_SW_PORT_MARK_VALID(skb->mark)) skb_mark = EDMA_TX_MHT_SW_PORT_MARK_GET(skb->mark); txdesc_ring = (struct edma_txdesc_ring *)dp_dev->dp_info.txr_sw_port_map[skb_mark][skbq]; } else { txdesc_ring = (struct edma_txdesc_ring *)dp_dev->dp_info.txr_map[0][skbq]; } #else txdesc_ring = (struct edma_txdesc_ring *)dp_dev->dp_info.txr_map[0][skbq]; #endif pcpu_stats = &dp_dev->dp_info.pcpu_stats; stats = this_cpu_ptr(pcpu_stats->tx_stats); /* * HW does not support TSO for packets with more than or equal to * 32 segments. HW hangs up if it sees more than 32 segments. * Perform SW GSO for such packets. */ result = edma_tx_gso_segment(skb, netdev, &segs); if (likely(result == EDMA_TX_GSO_NOT_NEEDED)) { /* * Transmit the packet */ ret = edma_tx_ring_xmit(netdev, NULL, skb, txdesc_ring, stats); /* * If return failure is due to no descriptor and if tx_requeue_stop is not enabled * then stop the queue and return status as "NETDEV_TX_BUSY". * This queue will be enabled again from EDMA tx complete. */ if (unlikely(ret == EDMA_TX_FAIL_NO_DESC)) { #ifdef NSS_DP_MHT_SW_PORT_MAP /* * When MHT SW port is enabled, Tx rings are mapped * to individual MHT ports but netdev still * remains same. Hence requeue cannot be done if * MHT SW port mapping is enabled on MHT netdevice. */ if (unlikely(dp_dev->nss_dp_mht_dev)) { printk("edma_dp_xmit hit 6\n"); goto no_requeue; } #endif if (likely(!dp_global_ctx.tx_requeue_stop)) { cpu_id = smp_processor_id(); edma_debug("Stopping tx queue due to lack of tx descriptors\n"); u64_stats_update_begin(&stats->syncp); ++stats->tx_queue_stopped[cpu_id]; u64_stats_update_end(&stats->syncp); netif_tx_stop_queue(netdev_get_tx_queue(netdev, skbq)); printk("edma_dp_xmit hit 7\n"); return NETDEV_TX_BUSY; } } #ifdef NSS_DP_MHT_SW_PORT_MAP no_requeue: #endif if (unlikely(ret != EDMA_TX_OK)) { dev_kfree_skb_any(skb); u64_stats_update_begin(&stats->syncp); ++stats->tx_drops; u64_stats_update_end(&stats->syncp); } printk("edma_dp_xmit hit 8\n"); return NETDEV_TX_OK; } else if (unlikely(result == EDMA_TX_GSO_FAIL)) { edma_debug("%px: SW GSO failed for segment size: (%d)\n", skb, skb_shinfo(skb)->gso_segs); dev_kfree_skb_any(skb); u64_stats_update_begin(&stats->syncp); ++stats->tx_gso_drop_pkts; u64_stats_update_end(&stats->syncp); printk("edma_dp_xmit hit 9\n"); return NETDEV_TX_OK; } u64_stats_update_begin(&stats->syncp); ++stats->tx_gso_pkts; u64_stats_update_end(&stats->syncp); dev_kfree_skb_any(skb); while (segs) { skb = segs; segs = segs->next; /* * Transmit the packet */ ret = edma_tx_ring_xmit(netdev, NULL, skb, txdesc_ring, stats); if (unlikely(ret != EDMA_TX_OK)) { dev_kfree_skb_any(skb); u64_stats_update_begin(&stats->syncp); ++stats->tx_drops; u64_stats_update_end(&stats->syncp); printk("edma_dp_xmit hit not ok\n"); } } printk("edma_dp_xmit hit 10\n"); return NETDEV_TX_OK; }
最新发布
09-23
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值