142 lines · 3.2 KB · C
RawDownload
/* * include/net/act_generic.h **/#ifndef _NET_ACT_GENERIC_H#define _NET_ACT_GENERIC_Hstatic inline int tcf_defact_release(struct tcf_defact *p, int bind){	int ret = 0;	if (p) {		if (bind) {			p->bindcnt--;		}		p->refcnt--;		if (p->bindcnt <= 0 && p->refcnt <= 0) {			kfree(p->defdata);			tcf_hash_destroy(p);			ret = 1;		}	}	return ret;} static inline intalloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata){	p->defdata = kmalloc(datalen, GFP_KERNEL);	if (p->defdata == NULL)		return -ENOMEM;	p->datalen = datalen;	memcpy(p->defdata, defdata, datalen);	return 0;} static inline intrealloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata){	/* safer to be just brute force for now */	kfree(p->defdata);	return alloc_defdata(p, datalen, defdata);} static inline inttcf_defact_init(struct rtattr *rta, struct rtattr *est,		struct tc_action *a, int ovr, int bind){	struct rtattr *tb[TCA_DEF_MAX];	struct tc_defact *parm;	struct tcf_defact *p;	void *defdata;	u32 datalen = 0;	int ret = 0; 	if (rta == NULL || rtattr_parse_nested(tb, TCA_DEF_MAX, rta) < 0)		return -EINVAL; 	if (tb[TCA_DEF_PARMS - 1] == NULL || 	    RTA_PAYLOAD(tb[TCA_DEF_PARMS - 1]) < sizeof(*parm))		return -EINVAL; 	parm = RTA_DATA(tb[TCA_DEF_PARMS - 1]);	defdata = RTA_DATA(tb[TCA_DEF_DATA - 1]);	if (defdata == NULL)		return -EINVAL; 	datalen = RTA_PAYLOAD(tb[TCA_DEF_DATA - 1]);	if (datalen <= 0)		return -EINVAL; 	p = tcf_hash_check(parm->index, a, ovr, bind);	if (p == NULL) {		p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind);		if (p == NULL)			return -ENOMEM; 		ret = alloc_defdata(p, datalen, defdata);		if (ret < 0) {			kfree(p);			return ret;		}		ret = ACT_P_CREATED;	} else {		if (!ovr) {			tcf_defact_release(p, bind);			return -EEXIST;		}		realloc_defdata(p, datalen, defdata);	} 	spin_lock_bh(&p->lock);	p->action = parm->action;	spin_unlock_bh(&p->lock);	if (ret == ACT_P_CREATED)		tcf_hash_insert(p);	return ret;} static inline int tcf_defact_cleanup(struct tc_action *a, int bind){	struct tcf_defact *p = PRIV(a, defact); 	if (p != NULL)		return tcf_defact_release(p, bind);	return 0;} static inline inttcf_defact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref){	unsigned char *b = skb->tail;	struct tc_defact opt;	struct tcf_defact *p = PRIV(a, defact);	struct tcf_t t; 	opt.index = p->index;	opt.refcnt = p->refcnt - ref;	opt.bindcnt = p->bindcnt - bind;	opt.action = p->action;	RTA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt);	RTA_PUT(skb, TCA_DEF_DATA, p->datalen, p->defdata);	t.install = jiffies_to_clock_t(jiffies - p->tm.install);	t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);	t.expires = jiffies_to_clock_t(p->tm.expires);	RTA_PUT(skb, TCA_DEF_TM, sizeof(t), &t);	return skb->len; rtattr_failure:	skb_trim(skb, b - skb->data);	return -1;} #define tca_use_default_ops \	.dump           =       tcf_defact_dump, \	.cleanup        =       tcf_defact_cleanup, \	.init           =       tcf_defact_init, \	.walk           =       tcf_generic_walker, \ #define tca_use_default_defines(name) \	static u32 idx_gen; \	static struct tcf_defact *tcf_##name_ht[MY_TAB_SIZE]; \	static DEFINE_RWLOCK(##name_lock);#endif /* _NET_ACT_GENERIC_H */