drivers/net/ethernet/cisco/enic/enic_clsf.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/cisco/enic/enic_clsf.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/cisco/enic/enic_clsf.c
Extension
.c
Size
7131 bytes
Lines
287
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

hlist_for_each_entry_safe(n, tmp, hhead, node) {
			enic_delfltr(enic, n->fltr_id);
			hlist_del(&n->node);
			kfree(n);
			enic->rfs_h.free++;
		}
	}
	spin_unlock_bh(&enic->rfs_h.lock);
}

struct enic_rfs_fltr_node *htbl_fltr_search(struct enic *enic, u16 fltr_id)
{
	int i;

	for (i = 0; i < (1 << ENIC_RFS_FLW_BITSHIFT); i++) {
		struct hlist_head *hhead;
		struct hlist_node *tmp;
		struct enic_rfs_fltr_node *n;

		hhead = &enic->rfs_h.ht_head[i];
		hlist_for_each_entry_safe(n, tmp, hhead, node)
			if (n->fltr_id == fltr_id)
				return n;
	}

	return NULL;
}

#ifdef CONFIG_RFS_ACCEL
void enic_flow_may_expire(struct timer_list *t)
{
	struct enic *enic = timer_container_of(enic, t, rfs_h.rfs_may_expire);
	bool res;
	int j;

	spin_lock_bh(&enic->rfs_h.lock);
	for (j = 0; j < ENIC_CLSF_EXPIRE_COUNT; j++) {
		struct hlist_head *hhead;
		struct hlist_node *tmp;
		struct enic_rfs_fltr_node *n;

		hhead = &enic->rfs_h.ht_head[enic->rfs_h.toclean++];
		hlist_for_each_entry_safe(n, tmp, hhead, node) {
			res = rps_may_expire_flow(enic->netdev, n->rq_id,
						  n->flow_id, n->fltr_id);
			if (res) {
				res = enic_delfltr(enic, n->fltr_id);
				if (unlikely(res))
					continue;
				hlist_del(&n->node);
				kfree(n);
				enic->rfs_h.free++;
			}
		}
	}
	spin_unlock_bh(&enic->rfs_h.lock);
	mod_timer(&enic->rfs_h.rfs_may_expire, jiffies + HZ/4);
}

static struct enic_rfs_fltr_node *htbl_key_search(struct hlist_head *h,
						  struct flow_keys *k)
{
	struct enic_rfs_fltr_node *tpos;

	hlist_for_each_entry(tpos, h, node)
		if (tpos->keys.addrs.v4addrs.src == k->addrs.v4addrs.src &&
		    tpos->keys.addrs.v4addrs.dst == k->addrs.v4addrs.dst &&
		    tpos->keys.ports.ports == k->ports.ports &&
		    tpos->keys.basic.ip_proto == k->basic.ip_proto &&
		    tpos->keys.basic.n_proto == k->basic.n_proto)
			return tpos;
	return NULL;
}

int enic_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
		       u16 rxq_index, u32 flow_id)
{
	struct flow_keys keys;
	struct enic_rfs_fltr_node *n;
	struct enic *enic;
	u16 tbl_idx;
	int res, i;

	enic = netdev_priv(dev);
	res = skb_flow_dissect_flow_keys(skb, &keys, 0);
	if (!res || keys.basic.n_proto != htons(ETH_P_IP) ||
	    (keys.basic.ip_proto != IPPROTO_TCP &&
	     keys.basic.ip_proto != IPPROTO_UDP))
		return -EPROTONOSUPPORT;

Annotation

Implementation Notes