aboutsummaryrefslogtreecommitdiffstats
path: root/firmware/tr_smctr.bin.ihex
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/tr_smctr.bin.ihex')
0 files changed, 0 insertions, 0 deletions
> 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
/*
 * include/net/act_generic.h
 *
*/
#ifndef _NET_ACT_GENERIC_H
#define _NET_ACT_GENERIC_H
static 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 int
alloc_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 int
realloc_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 int
tcf_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 int
tcf_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 */